// 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.

library fasta.scope;

import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart';

import 'builder/builder.dart';
import 'builder/extension_builder.dart';
import 'builder/library_builder.dart';
import 'builder/member_builder.dart';
import 'builder/name_iterator.dart';
import 'builder/type_variable_builder.dart';
import 'kernel/body_builder.dart' show JumpTarget;
import 'kernel/class_hierarchy_builder.dart' show ClassMember;
import 'kernel/kernel_helper.dart';
import 'util/helpers.dart' show DelayedActionPerformer;

import 'fasta_codes.dart'
    show
        LocatedMessage,
        Message,
        messageInternalProblemExtendingUnmodifiableScope,
        templateAccessError,
        templateDuplicatedDeclarationUse,
        templateDuplicatedNamePreviouslyUsedCause;

import 'problems.dart' show internalProblem, unsupported;

class MutableScope {
  /// Names declared in this scope.
  Map<String, Builder> _local;

  /// Setters declared in this scope.
  Map<String, MemberBuilder> _setters;

  /// The extensions declared in this scope.
  ///
  /// This includes all available extensions even if the extensions are not
  /// accessible by name because of duplicate imports.
  ///
  /// For instance:
  ///
  ///   lib1.dart:
  ///     extension Extension on String {
  ///       method1() {}
  ///       staticMethod1() {}
  ///     }
  ///   lib2.dart:
  ///     extension Extension on String {
  ///       method2() {}
  ///       staticMethod2() {}
  ///     }
  ///   main.dart:
  ///     import 'lib1.dart';
  ///     import 'lib2.dart';
  ///
  ///     main() {
  ///       'foo'.method1(); // This method is available.
  ///       'foo'.method2(); // This method is available.
  ///       // These methods are not available because Extension is ambiguous:
  ///       Extension.staticMethod1();
  ///       Extension.staticMethod2();
  ///     }
  ///
  Set<ExtensionBuilder>? _extensions;

  /// The scope that this scope is nested within, or `null` if this is the top
  /// level scope.
  Scope? _parent;

  final String classNameOrDebugName;

  MutableScope(this._local, this._setters, this._extensions, this._parent,
      this.classNameOrDebugName) {
    // ignore: unnecessary_null_comparison
    assert(classNameOrDebugName != null);
  }

  Scope? get parent => _parent;

  String toString() => "Scope($classNameOrDebugName, ${_local.keys})";
}

class Scope extends MutableScope {
  /// Indicates whether an attempt to declare new names in this scope should
  /// succeed.
  final bool isModifiable;

  Map<String, JumpTarget>? labels;

  Map<String, JumpTarget>? forwardDeclaredLabels;

  Map<String, int>? usedNames;

  Scope(
      {required Map<String, Builder> local,
      Map<String, MemberBuilder>? setters,
      Set<ExtensionBuilder>? extensions,
      Scope? parent,
      required String debugName,
      this.isModifiable: true})
      : super(local, setters = setters ?? const <String, MemberBuilder>{},
            extensions, parent, debugName);

  Scope.top({bool isModifiable: false})
      : this(
            local: <String, Builder>{},
            setters: <String, MemberBuilder>{},
            debugName: "top",
            isModifiable: isModifiable);

  Scope.immutable()
      : this(
            local: const <String, Builder>{},
            setters: const <String, MemberBuilder>{},
            debugName: "immutable",
            isModifiable: false);

  Scope.nested(Scope parent, String debugName, {bool isModifiable: true})
      : this(
            local: <String, Builder>{},
            setters: <String, MemberBuilder>{},
            parent: parent,
            debugName: debugName,
            isModifiable: isModifiable);

  Iterator<Builder> get iterator {
    return new ScopeLocalDeclarationIterator(this);
  }

  NameIterator get nameIterator {
    return new ScopeLocalDeclarationNameIterator(this);
  }

  void debug() {
    print("Locals:");
    _local.forEach((key, value) {
      print("  $key: $value (${identityHashCode(value)}) (${value.parent})");
    });
    print("Setters:");
    _setters.forEach((key, value) {
      print("  $key: $value (${identityHashCode(value)}) (${value.parent})");
    });
    print("Extensions:");
    _extensions?.forEach((v) {
      print("  $v");
    });
  }

