// Copyright (c) 2017, 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 'dart:async';
import 'dart:collection';

import 'package:analyzer/context/declared_variables.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/frontend_resolution.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/constant/evaluation.dart';
import 'package:analyzer/src/dart/constant/utilities.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/handle.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/error/pending_error.dart';
import 'package:analyzer/src/fasta/error_converter.dart';
import 'package:analyzer/src/fasta/resolution_applier.dart';
import 'package:analyzer/src/fasta/resolution_storer.dart' as kernel;
import 'package:analyzer/src/generated/declaration_resolver.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error_verifier.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/kernel/resynthesize.dart';
import 'package:analyzer/src/services/lint.dart';
import 'package:analyzer/src/task/dart.dart';
import 'package:analyzer/src/task/strong/checker.dart';
import 'package:front_end/src/dependency_walker.dart';
import 'package:front_end/src/incremental/kernel_driver.dart';
import 'package:kernel/kernel.dart' as kernel;
import 'package:kernel/type_algebra.dart' as kernel;

/**
 * Analyzer of a single library.
 */
class LibraryAnalyzer {
  final AnalysisOptions _analysisOptions;
  final DeclaredVariables _declaredVariables;
  final SourceFactory _sourceFactory;
  final FileState _library;

  final bool _enableKernelDriver;
  final bool _previewDart2;
  final KernelDriver _kernelDriver;

  final bool Function(Uri) _isLibraryUri;
  final AnalysisContextImpl _context;
  final ElementResynthesizer _resynthesizer;
  final TypeProvider _typeProvider;

  LibraryElement _libraryElement;

  final Map<FileState, LineInfo> _fileToLineInfo = {};
  final Map<FileState, IgnoreInfo> _fileToIgnoreInfo = {};

  final Map<FileState, RecordingErrorListener> _errorListeners = {};
  final Map<FileState, ErrorReporter> _errorReporters = {};
  final List<UsedImportedElements> _usedImportedElementsList = [];
  final List<UsedLocalElements> _usedLocalElementsList = [];
  final Map<FileState, List<PendingError>> _fileToPendingErrors = {};
  final List<ConstantEvaluationTarget> _constants = [];

  LibraryAnalyzer(
      this._analysisOptions,
      this._declaredVariables,
      this._sourceFactory,
      this._isLibraryUri,
      this._context,
      this._resynthesizer,
      this._library,
      {bool enableKernelDriver: false,
      bool previewDart2: false,
      KernelDriver kernelDriver})
      : _typeProvider = _context.typeProvider,
        _enableKernelDriver = enableKernelDriver,
        _previewDart2 = previewDart2,
        _kernelDriver = kernelDriver;

  /**
   * Compute analysis results for all units of the library.
   */
  Future<Map<FileState, UnitAnalysisResult>> analyze() async {
    return PerformanceStatistics.analysis.makeCurrentWhileAsync(() async {
      if (_previewDart2) {
        return await _analyze2();
      } else {
        return _analyze();
      }
    });
  }

  Map<FileState, UnitAnalysisResult> _analyze() {
    Map<FileState, CompilationUnit> units = {};

    // Parse all files.
    units[_library] = _parse(_library);
    for (FileState part in _library.partedFiles) {
      units[part] = _parse(part);
    }

    // Resolve URIs in directives to corresponding sources.
    units.forEach((file, unit) {
      _resolveUriBasedDirectives(file, unit);
    });

    try {
      _libraryElement = _resynthesizer
          .getElement(new ElementLocationImpl.con3([_library.uriStr]));

      _resolveDirectives(units);

      units.forEach((file, unit) {
        _resolveFile(file, unit);
        _computePendingMissingRequiredParameters(file, unit);
      });

      _computeConstants();

      PerformanceStatistics.errors.makeCurrentWhile(() {
        units.forEach((file, unit) {
          _computeVerifyErrors(file, unit);
        });
      });

      if (_analysisOptions.hint) {
        PerformanceStatistics.hints.makeCurrentWhile(() {
          units.forEach((file, unit) {
            {
              var visitor = new GatherUsedLocalElementsVisitor(_libraryElement);
              unit.accept(visitor);
              _usedLocalElementsList.add(visitor.usedElements);
            }
            {
              var visitor =
                  new GatherUsedImportedElementsVisitor(_libraryElement);
              unit.accept(visitor);
              _usedImportedElementsList.add(visitor.usedElements);
            }
          });
          units.forEach((file, unit) {
            _computeHints(file, unit);
          });
        });
      }

      if (_analysisOptions.lint) {
        PerformanceStatistics.lints.makeCurrentWhile(() {
          units.forEach((file, unit) {
            _computeLints(file, unit);
          });
        });
      }
    } finally {
      _context.dispose();
    }

    // Return full results.
    Map<FileState, UnitAnalysisResult> results = {};
    units.forEach((file, unit) {
      List<AnalysisError> errors = _getErrorListener(file).errors;
      errors = _filterIgnoredErrors(file, errors);
      results[file] = new UnitAnalysisResult(file, unit, errors);
    });
    return results;
  }

