c9d1c4a3b7
As opposite to constructing AST nodes and calling partial resolvers. Also the set of tests that we created for CFE integration is too large, so I started splitting it into pieces and cleaning up to use findNode, fincElement, and assertElement/Type(). R=brianwilkerson@google.com, paulberry@google.com Change-Id: Ide4f0bee9e89eb2daf2317d1d92303a992847f1b Reviewed-on: https://dart-review.googlesource.com/72240 Reviewed-by: Paul Berry <paulberry@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
585 lines
24 KiB
Dart
585 lines
24 KiB
Dart
// Copyright (c) 2016, 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:collection';
|
|
|
|
import 'package:analyzer/dart/ast/ast.dart';
|
|
import 'package:analyzer/dart/ast/token.dart';
|
|
import 'package:analyzer/dart/element/element.dart';
|
|
import 'package:analyzer/dart/element/type.dart';
|
|
import 'package:analyzer/file_system/file_system.dart';
|
|
import 'package:analyzer/file_system/memory_file_system.dart';
|
|
import 'package:analyzer/file_system/physical_file_system.dart';
|
|
import 'package:analyzer/src/context/context.dart';
|
|
import 'package:analyzer/src/dart/element/element.dart';
|
|
import 'package:analyzer/src/dart/element/type.dart';
|
|
import 'package:analyzer/src/dart/sdk/sdk.dart';
|
|
import 'package:analyzer/src/file_system/file_system.dart';
|
|
import 'package:analyzer/src/generated/engine.dart';
|
|
import 'package:analyzer/src/generated/resolver.dart';
|
|
import 'package:analyzer/src/generated/sdk.dart';
|
|
import 'package:analyzer/src/generated/source_io.dart';
|
|
import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
|
|
import 'package:analyzer/src/generated/testing/element_factory.dart';
|
|
import 'package:analyzer/src/generated/testing/test_type_provider.dart';
|
|
import 'package:analyzer/src/generated/utilities_dart.dart';
|
|
import 'package:analyzer/src/string_source.dart';
|
|
import 'package:test/test.dart';
|
|
|
|
/**
|
|
* The class `AnalysisContextFactory` defines utility methods used to create analysis contexts
|
|
* for testing purposes.
|
|
*/
|
|
class AnalysisContextFactory {
|
|
static String _DART_MATH = "dart:math";
|
|
|
|
static String _DART_INTERCEPTORS = "dart:_interceptors";
|
|
|
|
static String _DART_JS_HELPER = "dart:_js_helper";
|
|
|
|
/**
|
|
* Create and return an analysis context that has a fake core library already
|
|
* resolved. The given [resourceProvider] will be used when accessing the file
|
|
* system.
|
|
*/
|
|
static InternalAnalysisContext contextWithCore(
|
|
{UriResolver contributedResolver, ResourceProvider resourceProvider}) {
|
|
AnalysisContextForTests context = new AnalysisContextForTests();
|
|
return initContextWithCore(context, contributedResolver, resourceProvider);
|
|
}
|
|
|
|
/**
|
|
* Create and return an analysis context that uses the given [options] and has
|
|
* a fake core library already resolved. The given [resourceProvider] will be
|
|
* used when accessing the file system.
|
|
*/
|
|
static InternalAnalysisContext contextWithCoreAndOptions(
|
|
AnalysisOptions options,
|
|
{ResourceProvider resourceProvider}) {
|
|
AnalysisContextForTests context = new AnalysisContextForTests();
|
|
context._internalSetAnalysisOptions(options);
|
|
return initContextWithCore(context, null, resourceProvider);
|
|
}
|
|
|
|
/**
|
|
* Create and return an analysis context that has a fake core library already
|
|
* resolved. If not `null`, the given [packages] map will be used to create a
|
|
* package URI resolver. The given [resourceProvider] will be used when
|
|
* accessing the file system.
|
|
*/
|
|
static InternalAnalysisContext contextWithCoreAndPackages(
|
|
Map<String, String> packages,
|
|
{ResourceProvider resourceProvider}) {
|
|
AnalysisContextForTests context = new AnalysisContextForTests();
|
|
return initContextWithCore(
|
|
context, new TestPackageUriResolver(packages), resourceProvider);
|
|
}
|
|
|
|
/**
|
|
* Initialize the given analysis [context] with a fake core library that has
|
|
* already been resolved. If not `null`, the given [contributedResolver] will
|
|
* be added to the context's source factory. The given [resourceProvider] will
|
|
* be used when accessing the file system.
|
|
*/
|
|
static InternalAnalysisContext initContextWithCore(
|
|
InternalAnalysisContext context,
|
|
[UriResolver contributedResolver,
|
|
ResourceProvider resourceProvider]) {
|
|
resourceProvider ??= PhysicalResourceProvider.INSTANCE;
|
|
DartSdk sdk = new _AnalysisContextFactory_initContextWithCore(
|
|
resourceProvider, '/fake/sdk');
|
|
List<UriResolver> resolvers = <UriResolver>[
|
|
new DartUriResolver(sdk),
|
|
new ResourceUriResolver(resourceProvider)
|
|
];
|
|
if (contributedResolver != null) {
|
|
resolvers.add(contributedResolver);
|
|
}
|
|
SourceFactory sourceFactory = new SourceFactory(resolvers);
|
|
context.sourceFactory = sourceFactory;
|
|
AnalysisContext coreContext = sdk.context;
|
|
//
|
|
// dart:core
|
|
//
|
|
TestTypeProvider provider = new TestTypeProvider();
|
|
CompilationUnitElementImpl coreUnit =
|
|
new CompilationUnitElementImpl("core.dart");
|
|
Source coreSource = sourceFactory.forUri(DartSdk.DART_CORE);
|
|
coreContext.setContents(coreSource, "");
|
|
coreUnit.librarySource = coreUnit.source = coreSource;
|
|
ClassElementImpl overrideClassElement =
|
|
ElementFactory.classElement2("_Override");
|
|
ClassElementImpl proxyClassElement = ElementFactory.classElement2("_Proxy");
|
|
proxyClassElement.constructors = <ConstructorElement>[
|
|
ElementFactory.constructorElement(proxyClassElement, '', true)
|
|
..isCycleFree = true
|
|
..constantInitializers = <ConstructorInitializer>[]
|
|
];
|
|
ClassElement objectClassElement = provider.objectType.element;
|
|
coreUnit.types = <ClassElement>[
|
|
provider.boolType.element,
|
|
provider.deprecatedType.element,
|
|
provider.doubleType.element,
|
|
provider.functionType.element,
|
|
provider.intType.element,
|
|
provider.iterableType.element,
|
|
provider.iteratorType.element,
|
|
provider.listType.element,
|
|
provider.mapType.element,
|
|
provider.nullType.element,
|
|
provider.numType.element,
|
|
objectClassElement,
|
|
overrideClassElement,
|
|
proxyClassElement,
|
|
provider.stackTraceType.element,
|
|
provider.stringType.element,
|
|
provider.symbolType.element,
|
|
provider.typeType.element
|
|
];
|
|
coreUnit.functions = <FunctionElement>[
|
|
ElementFactory.functionElement3("identical", provider.boolType,
|
|
<ClassElement>[objectClassElement, objectClassElement], null),
|
|
ElementFactory.functionElement3("print", VoidTypeImpl.instance,
|
|
<ClassElement>[objectClassElement], null)
|
|
];
|
|
TopLevelVariableElement proxyTopLevelVariableElt =
|
|
ElementFactory.topLevelVariableElement3(
|
|
"proxy", true, false, proxyClassElement.type);
|
|
ConstTopLevelVariableElementImpl deprecatedTopLevelVariableElt =
|
|
ElementFactory.topLevelVariableElement3(
|
|
"deprecated", true, false, provider.deprecatedType);
|
|
TopLevelVariableElement overrideTopLevelVariableElt =
|
|
ElementFactory.topLevelVariableElement3(
|
|
"override", true, false, overrideClassElement.type);
|
|
{
|
|
ClassElement deprecatedElement = provider.deprecatedType.element;
|
|
InstanceCreationExpression initializer =
|
|
AstTestFactory.instanceCreationExpression2(
|
|
Keyword.CONST,
|
|
AstTestFactory.typeName(deprecatedElement),
|
|
[AstTestFactory.string2('next release')]);
|
|
ConstructorElement constructor = deprecatedElement.constructors.single;
|
|
initializer.staticElement = constructor;
|
|
initializer.constructorName.staticElement = constructor;
|
|
deprecatedTopLevelVariableElt.constantInitializer = initializer;
|
|
}
|
|
coreUnit.accessors = <PropertyAccessorElement>[
|
|
deprecatedTopLevelVariableElt.getter,
|
|
overrideTopLevelVariableElt.getter,
|
|
proxyTopLevelVariableElt.getter
|
|
];
|
|
coreUnit.topLevelVariables = <TopLevelVariableElement>[
|
|
deprecatedTopLevelVariableElt,
|
|
overrideTopLevelVariableElt,
|
|
proxyTopLevelVariableElt
|
|
];
|
|
LibraryElementImpl coreLibrary = new LibraryElementImpl.forNode(
|
|
coreContext, AstTestFactory.libraryIdentifier2(["dart", "core"]));
|
|
coreLibrary.definingCompilationUnit = coreUnit;
|
|
//
|
|
// dart:async
|
|
//
|
|
LibraryElementImpl asyncLibrary = new LibraryElementImpl.forNode(
|
|
coreContext, AstTestFactory.libraryIdentifier2(["dart", "async"]));
|
|
CompilationUnitElementImpl asyncUnit =
|
|
new CompilationUnitElementImpl("async.dart");
|
|
Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
|
|
coreContext.setContents(asyncSource, "");
|
|
asyncUnit.librarySource = asyncUnit.source = asyncSource;
|
|
asyncLibrary.definingCompilationUnit = asyncUnit;
|
|
// Future<T>
|
|
ClassElementImpl futureElement =
|
|
ElementFactory.classElement2("Future", ["T"]);
|
|
// FutureOr<T>
|
|
ClassElementImpl futureOrElement =
|
|
ElementFactory.classElement2("FutureOr", ["T"]);
|
|
futureElement.enclosingElement = asyncUnit;
|
|
// factory Future.value([value])
|
|
ConstructorElementImpl futureConstructor =
|
|
ElementFactory.constructorElement2(futureElement, "value");
|
|
futureConstructor.parameters = <ParameterElement>[
|
|
ElementFactory.positionalParameter2("value", provider.dynamicType)
|
|
];
|
|
futureConstructor.factory = true;
|
|
futureElement.constructors = <ConstructorElement>[futureConstructor];
|
|
// Future<R> then<R>(FutureOr<R> onValue(T value), { Function onError });
|
|
TypeDefiningElement futureThenR = DynamicElementImpl.instance;
|
|
DartType onValueReturnType = DynamicTypeImpl.instance;
|
|
futureThenR = ElementFactory.typeParameterWithType('R');
|
|
onValueReturnType = futureOrElement.type.instantiate([futureThenR.type]);
|
|
FunctionElementImpl thenOnValue = ElementFactory.functionElement3(
|
|
'onValue', onValueReturnType, [futureElement.typeParameters[0]], null);
|
|
thenOnValue.isSynthetic = true;
|
|
|
|
DartType futureRType = futureElement.type.instantiate([futureThenR.type]);
|
|
MethodElementImpl thenMethod = ElementFactory.methodElementWithParameters(
|
|
futureElement, "then", futureRType, [
|
|
ElementFactory.requiredParameter2("onValue", thenOnValue.type),
|
|
ElementFactory.namedParameter2("onError", provider.functionType)
|
|
]);
|
|
if (!futureThenR.type.isDynamic) {
|
|
thenMethod.typeParameters = <TypeParameterElement>[futureThenR];
|
|
}
|
|
thenOnValue.enclosingElement = thenMethod;
|
|
thenOnValue.type = new FunctionTypeImpl(thenOnValue);
|
|
(thenMethod.parameters[0] as ParameterElementImpl).type = thenOnValue.type;
|
|
thenMethod.type = new FunctionTypeImpl(thenMethod);
|
|
|
|
futureElement.methods = <MethodElement>[thenMethod];
|
|
// Completer
|
|
ClassElementImpl completerElement =
|
|
ElementFactory.classElement2("Completer", ["T"]);
|
|
ConstructorElementImpl completerConstructor =
|
|
ElementFactory.constructorElement2(completerElement, null);
|
|
completerElement.constructors = <ConstructorElement>[completerConstructor];
|
|
// StreamSubscription
|
|
ClassElementImpl streamSubscriptionElement =
|
|
ElementFactory.classElement2("StreamSubscription", ["T"]);
|
|
// Stream
|
|
ClassElementImpl streamElement =
|
|
ElementFactory.classElement2("Stream", ["T"]);
|
|
streamElement.abstract = true;
|
|
streamElement.constructors = <ConstructorElement>[
|
|
ElementFactory.constructorElement2(streamElement, null)
|
|
];
|
|
DartType returnType = streamSubscriptionElement.type
|
|
.instantiate(streamElement.type.typeArguments);
|
|
FunctionElementImpl listenOnData = ElementFactory.functionElement3(
|
|
'onData',
|
|
VoidTypeImpl.instance,
|
|
<TypeDefiningElement>[streamElement.typeParameters[0]],
|
|
null);
|
|
listenOnData.isSynthetic = true;
|
|
List<DartType> parameterTypes = <DartType>[
|
|
listenOnData.type,
|
|
];
|
|
// TODO(brianwilkerson) This is missing the optional parameters.
|
|
MethodElementImpl listenMethod =
|
|
ElementFactory.methodElement('listen', returnType, parameterTypes);
|
|
streamElement.methods = <MethodElement>[listenMethod];
|
|
listenMethod.type = new FunctionTypeImpl(listenMethod);
|
|
|
|
FunctionElementImpl listenParamFunction = parameterTypes[0].element;
|
|
listenParamFunction.enclosingElement = listenMethod;
|
|
listenParamFunction.type = new FunctionTypeImpl(listenParamFunction);
|
|
ParameterElementImpl listenParam = listenMethod.parameters[0];
|
|
listenParam.type = listenParamFunction.type;
|
|
|
|
asyncUnit.types = <ClassElement>[
|
|
completerElement,
|
|
futureElement,
|
|
futureOrElement,
|
|
streamElement,
|
|
streamSubscriptionElement
|
|
];
|
|
//
|
|
// dart:html
|
|
//
|
|
CompilationUnitElementImpl htmlUnit =
|
|
new CompilationUnitElementImpl("html_dartium.dart");
|
|
Source htmlSource = sourceFactory.forUri(DartSdk.DART_HTML);
|
|
coreContext.setContents(htmlSource, "");
|
|
htmlUnit.librarySource = htmlUnit.source = htmlSource;
|
|
ClassElementImpl elementElement = ElementFactory.classElement2("Element");
|
|
InterfaceType elementType = elementElement.type;
|
|
ClassElementImpl canvasElement =
|
|
ElementFactory.classElement("CanvasElement", elementType);
|
|
ClassElementImpl contextElement =
|
|
ElementFactory.classElement2("CanvasRenderingContext");
|
|
InterfaceType contextElementType = contextElement.type;
|
|
ClassElementImpl context2dElement = ElementFactory.classElement(
|
|
"CanvasRenderingContext2D", contextElementType);
|
|
canvasElement.methods = <MethodElement>[
|
|
ElementFactory.methodElement(
|
|
"getContext", contextElementType, [provider.stringType])
|
|
];
|
|
canvasElement.accessors = <PropertyAccessorElement>[
|
|
ElementFactory.getterElement("context2D", false, context2dElement.type)
|
|
];
|
|
canvasElement.fields = canvasElement.accessors
|
|
.map((PropertyAccessorElement accessor) => accessor.variable)
|
|
.cast<FieldElement>()
|
|
.toList();
|
|
ClassElementImpl documentElement =
|
|
ElementFactory.classElement("Document", elementType);
|
|
ClassElementImpl htmlDocumentElement =
|
|
ElementFactory.classElement("HtmlDocument", documentElement.type);
|
|
htmlDocumentElement.methods = <MethodElement>[
|
|
ElementFactory.methodElement(
|
|
"query", elementType, <DartType>[provider.stringType])
|
|
];
|
|
htmlUnit.types = <ClassElement>[
|
|
ElementFactory.classElement("AnchorElement", elementType),
|
|
ElementFactory.classElement("BodyElement", elementType),
|
|
ElementFactory.classElement("ButtonElement", elementType),
|
|
canvasElement,
|
|
contextElement,
|
|
context2dElement,
|
|
ElementFactory.classElement("DivElement", elementType),
|
|
documentElement,
|
|
elementElement,
|
|
htmlDocumentElement,
|
|
ElementFactory.classElement("InputElement", elementType),
|
|
ElementFactory.classElement("SelectElement", elementType)
|
|
];
|
|
htmlUnit.functions = <FunctionElement>[
|
|
ElementFactory.functionElement3("query", elementElement.type,
|
|
<ClassElement>[provider.stringType.element], const <ClassElement>[])
|
|
];
|
|
TopLevelVariableElementImpl document =
|
|
ElementFactory.topLevelVariableElement3(
|
|
"document", false, true, htmlDocumentElement.type);
|
|
htmlUnit.topLevelVariables = <TopLevelVariableElement>[document];
|
|
htmlUnit.accessors = <PropertyAccessorElement>[document.getter];
|
|
LibraryElementImpl htmlLibrary = new LibraryElementImpl.forNode(coreContext,
|
|
AstTestFactory.libraryIdentifier2(["dart", "dom", "html"]));
|
|
htmlLibrary.definingCompilationUnit = htmlUnit;
|
|
//
|
|
// dart:math
|
|
//
|
|
CompilationUnitElementImpl mathUnit =
|
|
new CompilationUnitElementImpl("math.dart");
|
|
Source mathSource = sourceFactory.forUri(_DART_MATH);
|
|
coreContext.setContents(mathSource, "");
|
|
mathUnit.librarySource = mathUnit.source = mathSource;
|
|
FunctionElement cosElement = ElementFactory.functionElement3(
|
|
"cos",
|
|
provider.doubleType,
|
|
<ClassElement>[provider.numType.element],
|
|
const <ClassElement>[]);
|
|
TopLevelVariableElement ln10Element =
|
|
ElementFactory.topLevelVariableElement3(
|
|
"LN10", true, false, provider.doubleType);
|
|
TypeParameterElement maxT =
|
|
ElementFactory.typeParameterWithType('T', provider.numType);
|
|
FunctionElementImpl maxElement = ElementFactory.functionElement3(
|
|
"max", maxT.type, [maxT, maxT], const <ClassElement>[]);
|
|
maxElement.typeParameters = [maxT];
|
|
maxElement.type = new FunctionTypeImpl(maxElement);
|
|
TopLevelVariableElement piElement = ElementFactory.topLevelVariableElement3(
|
|
"PI", true, false, provider.doubleType);
|
|
ClassElementImpl randomElement = ElementFactory.classElement2("Random");
|
|
randomElement.abstract = true;
|
|
ConstructorElementImpl randomConstructor =
|
|
ElementFactory.constructorElement2(randomElement, null);
|
|
randomConstructor.factory = true;
|
|
ParameterElementImpl seedParam = new ParameterElementImpl("seed", 0);
|
|
seedParam.parameterKind = ParameterKind.POSITIONAL;
|
|
seedParam.type = provider.intType;
|
|
randomConstructor.parameters = <ParameterElement>[seedParam];
|
|
randomElement.constructors = <ConstructorElement>[randomConstructor];
|
|
FunctionElement sinElement = ElementFactory.functionElement3(
|
|
"sin",
|
|
provider.doubleType,
|
|
<ClassElement>[provider.numType.element],
|
|
const <ClassElement>[]);
|
|
FunctionElement sqrtElement = ElementFactory.functionElement3(
|
|
"sqrt",
|
|
provider.doubleType,
|
|
<ClassElement>[provider.numType.element],
|
|
const <ClassElement>[]);
|
|
mathUnit.accessors = <PropertyAccessorElement>[
|
|
ln10Element.getter,
|
|
piElement.getter
|
|
];
|
|
mathUnit.functions = <FunctionElement>[
|
|
cosElement,
|
|
maxElement,
|
|
sinElement,
|
|
sqrtElement
|
|
];
|
|
mathUnit.topLevelVariables = <TopLevelVariableElement>[
|
|
ln10Element,
|
|
piElement
|
|
];
|
|
mathUnit.types = <ClassElement>[randomElement];
|
|
LibraryElementImpl mathLibrary = new LibraryElementImpl.forNode(
|
|
coreContext, AstTestFactory.libraryIdentifier2(["dart", "math"]));
|
|
mathLibrary.definingCompilationUnit = mathUnit;
|
|
//
|
|
// Set empty sources for the rest of the libraries.
|
|
//
|
|
Source source = sourceFactory.forUri(_DART_INTERCEPTORS);
|
|
coreContext.setContents(source, "");
|
|
source = sourceFactory.forUri(_DART_JS_HELPER);
|
|
coreContext.setContents(source, "");
|
|
//
|
|
// Record the elements.
|
|
//
|
|
Map<Source, LibraryElement> elementMap =
|
|
new HashMap<Source, LibraryElement>();
|
|
elementMap[coreSource] = coreLibrary;
|
|
if (asyncSource != null) {
|
|
elementMap[asyncSource] = asyncLibrary;
|
|
}
|
|
elementMap[htmlSource] = htmlLibrary;
|
|
elementMap[mathSource] = mathLibrary;
|
|
//
|
|
// Set the public and export namespaces. We don't use exports in the fake
|
|
// core library so public and export namespaces are the same.
|
|
//
|
|
for (LibraryElementImpl library in elementMap.values) {
|
|
Namespace namespace =
|
|
new NamespaceBuilder().createPublicNamespaceForLibrary(library);
|
|
library.exportNamespace = namespace;
|
|
library.publicNamespace = namespace;
|
|
}
|
|
context.recordLibraryElements(elementMap);
|
|
// Create the synthetic element for `loadLibrary`.
|
|
for (LibraryElementImpl library in elementMap.values) {
|
|
library.createLoadLibraryFunction(context.typeProvider);
|
|
}
|
|
return context;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* An analysis context that has a fake SDK that is much smaller and faster for
|
|
* testing purposes.
|
|
*/
|
|
class AnalysisContextForTests extends AnalysisContextImpl {
|
|
@override
|
|
void set analysisOptions(AnalysisOptions options) {
|
|
AnalysisOptions currentOptions = analysisOptions;
|
|
bool needsRecompute = currentOptions.analyzeFunctionBodiesPredicate !=
|
|
options.analyzeFunctionBodiesPredicate ||
|
|
currentOptions.generateImplicitErrors !=
|
|
options.generateImplicitErrors ||
|
|
currentOptions.generateSdkErrors != options.generateSdkErrors ||
|
|
currentOptions.dart2jsHint != options.dart2jsHint ||
|
|
(currentOptions.hint && !options.hint) ||
|
|
currentOptions.preserveComments != options.preserveComments;
|
|
if (needsRecompute) {
|
|
fail(
|
|
"Cannot set options that cause the sources to be reanalyzed in a test context");
|
|
}
|
|
super.analysisOptions = options;
|
|
}
|
|
|
|
@override
|
|
bool exists(Source source) =>
|
|
super.exists(source) || sourceFactory.dartSdk.context.exists(source);
|
|
|
|
@override
|
|
TimestampedData<String> getContents(Source source) {
|
|
if (source.isInSystemLibrary) {
|
|
return sourceFactory.dartSdk.context.getContents(source);
|
|
}
|
|
return super.getContents(source);
|
|
}
|
|
|
|
@override
|
|
int getModificationStamp(Source source) {
|
|
if (source.isInSystemLibrary) {
|
|
return sourceFactory.dartSdk.context.getModificationStamp(source);
|
|
}
|
|
return super.getModificationStamp(source);
|
|
}
|
|
|
|
/**
|
|
* Set the analysis options, even if they would force re-analysis. This method should only be
|
|
* invoked before the fake SDK is initialized.
|
|
*
|
|
* @param options the analysis options to be set
|
|
*/
|
|
void _internalSetAnalysisOptions(AnalysisOptions options) {
|
|
super.analysisOptions = options;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper for creating and managing single [AnalysisContext].
|
|
*/
|
|
class AnalysisContextHelper {
|
|
MemoryResourceProvider resourceProvider;
|
|
AnalysisContext context;
|
|
|
|
/**
|
|
* Creates new [AnalysisContext] using [AnalysisContextFactory].
|
|
*/
|
|
AnalysisContextHelper(
|
|
[AnalysisOptionsImpl options, MemoryResourceProvider provider]) {
|
|
resourceProvider = provider ?? new MemoryResourceProvider();
|
|
context = AnalysisContextFactory.contextWithCoreAndOptions(
|
|
options ?? new AnalysisOptionsImpl(),
|
|
resourceProvider: resourceProvider);
|
|
}
|
|
|
|
Source addSource(String path, String code) {
|
|
Source source = resourceProvider
|
|
.getFile(resourceProvider.convertPath(path))
|
|
.createSource();
|
|
if (path.endsWith(".dart") || path.endsWith(".html")) {
|
|
ChangeSet changeSet = new ChangeSet();
|
|
changeSet.addedSource(source);
|
|
context.applyChanges(changeSet);
|
|
}
|
|
context.setContents(source, code);
|
|
return source;
|
|
}
|
|
|
|
CompilationUnitElement getDefiningUnitElement(Source source) =>
|
|
context.getCompilationUnitElement(source, source);
|
|
|
|
CompilationUnit resolveDefiningUnit(Source source) {
|
|
LibraryElement libraryElement = context.computeLibraryElement(source);
|
|
return context.resolveCompilationUnit(source, libraryElement);
|
|
}
|
|
|
|
void runTasks() {
|
|
AnalysisResult result = context.performAnalysisTask();
|
|
while (result.changeNotices != null) {
|
|
result = context.performAnalysisTask();
|
|
}
|
|
}
|
|
}
|
|
|
|
class TestPackageUriResolver extends UriResolver {
|
|
Map<String, Source> sourceMap = new HashMap<String, Source>();
|
|
|
|
TestPackageUriResolver(Map<String, String> map) {
|
|
map.forEach((String uri, String contents) {
|
|
sourceMap[uri] = new StringSource(contents, '/test_pkg_source.dart');
|
|
});
|
|
}
|
|
|
|
@override
|
|
Source resolveAbsolute(Uri uri, [Uri actualUri]) {
|
|
String uriString = uri.toString();
|
|
return sourceMap[uriString];
|
|
}
|
|
|
|
@override
|
|
Uri restoreAbsolute(Source source) => throw new UnimplementedError();
|
|
}
|
|
|
|
class _AnalysisContextFactory_initContextWithCore extends FolderBasedDartSdk {
|
|
_AnalysisContextFactory_initContextWithCore(
|
|
ResourceProvider resourceProvider, String sdkPath)
|
|
: super(resourceProvider, resourceProvider.getFolder(sdkPath));
|
|
|
|
@override
|
|
LibraryMap initialLibraryMap(bool useDart2jsPaths) {
|
|
LibraryMap map = new LibraryMap();
|
|
_addLibrary(map, DartSdk.DART_ASYNC, false, "async.dart");
|
|
_addLibrary(map, DartSdk.DART_CORE, false, "core.dart");
|
|
_addLibrary(map, DartSdk.DART_HTML, false, "html_dartium.dart");
|
|
_addLibrary(map, AnalysisContextFactory._DART_MATH, false, "math.dart");
|
|
_addLibrary(map, AnalysisContextFactory._DART_INTERCEPTORS, true,
|
|
"_interceptors.dart");
|
|
_addLibrary(
|
|
map, AnalysisContextFactory._DART_JS_HELPER, true, "_js_helper.dart");
|
|
return map;
|
|
}
|
|
|
|
void _addLibrary(LibraryMap map, String uri, bool isInternal, String path) {
|
|
SdkLibraryImpl library = new SdkLibraryImpl(uri);
|
|
if (isInternal) {
|
|
library.category = "Internal";
|
|
}
|
|
library.path = path;
|
|
map.setLibrary(uri, library);
|
|
}
|
|
}
|