// 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 'package:analyzer/analysis_rule/rule_context.dart';
import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/source/file_source.dart';
import 'package:analyzer/src/context/source.dart';
import 'package:analyzer/src/dart/analysis/analysis_options.dart';
import 'package:analyzer/src/dart/analysis/file_analysis.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart' as file_state;
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/testing_data.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/constant/compute.dart';
import 'package:analyzer/src/dart/constant/constant_verifier.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/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/type_constraint_gatherer.dart';
import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
import 'package:analyzer/src/dart/resolver/resolution_visitor.dart';
import 'package:analyzer/src/dart/resolver/type_analyzer_options.dart';
import 'package:analyzer/src/error/best_practices_verifier.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/error/constructor_fields_verifier.dart';
import 'package:analyzer/src/error/dead_code_verifier.dart';
import 'package:analyzer/src/error/duplicate_definition_verifier.dart';
import 'package:analyzer/src/error/ignore_validator.dart';
import 'package:analyzer/src/error/imports_verifier.dart';
import 'package:analyzer/src/error/inheritance_override.dart';
import 'package:analyzer/src/error/language_version_override_verifier.dart';
import 'package:analyzer/src/error/override_verifier.dart';
import 'package:analyzer/src/error/redeclare_verifier.dart';
import 'package:analyzer/src/error/todo_finder.dart';
import 'package:analyzer/src/error/unicode_text_verifier.dart';
import 'package:analyzer/src/error/unused_local_elements_verifier.dart';
import 'package:analyzer/src/generated/element_walker.dart';
import 'package:analyzer/src/generated/error_verifier.dart';
import 'package:analyzer/src/generated/ffi_verifier.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/hint/sdk_constraint_verifier.dart';
import 'package:analyzer/src/ignore_comments/ignore_info.dart';
import 'package:analyzer/src/lint/analysis_rule_timers.dart';
import 'package:analyzer/src/lint/linter.dart';
import 'package:analyzer/src/lint/linter_visitor.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:analyzer/src/utilities/extensions/version.dart';
import 'package:analyzer/src/workspace/pub.dart';
import 'package:analyzer/src/workspace/workspace.dart';
import 'package:collection/collection.dart';

class AnalysisForCompletionResult {
  final FileState fileState;
  final CompilationUnit parsedUnit;
  final List<AstNode> resolvedNodes;

  AnalysisForCompletionResult({
    required this.fileState,
    required this.parsedUnit,
    required this.resolvedNodes,
  });
}

/// Analyzer of a single library.
class LibraryAnalyzer {
  final OperationPerformanceImpl performance;
  final AnalysisOptionsImpl _analysisOptions;
  final DeclaredVariables _declaredVariables;
  final LibraryFileKind _library;
  final LibraryResolutionContext libraryResolutionContext =
      LibraryResolutionContext();
  final InheritanceManager3 _inheritance;

  final LibraryElementImpl _libraryElement;

  final Map<FileState, FileAnalysis> _libraryFiles = {};
  late final LibraryVerificationContext _libraryVerificationContext;

  final TestingData? _testingData;
  final TypeSystemOperations _typeSystemOperations;

  /// Whether timing data should be gathered during lint rule execution.
  final bool _enableLintRuleTiming;

  LibraryAnalyzer(
    this._analysisOptions,
    this._declaredVariables,
    this._libraryElement,
    this._inheritance,
    this._library, {
    required this.performance,
    TestingData? testingData,
    required TypeSystemOperations typeSystemOperations,
    bool enableLintRuleTiming = false,
  }) : _testingData = testingData,
       _typeSystemOperations = typeSystemOperations,
       _enableLintRuleTiming = enableLintRuleTiming {
    _libraryVerificationContext = LibraryVerificationContext(
      libraryKind: _library,
      constructorFieldsVerifier: ConstructorFieldsVerifier(
        typeSystem: _typeSystem,
      ),
    );
  }

  TypeProviderImpl get _typeProvider => _libraryElement.typeProvider;

  TypeSystemImpl get _typeSystem => _libraryElement.typeSystem;

  /// Compute analysis results for all units of the library.
  List<UnitAnalysisResult> analyze() {
    performance.run('parseAndResolve', (performance) {
      _parseAndResolve();
    });

    performance.run('computeDiagnostics', (performance) {
      _computeDiagnostics();
    });

    // Return full results.
    var results = <UnitAnalysisResult>[];
    for (var fileAnalysis in _libraryFiles.values) {
      var diagnostics = fileAnalysis.diagnosticListener.diagnostics;
      diagnostics = _filterIgnoredDiagnostics(fileAnalysis, diagnostics);
      results.add(
        UnitAnalysisResult(fileAnalysis.file, fileAnalysis.unit, diagnostics),
      );
    }
    return results;
  }