  /// Patch up the scope, using the two replacement maps to replace builders in
  /// scope. The replacement maps maps from old LibraryBuilder to map, mapping
  /// from name to new (replacement) builder.
  void patchUpScope(Map<LibraryBuilder, Map<String, Builder>> replacementMap,
      Map<LibraryBuilder, Map<String, Builder>> replacementMapSetters) {
    // In the following we refer to non-setters as 'getters' for brevity.
    //
    // We have to replace all getters and setters in [_locals] and [_setters]
    // with the corresponding getters and setters in [replacementMap]
    // and [replacementMapSetters].
    //
    // Since field builders can be replaced by getter and setter builders and
    // vice versa when going from source to dill builder and back, we might not
    // have a 1-to-1 relationship between the existing and replacing builders.
    //
    // For this reason we start by collecting the names of all getters/setters
    // that need (some) replacement. Afterwards we go through these names
    // handling both getters and setters at the same time.
    Set<String> replacedNames = {};
    _local.forEach((String name, Builder builder) {
      if (replacementMap.containsKey(builder.parent)) {
        replacedNames.add(name);
      }
    });
    _setters.forEach((String name, Builder builder) {
      if (replacementMapSetters.containsKey(builder.parent)) {
        replacedNames.add(name);
      }
    });
    if (replacedNames.isNotEmpty) {
      for (String name in replacedNames) {
        // We start be collecting the relation between an existing getter/setter
        // and the getter/setter that will replace it. This information is used
        // below to handle all the different cases that can occur.
        Builder? existingGetter = _local[name];
        LibraryBuilder? replacementLibraryBuilderFromGetter;
        Builder? replacementGetterFromGetter;
        Builder? replacementSetterFromGetter;
        if (existingGetter != null &&
            replacementMap.containsKey(existingGetter.parent)) {
          replacementLibraryBuilderFromGetter =
              existingGetter.parent as LibraryBuilder;
          replacementGetterFromGetter =
              replacementMap[replacementLibraryBuilderFromGetter]![name];
          replacementSetterFromGetter =
              replacementMapSetters[replacementLibraryBuilderFromGetter]![name];
        }
        Builder? existingSetter = _setters[name];
        LibraryBuilder? replacementLibraryBuilderFromSetter;
        Builder? replacementGetterFromSetter;
        Builder? replacementSetterFromSetter;
        if (existingSetter != null &&
            replacementMap.containsKey(existingSetter.parent)) {
          replacementLibraryBuilderFromSetter =
              existingSetter.parent as LibraryBuilder;
          replacementGetterFromSetter =
              replacementMap[replacementLibraryBuilderFromSetter]![name];
          replacementSetterFromSetter =
              replacementMapSetters[replacementLibraryBuilderFromSetter]![name];
        }

        if (existingGetter == null) {
          // No existing getter.
          if (replacementGetterFromSetter != null) {
            // We might have had one implicitly from the setter. Use it here,
            // if so. (This is currently not possible, but added to match the
            // case for setters below.)
            _local[name] = replacementGetterFromSetter;
          }
        } else if (existingGetter.parent ==
            replacementLibraryBuilderFromGetter) {
          // The existing getter should be replaced.
          if (replacementGetterFromGetter != null) {
            // With a new getter.
            _local[name] = replacementGetterFromGetter;
          } else {
            // With `null`, i.e. removed. This means that the getter is
            // implicitly available through the setter. (This is currently not
            // possible, but handled here to match the case for setters below).
            _local.remove(name);
          }
        } else {
          // Leave the getter in - it wasn't replaced.
        }
        if (existingSetter == null) {
          // No existing setter.
          if (replacementSetterFromGetter != null) {
            // We might have had one implicitly from the getter. Use it here,
            // if so.
            _setters[name] = replacementSetterFromGetter as MemberBuilder;
          }
        } else if (existingSetter.parent ==
            replacementLibraryBuilderFromSetter) {
          // The existing setter should be replaced.
          if (replacementSetterFromSetter != null) {
            // With a new setter.
            _setters[name] = replacementSetterFromSetter as MemberBuilder;
          } else {
            // With `null`, i.e. removed. This means that the setter is
            // implicitly available through the getter. This happens when the
            // getter is a field builder for an assignable field.
            _setters.remove(name);
          }
        } else {
          // Leave the setter in - it wasn't replaced.
        }
      }
    }
    if (_extensions != null) {
      bool needsPatching = false;
      for (ExtensionBuilder extensionBuilder in _extensions!) {
        if (replacementMap.containsKey(extensionBuilder.parent)) {
          needsPatching = true;
          break;
        }
      }
      if (needsPatching) {
        Set<ExtensionBuilder> extensionsReplacement =
            new Set<ExtensionBuilder>();
        for (ExtensionBuilder extensionBuilder in _extensions!) {
          if (replacementMap.containsKey(extensionBuilder.parent)) {
            assert(replacementMap[extensionBuilder.parent]![
                    extensionBuilder.name] !=
                null);
            extensionsReplacement.add(
                replacementMap[extensionBuilder.parent]![extensionBuilder.name]
                    as ExtensionBuilder);
            break;
          } else {
            extensionsReplacement.add(extensionBuilder);
          }
        }
        _extensions!.clear();
        extensionsReplacement.addAll(extensionsReplacement);
      }
    }
  }