  Future<Map<FileState, UnitAnalysisResult>> _analyze2() async {
    Map<FileState, CompilationUnit> units = {};

    // Parse all files.
    units[_library] = _parse(_library);
    for (FileState part in _library.partedFiles) {
      units[part] = _parse(part);
    }

    // Resolve URIs in directives to corresponding sources.
    units.forEach((file, unit) {
      _resolveUriBasedDirectives(file, unit);
    });

    try {
      _libraryElement = _resynthesizer
          .getElement(new ElementLocationImpl.con3([_library.uriStr]));

      _resolveDirectives(units);

      // TODO(scheglov) Improve.
      AnalyzerTarget analyzerTarget;
      final kernelResult = await _kernelDriver.compileLibrary(
          (fileSystem, bool includeComments, dillTarget, uriTranslator,
                  {metadataCollector}) =>
              analyzerTarget ??= new AnalyzerTarget(fileSystem, dillTarget,
                  uriTranslator, _analysisOptions.strongMode, _library.uri),
          _library.uri);

      var resolutions = new _ResolutionProvider(analyzerTarget.resolutions);
      units.forEach((file, unit) {
        _resolveFile2(file, unit, resolutions);
        _computePendingMissingRequiredParameters(file, unit);

        // Invalid part URIs can result in an element with a null source
        if (unit.element.source != null) {
          final errorListener = new FastaErrorReporter(
              new ErrorReporter(_getErrorListener(file), unit.element.source));
          final libraryKernelResult = kernelResult.results
              .expand((r) => r.libraryResults)
              .where((r) => r.library.importUri == unit.element.source.uri)
              .firstWhere((_) => true, orElse: () => null);
          libraryKernelResult?.errors?.forEach((kernelError) =>
              errorListener.reportCompilationMessage(kernelError));
        }
      });

      _computeConstants();

      // TODO(scheglov) Restore.
//      PerformanceStatistics.errors.makeCurrentWhile(() {
//        units.forEach((file, unit) {
//          _computeVerifyErrors(file, unit);
//        });
//      });

      if (_analysisOptions.hint) {
        PerformanceStatistics.hints.makeCurrentWhile(() {
          units.forEach((file, unit) {
            {
              var visitor = new GatherUsedLocalElementsVisitor(_libraryElement);
              unit.accept(visitor);
              _usedLocalElementsList.add(visitor.usedElements);
            }
            {
              var visitor =
                  new GatherUsedImportedElementsVisitor(_libraryElement);
              unit.accept(visitor);
              _usedImportedElementsList.add(visitor.usedElements);
            }
          });
          units.forEach((file, unit) {
            _computeHints(file, unit);
          });
        });
      }

      if (_analysisOptions.lint) {
        PerformanceStatistics.lints.makeCurrentWhile(() {
          units.forEach((file, unit) {
            _computeLints(file, unit);
          });
        });
      }
    } finally {
      _context.dispose();
    }

    // Return full results.
    Map<FileState, UnitAnalysisResult> results = {};
    units.forEach((file, unit) {
      List<AnalysisError> errors = _getErrorListener(file).errors;
      errors = _filterIgnoredErrors(file, errors);
      results[file] = new UnitAnalysisResult(file, unit, errors);
    });
    return results;
  }

  /**
   * Compute [_constants] in all units.
   */
  void _computeConstants() {
    ConstantEvaluationEngine evaluationEngine = new ConstantEvaluationEngine(
        _typeProvider, _declaredVariables,
        typeSystem: _context.typeSystem);

    List<_ConstantNode> nodes = [];
    Map<ConstantEvaluationTarget, _ConstantNode> nodeMap = {};
    for (ConstantEvaluationTarget constant in _constants) {
      var node = new _ConstantNode(evaluationEngine, nodeMap, constant);
      nodes.add(node);
      nodeMap[constant] = node;
    }

    for (_ConstantNode node in nodes) {
      if (!node.isEvaluated) {
        new _ConstantWalker(evaluationEngine).walk(node);
      }
    }
  }

  void _computeHints(FileState file, CompilationUnit unit) {
    if (file.source == null) {
      return;
    }

    AnalysisErrorListener errorListener = _getErrorListener(file);
    ErrorReporter errorReporter = _getErrorReporter(file);

    //
    // Convert the pending errors into actual errors.
    //
    for (PendingError pendingError in _fileToPendingErrors[file]) {
      errorListener.onError(pendingError.toAnalysisError());
    }

    unit.accept(
        new DeadCodeVerifier(errorReporter, typeSystem: _context.typeSystem));

    // Dart2js analysis.
    if (_analysisOptions.dart2jsHint) {
      unit.accept(new Dart2JSVerifier(errorReporter));
    }

    InheritanceManager inheritanceManager = new InheritanceManager(
        _libraryElement,
        includeAbstractFromSuperclasses: true);

    unit.accept(new BestPracticesVerifier(
        errorReporter, _typeProvider, _libraryElement, inheritanceManager,
        typeSystem: _context.typeSystem));

    unit.accept(new OverrideVerifier(errorReporter, inheritanceManager));

    new ToDoFinder(errorReporter).findIn(unit);

    // Verify imports.
    {
      ImportsVerifier verifier = new ImportsVerifier();
      verifier.addImports(unit);
      _usedImportedElementsList.forEach(verifier.removeUsedElements);
      verifier.generateDuplicateImportHints(errorReporter);
      verifier.generateUnusedImportHints(errorReporter);
      verifier.generateUnusedShownNameHints(errorReporter);
    }

    // Unused local elements.
    {
      UsedLocalElements usedElements =
          new UsedLocalElements.merge(_usedLocalElementsList);
      UnusedLocalElementsVerifier visitor =
          new UnusedLocalElementsVerifier(errorListener, usedElements);
      unit.accept(visitor);
    }
  }