  /// Analyze [file] for a completion result.
  ///
  /// This method aims to avoid work that [analyze] does which would be
  /// unnecessary for a completion request.
  AnalysisForCompletionResult analyzeForCompletion({
    required FileState file,
    required int offset,
    required LibraryFragmentImpl unitElement,
    required OperationPerformanceImpl performance,
  }) {
    var fileAnalysis = performance.run('parse', (performance) {
      return _parse(file: file, unitElement: unitElement);
    });
    var parsedUnit = fileAnalysis.unit;
    var node = parsedUnit.nodeCovering(offset: offset);
    var diagnosticListener = RecordingDiagnosticListener();

    return performance.run('resolve', (performance) {
      TypeConstraintGenerationDataForTesting? inferenceDataForTesting =
          _testingData != null
              ? TypeConstraintGenerationDataForTesting()
              : null;

      // TODO(scheglov): We don't need to do this for the whole unit.
      parsedUnit.accept(
        ResolutionVisitor(
          unitElement: unitElement,
          diagnosticListener: diagnosticListener,
          nameScope: unitElement.scope,
          strictInference: _analysisOptions.strictInference,
          strictCasts: _analysisOptions.strictCasts,
          elementWalker: ElementWalker.forCompilationUnit(
            unitElement,
            libraryFilePath: _library.file.path,
            unitFilePath: file.path,
          ),
          dataForTesting: inferenceDataForTesting,
        ),
      );
      _testingData?.recordTypeConstraintGenerationDataForTesting(
        file.uri,
        inferenceDataForTesting!,
      );

      // TODO(scheglov): We don't need to do this for the whole unit.
      parsedUnit.accept(
        ScopeResolverVisitor(
          fileAnalysis.diagnosticReporter,
          nameScope: unitElement.scope,
        ),
      );

      var featureSet = _libraryElement.featureSet;
      var typeAnalyzerOptions = computeTypeAnalyzerOptions(featureSet);
      FlowAnalysisHelper flowAnalysisHelper = FlowAnalysisHelper(
        _testingData != null,
        typeSystemOperations: _typeSystemOperations,
        typeAnalyzerOptions: typeAnalyzerOptions,
      );
      _testingData?.recordFlowAnalysisDataForTesting(
        file.uri,
        flowAnalysisHelper.dataForTesting!,
      );

      var resolverVisitor = ResolverVisitor(
        _inheritance,
        _libraryElement,
        libraryResolutionContext,
        file.source,
        _typeProvider,
        diagnosticListener,
        featureSet: _libraryElement.featureSet,
        analysisOptions: _library.file.analysisOptions,
        flowAnalysisHelper: flowAnalysisHelper,
        libraryFragment: unitElement,
        typeAnalyzerOptions: typeAnalyzerOptions,
      );
      _testingData?.recordTypeConstraintGenerationDataForTesting(
        file.uri,
        resolverVisitor.inferenceHelper.dataForTesting!,
      );

      var nodeToResolve = node?.thisOrAncestorMatching((e) {
        return e.parent is ClassDeclaration ||
            e.parent is CompilationUnit ||
            e.parent is ExtensionDeclaration ||
            e.parent is MixinDeclaration;
      });
      if (nodeToResolve != null && nodeToResolve is! Directive) {
        var canResolveNode = resolverVisitor.prepareForResolving(nodeToResolve);
        if (canResolveNode) {
          nodeToResolve.accept(resolverVisitor);
          resolverVisitor.checkIdle();
          return AnalysisForCompletionResult(
            fileState: file,
            parsedUnit: parsedUnit,
            resolvedNodes: [nodeToResolve],
          );
        }
      }

      _libraryFiles.clear();
      _parseAndResolve();
      var unit = _libraryFiles.values.first.unit;
      return AnalysisForCompletionResult(
        fileState: file,
        parsedUnit: unit,
        resolvedNodes: [unit],
      );
    });
  }

  void _checkForInconsistentLanguageVersionOverride() {
    var libraryUnitAnalysis = _libraryFiles.values.first;
    var libraryUnit = libraryUnitAnalysis.unit;
    var libraryOverrideToken = libraryUnit.languageVersionToken;

    var elementToUnit = <LibraryFragmentImpl, CompilationUnit>{};
    for (var fileAnalysis in _libraryFiles.values) {
      elementToUnit[fileAnalysis.element] = fileAnalysis.unit;
    }

    for (var directive in libraryUnit.directives) {
      if (directive is PartDirectiveImpl) {
        var uri = directive.partInclude?.uri;
        if (uri is DirectiveUriWithUnitImpl) {
          var partUnit = elementToUnit[uri.libraryFragment];
          if (partUnit != null) {
            var shouldReport = false;
            var partOverrideToken = partUnit.languageVersionToken;
            if (libraryOverrideToken != null) {
              if (partOverrideToken != null) {
                if (partOverrideToken.major != libraryOverrideToken.major ||
                    partOverrideToken.minor != libraryOverrideToken.minor) {
                  shouldReport = true;
                }
              } else {
                shouldReport = true;
              }
            } else if (partOverrideToken != null) {
              shouldReport = true;
            }
            if (shouldReport) {
              libraryUnitAnalysis.diagnosticReporter.atNode(
                directive.uri,
                CompileTimeErrorCode.INCONSISTENT_LANGUAGE_VERSION_OVERRIDE,
              );
            }
          }
        }
      }
    }
  }

