| // Copyright (c) 2018, 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/dart/analysis/results.dart'; |
| import 'package:analyzer/dart/analysis/session.dart'; |
| import 'package:analyzer/dart/ast/ast.dart'; |
| import 'package:analyzer/dart/element/element.dart'; |
| import 'package:analyzer/error/error.dart'; |
| import 'package:analyzer/source/line_info.dart'; |
| import 'package:analyzer/src/dart/ast/utilities.dart'; |
| import 'package:analyzer/src/generated/resolver.dart'; |
| |
| abstract class AnalysisResultImpl implements AnalysisResult { |
| @override |
| final AnalysisSession session; |
| |
| @override |
| final String path; |
| |
| @override |
| final Uri uri; |
| |
| AnalysisResultImpl(this.session, this.path, this.uri); |
| } |
| |
| class ElementDeclarationResultImpl implements ElementDeclarationResult { |
| @override |
| final Element element; |
| |
| @override |
| final AstNode node; |
| |
| @override |
| final ParsedUnitResult parsedUnit; |
| |
| @override |
| final ResolvedUnitResult resolvedUnit; |
| |
| ElementDeclarationResultImpl( |
| this.element, this.node, this.parsedUnit, this.resolvedUnit); |
| } |
| |
| class ErrorsResultImpl extends FileResultImpl implements ErrorsResult { |
| @override |
| final List<AnalysisError> errors; |
| |
| ErrorsResultImpl(AnalysisSession session, String path, Uri uri, |
| LineInfo lineInfo, bool isPart, this.errors) |
| : super(session, path, uri, lineInfo, isPart); |
| } |
| |
| class FileResultImpl extends AnalysisResultImpl implements FileResult { |
| @override |
| final LineInfo lineInfo; |
| |
| @override |
| final bool isPart; |
| |
| FileResultImpl( |
| AnalysisSession session, String path, Uri uri, this.lineInfo, this.isPart) |
| : super(session, path, uri); |
| |
| @override |
| ResultState get state => ResultState.VALID; |
| } |
| |
| class ParsedLibraryResultImpl extends AnalysisResultImpl |
| implements ParsedLibraryResult { |
| @override |
| final ResultState state = ResultState.VALID; |
| |
| @override |
| final List<ParsedUnitResult> units; |
| |
| ParsedLibraryResultImpl( |
| AnalysisSession session, String path, Uri uri, this.units) |
| : super(session, path, uri); |
| |
| @Deprecated('This factory exists temporary until AnalysisSession migration.') |
| factory ParsedLibraryResultImpl.tmp(LibraryElement library) { |
| var libraryPath = library.source.fullName; |
| var analysisContext = library.context; |
| var units = <ParsedUnitResult>[]; |
| for (var unitElement in library.units) { |
| var unitSource = unitElement.source; |
| |
| if (!analysisContext.exists(unitSource)) { |
| continue; |
| } |
| |
| var content = analysisContext.getContents(unitSource).data; |
| var lineInfo = analysisContext.getLineInfo(unitSource); |
| var unit = analysisContext.parseCompilationUnit(unitSource); |
| units.add(ParsedUnitResultImpl(null, unitSource.fullName, unitSource.uri, |
| content, lineInfo, unitSource != library.source, unit, const [])); |
| } |
| return ParsedLibraryResultImpl( |
| null, libraryPath, library.source.uri, units); |
| } |
| |
| @override |
| ElementDeclarationResult getElementDeclaration(Element element) { |
| var elementPath = element.source.fullName; |
| var unitResult = units.firstWhere( |
| (r) => r.path == elementPath, |
| orElse: () { |
| throw ArgumentError('Element (${element.runtimeType}) $element is not ' |
| 'defined in this library.'); |
| }, |
| ); |
| |
| if (element.isSynthetic || element.nameOffset == -1) { |
| return null; |
| } |
| |
| var locator = NodeLocator2(element.nameOffset); |
| var node = locator.searchWithin(unitResult.unit)?.parent; |
| return ElementDeclarationResultImpl(element, node, unitResult, null); |
| } |
| } |
| |
| class ParsedUnitResultImpl extends FileResultImpl implements ParsedUnitResult { |
| @override |
| final String content; |
| |
| @override |
| final CompilationUnit unit; |
| |
| @override |
| final List<AnalysisError> errors; |
| |
| ParsedUnitResultImpl(AnalysisSession session, String path, Uri uri, |
| this.content, LineInfo lineInfo, bool isPart, this.unit, this.errors) |
| : super(session, path, uri, lineInfo, isPart); |
| |
| @override |
| ResultState get state => ResultState.VALID; |
| } |
| |
| class ResolvedLibraryResultImpl extends AnalysisResultImpl |
| implements ResolvedLibraryResult { |
| @override |
| final LibraryElement element; |
| |
| @override |
| final TypeProvider typeProvider; |
| |
| @override |
| final List<ResolvedUnitResult> units; |
| |
| ResolvedLibraryResultImpl(AnalysisSession session, String path, Uri uri, |
| this.element, this.typeProvider, this.units) |
| : super(session, path, uri); |
| |
| ResolvedLibraryResultImpl.external(AnalysisSession session, Uri uri) |
| : this(session, null, uri, null, null, null); |
| |
| @override |
| ResultState get state { |
| if (path == null) { |
| return ResultState.NOT_A_FILE; |
| } |
| return ResultState.VALID; |
| } |
| |
| @override |
| ElementDeclarationResult getElementDeclaration(Element element) { |
| if (state != ResultState.VALID) { |
| throw StateError('The result is not valid: $state'); |
| } |
| |
| var elementPath = element.source.fullName; |
| var unitResult = units.firstWhere( |
| (r) => r.path == elementPath, |
| orElse: () { |
| throw ArgumentError('Element (${element.runtimeType}) $element is not ' |
| 'defined in this library.'); |
| }, |
| ); |
| |
| if (element.isSynthetic || element.nameOffset == -1) { |
| return null; |
| } |
| |
| var locator = NodeLocator2(element.nameOffset); |
| var node = locator.searchWithin(unitResult.unit)?.parent; |
| return ElementDeclarationResultImpl(element, node, null, unitResult); |
| } |
| |
| @Deprecated('This method exists temporary until AnalysisSession migration.') |
| static Future<ResolvedLibraryResult> tmp(LibraryElement library) async { |
| var libraryPath = library.source.fullName; |
| var units = <ResolvedUnitResult>[]; |
| var analysisContext = library.context; |
| for (var unitElement in library.units) { |
| var unitSource = unitElement.source; |
| |
| if (!analysisContext.exists(unitSource)) { |
| continue; |
| } |
| |
| var path = unitSource.fullName; |
| var content = analysisContext.getContents(unitSource).data; |
| var lineInfo = analysisContext.getLineInfo(unitSource); |
| var unit = analysisContext.resolveCompilationUnit(unitSource, library); |
| units.add(ResolvedUnitResultImpl(null, path, unitSource.uri, true, |
| content, lineInfo, unitSource != library.source, unit, const [])); |
| } |
| return ResolvedLibraryResultImpl(null, libraryPath, library.source.uri, |
| library, library.context.typeProvider, units); |
| } |
| } |
| |
| class ResolvedUnitResultImpl extends FileResultImpl |
| implements ResolvedUnitResult { |
| /// Return `true` if the file exists. |
| final bool exists; |
| |
| @override |
| final String content; |
| |
| @override |
| final CompilationUnit unit; |
| |
| @override |
| final List<AnalysisError> errors; |
| |
| ResolvedUnitResultImpl( |
| AnalysisSession session, |
| String path, |
| Uri uri, |
| this.exists, |
| this.content, |
| LineInfo lineInfo, |
| bool isPart, |
| this.unit, |
| this.errors) |
| : super(session, path, uri, lineInfo, isPart); |
| |
| @override |
| LibraryElement get libraryElement => unit.declaredElement.library; |
| |
| @override |
| ResultState get state => exists ? ResultState.VALID : ResultState.NOT_A_FILE; |
| |
| @override |
| TypeProvider get typeProvider => unit.declaredElement.context.typeProvider; |
| |
| @override |
| TypeSystem get typeSystem => unit.declaredElement.context.typeSystem; |
| } |
| |
| class UnitElementResultImpl extends AnalysisResultImpl |
| implements UnitElementResult { |
| @override |
| final String signature; |
| |
| @override |
| final CompilationUnitElement element; |
| |
| UnitElementResultImpl(AnalysisSession session, String path, Uri uri, |
| this.signature, this.element) |
| : super(session, path, uri); |
| |
| @override |
| ResultState get state => ResultState.VALID; |
| } |