// Copyright (c) 2020, 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:typed_data';

import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
import 'package:analyzer/src/context/packages.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/cache.dart';
import 'package:analyzer/src/dart/analysis/context_root.dart';
import 'package:analyzer/src/dart/analysis/driver.dart' show ErrorEncoding;
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/analysis/feature_set_provider.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/library_analyzer.dart';
import 'package:analyzer/src/dart/analysis/library_context.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
import 'package:analyzer/src/dart/analysis/results.dart';
import 'package:analyzer/src/dart/analysis/search.dart';
import 'package:analyzer/src/dart/micro/analysis_context.dart';
import 'package:analyzer/src/dart/micro/utils.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/api_signature.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';
import 'package:analyzer/src/task/options.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:analyzer/src/utilities/extensions/file_system.dart';
import 'package:analyzer/src/workspace/workspace.dart';
import 'package:collection/collection.dart';
import 'package:meta/meta.dart';
import 'package:yaml/yaml.dart';

class CiderFileContent implements FileContent {
  final CiderFileContentStrategy strategy;
  final String path;
  final String digestStr;

  CiderFileContent({
    required this.strategy,
    required this.path,
    required this.digestStr,
  });

  @override
  String get content {
    final contentWithDigest = _getContent();

    if (contentWithDigest.digestStr != digestStr) {
      throw StateError('File was changed, but not invalidated: $path');
    }

    return contentWithDigest.content;
  }

  @override
  String get contentHash => digestStr;

  @override
  bool get exists => digestStr.isNotEmpty;

  _ContentWithDigest _getContent() {
    String content;
    try {
      final file = strategy.resourceProvider.getFile(path);
      content = file.readAsStringSync();
    } catch (_) {
      content = '';
    }

    final digestStr = strategy.getFileDigest(path);
    return _ContentWithDigest(
      content: content,
      digestStr: digestStr,
    );
  }
}

class CiderFileContentStrategy implements FileContentStrategy {
  final ResourceProvider resourceProvider;

  /// A function that returns the digest for a file as a String. The function
  /// returns a non null value, returns an empty string if file does
  /// not exist/has no contents.
  final String Function(String path) getFileDigest;

  CiderFileContentStrategy({
    required this.resourceProvider,
    required this.getFileDigest,
  });

  @override
  CiderFileContent get(String path) {
    final digestStr = getFileDigest(path);
    return CiderFileContent(
      strategy: this,
      path: path,
      digestStr: digestStr,
    );
  }
}

class CiderSearchInfo {
  final CharacterLocation startPosition;
  final int length;
  final MatchKind kind;

  CiderSearchInfo(this.startPosition, this.length, this.kind);

  @override
  bool operator ==(Object other) =>
      other is CiderSearchInfo &&
      startPosition == other.startPosition &&
      length == other.length &&
      kind == other.kind;
}

class CiderSearchMatch {
  final String path;
  final List<CiderSearchInfo> references;

  CiderSearchMatch(this.path, this.references);

  @override
  bool operator ==(Object other) =>
      other is CiderSearchMatch &&
      path == other.path &&
      const ListEquality<CiderSearchInfo>()
          .equals(references, other.references);

  @override
  String toString() {
    return '($path, $references)';
  }
}

class FileContext {
  final AnalysisOptionsImpl analysisOptions;
  final FileState file;

  FileContext(this.analysisOptions, this.file);
}

class FileResolver {
  final PerformanceLog logger;
  final ResourceProvider resourceProvider;
  ByteStore byteStore;
  final SourceFactory sourceFactory;

  /// A function that returns the digest for a file as a String. The function
  /// returns a non null value, can return an empty string if file does
  /// not exist/has no contents.
  final String Function(String path) getFileDigest;

  /// A function that returns true if the given file path is likely to be that
  /// of a file that is generated.
  final bool Function(String path) isGenerated;

  /// A function that fetches the given list of files. This function can be used
  /// to batch file reads in systems where file fetches are expensive.
  final void Function(List<String> paths)? prefetchFiles;

  final Workspace workspace;

  /// This field gets value only during testing.
  final FileResolverTestData? testData;

  FileSystemState? fsState;

  MicroContextObjects? contextObjects;

  LibraryContext? libraryContext;

  /// List of keys for cache elements that are invalidated. Track elements that
  /// are invalidated during [changeFiles]. Used in [releaseAndClearRemovedIds]
  /// to release the cache items and is then cleared.
  final Set<String> removedCacheKeys = {};