  void _computeConstantErrors(FileAnalysis fileAnalysis) {
    ConstantVerifier constantVerifier = ConstantVerifier(
      fileAnalysis.diagnosticReporter,
      _libraryElement,
      _declaredVariables,
      retainDataForTesting: _testingData != null,
    );
    fileAnalysis.unit.accept(constantVerifier);
    _testingData?.recordExhaustivenessDataForTesting(
      fileAnalysis.file.uri,
      constantVerifier.exhaustivenessDataForTesting!,
    );
  }

  /// Compute constants in all units.
  void _computeConstants() {
    var configuration = ConstantEvaluationConfiguration();
    var constants = [
      for (var fileAnalysis in _libraryFiles.values)
        ..._findConstants(
          unit: fileAnalysis.unit,
          configuration: configuration,
        ),
    ];
    computeConstants(
      declaredVariables: _declaredVariables,
      constants: constants,
      featureSet: _libraryElement.featureSet,
      configuration: configuration,
    );
  }

  /// Compute diagnostics in [_libraryFiles], including errors and warnings,
  /// lints, and a few other cases.
  void _computeDiagnostics() {
    for (var fileAnalysis in _libraryFiles.values) {
      _computeVerifyErrors(fileAnalysis);
    }

    MemberDuplicateDefinitionVerifier.checkLibrary(
      inheritance: _inheritance,
      libraryVerificationContext: _libraryVerificationContext,
      libraryElement: _libraryElement,
      files: _libraryFiles,
    );

    _libraryVerificationContext.constructorFieldsVerifier.report();

    if (_analysisOptions.warning) {
      var usedLocalElements = <UsedLocalElements>[];
      for (var fileAnalysis in _libraryFiles.values) {
        {
          var visitor = GatherUsedLocalElementsVisitor(_libraryElement);
          fileAnalysis.unit.accept(visitor);
          usedLocalElements.add(visitor.usedElements);
        }
      }
      var usedElements = UsedLocalElements.merge(usedLocalElements);
      for (var fileAnalysis in _libraryFiles.values) {
        _computeWarnings(fileAnalysis, usedElements: usedElements);
      }
    }

    if (_analysisOptions.lint) {
      _computeLints();
    }

    _checkForInconsistentLanguageVersionOverride();

    var validateUnnecessaryIgnores = _analysisOptions.isLintEnabled(
      'unnecessary_ignore',
    );

    // This must happen after all other diagnostics have been computed but
    // before the list of diagnostics has been filtered.
    for (var fileAnalysis in _libraryFiles.values
    // Only validate non-generated files.
    .whereNot((f) => f.file.source.isGenerated)) {
      IgnoreValidator(
        fileAnalysis.diagnosticReporter,
        fileAnalysis.diagnosticListener.diagnostics,
        fileAnalysis.ignoreInfo,
        fileAnalysis.unit.lineInfo,
        _analysisOptions.unignorableDiagnosticCodeNames,
        validateUnnecessaryIgnores,
      ).reportErrors();
    }
  }