  void _computeLints(FileState file, CompilationUnit unit) {
    if (file.source == null) {
      return;
    }

    ErrorReporter errorReporter = _getErrorReporter(file);

    List<AstVisitor> visitors = <AstVisitor>[];
    for (Linter linter in _analysisOptions.lintRules) {
      AstVisitor visitor = linter.getVisitor();
      if (visitor != null) {
        linter.reporter = errorReporter;
        if (_analysisOptions.enableTiming) {
          visitor = new TimedAstVisitor(visitor, lintRegistry.getTimer(linter));
        }
        visitors.add(visitor);
      }
    }

    AstVisitor visitor = new ExceptionHandlingDelegatingAstVisitor(
        visitors, ExceptionHandlingDelegatingAstVisitor.logException);

    unit.accept(visitor);
  }

  void _computePendingMissingRequiredParameters(
      FileState file, CompilationUnit unit) {
    // TODO(scheglov) This can be done without "pending" if we resynthesize.
    var computer = new RequiredConstantsComputer(file.source);
    unit.accept(computer);
    _constants.addAll(computer.requiredConstants);
    _fileToPendingErrors[file] = computer.pendingErrors;
  }

  void _computeVerifyErrors(FileState file, CompilationUnit unit) {
    if (file.source == null) {
      return;
    }

    RecordingErrorListener errorListener = _getErrorListener(file);

    if (_analysisOptions.strongMode) {
      AnalysisOptionsImpl options = _analysisOptions as AnalysisOptionsImpl;
      CodeChecker checker = new CodeChecker(
          _typeProvider,
          new StrongTypeSystemImpl(_typeProvider,
              implicitCasts: options.implicitCasts,
              declarationCasts: options.declarationCasts,
              nonnullableTypes: options.nonnullableTypes),
          errorListener,
          options);
      checker.visitCompilationUnit(unit);
    }

    ErrorReporter errorReporter = _getErrorReporter(file);

    //
    // Validate the directives.
    //
    _validateUriBasedDirectives(file, unit);

    //
    // Use the ConstantVerifier to compute errors.
    //
    ConstantVerifier constantVerifier = new ConstantVerifier(
        errorReporter, _libraryElement, _typeProvider, _declaredVariables);
    unit.accept(constantVerifier);

    //
    // Use the ErrorVerifier to compute errors.
    //
    ErrorVerifier errorVerifier = new ErrorVerifier(
        errorReporter,
        _libraryElement,
        _typeProvider,
        new InheritanceManager(_libraryElement),
        _analysisOptions.enableSuperMixins);
    unit.accept(errorVerifier);
  }

  /// Create a new [ResolutionApplier] for the given front-end [resolution].
  /// The [context] element is used to associate synthetic elements and access
  /// type parameters from the enclosing scopes.
  ResolutionApplier _createResolutionApplier(
      ElementImpl context, CollectedResolution resolution) {
    return new _ResolutionApplierContext(
            _resynthesizer, _typeProvider, _libraryElement, resolution, context)
        .applier;
  }

  /**
   * Return a subset of the given [errors] that are not marked as ignored in
   * the [file].
   */
  List<AnalysisError> _filterIgnoredErrors(
      FileState file, List<AnalysisError> errors) {
    if (errors.isEmpty) {
      return errors;
    }

    IgnoreInfo ignoreInfo = _fileToIgnoreInfo[file];
    if (!ignoreInfo.hasIgnores) {
      return errors;
    }

    LineInfo lineInfo = _fileToLineInfo[file];

    bool isIgnored(AnalysisError error) {
      int errorLine = lineInfo.getLocation(error.offset).lineNumber;
      String errorCode = error.errorCode.name.toLowerCase();
      return ignoreInfo.ignoredAt(errorCode, errorLine);
    }

    return errors.where((AnalysisError e) => !isIgnored(e)).toList();
  }

  RecordingErrorListener _getErrorListener(FileState file) =>
      _errorListeners.putIfAbsent(file, () => new RecordingErrorListener());

  ErrorReporter _getErrorReporter(FileState file) {
    return _errorReporters.putIfAbsent(file, () {
      RecordingErrorListener listener = _getErrorListener(file);
      return new ErrorReporter(listener, file.source);
    });
  }

  /**
   * Return the name of the library that the given part is declared to be a
   * part of, or `null` if the part does not contain a part-of directive.
   */
  _NameOrSource _getPartLibraryNameOrUri(Source partSource,
      CompilationUnit partUnit, List<Directive> directivesToResolve) {
    for (Directive directive in partUnit.directives) {
      if (directive is PartOfDirective) {
        directivesToResolve.add(directive);
        LibraryIdentifier libraryName = directive.libraryName;
        if (libraryName != null) {
          return new _NameOrSource(libraryName.name, null);
        }
        String uri = directive.uri?.stringValue;
        if (uri != null) {
          Source librarySource = _sourceFactory.resolveUri(partSource, uri);
          if (librarySource != null) {
            return new _NameOrSource(null, librarySource);
          }
        }
      }
    }
    return null;
  }