  /// The cache of file results, cleared on [changeFiles].
  ///
  /// It is used to allow assists and fixes without resolving the same file
  /// multiple times, as we compute more than one assist, or fixes when there
  /// are more than one error on a line.
  @visibleForTesting
  final Map<String, ResolvedLibraryResult> cachedResults = {};

  /// The cache of error results.
  final Cache<String, Uint8List> _errorResultsCache =
      Cache(128 * 1024, (bytes) => bytes.length);

  FileResolver({
    required this.logger,
    required this.resourceProvider,
    required this.sourceFactory,
    required this.getFileDigest,
    required this.prefetchFiles,
    required this.workspace,
    required this.isGenerated,
    required this.byteStore,
    this.testData,
  });

  /// Update the resolver to reflect the fact that the files with the given
  /// [paths] were changed. For each specified file we need to make sure that
  /// when the file, of any file that directly or indirectly referenced it,
  /// is resolved, we use the new state of the file.
  void changeFiles(List<String> paths) {
    if (fsState == null) {
      return;
    }

    // Forget all results, anything is potentially affected.
    cachedResults.clear();

    // Remove the specified files and files that transitively depend on it.
    final removedFiles = <FileState>{};
    for (final path in paths) {
      fsState!.changeFile(path, removedFiles);
    }

    // Schedule disposing references to cached unlinked data.
    for (final removedFile in removedFiles) {
      removedCacheKeys.add(removedFile.unlinkedKey);
    }

    // Remove libraries represented by removed files.
    // If we need these libraries later, we will relink and reattach them.
    libraryContext?.remove(removedFiles, removedCacheKeys);

    releaseAndClearRemovedIds();
  }

  /// Collects all the cached artifacts and add all the cache id's for the
  /// removed artifacts to [removedCacheKeys].
  @Deprecated('Use dispose() instead')
  void collectSharedDataIdentifiers() {
    removedCacheKeys.addAll(fsState!.dispose());
    removedCacheKeys.addAll(libraryContext!.dispose());
  }

  /// Notifies this object that it is about to be discarded, so it should
  /// release any shared data.
  void dispose() {
    removedCacheKeys.addAll(fsState!.dispose());
    removedCacheKeys.addAll(libraryContext!.dispose());
    releaseAndClearRemovedIds();
  }

  /// Looks for references to the given Element. All the files currently
  ///  cached by the resolver are searched, generated files are ignored.
  Future<List<CiderSearchMatch>> findReferences2(Element element,
      {OperationPerformanceImpl? performance}) async {
    return logger.runAsync('findReferences for ${element.name}', () async {
      var references = <CiderSearchMatch>[];

      Future<void> collectReferences2(
          String path, OperationPerformanceImpl performance) async {
        await performance.runAsync('collectReferences', (_) async {
          var resolved = await resolve2(path: path);
          var collector = ReferencesCollector(element);
          resolved.unit.accept(collector);
          var matches = collector.references;
          if (matches.isNotEmpty) {
            var lineInfo = resolved.unit.lineInfo;
            references.add(CiderSearchMatch(
                path,
                matches
                    .map((match) => CiderSearchInfo(
                        lineInfo.getLocation(match.offset),
                        match.length,
                        match.matchKind))
                    .toList()));
          }
        });
      }

      performance ??= OperationPerformanceImpl('<default>');
      // TODO(keertip): check if element is named constructor.
      if (element is LocalVariableElement ||
          (element is ParameterElement && !element.isNamed)) {
        await collectReferences2(element.source!.fullName, performance!);
      } else if (element is ImportElement) {
        return await _searchReferences_Import(element);
      } else {
        var result = performance!.run('getFilesContaining', (performance) {
          return fsState!.getFilesContaining(element.displayName);
        });
        for (var filePath in result) {
          await collectReferences2(filePath, performance!);
        }
      }
      return references;
    });
  }