  void _computeLints() {
    var definingUnit = _libraryElement.definingCompilationUnit;
    var analysesToContextUnits = <FileAnalysis, RuleContextUnit>{};
    RuleContextUnit? definingContextUnit;
    WorkspacePackageImpl? workspacePackage;
    for (var fileAnalysis in _libraryFiles.values) {
      var linterContextUnit = RuleContextUnit(
        file: fileAnalysis.file.resource,
        content: fileAnalysis.file.content,
        unit: fileAnalysis.unit,
        diagnosticReporter: fileAnalysis.diagnosticReporter,
      );
      analysesToContextUnits[fileAnalysis] = linterContextUnit;
      if (fileAnalysis.unit.declaredFragment == definingUnit) {
        definingContextUnit = linterContextUnit;
        workspacePackage = fileAnalysis.file.workspacePackage;
      }
    }

    var allUnits = analysesToContextUnits.values.toList();
    definingContextUnit ??= allUnits.first;

    var nodeRegistry = RuleVisitorRegistryImpl(
      enableTiming: _enableLintRuleTiming,
    );
    var context = RuleContextWithResolvedResults(
      allUnits,
      definingContextUnit,
      _typeProvider,
      _typeSystem,
      workspacePackage,
    );

    for (var linter in _analysisOptions.lintRules) {
      var timer =
          _enableLintRuleTiming ? analysisRuleTimers.getTimer(linter) : null;
      timer?.start();
      linter.registerNodeProcessors(nodeRegistry, context);
      timer?.stop();
    }

    for (var MapEntry(key: fileAnalysis, value: currentUnit)
        in analysesToContextUnits.entries) {
      // Skip computing lints on files that don't exist.
      // See: https://github.com/Dart-Code/Dart-Code/issues/5343
      if (!fileAnalysis.file.exists) continue;

      var unit = currentUnit.unit;
      var diagnosticReporter = currentUnit.diagnosticReporter;

      for (var rule in _analysisOptions.lintRules) {
        rule.reporter = diagnosticReporter;
      }

      // Run lint rules that handle specific node types.
      context.currentUnit = currentUnit;
      unit.accept(
        AnalysisRuleVisitor(
          nodeRegistry,
          shouldPropagateExceptions: _analysisOptions.propagateLinterExceptions,
        ),
      );
    }

    // Now that all lint rules have visited the code in each of the compilation
    // units, we can accept each lint rule's `afterLibrary` hook.
    AnalysisRuleVisitor(
      nodeRegistry,
      shouldPropagateExceptions: _analysisOptions.propagateLinterExceptions,
    ).afterLibrary();
  }

  void _computeVerifyErrors(FileAnalysis fileAnalysis) {
    var diagnosticReporter = fileAnalysis.diagnosticReporter;
    var unit = fileAnalysis.unit;

    _computeConstantErrors(fileAnalysis);

    // Compute inheritance and override errors.
    InheritanceOverrideVerifier(
      _typeSystem,
      _inheritance,
      diagnosticReporter,
    ).verifyUnit(unit);

    // Use the ErrorVerifier to compute errors.
    ErrorVerifier errorVerifier = ErrorVerifier(
      diagnosticReporter,
      _libraryElement,
      unit.declaredFragment!,
      _typeProvider,
      _inheritance,
      _libraryVerificationContext,
      _analysisOptions,
      typeSystemOperations: _typeSystemOperations,
    );
    unit.accept(errorVerifier);

    // Verify constraints on FFI uses. The CFE enforces these constraints as
    // compile-time errors and so does the analyzer.
    unit.accept(
      FfiVerifier(
        _typeSystem,
        diagnosticReporter,
        strictCasts: _analysisOptions.strictCasts,
      ),
    );
  }

  void _computeWarnings(
    FileAnalysis fileAnalysis, {
    required UsedLocalElements usedElements,
  }) {
    var diagnosticReporter = fileAnalysis.diagnosticReporter;
    var unit = fileAnalysis.unit;

    UnicodeTextVerifier(
      diagnosticReporter,
    ).verify(unit, fileAnalysis.file.content);

    unit.accept(DeadCodeVerifier(diagnosticReporter, _libraryElement));

    unit.accept(
      BestPracticesVerifier(
        diagnosticReporter,
        _typeProvider,
        _libraryElement,
        unit,
        typeSystem: _typeSystem,
        analysisOptions: _analysisOptions,
        workspacePackage: _library.file.workspacePackage,
      ),
    );

    unit.accept(OverrideVerifier(diagnosticReporter));

    unit.accept(RedeclareVerifier(diagnosticReporter));

    TodoFinder(diagnosticReporter).findIn(unit);
    LanguageVersionOverrideVerifier(diagnosticReporter).verify(unit);

    // Verify imports.
    if (!_hasDiagnosticReportedThatPreventsImportWarnings()) {
      var verifier = ImportsVerifier(fileAnalysis: fileAnalysis);
      verifier.addImports(unit);
      verifier.generateDuplicateExportWarnings(diagnosticReporter);
      verifier.generateDuplicateImportWarnings(diagnosticReporter);
      verifier.generateDuplicateShownHiddenNameWarnings(diagnosticReporter);
      verifier.generateUnusedImportWarnings(diagnosticReporter);
      verifier.generateUnusedShownNameHints(diagnosticReporter);
      verifier.generateUnnecessaryImportHints(diagnosticReporter);
    }

    // Unused local elements.
    unit.accept(
      UnusedLocalElementsVerifier(
        fileAnalysis.diagnosticListener,
        usedElements,
        _libraryElement,
      ),
    );

    //
    // Find code that uses features from an SDK version that does not satisfy
    // the SDK constraints specified in analysis options.
    //
    var package = fileAnalysis.file.workspacePackage;
    var sdkVersionConstraint =
        (package is PubPackage) ? package.sdkVersionConstraint : null;
    if (sdkVersionConstraint != null) {
      SdkConstraintVerifier verifier = SdkConstraintVerifier(
        diagnosticReporter,
        sdkVersionConstraint.withoutPreRelease,
      );
      unit.accept(verifier);
    }
  }