  /**
   * Return `true` if the given [source] is a library.
   */
  bool _isLibrarySource(Source source) {
    return _isLibraryUri(source.uri);
  }

  /**
   * Return a new parsed unresolved [CompilationUnit].
   */
  CompilationUnit _parse(FileState file) {
    RecordingErrorListener errorListener = _getErrorListener(file);
    String content = file.content;
    CompilationUnit unit = file.parse(errorListener);

    LineInfo lineInfo = unit.lineInfo;
    _fileToLineInfo[file] = lineInfo;
    _fileToIgnoreInfo[file] = IgnoreInfo.calculateIgnores(content, lineInfo);

    return unit;
  }

  void _resolveDirectives(Map<FileState, CompilationUnit> units) {
    CompilationUnit definingCompilationUnit = units[_library];
    definingCompilationUnit.element = _libraryElement.definingCompilationUnit;

    bool matchNodeElement(Directive node, Element element) {
      if (_enableKernelDriver) {
        return node.keyword.offset == element.nameOffset;
      } else {
        return node.offset == element.nameOffset;
      }
    }

    ErrorReporter libraryErrorReporter = _getErrorReporter(_library);
    LibraryIdentifier libraryNameNode = null;
    bool hasPartDirective = false;
    var seenPartSources = new Set<Source>();
    var directivesToResolve = <Directive>[];
    int partIndex = 0;
    for (Directive directive in definingCompilationUnit.directives) {
      if (directive is LibraryDirective) {
        libraryNameNode = directive.name;
        directivesToResolve.add(directive);
      } else if (directive is ImportDirective) {
        for (ImportElement importElement in _libraryElement.imports) {
          if (matchNodeElement(directive, importElement)) {
            directive.element = importElement;
            Source source = importElement.importedLibrary?.source;
            if (source != null && !_isLibrarySource(source)) {
              ErrorCode errorCode = importElement.isDeferred
                  ? StaticWarningCode.IMPORT_OF_NON_LIBRARY
                  : CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY;
              libraryErrorReporter.reportErrorForNode(
                  errorCode, directive.uri, [directive.uri]);
            }
          }
        }
      } else if (directive is ExportDirective) {
        for (ExportElement exportElement in _libraryElement.exports) {
          if (matchNodeElement(directive, exportElement)) {
            directive.element = exportElement;
            Source source = exportElement.exportedLibrary?.source;
            if (source != null && !_isLibrarySource(source)) {
              libraryErrorReporter.reportErrorForNode(
                  CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
                  directive.uri,
                  [directive.uri]);
            }
          }
        }
      } else if (directive is PartDirective) {
        hasPartDirective = true;
        StringLiteral partUri = directive.uri;

        FileState partFile = _library.partedFiles[partIndex];
        CompilationUnit partUnit = units[partFile];
        CompilationUnitElement partElement = _libraryElement.parts[partIndex];
        partUnit.element = partElement;
        directive.element = partElement;
        partIndex++;

        Source partSource = directive.uriSource;
        if (partSource == null) {
          continue;
        }

        //
        // Validate that the part source is unique in the library.
        //
        if (!seenPartSources.add(partSource)) {
          libraryErrorReporter.reportErrorForNode(
              CompileTimeErrorCode.DUPLICATE_PART, partUri, [partSource.uri]);
        }

        //
        // Validate that the part contains a part-of directive with the same
        // name or uri as the library.
        //
        if (_context.exists(partSource)) {
          _NameOrSource nameOrSource = _getPartLibraryNameOrUri(
              partSource, partUnit, directivesToResolve);
          if (nameOrSource == null) {
            libraryErrorReporter.reportErrorForNode(
                CompileTimeErrorCode.PART_OF_NON_PART,
                partUri,
                [partUri.toSource()]);
          } else {
            String name = nameOrSource.name;
            if (name != null) {
              if (libraryNameNode == null) {
                libraryErrorReporter.reportErrorForNode(
                    ResolverErrorCode.PART_OF_UNNAMED_LIBRARY, partUri, [name]);
              } else if (libraryNameNode.name != name) {
                libraryErrorReporter.reportErrorForNode(
                    StaticWarningCode.PART_OF_DIFFERENT_LIBRARY,
                    partUri,
                    [libraryNameNode.name, name]);
              }
            } else {
              Source source = nameOrSource.source;
              if (source != _library.source) {
                libraryErrorReporter.reportErrorForNode(
                    StaticWarningCode.PART_OF_DIFFERENT_LIBRARY,
                    partUri,
                    [_library.uriStr, source.uri]);
              }
            }
          }
        }
      }
    }

    if (hasPartDirective &&
        libraryNameNode == null &&
        !_context.analysisOptions.enableUriInPartOf) {
      libraryErrorReporter.reportErrorForOffset(
          ResolverErrorCode.MISSING_LIBRARY_DIRECTIVE_WITH_PART, 0, 0);
    }

    //
    // Resolve the relevant directives to the library element.
    //
    for (Directive directive in directivesToResolve) {
      directive.element = _libraryElement;
    }

    // TODO(scheglov) remove DirectiveResolver class
  }