  Future<ErrorsResult> getErrors2({
    required String path,
    OperationPerformanceImpl? performance,
  }) async {
    _throwIfNotAbsoluteNormalizedPath(path);

    performance ??= OperationPerformanceImpl('<default>');

    return logger.runAsync('Get errors for $path', () async {
      var fileContext = getFileContext(
        path: path,
        performance: performance!,
      );
      var file = fileContext.file;
      // TODO(scheglov) Casts are unsafe.
      final kind = file.kind as LibraryFileStateKind;

      final errorsSignatureBuilder = ApiSignature();
      errorsSignatureBuilder.addString(kind.libraryCycle.apiSignature);
      errorsSignatureBuilder.addString(file.contentHash);
      final errorsKey = '${errorsSignatureBuilder.toHex()}.errors';

      final List<AnalysisError> errors;
      final bytes = _errorResultsCache.get(errorsKey);
      if (bytes != null) {
        var data = CiderUnitErrors.fromBuffer(bytes);
        errors = data.errors.map((error) {
          return ErrorEncoding.decode(file.source, error)!;
        }).toList();
      } else {
        var unitResult = await resolve2(
          path: path,
          performance: performance,
        );
        errors = unitResult.errors;

        _errorResultsCache.put(
          errorsKey,
          CiderUnitErrorsBuilder(
            errors: errors.map(ErrorEncoding.encode).toList(),
          ).toBuffer(),
        );
      }

      return ErrorsResultImpl(
        contextObjects!.analysisSession,
        path,
        file.uri,
        file.lineInfo,
        false, // isPart
        errors,
      );
    });
  }

  FileContext getFileContext({
    required String path,
    required OperationPerformanceImpl performance,
  }) {
    return performance.run('fileContext', (performance) {
      var analysisOptions = performance.run('analysisOptions', (performance) {
        return _getAnalysisOptions(
          path: path,
          performance: performance,
        );
      });

      performance.run('createContext', (_) {
        _createContext(path, analysisOptions);
      });

      var file = performance.run('fileForPath', (performance) {
        return fsState!.getFileForPath2(
          path: path,
          performance: performance,
        );
      });

      return FileContext(analysisOptions, file);
    });
  }

  /// Return files that have a top-level declaration with the [name].
  List<FileState> getFilesWithTopLevelDeclarations(String name) {
    final fsState = this.fsState;
    if (fsState == null) {
      return const [];
    }
    return fsState.getFilesWithTopLevelDeclarations(name);
  }

  Future<LibraryElement> getLibraryByUri2({
    required String uriStr,
    OperationPerformanceImpl? performance,
  }) async {
    performance ??= OperationPerformanceImpl('<default>');

    var uri = Uri.parse(uriStr);
    var path = sourceFactory.forUri2(uri)?.fullName;

    if (path == null) {
      throw ArgumentError('$uri cannot be resolved to a file.');
    }

    var fileContext = getFileContext(
      path: path,
      performance: performance,
    );
    var file = fileContext.file;

    final kind = file.kind;
    if (kind is! LibraryFileStateKind) {
      throw ArgumentError('$uri is not a library.');
    }

    await performance.runAsync('libraryContext', (performance) async {
      await libraryContext!.load(
        targetLibrary: kind,
        performance: performance,
      );
    });

    return libraryContext!.elementFactory.libraryOfUri2(uri);
  }

  String getLibraryLinkedSignature({
    required String path,
    required OperationPerformanceImpl performance,
  }) {
    _throwIfNotAbsoluteNormalizedPath(path);

    var file = fsState!.getFileForPath2(
      path: path,
      performance: performance,
    );

    // TODO(scheglov) Casts are unsafe.
    final kind = file.kind as LibraryFileStateKind;
    return kind.libraryCycle.apiSignature;
  }

  /// Ensure that libraries necessary for resolving [path] are linked.
  ///
  /// Libraries are linked in library cycles, from the bottom to top, so that
  /// when we link a cycle, everything it transitively depends is ready. We
  /// load newly linked libraries from bytes, and when we link a new library
  /// cycle we partially resynthesize AST and elements from previously
  /// loaded libraries.
  ///
  /// But when we are done linking libraries, and want to resolve just the
  /// very top library that transitively depends on the whole dependency
  /// tree, this library will not reference as many elements in the
  /// dependencies as we needed for linking. Most probably it references
  /// elements from directly imported libraries, and a couple of layers below.
  /// So, keeping all previously resynthesized data is usually a waste.
  ///
  /// This method ensures that we discard the libraries context, with all its
  /// partially resynthesized data, and so prepare for loading linked summaries
  /// from bytes, which will be done by [getErrors2]. It is OK for it to
  /// spend some more time on this.
  Future<void> linkLibraries2({
    required String path,
  }) async {
    _throwIfNotAbsoluteNormalizedPath(path);

    var performance = OperationPerformanceImpl('<unused>');

    var fileContext = getFileContext(
      path: path,
      performance: performance,
    );
    var file = fileContext.file;
    final libraryKind = file.kind.library ?? file.kind.asLibrary;

    // Load the library, link if necessary.
    await libraryContext!.load(
      targetLibrary: libraryKind,
      performance: performance,
    );

    // Unload libraries, but don't release the linked data.
    // If we are the only consumer of it, we will lose it.
    final linkedKeysToRelease = libraryContext!.unloadAll();

    // Load the library again, the reference count is `>= 2`.
    await libraryContext!.load(
      targetLibrary: libraryKind,
      performance: performance,
    );

    // Release the linked data, the reference count is `>= 1`.
    byteStore.release(linkedKeysToRelease);
  }