  /// Returns a subset of the given [diagnostics] that are not marked as ignored in
  /// the file.
  List<Diagnostic> _filterIgnoredDiagnostics(
    FileAnalysis fileAnalysis,
    List<Diagnostic> diagnostics,
  ) {
    if (diagnostics.isEmpty) {
      return diagnostics;
    }

    IgnoreInfo ignoreInfo = fileAnalysis.ignoreInfo;
    if (!ignoreInfo.hasIgnores) {
      return diagnostics;
    }

    var unignorableCodes = _analysisOptions.unignorableDiagnosticCodeNames;

    bool isIgnored(Diagnostic diagnostic) {
      var code = diagnostic.diagnosticCode;
      // Don't allow un-ignorable codes to be ignored.
      if (unignorableCodes.contains(code.name) ||
          unignorableCodes.contains(code.uniqueName) ||
          // Lint rules have lower case names.
          unignorableCodes.contains(code.name.toUpperCase())) {
        return false;
      }
      return ignoreInfo.ignored(diagnostic);
    }

    return diagnostics.where((Diagnostic e) => !isIgnored(e)).toList();
  }

  /// Find constants in [unit] to compute.
  List<ConstantEvaluationTarget> _findConstants({
    required CompilationUnit unit,
    required ConstantEvaluationConfiguration configuration,
  }) {
    ConstantFinder constantFinder = ConstantFinder(
      configuration: configuration,
    );
    unit.accept(constantFinder);

    var dependenciesFinder = ConstantExpressionsDependenciesFinder();
    unit.accept(dependenciesFinder);
    return [
      ...constantFinder.constantsToCompute,
      ...dependenciesFinder.dependencies,
    ];
  }

  bool _hasDiagnosticReportedThatPreventsImportWarnings() {
    var errorCodes =
        _libraryFiles.values.map((analysis) {
          return analysis.diagnosticListener.diagnostics.map(
            (e) => e.diagnosticCode,
          );
        }).flattenedToSet;

    for (var errorCode in errorCodes) {
      if (const {
        CompileTimeErrorCode.AMBIGUOUS_IMPORT,
        CompileTimeErrorCode.CONST_WITH_NON_TYPE,
        CompileTimeErrorCode.EXTENDS_NON_CLASS,
        CompileTimeErrorCode.IMPLEMENTS_NON_CLASS,
        CompileTimeErrorCode.MIXIN_OF_NON_CLASS,
        CompileTimeErrorCode.NEW_WITH_NON_TYPE,
        CompileTimeErrorCode.NOT_A_TYPE,
        CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
        CompileTimeErrorCode.UNDEFINED_ANNOTATION,
        CompileTimeErrorCode.UNDEFINED_CLASS,
        CompileTimeErrorCode.UNDEFINED_FUNCTION,
        CompileTimeErrorCode.UNDEFINED_IDENTIFIER,
        CompileTimeErrorCode.UNDEFINED_PREFIXED_NAME,
        WarningCode.DEPRECATED_EXPORT_USE,
      }.contains(errorCode)) {
        return true;
      }
    }

    return false;
  }

  /// Return a new parsed unresolved [CompilationUnit].
  FileAnalysis _parse({
    required FileState file,
    required LibraryFragmentImpl unitElement,
  }) {
    var diagnosticListener = RecordingDiagnosticListener();
    var unit = file.parse(
      diagnosticListener: diagnosticListener,
      performance: OperationPerformanceImpl('<root>'),
    );
    unit.declaredFragment = unitElement;

    // TODO(scheglov): Store [IgnoreInfo] as unlinked data.

    var result = FileAnalysis(
      file: file,
      diagnosticListener: diagnosticListener,
      unit: unit,
      element: unitElement,
    );
    _libraryFiles[file] = result;
    return result;
  }

  /// Parse and resolve all files in [_library].
  void _parseAndResolve() {
    _resolveDirectives(
      enclosingFile: null,
      fileKind: _library,
      fileElement: _libraryElement.definingCompilationUnit,
    );

    for (var fileAnalysis in _libraryFiles.values) {
      _resolveFile(fileAnalysis);
    }

    // Stop tracking usages by scopes.
    for (var fileAnalysis in _libraryFiles.values) {
      var scope = fileAnalysis.element.scope;
      scope.importsTrackingDestroy();
    }

    _computeConstants();
  }