  Scope copyWithParent(Scope parent, String debugName) {
    return new Scope(
        local: super._local,
        setters: super._setters,
        extensions: _extensions,
        parent: parent,
        debugName: debugName,
        isModifiable: isModifiable);
  }

  /// Don't use this. Use [becomePartOf] instead.
  void set parent(_) => unsupported("parent=", -1, null);

  /// This scope becomes equivalent to [scope]. This is used for parts to
  /// become part of their library's scope.
  void becomePartOf(Scope scope) {
    assert(_parent!._parent == null);
    assert(scope._parent!._parent == null);
    super._local = scope._local;
    super._setters = scope._setters;
    super._parent = scope._parent;
    super._extensions = scope._extensions;
  }

  Scope createNestedScope(String debugName, {bool isModifiable: true}) {
    return new Scope.nested(this, debugName, isModifiable: isModifiable);
  }

  Scope withTypeVariables(List<TypeVariableBuilder>? typeVariables) {
    if (typeVariables == null) return this;
    Scope newScope =
        new Scope.nested(this, "type variables", isModifiable: false);
    for (TypeVariableBuilder t in typeVariables) {
      newScope._local[t.name] = t;
    }
    return newScope;
  }

  /// Create a special scope for use by labeled statements. This scope doesn't
  /// introduce a new scope for local variables, only for labels. This deals
  /// with corner cases like this:
  ///
  ///     L: var x;
  ///     x = 42;
  ///     print("The answer is $x.");
  Scope createNestedLabelScope() {
    return new Scope(
        local: _local,
        setters: _setters,
        extensions: _extensions,
        parent: _parent,
        debugName: "label",
        isModifiable: true);
  }

  void recordUse(String name, int charOffset) {
    if (isModifiable) {
      usedNames ??= <String, int>{};
      // Don't use putIfAbsent to avoid the context allocation needed
      // for the closure.
      usedNames![name] ??= charOffset;
    }
  }

  Builder? lookupIn(String name, int charOffset, Uri fileUri,
      Map<String, Builder> map, bool isInstanceScope) {
    Builder? builder = map[name];
    if (builder == null) return null;
    if (builder.next != null) {
      return new AmbiguousBuilder(name.isEmpty ? classNameOrDebugName : name,
          builder, charOffset, fileUri);
    } else if (!isInstanceScope && builder.isDeclarationInstanceMember) {
      return null;
    } else if (builder is MemberBuilder && builder.isConflictingSetter) {
      // TODO(johnniwinther): Use a variant of [AmbiguousBuilder] for this case.
      return null;
    } else {
      return builder;
    }
  }

  Builder? lookup(String name, int charOffset, Uri fileUri,
      {bool isInstanceScope: true}) {
    recordUse(name, charOffset);
    Builder? builder =
        lookupIn(name, charOffset, fileUri, _local, isInstanceScope);
    if (builder != null) return builder;
    builder = lookupIn(name, charOffset, fileUri, _setters, isInstanceScope);
    if (builder != null && !builder.hasProblem) {
      return new AccessErrorBuilder(name, builder, charOffset, fileUri);
    }
    if (!isInstanceScope) {
      // For static lookup, do not search the parent scope.
      return builder;
    }
    return builder ?? _parent?.lookup(name, charOffset, fileUri);
  }

  Builder? lookupSetter(String name, int charOffset, Uri fileUri,
      {bool isInstanceScope: true}) {
    recordUse(name, charOffset);
    Builder? builder =
        lookupIn(name, charOffset, fileUri, _setters, isInstanceScope);
    if (builder != null) return builder;
    builder = lookupIn(name, charOffset, fileUri, _local, isInstanceScope);
    if (builder != null && !builder.hasProblem) {
      return new AccessErrorBuilder(name, builder, charOffset, fileUri);
    }
    if (!isInstanceScope) {
      // For static lookup, do not search the parent scope.
      return builder;
    }
    return builder ?? _parent?.lookupSetter(name, charOffset, fileUri);
  }