  void _resolveFile(FileState file, CompilationUnit unit) {
    Source source = file.source;
    if (source == null) {
      return;
    }

    RecordingErrorListener errorListener = _getErrorListener(file);

    CompilationUnitElement unitElement = unit.element;

    // TODO(scheglov) Hack: set types for top-level variables
    // Otherwise TypeResolverVisitor will set declared types, and because we
    // don't run InferStaticVariableTypeTask, we will stuck with these declared
    // types. And we don't need to run this task - resynthesized elements have
    // inferred types.
    for (var e in unitElement.topLevelVariables) {
      if (!e.isSynthetic) {
        e.type;
      }
    }

    new DeclarationResolver(enableKernelDriver: _enableKernelDriver)
        .resolve(unit, unitElement);

    // TODO(scheglov) remove EnumMemberBuilder class

    new TypeParameterBoundsResolver(
            _typeProvider, _libraryElement, source, errorListener)
        .resolveTypeBounds(unit);

    unit.accept(new TypeResolverVisitor(
        _libraryElement, source, _typeProvider, errorListener));

    LibraryScope libraryScope = new LibraryScope(_libraryElement);
    unit.accept(new VariableResolverVisitor(
        _libraryElement, source, _typeProvider, errorListener,
        nameScope: libraryScope));

    unit.accept(new PartialResolverVisitor(_libraryElement, source,
        _typeProvider, AnalysisErrorListener.NULL_LISTENER));

    // Nothing for RESOLVED_UNIT8?
    // Nothing for RESOLVED_UNIT9?
    // Nothing for RESOLVED_UNIT10?

    unit.accept(new ResolverVisitor(
        _libraryElement, source, _typeProvider, errorListener));

    //
    // Find constants to compute.
    //
    {
      ConstantFinder constantFinder = new ConstantFinder();
      unit.accept(constantFinder);
      _constants.addAll(constantFinder.constantsToCompute);
    }

    //
    // Find constant dependencies to compute.
    //
    {
      var finder = new ConstantExpressionsDependenciesFinder();
      unit.accept(finder);
      _constants.addAll(finder.dependencies);
    }
  }

  void _resolveFile2(
      FileState file, CompilationUnit unit, _ResolutionProvider resolutions) {
    CompilationUnitElement unitElement = unit.element;
    new DeclarationResolver(enableKernelDriver: true, applyKernelTypes: true)
        .resolve(unit, unitElement);

    for (var declaration in unit.declarations) {
      if (declaration is ClassDeclaration) {
        if (declaration.metadata.isNotEmpty) {
          var resolution = resolutions.next();
          var applier = _createResolutionApplier(null, resolution);
          applier.applyToAnnotations(declaration);
          applier.checkDone();
        }
        for (var member in declaration.members) {
          if (member is ConstructorDeclaration) {
            var context = member.element as ConstructorElementImpl;
            ConstructorName redirectName = member.redirectedConstructor;
            if (redirectName != null) {
              var redirectedConstructor = context.redirectedConstructor;
              redirectName.staticElement = redirectedConstructor;
              ResolutionApplier.applyConstructorElement(
                  redirectedConstructor.returnType,
                  redirectedConstructor,
                  redirectName);
              // TODO(scheglov) Add support for type parameterized redirects.
            } else {
              var resolution = resolutions.next();
              var applier = _createResolutionApplier(context, resolution);
              member.initializers.accept(applier);
              member.parameters.accept(applier);
              member.body.accept(applier);
              applier.applyToAnnotations(member);
              applier.checkDone();
            }
          } else if (member is FieldDeclaration) {
            List<VariableDeclaration> fields = member.fields.variables;
            var context = fields[0].element as ElementImpl;
            var resolution = resolutions.next();
            var applier = _createResolutionApplier(context, resolution);
            for (var field in fields.reversed) {
              field.initializer?.accept(applier);
            }
            applier.applyToAnnotations(member);
            applier.checkDone();
          } else if (member is MethodDeclaration) {
            ExecutableElementImpl context = member.element;
            var resolution = resolutions.next();
            var applier = _createResolutionApplier(context, resolution);
            member.parameters?.accept(applier);
            member.body.accept(applier);
            applier.applyToAnnotations(member);
            applier.checkDone();
          } else {
            throw new StateError('(${declaration.runtimeType}) $declaration');
          }
        }
      } else if (declaration is ClassTypeAlias) {
        // No bodies to resolve.
      } else if (declaration is EnumDeclaration) {
        // No bodies to resolve.
      } else if (declaration is FunctionDeclaration) {
        var context = declaration.element as ExecutableElementImpl;
        var resolution = resolutions.next();
        var applier = _createResolutionApplier(context, resolution);
        declaration.functionExpression.parameters?.accept(applier);
        declaration.functionExpression.body.accept(applier);
        applier.applyToAnnotations(declaration);
        applier.checkDone();
      } else if (declaration is FunctionTypeAlias) {
        // No bodies to resolve.
      } else if (declaration is TopLevelVariableDeclaration) {
        List<VariableDeclaration> variables = declaration.variables.variables;
        var context = variables[0].element as ElementImpl;
        var resolution = resolutions.next();
        var applier = _createResolutionApplier(context, resolution);
        for (var variable in variables.reversed) {
          variable.initializer?.accept(applier);
        }
        applier.applyToAnnotations(declaration);
        applier.checkDone();
      } else {
        throw new StateError('(${declaration.runtimeType}) $declaration');
      }
    }

    //
    // Find constants to compute.
    //
    {
      ConstantFinder constantFinder = new ConstantFinder();
      unit.accept(constantFinder);
      _constants.addAll(constantFinder.constantsToCompute);
    }

    //
    // Find constant dependencies to compute.
    //
    {
      var finder = new ConstantExpressionsDependenciesFinder();
      unit.accept(finder);
      _constants.addAll(finder.dependencies);
    }
  }