  /// Releases from the cache and clear [removedCacheKeys].
  void releaseAndClearRemovedIds() {
    byteStore.release(removedCacheKeys);
    removedCacheKeys.clear();
  }

  /// Remove cached [FileState]'s that were not used in the current analysis
  /// session. The list of files analyzed is used to compute the set of unused
  /// [FileState]'s. Adds the cache id's for the removed [FileState]'s to
  /// [removedCacheKeys].
  void removeFilesNotNecessaryForAnalysisOf(List<String> files) {
    var removedFiles = fsState!.removeUnusedFiles(files);
    for (var removedFile in removedFiles) {
      removedCacheKeys.add(removedFile.unlinkedKey);
    }
    libraryContext?.remove(removedFiles, removedCacheKeys);
    releaseAndClearRemovedIds();
  }

  Future<ResolvedUnitResult> resolve2({
    required String path,
    OperationPerformanceImpl? performance,
  }) async {
    _throwIfNotAbsoluteNormalizedPath(path);

    performance ??= OperationPerformanceImpl('<default>');

    return logger.runAsync('Resolve $path', () async {
      var fileContext = getFileContext(
        path: path,
        performance: performance!,
      );
      var file = fileContext.file;

      final libraryKind = file.kind.library ?? file.kind.asLibrary;
      final libraryFile = libraryKind.file;

      var libraryResult = await resolveLibrary2(
        path: libraryFile.path,
        performance: performance,
      );
      return libraryResult.units.firstWhere(
        (unitResult) => unitResult.path == path,
      );
    });
  }

  /// The [completionLine] and [completionColumn] are zero based.
  Future<ResolvedForCompletionResultImpl> resolveForCompletion({
    required int completionLine,
    required int completionColumn,
    required String path,
    OperationPerformanceImpl? performance,
  }) async {
    _throwIfNotAbsoluteNormalizedPath(path);

    performance ??= OperationPerformanceImpl('<default>');

    return logger.runAsync('Resolve $path', () async {
      final fileContext = getFileContext(
        path: path,
        performance: performance!,
      );
      final file = fileContext.file;
      final libraryKind = file.kind.library ?? file.kind.asLibrary;

      final lineOffset = file.lineInfo.getOffsetOfLine(completionLine);
      final completionOffset = lineOffset + completionColumn;

      await performance.runAsync('libraryContext', (performance) async {
        await libraryContext!.load(
          targetLibrary: libraryKind,
          performance: performance,
        );
      });

      final unitElement = libraryContext!.computeUnitElement(libraryKind, file);

      return logger.run('Compute analysis results', () {
        final elementFactory = libraryContext!.elementFactory;
        final analysisSession = elementFactory.analysisSession;

        var libraryAnalyzer = LibraryAnalyzer(
          fileContext.analysisOptions,
          contextObjects!.declaredVariables,
          sourceFactory,
          elementFactory.libraryOfUri2(libraryKind.file.uri),
          analysisSession.inheritanceManager,
          libraryKind,
        );

        final analysisResult = performance!.run('analyze', (performance) {
          return libraryAnalyzer.analyzeForCompletion(
            file: file,
            offset: completionOffset,
            unitElement: unitElement,
            performance: performance,
          );
        });

        return ResolvedForCompletionResultImpl(
          analysisSession: analysisSession,
          path: path,
          uri: file.uri,
          exists: file.exists,
          content: file.content,
          lineInfo: file.lineInfo,
          parsedUnit: analysisResult.parsedUnit,
          unitElement: unitElement,
          resolvedNodes: analysisResult.resolvedNodes,
        );
      });
    });
  }