  /// Reports URI-related import directive errors to the [diagnosticReporter].
  void _reportImportDirectiveErrors({
    required ImportDirectiveImpl directive,
    required LibraryImportState state,
    required DiagnosticReporter diagnosticReporter,
  }) {
    if (state is LibraryImportWithUri) {
      var selectedUriStr = state.selectedUri.relativeUriStr;
      if (selectedUriStr.startsWith('dart-ext:')) {
        diagnosticReporter.atNode(
          directive.uri,
          CompileTimeErrorCode.USE_OF_NATIVE_EXTENSION,
        );
      } else if (state.importedSource == null) {
        var errorCode =
            state.isDocImport
                ? WarningCode.URI_DOES_NOT_EXIST_IN_DOC_IMPORT
                : CompileTimeErrorCode.URI_DOES_NOT_EXIST;
        diagnosticReporter.atNode(
          directive.uri,
          errorCode,
          arguments: [selectedUriStr],
        );
      } else if (state is LibraryImportWithFile && !state.importedFile.exists) {
        var errorCode =
            state.isDocImport
                ? WarningCode.URI_DOES_NOT_EXIST_IN_DOC_IMPORT
                : state.importedSource.isGenerated
                ? CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED
                : CompileTimeErrorCode.URI_DOES_NOT_EXIST;
        diagnosticReporter.atNode(
          directive.uri,
          errorCode,
          arguments: [selectedUriStr],
        );
      } else if (state.importedLibrarySource == null) {
        diagnosticReporter.atNode(
          directive.uri,
          CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY,
          arguments: [selectedUriStr],
        );
      }
    } else if (state is LibraryImportWithUriStr) {
      diagnosticReporter.atNode(
        directive.uri,
        CompileTimeErrorCode.INVALID_URI,
        arguments: [state.selectedUri.relativeUriStr],
      );
    } else {
      diagnosticReporter.atNode(
        directive.uri,
        CompileTimeErrorCode.URI_WITH_INTERPOLATION,
      );
    }
  }

  /// Parses the file of [fileKind], and resolves directives.
  /// Recursively parses augmentations and parts.
  void _resolveDirectives({
    required FileAnalysis? enclosingFile,
    required FileKind fileKind,
    required LibraryFragmentImpl fileElement,
  }) {
    var fileAnalysis = _parse(file: fileKind.file, unitElement: fileElement);
    var containerUnit = fileAnalysis.unit;

    var containerDiagnosticReporter = fileAnalysis.diagnosticReporter;

    var libraryExportIndex = 0;
    var libraryImportIndex = 0;
    var partIndex = 0;

    for (Directive directive in containerUnit.directives) {
      if (directive is ExportDirectiveImpl) {
        var index = libraryExportIndex++;
        _resolveLibraryExportDirective(
          directive: directive,
          element: fileElement.libraryExports[index],
          state: fileKind.libraryExports[index],
          diagnosticReporter: containerDiagnosticReporter,
        );
      } else if (directive is ImportDirectiveImpl) {
        var index = libraryImportIndex++;
        _resolveLibraryImportDirective(
          directive: directive,
          element: fileElement.libraryImports[index],
          state: fileKind.libraryImports[index],
          diagnosticReporter: containerDiagnosticReporter,
        );
      } else if (directive is LibraryDirectiveImpl) {
        if (fileKind == _library) {
          directive.element = _libraryElement;
        }
      } else if (directive is PartDirectiveImpl) {
        var index = partIndex++;
        _resolvePartDirective(
          enclosingFile: fileAnalysis,
          directive: directive,
          partState: fileKind.partIncludes[index],
          partElement: fileElement.parts[index],
          diagnosticReporter: containerDiagnosticReporter,
        );
      }
    }

    var docImports =
        containerUnit.directives
            .whereType<LibraryDirective>()
            .firstOrNull
            ?.documentationComment
            ?.docImports;
    if (docImports != null) {
      for (var i = 0; i < docImports.length; i++) {
        _resolveLibraryDocImportDirective(
          directive: docImports[i].import as ImportDirectiveImpl,
          state: fileKind.docLibraryImports[i],
          diagnosticReporter: containerDiagnosticReporter,
        );
      }
    }
  }