  /**
   * Return the result of resolve the given [uriContent], reporting errors
   * against the [uriLiteral].
   */
  Source _resolveUri(FileState file, bool isImport, StringLiteral uriLiteral,
      String uriContent) {
    UriValidationCode code =
        UriBasedDirectiveImpl.validateUri(isImport, uriLiteral, uriContent);
    if (code == null) {
      try {
        Uri.parse(uriContent);
      } on FormatException {
        return null;
      }
      return _sourceFactory.resolveUri(file.source, uriContent);
    } else if (code == UriValidationCode.URI_WITH_DART_EXT_SCHEME) {
      return null;
    } else if (code == UriValidationCode.URI_WITH_INTERPOLATION) {
      _getErrorReporter(file).reportErrorForNode(
          CompileTimeErrorCode.URI_WITH_INTERPOLATION, uriLiteral);
      return null;
    } else if (code == UriValidationCode.INVALID_URI) {
      _getErrorReporter(file).reportErrorForNode(
          CompileTimeErrorCode.INVALID_URI, uriLiteral, [uriContent]);
      return null;
    }
    return null;
  }

  void _resolveUriBasedDirectives(FileState file, CompilationUnit unit) {
    for (Directive directive in unit.directives) {
      if (directive is UriBasedDirective) {
        StringLiteral uriLiteral = directive.uri;
        String uriContent = uriLiteral.stringValue?.trim();
        directive.uriContent = uriContent;
        Source defaultSource = _resolveUri(
            file, directive is ImportDirective, uriLiteral, uriContent);
        directive.uriSource = defaultSource;
      }
    }
  }

  /**
   * Check the given [directive] to see if the referenced source exists and
   * report an error if it does not.
   */
  void _validateUriBasedDirective(
      FileState file, UriBasedDirectiveImpl directive) {
    Source source = directive.uriSource;
    if (source != null) {
      if (_context.exists(source)) {
        return;
      }
    } else {
      // Don't report errors already reported by ParseDartTask.resolveDirective
      // TODO(scheglov) we don't use this task here
      if (directive.validate() != null) {
        return;
      }
    }
    StringLiteral uriLiteral = directive.uri;
    CompileTimeErrorCode errorCode = CompileTimeErrorCode.URI_DOES_NOT_EXIST;
    if (_isGenerated(source)) {
      errorCode = CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED;
    }
    _getErrorReporter(file)
        .reportErrorForNode(errorCode, uriLiteral, [directive.uriContent]);
  }

  /**
   * Check each directive in the given [unit] to see if the referenced source
   * exists and report an error if it does not.
   */
  void _validateUriBasedDirectives(FileState file, CompilationUnit unit) {
    for (Directive directive in unit.directives) {
      if (directive is UriBasedDirective) {
        _validateUriBasedDirective(file, directive);
      }
    }
  }

  /**
   * Return `true` if the given [source] refers to a file that is assumed to be
   * generated.
   */
  static bool _isGenerated(Source source) {
    if (source == null) {
      return false;
    }
    // TODO(brianwilkerson) Generalize this mechanism.
    const List<String> suffixes = const <String>[
      '.g.dart',
      '.pb.dart',
      '.pbenum.dart',
      '.pbserver.dart',
      '.pbjson.dart',
      '.template.dart'
    ];
    String fullName = source.fullName;
    for (String suffix in suffixes) {
      if (fullName.endsWith(suffix)) {
        return true;
      }
    }
    return false;
  }
}

/**
 * Analysis result for single file.
 */
class UnitAnalysisResult {
  final FileState file;
  final CompilationUnit unit;
  final List<AnalysisError> errors;

  UnitAnalysisResult(this.file, this.unit, this.errors);
}

/**
 * [Node] that is used to compute constants in dependency order.
 */
class _ConstantNode extends Node<_ConstantNode> {
  final ConstantEvaluationEngine evaluationEngine;
  final Map<ConstantEvaluationTarget, _ConstantNode> nodeMap;
  final ConstantEvaluationTarget constant;

  bool isEvaluated = false;

  _ConstantNode(this.evaluationEngine, this.nodeMap, this.constant);

  @override
  List<_ConstantNode> computeDependencies() {
    List<ConstantEvaluationTarget> targets = [];
    evaluationEngine.computeDependencies(constant, targets.add);
    return targets.map(_getNode).toList();
  }

  _ConstantNode _getNode(ConstantEvaluationTarget constant) {
    return nodeMap.putIfAbsent(
        constant, () => new _ConstantNode(evaluationEngine, nodeMap, constant));
  }
}

/**
 * [DependencyWalker] for computing constants and detecting cycles.
 */
class _ConstantWalker extends DependencyWalker<_ConstantNode> {
  final ConstantEvaluationEngine evaluationEngine;

  _ConstantWalker(this.evaluationEngine);

  @override
  void evaluate(_ConstantNode node) {
    evaluationEngine.computeConstantValue(node.constant);
    node.isEvaluated = true;
  }