  Builder? lookupLocalMember(String name, {required bool setter}) {
    return setter ? _setters[name] : _local[name];
  }

  void addLocalMember(String name, Builder member, {required bool setter}) {
    if (setter) {
      _setters[name] = member as MemberBuilder;
    } else {
      _local[name] = member;
    }
  }

  void forEachLocalMember(void Function(String name, Builder member) f) {
    _local.forEach(f);
  }

  void forEachLocalSetter(void Function(String name, MemberBuilder member) f) {
    _setters.forEach(f);
  }

  Iterable<Builder> get localMembers => _local.values;

  Iterable<MemberBuilder> get localSetters => _setters.values;

  bool hasLocalLabel(String name) =>
      labels != null && labels!.containsKey(name);

  void declareLabel(String name, JumpTarget target) {
    if (isModifiable) {
      labels ??= <String, JumpTarget>{};
      labels![name] = target;
    } else {
      internalProblem(
          messageInternalProblemExtendingUnmodifiableScope, -1, null);
    }
  }

  void forwardDeclareLabel(String name, JumpTarget target) {
    declareLabel(name, target);
    forwardDeclaredLabels ??= <String, JumpTarget>{};
    forwardDeclaredLabels![name] = target;
  }

  bool claimLabel(String name) {
    if (forwardDeclaredLabels == null ||
        forwardDeclaredLabels!.remove(name) == null) {
      return false;
    }
    if (forwardDeclaredLabels!.length == 0) {
      forwardDeclaredLabels = null;
    }
    return true;
  }

  Map<String, JumpTarget>? get unclaimedForwardDeclarations {
    return forwardDeclaredLabels;
  }

  Builder? lookupLabel(String name) {
    return labels?[name] ?? _parent?.lookupLabel(name);
  }

  /// Declares that the meaning of [name] in this scope is [builder].
  ///
  /// If name was used previously in this scope, this method returns a message
  /// that can be used as context for reporting a compile-time error about
  /// [name] being used before its declared. [fileUri] is used to bind the
  /// location of this message.
  LocatedMessage? declare(String name, Builder builder, Uri fileUri) {
    if (isModifiable) {
      int? offset = usedNames?[name];
      if (offset != null) {
        return templateDuplicatedNamePreviouslyUsedCause
            .withArguments(name)
            .withLocation(fileUri, offset, name.length);
      }
      _local[name] = builder;
    } else {
      internalProblem(
          messageInternalProblemExtendingUnmodifiableScope, -1, null);
    }
    return null;
  }

  /// Adds [builder] to the extensions in this scope.
  void addExtension(ExtensionBuilder builder) {
    _extensions ??= <ExtensionBuilder>{};
    _extensions!.add(builder);
  }

  /// Calls [f] for each extension in this scope and parent scopes.
  void forEachExtension(void Function(ExtensionBuilder) f) {
    _extensions?.forEach(f);
    _parent?.forEachExtension(f);
  }

  void merge(
      Scope scope,
      Builder computeAmbiguousDeclaration(
          String name, Builder existing, Builder member)) {
    Map<String, Builder> map = _local;

    void mergeMember(String name, Builder member) {
      Builder? existing = map[name];
      if (existing != null) {
        if (existing != member) {
          member = computeAmbiguousDeclaration(name, existing, member);
        }
      }
      map[name] = member;
    }

    scope._local.forEach(mergeMember);
    map = _setters;
    scope._setters.forEach(mergeMember);
  }

  void forEach(f(String name, Builder member)) {
    _local.forEach(f);
    _setters.forEach(f);
  }

  String get debugString {
    StringBuffer buffer = new StringBuffer();
    int nestingLevel = writeOn(buffer);
    for (int i = nestingLevel; i >= 0; i--) {
      buffer.writeln("${'  ' * i}}");
    }
    return "$buffer";
  }

  int writeOn(StringSink sink) {
    int nestingLevel = (_parent?.writeOn(sink) ?? -1) + 1;
    String indent = "  " * nestingLevel;
    sink.writeln("$indent{");
    _local.forEach((String name, Builder member) {
      sink.writeln("$indent  $name");
    });
    _setters.forEach((String name, Builder member) {
      sink.writeln("$indent  $name=");
    });
    return nestingLevel;
  }