  Future<ResolvedLibraryResult> resolveLibrary2({
    required String path,
    OperationPerformanceImpl? performance,
  }) async {
    _throwIfNotAbsoluteNormalizedPath(path);

    performance ??= OperationPerformanceImpl('<default>');

    var cachedResult = cachedResults[path];
    if (cachedResult != null) {
      return cachedResult;
    }

    return logger.runAsync('Resolve $path', () async {
      var fileContext = getFileContext(
        path: path,
        performance: performance!,
      );
      var file = fileContext.file;
      final libraryKind = file.kind.library ?? file.kind.asLibrary;

      await performance.runAsync('libraryContext', (performance) async {
        await libraryContext!.load(
          targetLibrary: libraryKind,
          performance: performance,
        );
      });

      testData?.addResolvedLibrary(path);

      late List<UnitAnalysisResult> results;

      logger.run('Compute analysis results', () {
        var libraryAnalyzer = LibraryAnalyzer(
          fileContext.analysisOptions,
          contextObjects!.declaredVariables,
          sourceFactory,
          libraryContext!.elementFactory.libraryOfUri2(libraryKind.file.uri),
          libraryContext!.elementFactory.analysisSession.inheritanceManager,
          libraryKind,
        );

        results = performance!.run('analyze', (performance) {
          return libraryAnalyzer.analyze();
        });
      });

      var resolvedUnits = results.map((fileResult) {
        var file = fileResult.file;
        return ResolvedUnitResultImpl(
          contextObjects!.analysisSession,
          file.path,
          file.uri,
          file.exists,
          file.content,
          file.lineInfo,
          file.isPart,
          fileResult.unit,
          fileResult.errors,
        );
      }).toList();

      var libraryUnit = resolvedUnits.first;
      var result = ResolvedLibraryResultImpl(contextObjects!.analysisSession,
          libraryUnit.libraryElement, resolvedUnits);

      cachedResults[path] = result;

      return result;
    });
  }

  /// Make sure that [fsState], [contextObjects], and [libraryContext] are
  /// created and configured with the given [fileAnalysisOptions].
  ///
  /// The [fsState] is not affected by [fileAnalysisOptions].
  ///
  /// The [fileAnalysisOptions] only affect reported diagnostics, but not
  /// elements and types. So, we really need to reconfigure only when we are
  /// going to resolve some files using these new options.
  ///
  /// Specifically, "implicit casts" and "strict inference" affect the type
  /// system. And there are lints that are enabled for one package, but not
  /// for another.
  void _createContext(String path, AnalysisOptionsImpl fileAnalysisOptions) {
    if (contextObjects != null) {
      libraryContext!.analysisContext.analysisOptions = fileAnalysisOptions;
      return;
    }

    var analysisOptions = AnalysisOptionsImpl()
      ..implicitCasts = fileAnalysisOptions.implicitCasts
      ..strictInference = fileAnalysisOptions.strictInference;

    if (fsState == null) {
      var featureSetProvider = FeatureSetProvider.build(
        sourceFactory: sourceFactory,
        resourceProvider: resourceProvider,
        packages: Packages.empty,
        packageDefaultFeatureSet: analysisOptions.contextFeatures,
        nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
        nonPackageDefaultFeatureSet: analysisOptions.nonPackageFeatureSet,
      );

      fsState = FileSystemState(
        logger,
        byteStore,
        resourceProvider,
        'contextName',
        sourceFactory,
        workspace,
        DeclaredVariables.fromMap({}),
        Uint32List(0), // _saltForUnlinked
        Uint32List(0), // _saltForElements
        featureSetProvider,
        fileContentStrategy: CiderFileContentStrategy(
          resourceProvider: resourceProvider,
          getFileDigest: getFileDigest,
        ),
        prefetchFiles: prefetchFiles,
        isGenerated: isGenerated,
        testData: testData?.fileSystem,
      );
    }

    if (contextObjects == null) {
      var rootFolder = resourceProvider.getFolder(workspace.root);
      var root = ContextRootImpl(resourceProvider, rootFolder, workspace);
      root.included.add(rootFolder);

      contextObjects = createMicroContextObjects(
        fileResolver: this,
        analysisOptions: analysisOptions,
        sourceFactory: sourceFactory,
        root: root,
        resourceProvider: resourceProvider,
      );

      libraryContext = LibraryContext(
        declaredVariables: contextObjects!.declaredVariables,
        byteStore: byteStore,
        analysisOptions: contextObjects!.analysisOptions,
        analysisSession: contextObjects!.analysisSession,
        logger: logger,
        fileSystemState: fsState!,
        sourceFactory: sourceFactory,
        externalSummaries: SummaryDataStore(),
        macroExecutor: null,
        macroKernelBuilder: null,
        testData: testData?.libraryContext,
      );

      contextObjects!.analysisSession.elementFactory =
          libraryContext!.elementFactory;
    }
  }