  @override
  void evaluateScc(List<_ConstantNode> scc) {
    var constantsInCycle = scc.map((node) => node.constant);
    for (_ConstantNode node in scc) {
      if (node.constant is ConstructorElementImpl) {
        (node.constant as ConstructorElementImpl).isCycleFree = false;
      }
      evaluationEngine.generateCycleError(constantsInCycle, node.constant);
      node.isEvaluated = true;
    }
  }
}

/**
 * Either the name or the source associated with a part-of directive.
 */
class _NameOrSource {
  final String name;
  final Source source;
  _NameOrSource(this.name, this.source);
}

/// Concrete implementation of [TypeContext].
class _ResolutionApplierContext implements TypeContext {
  final KernelResynthesizer resynthesizer;
  final TypeProvider typeProvider;
  final LibraryElement libraryElement;
  final CollectedResolution resolution;

  @override
  ClassElement enclosingClassElement;

  List<ElementImpl> contextStack = [];
  ElementImpl context;

  List<Element> declaredElements = [];
  Map<kernel.TreeNode, Element> declarationToElement = new HashMap.identity();
  Map<FunctionElementImpl, kernel.TreeNode> functionElementToDeclaration =
      new HashMap.identity();
  Map<ParameterElementImpl, kernel.VariableDeclaration>
      parameterElementToDeclaration = new HashMap.identity();

  ResolutionApplier applier;

  _ResolutionApplierContext(this.resynthesizer, this.typeProvider,
      this.libraryElement, this.resolution, this.context) {
    for (Element element = context;
        element != null;
        element = element.enclosingElement) {
      if (element is ClassElement) {
        enclosingClassElement = element;
        break;
      }
    }

    // Convert local declarations into elements.
    for (var declaredNode in resolution.kernelDeclarations) {
      translateKernelDeclaration(declaredNode);
    }

    // Convert referenced nodes into elements.
    List<Element> referencedElements = [];
    for (var referencedNode in resolution.kernelReferences) {
      Element element;
      if (referencedNode is kernel.VariableDeclaration) {
        kernel.TreeNode parent = referencedNode.parent;
        if (parent is kernel.Statement) {
          element = declarationToElement[referencedNode];
        } else {
          assert(parent is kernel.FunctionNode || parent is kernel.Catch);
          // Might be a parameter of a local function.
          element = declarationToElement[referencedNode];
          // If no element, then it is a parameter of the context executable.
          if (element == null) {
            ExecutableElementImpl contextExecutable = context;
            for (var parameter in contextExecutable.parameters) {
              if (parameter.name == referencedNode.name) {
                element = parameter;
                break;
              }
            }
          }
        }
        assert(element != null);
      } else if (referencedNode is kernel.NamedNode) {
        element = resynthesizer
            .getElementFromCanonicalName(referencedNode.canonicalName);
        assert(element != null);
      } else if (referencedNode is kernel.DynamicType) {
        element = DynamicElementImpl.instance;
      } else if (referencedNode is kernel.FunctionType) {
        element = resynthesizer
            .getElementFromCanonicalName(referencedNode.typedef.canonicalName);
        assert(element != null);
      } else if (referencedNode is kernel.InterfaceType) {
        element = resynthesizer.getElementFromCanonicalName(
            referencedNode.classNode.canonicalName);
        assert(element != null);
      } else if (referencedNode is kernel.MemberGetterNode) {
        if (referencedNode.member == null) {
          element = null;
        } else {
          var memberElement = resynthesizer
              .getElementFromCanonicalName(referencedNode.member.canonicalName);
          assert(memberElement != null);
          if (memberElement is PropertyInducingElementImpl) {
            element = memberElement.getter;
            assert(element != null);
          } else {
            element = memberElement;
          }
        }
      } else if (referencedNode is kernel.MemberSetterNode) {
        if (referencedNode.member == null) {
          element = null;
        } else {
          var memberElement = resynthesizer
              .getElementFromCanonicalName(referencedNode.member.canonicalName);
          assert(memberElement != null);
          if (memberElement is PropertyInducingElementImpl) {
            element = memberElement.setter;
            assert(element != null);
          } else {
            element = memberElement;
          }
        }
      } else if (referencedNode is kernel.ImportPrefixNode) {
        assert(referencedNode.name != null);
        for (var import in libraryElement.imports) {
          if (import.prefix?.name == referencedNode.name) {
            element = import.prefix;
            break;
          }
        }
        assert(element != null);
      } else if (referencedNode is kernel.NullNode) {
        element = null;
      } else if (referencedNode == null) {
        // This will occur if an identifier could not be resolved, such as a
        // reference to a member when the target has type `dynamic`.
        element = null;
      } else {
        throw new UnimplementedError(
            'Declaration: (${referencedNode.runtimeType}) $referencedNode');
      }
      referencedElements.add(element);
    }

    applier = new ValidatingResolutionApplier(
        this,
        declaredElements,
        referencedElements,
        resolution.kernelTypes,
        resolution.declarationOffsets,
        resolution.referenceOffsets,
        resolution.typeOffsets);
  }

  @override
  DartType get stringType => typeProvider.stringType;

  @override
  DartType get typeType => typeProvider.typeType;

  @override
  void encloseVariable(ElementImpl element) {
    context.encloseElement(element);
  }