  Scope computeMixinScope() {
    Map<String, Builder> local = <String, Builder>{};
    bool needsCopy = false;
    for (MapEntry<String, Builder> entry in _local.entries) {
      String name = entry.key;
      Builder declaration = entry.value;
      if (declaration.isStatic) {
        needsCopy = true;
      } else {
        local[name] = declaration;
      }
    }
    Map<String, MemberBuilder> setters = <String, MemberBuilder>{};
    for (MapEntry<String, MemberBuilder> entry in _setters.entries) {
      String name = entry.key;
      MemberBuilder declaration = entry.value;
      if (declaration.isStatic) {
        needsCopy = true;
      } else {
        setters[name] = declaration;
      }
    }
    return needsCopy
        ? new Scope(
            local: local,
            setters: setters,
            extensions: _extensions,
            parent: _parent,
            debugName: classNameOrDebugName,
            isModifiable: isModifiable)
        : this;
  }
}

class ConstructorScope {
  /// Constructors declared in this scope.
  final Map<String, MemberBuilder> local;

  final String className;

  ConstructorScope(this.className, this.local);

  void forEach(f(String name, MemberBuilder member)) {
    local.forEach(f);
  }

  MemberBuilder? lookup(String name, int charOffset, Uri fileUri) {
    MemberBuilder? builder = local[name];
    if (builder == null) return null;
    if (builder.next != null) {
      return new AmbiguousMemberBuilder(
          name.isEmpty ? className : name, builder, charOffset, fileUri);
    } else {
      return builder;
    }
  }

  String toString() => "ConstructorScope($className, ${local.keys})";
}

abstract class LazyScope extends Scope {
  LazyScope(Map<String, Builder> local, Map<String, MemberBuilder> setters,
      Scope? parent, String debugName, {bool isModifiable: true})
      : super(
            local: local,
            setters: setters,
            parent: parent,
            debugName: debugName,
            isModifiable: isModifiable);

  /// Override this method to lazily populate the scope before access.
  void ensureScope();

  @override
  Map<String, Builder> get _local {
    ensureScope();
    return super._local;
  }

  @override
  Map<String, MemberBuilder> get _setters {
    ensureScope();
    return super._setters;
  }

  @override
  Set<ExtensionBuilder>? get _extensions {
    ensureScope();
    return super._extensions;
  }
}

class ScopeBuilder {
  final Scope scope;

  ScopeBuilder(this.scope);

  void addMember(String name, Builder builder) {
    scope._local[name] = builder;
  }

  void addSetter(String name, MemberBuilder builder) {
    scope._setters[name] = builder;
  }

  void addExtension(ExtensionBuilder builder) {
    scope.addExtension(builder);
  }

  Builder? operator [](String name) => scope._local[name];
}

class ConstructorScopeBuilder {
  final ConstructorScope scope;

  ConstructorScopeBuilder(this.scope);

  void addMember(String name, MemberBuilder builder) {
    scope.local[name] = builder;
  }

  MemberBuilder? operator [](String name) => scope.local[name];
}

abstract class ProblemBuilder extends BuilderImpl {
  final String name;

  final Builder builder;

  final int charOffset;

  final Uri fileUri;

  ProblemBuilder(this.name, this.builder, this.charOffset, this.fileUri);

  get target => null;

  bool get hasProblem => true;

  Message get message;

  @override
  String get fullNameForErrors => name;
}

/// Represents a [builder] that's being accessed incorrectly. For example, an
/// attempt to write to a final field, or to read from a setter.
class AccessErrorBuilder extends ProblemBuilder {
  AccessErrorBuilder(String name, Builder builder, int charOffset, Uri fileUri)
      : super(name, builder, charOffset, fileUri);

  @override
  Builder get parent => builder;

  @override
  bool get isFinal => builder.isFinal;

  @override
  bool get isField => builder.isField;

  @override
  bool get isRegularMethod => builder.isRegularMethod;

  @override
  bool get isGetter => !builder.isGetter;

  @override
  bool get isSetter => !builder.isSetter;

  @override
  bool get isDeclarationInstanceMember => builder.isDeclarationInstanceMember;

  @override
  bool get isClassInstanceMember => builder.isClassInstanceMember;