  void _resolveFile(FileAnalysis fileAnalysis) {
    var source = fileAnalysis.file.source;
    var diagnosticListener = fileAnalysis.diagnosticListener;
    var unit = fileAnalysis.unit;
    var unitElement = fileAnalysis.element;

    TypeConstraintGenerationDataForTesting? inferenceDataForTesting =
        _testingData != null ? TypeConstraintGenerationDataForTesting() : null;

    unit.accept(
      ResolutionVisitor(
        unitElement: unitElement,
        diagnosticListener: diagnosticListener,
        nameScope: unitElement.scope,
        strictInference: _analysisOptions.strictInference,
        strictCasts: _analysisOptions.strictCasts,
        elementWalker: ElementWalker.forCompilationUnit(
          unitElement,
          libraryFilePath: _library.file.path,
          unitFilePath: fileAnalysis.file.path,
        ),
        dataForTesting: inferenceDataForTesting,
      ),
    );
    _testingData?.recordTypeConstraintGenerationDataForTesting(
      fileAnalysis.file.uri,
      inferenceDataForTesting!,
    );

    var docImportLibraries = [
      for (var import in _library.docLibraryImports)
        if (import is LibraryImportWithFile)
          _libraryElement.session.elementFactory.libraryOfUri2(
            import.importedFile.uri,
          ),
    ];
    unit.accept(
      ScopeResolverVisitor(
        fileAnalysis.diagnosticReporter,
        nameScope: unitElement.scope,
        docImportLibraries: docImportLibraries,
      ),
    );

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

    var typeAnalyzerOptions = computeTypeAnalyzerOptions(unit.featureSet);
    FlowAnalysisHelper flowAnalysisHelper = FlowAnalysisHelper(
      _testingData != null,
      typeSystemOperations: _typeSystemOperations,
      typeAnalyzerOptions: typeAnalyzerOptions,
    );
    _testingData?.recordFlowAnalysisDataForTesting(
      fileAnalysis.file.uri,
      flowAnalysisHelper.dataForTesting!,
    );

    var resolver = ResolverVisitor(
      _inheritance,
      _libraryElement,
      libraryResolutionContext,
      source,
      _typeProvider,
      diagnosticListener,
      analysisOptions: _library.file.analysisOptions,
      featureSet: unit.featureSet,
      flowAnalysisHelper: flowAnalysisHelper,
      libraryFragment: unitElement,
      typeAnalyzerOptions: typeAnalyzerOptions,
    );
    unit.accept(resolver);
    _testingData?.recordTypeConstraintGenerationDataForTesting(
      fileAnalysis.file.uri,
      resolver.inferenceHelper.dataForTesting!,
    );
  }

  /// Resolves the `@docImport` directive URI and reports any import errors of
  /// the [directive] to the [diagnosticReporter].
  void _resolveLibraryDocImportDirective({
    required ImportDirectiveImpl directive,
    required LibraryImportState state,
    required DiagnosticReporter diagnosticReporter,
  }) {
    _resolveUriConfigurations(
      configurationNodes: directive.configurations,
      configurationUris: state.uris.configurations,
    );
    _reportImportDirectiveErrors(
      directive: directive,
      state: state,
      diagnosticReporter: diagnosticReporter,
    );
  }

  void _resolveLibraryExportDirective({
    required ExportDirectiveImpl directive,
    required LibraryExportImpl element,
    required LibraryExportState state,
    required DiagnosticReporter diagnosticReporter,
  }) {
    directive.libraryExport = element;
    _resolveUriConfigurations(
      configurationNodes: directive.configurations,
      configurationUris: state.uris.configurations,
    );
    if (state is LibraryExportWithUri) {
      var selectedUriStr = state.selectedUri.relativeUriStr;
      if (selectedUriStr.startsWith('dart-ext:')) {
        diagnosticReporter.atNode(
          directive.uri,
          CompileTimeErrorCode.USE_OF_NATIVE_EXTENSION,
        );
      } else if (state.exportedSource == null) {
        diagnosticReporter.atNode(
          directive.uri,
          CompileTimeErrorCode.URI_DOES_NOT_EXIST,
          arguments: [selectedUriStr],
        );
      } else if (state is LibraryExportWithFile && !state.exportedFile.exists) {
        var errorCode =
            isGeneratedSource(state.exportedSource)
                ? CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED
                : CompileTimeErrorCode.URI_DOES_NOT_EXIST;
        diagnosticReporter.atNode(
          directive.uri,
          errorCode,
          arguments: [selectedUriStr],
        );
      } else if (state.exportedLibrarySource == null) {
        diagnosticReporter.atNode(
          directive.uri,
          CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
          arguments: [selectedUriStr],
        );
      }
    } else if (state is LibraryExportWithUriStr) {
      diagnosticReporter.atNode(
        directive.uri,
        CompileTimeErrorCode.INVALID_URI,
        arguments: [state.selectedUri.relativeUriStr],
      );
    } else {
      diagnosticReporter.atNode(
        directive.uri,
        CompileTimeErrorCode.URI_WITH_INTERPOLATION,
      );
    }
  }

  void _resolveLibraryImportDirective({
    required ImportDirectiveImpl directive,
    required LibraryImportImpl element,
    required LibraryImportState state,
    required DiagnosticReporter diagnosticReporter,
  }) {
    directive.libraryImport = element;
    directive.prefix?.element = element.prefix?.element;
    _resolveUriConfigurations(
      configurationNodes: directive.configurations,
      configurationUris: state.uris.configurations,
    );
    _reportImportDirectiveErrors(
      directive: directive,
      state: state,
      diagnosticReporter: diagnosticReporter,
    );
  }