  @override
  void enterLocalFunction(FunctionElementImpl element) {
    context.encloseElement(element);

    // The function is the new resolution context.
    contextStack.add(context);
    context = element;

    var declaration = functionElementToDeclaration[element];

    // Get the declaration kernel type.
    kernel.FunctionType kernelType;
    if (declaration is kernel.VariableDeclaration) {
      kernelType = declaration.type;
    } else if (declaration is kernel.FunctionExpression) {
      kernelType = declaration.function.functionType;
    } else {
      throw new StateError('(${declaration.runtimeType}) $declaration');
    }

    element.returnType = resynthesizer.getType(context, kernelType.returnType);

    for (var parameter in element.parameters) {
      ParameterElementImpl parameterImpl = parameter;
      var kernelParameter = parameterElementToDeclaration[parameter];
      parameterImpl.type = resynthesizer.getType(context, kernelParameter.type);
    }

    element.type = new FunctionTypeImpl(element);
  }

  @override
  void exitLocalFunction(FunctionElementImpl element) {
    assert(identical(context, element));
    context = contextStack.removeLast();
  }

  /// Translate the given [declaration].
  void translateKernelDeclaration(kernel.TreeNode declaration) {
    if (declaration is kernel.VariableDeclaration) {
      kernel.TreeNode functionDeclaration = declaration.parent;
      if (functionDeclaration is kernel.FunctionDeclaration) {
        var element =
            new FunctionElementImpl(declaration.name, declaration.fileOffset);
        functionElementToDeclaration[element] = declaration;
        _addFormalParameters(element, functionDeclaration.function);
        declaredElements.add(element);
        declarationToElement[declaration] = element;
      } else {
        // TODO(scheglov) Do we need ConstLocalVariableElementImpl?
        var element = new LocalVariableElementImpl(
            declaration.name, declaration.fileOffset);
        declaredElements.add(element);
        declarationToElement[declaration] = element;
      }
    } else if (declaration is kernel.FunctionExpression) {
      var element = new FunctionElementImpl('', declaration.fileOffset);
      functionElementToDeclaration[element] = declaration;
      _addFormalParameters(element, declaration.function);
      declaredElements.add(element);
      declarationToElement[declaration] = element;
    } else {
      throw new UnimplementedError(
          'Declaration: (${declaration.runtimeType}) $declaration');
    }
  }

  @override
  DartType translateType(kernel.DartType kernelType) {
    if (kernelType is kernel.NullType) {
      return null;
    } else if (kernelType is kernel.FunctionReferenceDartType) {
      kernel.VariableDeclaration variable = kernelType.function.variable;
      FunctionElement element = declarationToElement[variable];
      return element.type;
    } else if (kernelType is kernel.MemberInvocationDartType) {
      kernel.Member member = kernelType.member;
      if (member is kernel.Procedure &&
          member.kind == kernel.ProcedureKind.Method) {
        ExecutableElementImpl element =
            resynthesizer.getElementFromCanonicalName(member.canonicalName);
        return resynthesizer.instantiateFunctionType(
            context,
            element,
            member.function,
            member.function.functionType.withoutTypeParameters,
            kernelType.type);
      }
      return DynamicTypeImpl.instance;
    } else if (kernelType is kernel.IndexAssignNullFunctionType) {
      return null;
    } else {
      return resynthesizer.getType(context, kernelType);
    }
  }

  /// Add formal parameters defined in the [kernelFunction] to the [element].
  void _addFormalParameters(
      FunctionElementImpl element, kernel.FunctionNode kernelFunction) {
    // Set type parameters.
    {
      var astParameters = <TypeParameterElement>[];
      for (var kernelParameter in kernelFunction.typeParameters) {
        var astParameter = new TypeParameterElementImpl(
            kernelParameter.name, kernelParameter.fileOffset);
        astParameter.type = new TypeParameterTypeImpl(astParameter);
        // TODO(scheglov) remember mapping to set bounds later
        astParameters.add(astParameter);
      }
      element.typeParameters = astParameters;
    }

    // Set formal parameters.
    {
      var astParameters = <ParameterElement>[];

      // Add positional parameters
      var kernelPositionalParameters = kernelFunction.positionalParameters;
      for (var i = 0; i < kernelPositionalParameters.length; i++) {
        var kernelParameter = kernelPositionalParameters[i];
        var astParameter = new ParameterElementImpl(
            kernelParameter.name, kernelParameter.fileOffset);
        astParameter.parameterKind = i < kernelFunction.requiredParameterCount
            ? ParameterKind.REQUIRED
            : ParameterKind.POSITIONAL;
        astParameters.add(astParameter);
        declarationToElement[kernelParameter] = astParameter;
        parameterElementToDeclaration[astParameter] = kernelParameter;
      }

      // Add named parameters.
      for (var kernelParameter in kernelFunction.namedParameters) {
        var astParameter = new ParameterElementImpl(
            kernelParameter.name, kernelParameter.fileOffset);
        astParameter.parameterKind = ParameterKind.NAMED;
        astParameters.add(astParameter);
        declarationToElement[kernelParameter] = astParameter;
        parameterElementToDeclaration[astParameter] = kernelParameter;
      }

      element.parameters = astParameters;
    }
  }
}

/// [Iterator] like object that provides [CollectedResolution]s.
class _ResolutionProvider {
  final List<CollectedResolution> resolutions;
  int index = 0;

  _ResolutionProvider(this.resolutions);

  CollectedResolution next() => resolutions[index++];
}