  /// Return the analysis options.
  ///
  /// If the [path] is not `null`, read it.
  ///
  /// If the [workspace] is a [WorkspaceWithDefaultAnalysisOptions], get the
  /// default options, if the file exists.
  ///
  /// Otherwise, return the default options.
  AnalysisOptionsImpl _getAnalysisOptions({
    required String path,
    required OperationPerformanceImpl performance,
  }) {
    YamlMap? optionMap;

    var separator = resourceProvider.pathContext.separator;
    var isThirdParty = path
            .contains('${separator}third_party${separator}dart$separator') ||
        path.contains('${separator}third_party${separator}dart_lang$separator');

    File? optionsFile;
    if (!isThirdParty) {
      optionsFile = performance.run('findAnalysisOptionsYamlFile', (_) {
        var folder = resourceProvider.getFile(path).parent;
        return folder.findAnalysisOptionsYamlFile();
      });
    }

    if (optionsFile != null) {
      performance.run('getOptionsFromFile', (_) {
        try {
          var optionsProvider = AnalysisOptionsProvider(sourceFactory);
          optionMap = optionsProvider.getOptionsFromFile(optionsFile!);
        } catch (_) {}
      });
    } else {
      var source = performance.run('defaultOptions', (_) {
        if (workspace is WorkspaceWithDefaultAnalysisOptions) {
          if (isThirdParty) {
            return sourceFactory.forUri(
              WorkspaceWithDefaultAnalysisOptions.thirdPartyUri,
            );
          } else {
            return sourceFactory.forUri(
              WorkspaceWithDefaultAnalysisOptions.uri,
            );
          }
        }
        return null;
      });

      if (source != null && source.exists()) {
        performance.run('getOptionsFromFile', (_) {
          try {
            var optionsProvider = AnalysisOptionsProvider(sourceFactory);
            optionMap = optionsProvider.getOptionsFromSource(source);
          } catch (_) {}
        });
      }
    }

    var options = AnalysisOptionsImpl();

    if (optionMap != null) {
      performance.run('applyToAnalysisOptions', (_) {
        applyToAnalysisOptions(options, optionMap!);
      });
    }

    if (isThirdParty) {
      options.hint = false;
    }

    return options;
  }

  Future<List<CiderSearchMatch>> _searchReferences_Import(
      ImportElement element) async {
    var results = <CiderSearchMatch>[];
    LibraryElement libraryElement = element.library;
    for (CompilationUnitElement unitElement in libraryElement.units) {
      String unitPath = unitElement.source.fullName;
      var unitResult = await resolve2(path: unitPath);
      var visitor = ImportElementReferencesVisitor(element, unitElement);
      unitResult.unit.accept(visitor);
      var lineInfo = unitResult.lineInfo;
      var infos = visitor.results
          .map((searchResult) => CiderSearchInfo(
              lineInfo.getLocation(searchResult.offset),
              searchResult.length,
              MatchKind.REFERENCE))
          .toList();
      results.add(CiderSearchMatch(unitPath, infos));
    }
    return results;
  }

  void _throwIfNotAbsoluteNormalizedPath(String path) {
    var pathContext = resourceProvider.pathContext;
    if (pathContext.normalize(path) != path) {
      throw ArgumentError(
        'Only normalized paths are supported: $path',
      );
    }
  }
}

class FileResolverTestData {
  final fileSystem = FileSystemTestData();

  late final libraryContext = LibraryContextTestData(
    fileSystemTestData: fileSystem,
  );

  /// The paths of libraries which were resolved.
  ///
  /// The library path is added every time when it is resolved.
  final List<String> resolvedLibraries = [];

  void addResolvedLibrary(String path) {
    resolvedLibraries.add(path);
  }
}

class _ContentWithDigest {
  final String content;
  final String digestStr;

  _ContentWithDigest({
    required this.content,
    required this.digestStr,
  });
}
