blob: 87ec58a6cf4c4ec4b0fb4a91eb2597439b513274 [file] [log] [blame]
// 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 'dart:async';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/element/element.dart';
/// A wrapper around [AnalysisSession] that provides additional utilities.
///
/// The methods in this class that return analysis results will throw an
/// [InconsistentAnalysisException] if the result to be returned might be
/// inconsistent with any previously returned results.
class AnalysisSessionHelper {
final AnalysisSession session;
final Map<String, ResolvedLibraryResult> _resolvedLibraries = {};
AnalysisSessionHelper(this.session);
/// Return the [ClassElement] with the given [className] that is exported
/// from the library with the given [libraryUri], or `null` if the library
/// does not export a class with such name.
Future<ClassElement> getClass(String libraryUri, String className) async {
var libraryElement = await session.getLibraryByUri(libraryUri);
var element = libraryElement.exportNamespace.get(className);
if (element is ClassElement) {
return element;
} else {
return null;
}
}
/// Return the declaration of the [element], or `null` is the [element]
/// is synthetic, or is declared in a file that is not a part of a library.
Future<ElementDeclarationResult> getElementDeclaration(
Element element) async {
var libraryPath = element.library.source.fullName;
// This should not happen in valid code, but sometimes we treat a file
// with a `part of` directive as a library, because there is no library
// that contains this part, or because it is imported as a library.
if (isPart(libraryPath)) {
return null;
}
var resolvedLibrary = await _getResolvedLibrary(libraryPath);
return resolvedLibrary.getElementDeclaration(element);
}
/// Return the resolved unit that declares the given [element].
Future<ResolvedUnitResult> getResolvedUnitByElement(Element element) async {
var libraryPath = element.library.source.fullName;
var resolvedLibrary = await _getResolvedLibrary(libraryPath);
var unitPath = element.source.fullName;
return resolvedLibrary.units.singleWhere((resolvedUnit) {
return resolvedUnit.path == unitPath;
});
}
/// Return the [PropertyAccessorElement] with the given [name] that is
/// exported from the library with the given [uri], or `null` if the
/// library does not export a top-level accessor with such name.
Future<PropertyAccessorElement> getTopLevelPropertyAccessor(
String uri, String name) async {
var libraryElement = await session.getLibraryByUri(uri);
var element = libraryElement.exportNamespace.get(name);
if (element is PropertyAccessorElement) {
return element;
} else {
return null;
}
}
/// Return `true` if the file with the [path] is a part.
bool isPart(String path) {
return session.getFile(path).isPart;
}
/// Return a newly resolved, or cached library with the given [path].
Future<ResolvedLibraryResult> _getResolvedLibrary(String path) async {
var result = _resolvedLibraries[path];
if (result == null) {
result = await session.getResolvedLibrary(path);
_resolvedLibraries[path] = result;
}
return result;
}
}