  void _resolvePartDirective({
    required FileAnalysis enclosingFile,
    required PartDirectiveImpl? directive,
    required PartIncludeState partState,
    required PartIncludeImpl partElement,
    required DiagnosticReporter diagnosticReporter,
  }) {
    directive?.partInclude = partElement;

    void reportOnDirectiveUri(
      DiagnosticCode diagnosticCode, {
      List<Object>? arguments = const [],
    }) {
      if (directive != null) {
        diagnosticReporter.atNode(
          directive.uri,
          diagnosticCode,
          arguments: arguments,
        );
      }
    }

    if (partState is! PartIncludeWithUriStr) {
      reportOnDirectiveUri(CompileTimeErrorCode.URI_WITH_INTERPOLATION);
      return;
    }

    if (partState is! PartIncludeWithUri) {
      reportOnDirectiveUri(
        CompileTimeErrorCode.INVALID_URI,
        arguments: [partState.selectedUri.relativeUriStr],
      );
      return;
    }

    if (partState is! PartIncludeWithFile) {
      reportOnDirectiveUri(
        CompileTimeErrorCode.URI_DOES_NOT_EXIST,
        arguments: [partState.selectedUri.relativeUriStr],
      );
      return;
    }

    var includedFile = partState.includedFile;
    var includedKind = includedFile.kind;

    if (includedKind is! PartFileKind) {
      DiagnosticCode diagnosticCode;
      if (includedFile.exists) {
        diagnosticCode = CompileTimeErrorCode.PART_OF_NON_PART;
      } else if (isGeneratedSource(includedFile.source)) {
        diagnosticCode = CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED;
      } else {
        diagnosticCode = CompileTimeErrorCode.URI_DOES_NOT_EXIST;
      }
      reportOnDirectiveUri(diagnosticCode, arguments: [includedFile.uriStr]);
      return;
    }

    //
    // Validate that the part source is unique in the library.
    //
    if (_libraryFiles.containsKey(includedFile)) {
      reportOnDirectiveUri(
        CompileTimeErrorCode.DUPLICATE_PART,
        arguments: [includedFile.uri],
      );
      return;
    }

    var partElementUri = partElement.uri;
    if (partElementUri is! DirectiveUriWithUnitImpl) {
      switch (includedKind) {
        case PartOfNameFileKind():
          if (!_libraryElement.featureSet.isEnabled(Feature.enhanced_parts)) {
            var name = includedKind.unlinked.name;
            var libraryName = _libraryElement.name;
            if (libraryName.isEmpty) {
              reportOnDirectiveUri(
                CompileTimeErrorCode.PART_OF_UNNAMED_LIBRARY,
                arguments: [name],
              );
            } else {
              reportOnDirectiveUri(
                CompileTimeErrorCode.PART_OF_DIFFERENT_LIBRARY,
                arguments: [libraryName, name],
              );
            }
          }
        case PartOfUriFileKind():
          reportOnDirectiveUri(
            CompileTimeErrorCode.PART_OF_DIFFERENT_LIBRARY,
            arguments: [enclosingFile.file.uriStr, includedFile.uriStr],
          );
      }
      return;
    }

    if (directive != null) {
      _resolveUriConfigurations(
        configurationNodes: directive.configurations,
        configurationUris: partState.uris.configurations,
      );
    }

    _resolveDirectives(
      enclosingFile: enclosingFile,
      fileKind: includedKind,
      fileElement: partElementUri.libraryFragment,
    );
  }

  void _resolveUriConfigurations({
    required List<ConfigurationImpl> configurationNodes,
    required List<file_state.DirectiveUri> configurationUris,
  }) {
    for (var i = 0; i < configurationNodes.length; i++) {
      var node = configurationNodes[i];
      node.resolvedUri = configurationUris[i].asDirectiveUri;
    }
  }
}

/// Analysis result for single file.
class UnitAnalysisResult {
  final FileState file;
  final CompilationUnitImpl unit;
  final List<Diagnostic> diagnostics;

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

extension on file_state.DirectiveUri {
  DirectiveUriImpl get asDirectiveUri {
    var self = this;
    if (self is file_state.DirectiveUriWithSource) {
      return DirectiveUriWithSourceImpl(
        relativeUriString: self.relativeUriStr,
        relativeUri: self.relativeUri,
        source: self.source,
      );
    } else if (self is file_state.DirectiveUriWithUri) {
      return DirectiveUriWithRelativeUriImpl(
        relativeUriString: self.relativeUriStr,
        relativeUri: self.relativeUri,
      );
    } else if (self is file_state.DirectiveUriWithString) {
      return DirectiveUriWithRelativeUriStringImpl(
        relativeUriString: self.relativeUriStr,
      );
    }
    return DirectiveUriImpl();
  }
}

extension on FileSource {
  bool get isGenerated => isGeneratedSource(this);
}
