// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/src/dart/element/element.dart'; /// Keeps track of the set of non-synthetic child fragments of a fragment, /// yielding them one at a time in response to "get" method calls. class ElementWalker { /// The fragment whose child fragments are being walked. final FragmentImpl fragment; String? libraryFilePath; String? unitFilePath; List? _classes; int _classIndex = 0; List? _constructors; int _constructorIndex = 0; List? _enums; int _enumIndex = 0; List? _extensions; int _extensionIndex = 0; List? _extensionTypes; int _extensionTypeIndex = 0; List? _functions; int _functionIndex = 0; List? _getters; int _getterIndex = 0; List? _mixins; int _mixinIndex = 0; List? _parameters; int _parameterIndex = 0; List? _setters; int _setterIndex = 0; List? _typedefs; int _typedefIndex = 0; List? _typeParameters; int _typeParameterIndex = 0; List? _variables; int _variableIndex = 0; /// Creates an [ElementWalker] which walks the child elements of a class /// element. ElementWalker.forClass(ClassFragmentImpl this.fragment) : _constructors = fragment.isMixinApplication ? null : fragment.constructors.where(_isNotSynthetic).toList(), _functions = fragment.methods, _getters = fragment.getters.where(_isNotSynthetic).toList(), _setters = fragment.setters.where(_isNotSynthetic).toList(), _typeParameters = fragment.typeParameters, _variables = fragment.fields.where(_isNotSynthetic).toList(); /// Creates an [ElementWalker] which walks the child elements of a compilation /// unit element. ElementWalker.forCompilationUnit( LibraryFragmentImpl this.fragment, { this.libraryFilePath, this.unitFilePath, }) : _classes = fragment.classes, _enums = fragment.enums, _extensions = fragment.extensions, _extensionTypes = fragment.extensionTypes, _functions = fragment.functions, _getters = fragment.getters.where(_isNotSynthetic).toList(), _mixins = fragment.mixins, _setters = fragment.setters.where(_isNotSynthetic).toList(), _typedefs = fragment.typeAliases, _variables = fragment.topLevelVariables.where(_isNotSynthetic).toList(); /// Creates an [ElementWalker] which walks the child elements of a enum /// element. ElementWalker.forEnum(EnumFragmentImpl this.fragment) : _constructors = fragment.constructors.where(_isNotSynthetic).toList(), _functions = fragment.methods, _getters = fragment.getters.where(_isNotSynthetic).toList(), _setters = fragment.setters.where(_isNotSynthetic).toList(), _typeParameters = fragment.typeParameters, _variables = fragment.fields.where(_isNotSynthetic).toList(); /// Creates an [ElementWalker] which walks the child elements of a compilation /// unit element. ElementWalker.forExecutable(ExecutableFragmentImpl this.fragment) : _functions = const [], _parameters = fragment.formalParameters, _typeParameters = fragment.typeParameters; /// Creates an [ElementWalker] which walks the child elements of an extension /// element. ElementWalker.forExtension(ExtensionFragmentImpl this.fragment) : _functions = fragment.methods, _getters = fragment.getters.where(_isNotSynthetic).toList(), _setters = fragment.setters.where(_isNotSynthetic).toList(), _typeParameters = fragment.typeParameters, _variables = fragment.fields.where(_isNotSynthetic).toList(); ElementWalker.forExtensionType(ExtensionTypeFragmentImpl this.fragment) : _constructors = fragment.constructors, _functions = fragment.methods, _getters = fragment.getters.where(_isNotSynthetic).toList(), _setters = fragment.setters.where(_isNotSynthetic).toList(), _typeParameters = fragment.typeParameters, _variables = fragment.fields.where(_isNotSynthetic).toList(); /// Creates an [ElementWalker] which walks the child elements of a typedef /// element. ElementWalker.forGenericFunctionType( GenericFunctionTypeFragmentImpl this.fragment, ) : _parameters = fragment.formalParameters, _typeParameters = fragment.typeParameters; /// Creates an [ElementWalker] which walks the child elements of a typedef /// element defined using a generic function type. ElementWalker.forGenericTypeAlias(TypeAliasFragmentImpl this.fragment) : _typeParameters = fragment.typeParameters; /// Creates an [ElementWalker] which walks the child elements of a mixin /// element. ElementWalker.forMixin(MixinFragmentImpl this.fragment) : _constructors = fragment.constructors.where(_isNotSynthetic).toList(), _functions = fragment.methods, _getters = fragment.getters.where(_isNotSynthetic).toList(), _setters = fragment.setters.where(_isNotSynthetic).toList(), _typeParameters = fragment.typeParameters, _variables = fragment.fields.where(_isNotSynthetic).toList(); /// Creates an [ElementWalker] which walks the child elements of a parameter /// element. ElementWalker.forParameter(FormalParameterFragmentImpl this.fragment) : _parameters = fragment.formalParameters, _typeParameters = fragment.typeParameters; /// Creates an [ElementWalker] which walks the child elements of a typedef /// element. ElementWalker.forTypedef(TypeAliasFragmentImpl this.fragment) : _parameters = (fragment.aliasedElement as GenericFunctionTypeFragmentImpl) .formalParameters, _typeParameters = fragment.typeParameters; void consumeLocalElements() { _functionIndex = _functions!.length; } void consumeParameters() { _parameterIndex = _parameters!.length; } /// Returns the next non-synthetic child of [fragment] which is a class; /// throws an [IndexError] if there are no more. ClassFragmentImpl getClass() { return _classes![_classIndex++]; } /// Returns the next non-synthetic child of [fragment] which is a constructor; /// throws an [IndexError] if there are no more. ConstructorFragmentImpl getConstructor() => _constructors![_constructorIndex++]; /// Returns the next non-synthetic child of [fragment] which is an enum; /// throws an [IndexError] if there are no more. EnumFragmentImpl getEnum() => _enums![_enumIndex++]; ExtensionFragmentImpl getExtension() => _extensions![_extensionIndex++]; ExtensionTypeFragmentImpl getExtensionType() => _extensionTypes![_extensionTypeIndex++]; /// Returns the next non-synthetic child of [fragment] which is a top level /// function, method, or local function; throws an [IndexError] if there are /// no more. ExecutableFragmentImpl getFunction() => _functions![_functionIndex++]; /// Returns the next non-synthetic child of [fragment] which is a getter; /// throws an [IndexError] if there are no more. GetterFragmentImpl getGetter() { return _getters![_getterIndex++]; } /// Returns the next non-synthetic child of [fragment] which is a mixin; /// throws an [IndexError] if there are no more. MixinFragmentImpl getMixin() => _mixins![_mixinIndex++]; /// Returns the next non-synthetic child of [fragment] which is a parameter; /// throws an [IndexError] if there are no more. FormalParameterFragmentImpl getParameter() => _parameters![_parameterIndex++]; /// Returns the next non-synthetic child of [fragment] which is a setter; /// throws an [IndexError] if there are no more. SetterFragmentImpl getSetter() { return _setters![_setterIndex++]; } /// Returns the next non-synthetic child of [fragment] which is a typedef; /// throws an [IndexError] if there are no more. TypeAliasFragmentImpl getTypedef() => _typedefs![_typedefIndex++]; /// Returns the next non-synthetic child of [fragment] which is a type /// parameter; throws an [IndexError] if there are no more. TypeParameterFragmentImpl getTypeParameter() => _typeParameters![_typeParameterIndex++]; /// Returns the next non-synthetic child of [fragment] which is a top level /// variable, field, or local variable; throws an [IndexError] if there are no /// more. VariableFragmentImpl getVariable() { return _variables![_variableIndex++]; } /// Verifies that all non-synthetic children of [fragment] have been obtained /// from their corresponding "get" method calls; if not, throws a /// [StateError]. void validate() { void check(List? elements, int index) { if (elements != null && elements.length != index) { throw StateError( 'Unmatched ${elements[index].runtimeType} ${elements[index]}', ); } } check(_classes, _classIndex); check(_constructors, _constructorIndex); check(_enums, _enumIndex); check(_functions, _functionIndex); check(_getters, _getterIndex); check(_parameters, _parameterIndex); check(_setters, _setterIndex); check(_typedefs, _typedefIndex); check(_typeParameters, _typeParameterIndex); check(_variables, _variableIndex); } static bool _isNotSynthetic(FragmentImpl e) => !e.isSynthetic; }