  @override
  bool get isExtensionInstanceMember => builder.isExtensionInstanceMember;

  @override
  bool get isStatic => builder.isStatic;

  @override
  bool get isTopLevel => builder.isTopLevel;

  @override
  bool get isTypeDeclaration => builder.isTypeDeclaration;

  @override
  bool get isLocal => builder.isLocal;

  @override
  Message get message => templateAccessError.withArguments(name);
}

class AmbiguousBuilder extends ProblemBuilder {
  AmbiguousBuilder(String name, Builder builder, int charOffset, Uri fileUri)
      : super(name, builder, charOffset, fileUri);

  @override
  Builder? get parent => null;

  @override
  Message get message => templateDuplicatedDeclarationUse.withArguments(name);

  // TODO(ahe): Also provide context.

  Builder getFirstDeclaration() {
    Builder declaration = builder;
    while (declaration.next != null) {
      declaration = declaration.next!;
    }
    return declaration;
  }
}

mixin ErroneousMemberBuilderMixin implements MemberBuilder {
  @override
  Member get member => throw new UnsupportedError('$runtimeType.member');

  @override
  Member? get readTarget => null;

  @override
  Member? get writeTarget => null;

  @override
  Member? get invokeTarget => null;

  @override
  Iterable<Member> get exportedMembers => const [];

  bool get isNative => false;

  @override
  bool get isAssignable => false;

  @override
  bool get isExternal => false;

  @override
  bool get isAbstract => false;

  @override
  bool get isConflictingSetter => false;

  @override
  void set parent(Builder? value) {
    throw new UnsupportedError('AmbiguousMemberBuilder.parent=');
  }

  @override
  LibraryBuilder get library {
    throw new UnsupportedError('AmbiguousMemberBuilder.parent=');
  }

  // TODO(johnniwinther): Remove this and create a [ProcedureBuilder] interface.
  @override
  ProcedureKind? get kind => null;

  @override
  void buildOutlineExpressions(
      LibraryBuilder library,
      CoreTypes coreTypes,
      List<DelayedActionPerformer> delayedActionPerformers,
      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
    throw new UnsupportedError(
        'AmbiguousMemberBuilder.buildOutlineExpressions');
  }

  @override
  List<ClassMember> get localMembers => const <ClassMember>[];

  @override
  List<ClassMember> get localSetters => const <ClassMember>[];
}

class AmbiguousMemberBuilder extends AmbiguousBuilder
    with ErroneousMemberBuilderMixin {
  AmbiguousMemberBuilder(
      String name, Builder builder, int charOffset, Uri fileUri)
      : super(name, builder, charOffset, fileUri);
}

class ScopeLocalDeclarationIterator implements Iterator<Builder> {
  Iterator<Builder>? local;
  final Iterator<Builder> setters;

  Builder? _current;

  ScopeLocalDeclarationIterator(Scope scope)
      : local = scope._local.values.iterator,
        setters = scope._setters.values.iterator;

  @override
  bool moveNext() {
    Builder? next = _current?.next;
    if (next != null) {
      _current = next;
      return true;
    }
    if (local != null) {
      if (local!.moveNext()) {
        _current = local!.current;
        return true;
      }
      local = null;
    }
    if (setters.moveNext()) {
      _current = setters.current;
      return true;
    } else {
      _current = null;
      return false;
    }
  }

  @override
  Builder get current {
    return _current ?? (throw new StateError('No element'));
  }
}

class ScopeLocalDeclarationNameIterator extends ScopeLocalDeclarationIterator
    implements NameIterator {
  Iterator<String>? localNames;
  final Iterator<String> setterNames;

  String? _name;

  ScopeLocalDeclarationNameIterator(Scope scope)
      : localNames = scope._local.keys.iterator,
        setterNames = scope._setters.keys.iterator,
        super(scope);

  @override
  bool moveNext() {
    Builder? next = _current?.next;
    if (next != null) {
      _current = next;
      return true;
    }
    if (local != null) {
      if (local!.moveNext()) {
        localNames!.moveNext();
        _current = local!.current;
        _name = localNames!.current;
        return true;
      }
      localNames = null;
    }
    if (setters.moveNext()) {
      setterNames.moveNext();
      _current = setters.current;
      _name = setterNames.current;
      return true;
    } else {
      _current = null;
      return false;
    }
  }

  @override
  String get name {
    return _name ?? (throw new StateError('No element'));
  }
}
