mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:39:49 +00:00
Split resolver_test.dart into smaller files.
R=brianwilkerson@google.com Review URL: https://codereview.chromium.org/1782463002 .
This commit is contained in:
parent
00e6b92e20
commit
8defa5f77c
|
@ -5193,7 +5193,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Check the given [typeReference] and that the [name] is not the reference to
|
||||
* Check the given [typeReference] and that the [name] is not a reference to
|
||||
* an instance member.
|
||||
*
|
||||
* See [StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER].
|
||||
|
|
|
@ -35,7 +35,7 @@ import 'package:unittest/unittest.dart';
|
|||
import '../reflective_tests.dart';
|
||||
import '../utils.dart';
|
||||
import 'parser_test.dart';
|
||||
import 'resolver_test.dart';
|
||||
import 'resolver_test_case.dart';
|
||||
import 'test_support.dart';
|
||||
|
||||
main() {
|
||||
|
|
562
pkg/analyzer/test/generated/analysis_context_factory.dart
Normal file
562
pkg/analyzer/test/generated/analysis_context_factory.dart
Normal file
|
@ -0,0 +1,562 @@
|
|||
// 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.
|
||||
|
||||
library analyzer.test.generated.analysis_context_factory;
|
||||
|
||||
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/src/context/context.dart';
|
||||
import 'package:analyzer/src/dart/element/element.dart';
|
||||
import 'package:analyzer/src/dart/element/type.dart';
|
||||
import 'package:analyzer/src/generated/engine.dart';
|
||||
import 'package:analyzer/src/generated/java_engine_io.dart';
|
||||
import 'package:analyzer/src/generated/java_io.dart';
|
||||
import 'package:analyzer/src/generated/resolver.dart';
|
||||
import 'package:analyzer/src/generated/sdk.dart';
|
||||
import 'package:analyzer/src/generated/sdk_io.dart' show DirectoryBasedDartSdk;
|
||||
import 'package:analyzer/src/generated/source_io.dart';
|
||||
import 'package:analyzer/src/generated/testing/ast_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:unittest/unittest.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 an analysis context that has a fake core library already resolved.
|
||||
* Return the context that was created.
|
||||
*/
|
||||
static InternalAnalysisContext contextWithCore() {
|
||||
AnalysisContextForTests context = new AnalysisContextForTests();
|
||||
return initContextWithCore(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an analysis context that uses the given [options] and has a fake
|
||||
* core library already resolved. Return the context that was created.
|
||||
*/
|
||||
static InternalAnalysisContext contextWithCoreAndOptions(
|
||||
AnalysisOptions options) {
|
||||
AnalysisContextForTests context = new AnalysisContextForTests();
|
||||
context._internalSetAnalysisOptions(options);
|
||||
return initContextWithCore(context);
|
||||
}
|
||||
|
||||
static InternalAnalysisContext contextWithCoreAndPackages(
|
||||
Map<String, String> packages) {
|
||||
AnalysisContextForTests context = new AnalysisContextForTests();
|
||||
return initContextWithCore(context, new TestPackageUriResolver(packages));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the given analysis context with a fake core library already resolved.
|
||||
*
|
||||
* @param context the context to be initialized (not `null`)
|
||||
* @return the analysis context that was created
|
||||
*/
|
||||
static InternalAnalysisContext initContextWithCore(
|
||||
InternalAnalysisContext context,
|
||||
[UriResolver contributedResolver]) {
|
||||
DirectoryBasedDartSdk sdk = new _AnalysisContextFactory_initContextWithCore(
|
||||
new JavaFile("/fake/sdk"),
|
||||
enableAsync: context.analysisOptions.enableAsync);
|
||||
List<UriResolver> resolvers = <UriResolver>[
|
||||
new DartUriResolver(sdk),
|
||||
new FileUriResolver()
|
||||
];
|
||||
if (contributedResolver != null) {
|
||||
resolvers.add(contributedResolver);
|
||||
}
|
||||
SourceFactory sourceFactory = new SourceFactory(resolvers);
|
||||
context.sourceFactory = sourceFactory;
|
||||
AnalysisContext coreContext = sdk.context;
|
||||
(coreContext.analysisOptions as AnalysisOptionsImpl).strongMode =
|
||||
context.analysisOptions.strongMode;
|
||||
//
|
||||
// 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 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,
|
||||
proxyClassElement,
|
||||
provider.stackTraceType.element,
|
||||
provider.stringType.element,
|
||||
provider.symbolType.element,
|
||||
provider.typeType.element
|
||||
];
|
||||
coreUnit.functions = <FunctionElement>[
|
||||
ElementFactory.functionElement3("identical", provider.boolType.element,
|
||||
<ClassElement>[objectClassElement, objectClassElement], null),
|
||||
ElementFactory.functionElement3("print", VoidTypeImpl.instance.element,
|
||||
<ClassElement>[objectClassElement], null)
|
||||
];
|
||||
TopLevelVariableElement proxyTopLevelVariableElt = ElementFactory
|
||||
.topLevelVariableElement3("proxy", true, false, proxyClassElement.type);
|
||||
ConstTopLevelVariableElementImpl deprecatedTopLevelVariableElt =
|
||||
ElementFactory.topLevelVariableElement3(
|
||||
"deprecated", true, false, provider.deprecatedType);
|
||||
{
|
||||
ClassElement deprecatedElement = provider.deprecatedType.element;
|
||||
InstanceCreationExpression initializer = AstFactory
|
||||
.instanceCreationExpression2(
|
||||
Keyword.CONST,
|
||||
AstFactory.typeName(deprecatedElement),
|
||||
[AstFactory.string2('next release')]);
|
||||
ConstructorElement constructor = deprecatedElement.constructors.single;
|
||||
initializer.staticElement = constructor;
|
||||
initializer.constructorName.staticElement = constructor;
|
||||
deprecatedTopLevelVariableElt.constantInitializer = initializer;
|
||||
}
|
||||
coreUnit.accessors = <PropertyAccessorElement>[
|
||||
proxyTopLevelVariableElt.getter,
|
||||
deprecatedTopLevelVariableElt.getter
|
||||
];
|
||||
coreUnit.topLevelVariables = <TopLevelVariableElement>[
|
||||
proxyTopLevelVariableElt,
|
||||
deprecatedTopLevelVariableElt
|
||||
];
|
||||
LibraryElementImpl coreLibrary = new LibraryElementImpl.forNode(
|
||||
coreContext, AstFactory.libraryIdentifier2(["dart", "core"]));
|
||||
coreLibrary.definingCompilationUnit = coreUnit;
|
||||
//
|
||||
// dart:async
|
||||
//
|
||||
Source asyncSource;
|
||||
LibraryElementImpl asyncLibrary;
|
||||
if (context.analysisOptions.enableAsync) {
|
||||
asyncLibrary = new LibraryElementImpl.forNode(
|
||||
coreContext, AstFactory.libraryIdentifier2(["dart", "async"]));
|
||||
CompilationUnitElementImpl asyncUnit =
|
||||
new CompilationUnitElementImpl("async.dart");
|
||||
asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
|
||||
coreContext.setContents(asyncSource, "");
|
||||
asyncUnit.librarySource = asyncUnit.source = asyncSource;
|
||||
asyncLibrary.definingCompilationUnit = asyncUnit;
|
||||
// Future
|
||||
ClassElementImpl futureElement =
|
||||
ElementFactory.classElement2("Future", ["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 then(onValue(T value), { Function onError });
|
||||
TypeDefiningElement futureThenR = DynamicElementImpl.instance;
|
||||
if (context.analysisOptions.strongMode) {
|
||||
futureThenR = ElementFactory.typeParameterWithType('R');
|
||||
}
|
||||
FunctionElementImpl thenOnValue = ElementFactory.functionElement3(
|
||||
'onValue', futureThenR, [futureElement.typeParameters[0]], null);
|
||||
thenOnValue.synthetic = 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 = [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.constructors = <ConstructorElement>[
|
||||
ElementFactory.constructorElement2(streamElement, null)
|
||||
];
|
||||
DartType returnType = streamSubscriptionElement.type
|
||||
.instantiate(streamElement.type.typeArguments);
|
||||
FunctionElementImpl listenOnData = ElementFactory.functionElement3(
|
||||
'onData',
|
||||
VoidTypeImpl.instance.element,
|
||||
<TypeDefiningElement>[streamElement.typeParameters[0]],
|
||||
null);
|
||||
listenOnData.synthetic = 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,
|
||||
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)
|
||||
.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,
|
||||
<ClassElement>[provider.stringType.element], ClassElement.EMPTY_LIST)
|
||||
];
|
||||
TopLevelVariableElementImpl document =
|
||||
ElementFactory.topLevelVariableElement3(
|
||||
"document", false, true, htmlDocumentElement.type);
|
||||
htmlUnit.topLevelVariables = <TopLevelVariableElement>[document];
|
||||
htmlUnit.accessors = <PropertyAccessorElement>[document.getter];
|
||||
LibraryElementImpl htmlLibrary = new LibraryElementImpl.forNode(
|
||||
coreContext, AstFactory.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.element,
|
||||
<ClassElement>[provider.numType.element],
|
||||
ClassElement.EMPTY_LIST);
|
||||
TopLevelVariableElement ln10Element = ElementFactory
|
||||
.topLevelVariableElement3("LN10", true, false, provider.doubleType);
|
||||
TypeParameterElement maxT =
|
||||
ElementFactory.typeParameterWithType('T', provider.numType);
|
||||
FunctionElementImpl maxElement = ElementFactory.functionElement3(
|
||||
"max", maxT, [maxT, maxT], ClassElement.EMPTY_LIST);
|
||||
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.element,
|
||||
<ClassElement>[provider.numType.element],
|
||||
ClassElement.EMPTY_LIST);
|
||||
FunctionElement sqrtElement = ElementFactory.functionElement3(
|
||||
"sqrt",
|
||||
provider.doubleType.element,
|
||||
<ClassElement>[provider.numType.element],
|
||||
ClassElement.EMPTY_LIST);
|
||||
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, AstFactory.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.
|
||||
//
|
||||
HashMap<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 ||
|
||||
currentOptions.enableStrictCallChecks != options.enableStrictCallChecks;
|
||||
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 {
|
||||
AnalysisContext context;
|
||||
|
||||
/**
|
||||
* Creates new [AnalysisContext] using [AnalysisContextFactory].
|
||||
*/
|
||||
AnalysisContextHelper([AnalysisOptionsImpl options]) {
|
||||
if (options == null) {
|
||||
options = new AnalysisOptionsImpl();
|
||||
}
|
||||
options.cacheSize = 256;
|
||||
context = AnalysisContextFactory.contextWithCoreAndOptions(options);
|
||||
}
|
||||
|
||||
Source addSource(String path, String code) {
|
||||
Source source = new FileBasedSource(FileUtilities2.createFile(path));
|
||||
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<Uri, Source> sourceMap = new HashMap<Uri, Source>();
|
||||
|
||||
TestPackageUriResolver(Map<String, String> map) {
|
||||
map.forEach((String uri, String contents) {
|
||||
sourceMap[Uri.parse(uri)] =
|
||||
new StringSource(contents, '/test_pkg_source.dart');
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Source resolveAbsolute(Uri uri, [Uri actualUri]) => sourceMap[uri];
|
||||
|
||||
@override
|
||||
Uri restoreAbsolute(Source source) => throw new UnimplementedError();
|
||||
}
|
||||
|
||||
class _AnalysisContextFactory_initContextWithCore
|
||||
extends DirectoryBasedDartSdk {
|
||||
final bool enableAsync;
|
||||
_AnalysisContextFactory_initContextWithCore(JavaFile arg0,
|
||||
{this.enableAsync: true})
|
||||
: super(arg0);
|
||||
|
||||
@override
|
||||
LibraryMap initialLibraryMap(bool useDart2jsPaths) {
|
||||
LibraryMap map = new LibraryMap();
|
||||
if (enableAsync) {
|
||||
_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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,619 @@
|
|||
// 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.
|
||||
|
||||
library analyzer.test.generated.checked_mode_compile_time_error_code_test;
|
||||
|
||||
import 'package:analyzer/src/generated/error.dart';
|
||||
import 'package:analyzer/src/generated/source_io.dart';
|
||||
|
||||
import '../reflective_tests.dart';
|
||||
import '../utils.dart';
|
||||
import 'resolver_test_case.dart';
|
||||
|
||||
main() {
|
||||
initializeTestEnvironment();
|
||||
runReflectiveTests(CheckedModeCompileTimeErrorCodeTest);
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class CheckedModeCompileTimeErrorCodeTest extends ResolverTestCase {
|
||||
void test_fieldFormalParameterAssignableToField_extends() {
|
||||
// According to checked-mode type checking rules, a value of type B is
|
||||
// assignable to a field of type A, because B extends A (and hence is a
|
||||
// subtype of A).
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A();
|
||||
}
|
||||
class B extends A {
|
||||
const B();
|
||||
}
|
||||
class C {
|
||||
final A a;
|
||||
const C(this.a);
|
||||
}
|
||||
var v = const C(const B());''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertNoErrors(source);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldFormalParameterAssignableToField_fieldType_unresolved_null() {
|
||||
// Null always passes runtime type checks, even when the type is
|
||||
// unresolved.
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
final Unresolved x;
|
||||
const A(String this.x);
|
||||
}
|
||||
var v = const A(null);''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldFormalParameterAssignableToField_implements() {
|
||||
// According to checked-mode type checking rules, a value of type B is
|
||||
// assignable to a field of type A, because B implements A (and hence is a
|
||||
// subtype of A).
|
||||
Source source = addSource(r'''
|
||||
class A {}
|
||||
class B implements A {
|
||||
const B();
|
||||
}
|
||||
class C {
|
||||
final A a;
|
||||
const C(this.a);
|
||||
}
|
||||
var v = const C(const B());''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertNoErrors(source);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldFormalParameterAssignableToField_list_dynamic() {
|
||||
// [1, 2, 3] has type List<dynamic>, which is a subtype of List<int>.
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A(List<int> x);
|
||||
}
|
||||
var x = const A(const [1, 2, 3]);''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertNoErrors(source);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldFormalParameterAssignableToField_list_nonDynamic() {
|
||||
// <int>[1, 2, 3] has type List<int>, which is a subtype of List<num>.
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A(List<num> x);
|
||||
}
|
||||
var x = const A(const <int>[1, 2, 3]);''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertNoErrors(source);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldFormalParameterAssignableToField_map_dynamic() {
|
||||
// {1: 2} has type Map<dynamic, dynamic>, which is a subtype of
|
||||
// Map<int, int>.
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A(Map<int, int> x);
|
||||
}
|
||||
var x = const A(const {1: 2});''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertNoErrors(source);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldFormalParameterAssignableToField_map_keyDifferent() {
|
||||
// <int, int>{1: 2} has type Map<int, int>, which is a subtype of
|
||||
// Map<num, int>.
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A(Map<num, int> x);
|
||||
}
|
||||
var x = const A(const <int, int>{1: 2});''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertNoErrors(source);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldFormalParameterAssignableToField_map_valueDifferent() {
|
||||
// <int, int>{1: 2} has type Map<int, int>, which is a subtype of
|
||||
// Map<int, num>.
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A(Map<int, num> x);
|
||||
}
|
||||
var x = const A(const <int, int>{1: 2});''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertNoErrors(source);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldFormalParameterAssignableToField_notype() {
|
||||
// If a field is declared without a type, then any value may be assigned to
|
||||
// it.
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
final x;
|
||||
const A(this.x);
|
||||
}
|
||||
var v = const A(5);''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertNoErrors(source);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldFormalParameterAssignableToField_null() {
|
||||
// Null is assignable to anything.
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
final int x;
|
||||
const A(this.x);
|
||||
}
|
||||
var v = const A(null);''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertNoErrors(source);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldFormalParameterAssignableToField_typedef() {
|
||||
// foo has the runtime type dynamic -> dynamic, so it should be assignable
|
||||
// to A.f.
|
||||
Source source = addSource(r'''
|
||||
typedef String Int2String(int x);
|
||||
class A {
|
||||
final Int2String f;
|
||||
const A(this.f);
|
||||
}
|
||||
foo(x) => 1;
|
||||
var v = const A(foo);''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertNoErrors(source);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldFormalParameterAssignableToField_typeSubstitution() {
|
||||
// foo has the runtime type dynamic -> dynamic, so it should be assignable
|
||||
// to A.f.
|
||||
Source source = addSource(r'''
|
||||
class A<T> {
|
||||
final T x;
|
||||
const A(this.x);
|
||||
}
|
||||
var v = const A<int>(3);''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertNoErrors(source);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldFormalParameterNotAssignableToField() {
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
final int x;
|
||||
const A(this.x);
|
||||
}
|
||||
var v = const A('foo');''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
|
||||
StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldFormalParameterNotAssignableToField_extends() {
|
||||
// According to checked-mode type checking rules, a value of type A is not
|
||||
// assignable to a field of type B, because B extends A (the subtyping
|
||||
// relationship is in the wrong direction).
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A();
|
||||
}
|
||||
class B extends A {
|
||||
const B();
|
||||
}
|
||||
class C {
|
||||
final B b;
|
||||
const C(this.b);
|
||||
}
|
||||
var v = const C(const A());''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldFormalParameterNotAssignableToField_fieldType() {
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
final int x;
|
||||
const A(String this.x);
|
||||
}
|
||||
var v = const A('foo');''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
|
||||
StaticWarningCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldFormalParameterNotAssignableToField_fieldType_unresolved() {
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
final Unresolved x;
|
||||
const A(String this.x);
|
||||
}
|
||||
var v = const A('foo');''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
|
||||
StaticWarningCode.UNDEFINED_CLASS
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldFormalParameterNotAssignableToField_implements() {
|
||||
// According to checked-mode type checking rules, a value of type A is not
|
||||
// assignable to a field of type B, because B implements A (the subtyping
|
||||
// relationship is in the wrong direction).
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A();
|
||||
}
|
||||
class B implements A {}
|
||||
class C {
|
||||
final B b;
|
||||
const C(this.b);
|
||||
}
|
||||
var v = const C(const A());''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldFormalParameterNotAssignableToField_list() {
|
||||
// <num>[1, 2, 3] has type List<num>, which is not a subtype of List<int>.
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A(List<int> x);
|
||||
}
|
||||
var x = const A(const <num>[1, 2, 3]);''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldFormalParameterNotAssignableToField_map_keyMismatch() {
|
||||
// <num, int>{1: 2} has type Map<num, int>, which is not a subtype of
|
||||
// Map<int, int>.
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A(Map<int, int> x);
|
||||
}
|
||||
var x = const A(const <num, int>{1: 2});''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldFormalParameterNotAssignableToField_map_valueMismatch() {
|
||||
// <int, num>{1: 2} has type Map<int, num>, which is not a subtype of
|
||||
// Map<int, int>.
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A(Map<int, int> x);
|
||||
}
|
||||
var x = const A(const <int, num>{1: 2});''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldFormalParameterNotAssignableToField_optional() {
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
final int x;
|
||||
const A([this.x = 'foo']);
|
||||
}
|
||||
var v = const A();''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
|
||||
StaticTypeWarningCode.INVALID_ASSIGNMENT
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldFormalParameterNotAssignableToField_typedef() {
|
||||
// foo has the runtime type String -> int, so it should not be assignable
|
||||
// to A.f (A.f requires it to be int -> String).
|
||||
Source source = addSource(r'''
|
||||
typedef String Int2String(int x);
|
||||
class A {
|
||||
final Int2String f;
|
||||
const A(this.f);
|
||||
}
|
||||
int foo(String x) => 1;
|
||||
var v = const A(foo);''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
|
||||
StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldInitializerNotAssignable() {
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
final int x;
|
||||
const A() : x = '';
|
||||
}''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE,
|
||||
StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldTypeMismatch() {
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A(x) : y = x;
|
||||
final int y;
|
||||
}
|
||||
var v = const A('foo');''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldTypeMismatch_generic() {
|
||||
Source source = addSource(r'''
|
||||
class C<T> {
|
||||
final T x = y;
|
||||
const C();
|
||||
}
|
||||
const int y = 1;
|
||||
var v = const C<String>();
|
||||
''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
|
||||
StaticTypeWarningCode.INVALID_ASSIGNMENT
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldTypeMismatch_unresolved() {
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A(x) : y = x;
|
||||
final Unresolved y;
|
||||
}
|
||||
var v = const A('foo');''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
|
||||
StaticWarningCode.UNDEFINED_CLASS
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldTypeOk_generic() {
|
||||
Source source = addSource(r'''
|
||||
class C<T> {
|
||||
final T x = y;
|
||||
const C();
|
||||
}
|
||||
const int y = 1;
|
||||
var v = const C<int>();
|
||||
''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldTypeOk_null() {
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A(x) : y = x;
|
||||
final int y;
|
||||
}
|
||||
var v = const A(null);''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertNoErrors(source);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_fieldTypeOk_unresolved_null() {
|
||||
// Null always passes runtime type checks, even when the type is
|
||||
// unresolved.
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A(x) : y = x;
|
||||
final Unresolved y;
|
||||
}
|
||||
var v = const A(null);''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_listElementTypeNotAssignable() {
|
||||
Source source = addSource("var v = const <String> [42];");
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE,
|
||||
StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_mapKeyTypeNotAssignable() {
|
||||
Source source = addSource("var v = const <String, int > {1 : 2};");
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
|
||||
StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_mapValueTypeNotAssignable() {
|
||||
Source source = addSource("var v = const <String, String> {'a' : 2};");
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
|
||||
StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_parameterAssignable_null() {
|
||||
// Null is assignable to anything.
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A(int x);
|
||||
}
|
||||
var v = const A(null);''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertNoErrors(source);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_parameterAssignable_typeSubstitution() {
|
||||
Source source = addSource(r'''
|
||||
class A<T> {
|
||||
const A(T x);
|
||||
}
|
||||
var v = const A<int>(3);''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertNoErrors(source);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_parameterAssignable_undefined_null() {
|
||||
// Null always passes runtime type checks, even when the type is
|
||||
// unresolved.
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A(Unresolved x);
|
||||
}
|
||||
var v = const A(null);''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_parameterNotAssignable() {
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A(int x);
|
||||
}
|
||||
var v = const A('foo');''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
|
||||
StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_parameterNotAssignable_typeSubstitution() {
|
||||
Source source = addSource(r'''
|
||||
class A<T> {
|
||||
const A(T x);
|
||||
}
|
||||
var v = const A<int>('foo');''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
|
||||
StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_parameterNotAssignable_undefined() {
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A(Unresolved x);
|
||||
}
|
||||
var v = const A('foo');''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
|
||||
StaticWarningCode.UNDEFINED_CLASS
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_redirectingConstructor_paramTypeMismatch() {
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A.a1(x) : this.a2(x);
|
||||
const A.a2(String x);
|
||||
}
|
||||
var v = const A.a1(0);''');
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_topLevelVarAssignable_null() {
|
||||
Source source = addSource("const int x = null;");
|
||||
computeLibrarySourceErrors(source);
|
||||
assertNoErrors(source);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_topLevelVarAssignable_undefined_null() {
|
||||
// Null always passes runtime type checks, even when the type is
|
||||
// unresolved.
|
||||
Source source = addSource("const Unresolved x = null;");
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_topLevelVarNotAssignable() {
|
||||
Source source = addSource("const int x = 'foo';");
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
|
||||
StaticTypeWarningCode.INVALID_ASSIGNMENT
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void test_topLevelVarNotAssignable_undefined() {
|
||||
Source source = addSource("const Unresolved x = 'foo';");
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, [
|
||||
CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
|
||||
StaticWarningCode.UNDEFINED_CLASS
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ import 'package:unittest/unittest.dart' show expect;
|
|||
|
||||
import '../reflective_tests.dart';
|
||||
import '../utils.dart';
|
||||
import 'resolver_test.dart';
|
||||
import 'resolver_test_case.dart';
|
||||
|
||||
main() {
|
||||
initializeTestEnvironment();
|
||||
|
|
|
@ -27,7 +27,7 @@ import 'package:unittest/unittest.dart';
|
|||
import '../reflective_tests.dart';
|
||||
import '../utils.dart';
|
||||
import 'engine_test.dart';
|
||||
import 'resolver_test.dart';
|
||||
import 'resolver_test_case.dart';
|
||||
import 'test_support.dart';
|
||||
|
||||
main() {
|
||||
|
|
|
@ -17,7 +17,7 @@ import 'package:unittest/unittest.dart';
|
|||
|
||||
import '../reflective_tests.dart';
|
||||
import '../utils.dart';
|
||||
import 'resolver_test.dart';
|
||||
import 'resolver_test_case.dart';
|
||||
import 'test_support.dart';
|
||||
|
||||
main() {
|
||||
|
|
1011
pkg/analyzer/test/generated/element_resolver_test.dart
Normal file
1011
pkg/analyzer/test/generated/element_resolver_test.dart
Normal file
File diff suppressed because it is too large
Load diff
|
@ -8,7 +8,7 @@ import 'package:analyzer/src/generated/source_io.dart';
|
|||
|
||||
import '../reflective_tests.dart';
|
||||
import '../utils.dart';
|
||||
import 'resolver_test.dart';
|
||||
import 'resolver_test_case.dart';
|
||||
|
||||
main() {
|
||||
initializeTestEnvironment();
|
||||
|
|
2983
pkg/analyzer/test/generated/hint_code_test.dart
Normal file
2983
pkg/analyzer/test/generated/hint_code_test.dart
Normal file
File diff suppressed because it is too large
Load diff
|
@ -31,7 +31,8 @@ import 'package:analyzer/task/model.dart';
|
|||
import 'package:unittest/unittest.dart';
|
||||
|
||||
import '../reflective_tests.dart';
|
||||
import 'resolver_test.dart';
|
||||
import 'analysis_context_factory.dart';
|
||||
import 'resolver_test_case.dart';
|
||||
import 'test_support.dart';
|
||||
|
||||
main() {
|
||||
|
|
1269
pkg/analyzer/test/generated/inheritance_manager_test.dart
Normal file
1269
pkg/analyzer/test/generated/inheritance_manager_test.dart
Normal file
File diff suppressed because it is too large
Load diff
|
@ -14,7 +14,7 @@ import 'package:unittest/unittest.dart';
|
|||
|
||||
import '../reflective_tests.dart';
|
||||
import '../utils.dart';
|
||||
import 'resolver_test.dart';
|
||||
import 'resolver_test_case.dart';
|
||||
import 'test_support.dart';
|
||||
|
||||
main() {
|
||||
|
|
1156
pkg/analyzer/test/generated/non_hint_code_test.dart
Normal file
1156
pkg/analyzer/test/generated/non_hint_code_test.dart
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
839
pkg/analyzer/test/generated/resolver_test_case.dart
Normal file
839
pkg/analyzer/test/generated/resolver_test_case.dart
Normal file
|
@ -0,0 +1,839 @@
|
|||
// 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.
|
||||
|
||||
library analyzer.test.generated.resolver_test_case;
|
||||
|
||||
import 'package:analyzer/dart/ast/ast.dart';
|
||||
import 'package:analyzer/dart/ast/visitor.dart';
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:analyzer/dart/element/type.dart';
|
||||
import 'package:analyzer/src/dart/element/element.dart';
|
||||
import 'package:analyzer/src/dart/element/type.dart';
|
||||
import 'package:analyzer/src/generated/engine.dart';
|
||||
import 'package:analyzer/src/generated/error.dart';
|
||||
import 'package:analyzer/src/generated/java_core.dart';
|
||||
import 'package:analyzer/src/generated/java_engine.dart';
|
||||
import 'package:analyzer/src/generated/java_engine_io.dart';
|
||||
import 'package:analyzer/src/generated/resolver.dart';
|
||||
import 'package:analyzer/src/generated/source_io.dart';
|
||||
import 'package:analyzer/src/generated/testing/ast_factory.dart';
|
||||
import 'package:analyzer/src/generated/testing/element_factory.dart';
|
||||
import 'package:unittest/unittest.dart';
|
||||
|
||||
import 'analysis_context_factory.dart';
|
||||
import 'test_support.dart';
|
||||
|
||||
class ResolverTestCase extends EngineTestCase {
|
||||
/**
|
||||
* The analysis context used to parse the compilation units being resolved.
|
||||
*/
|
||||
InternalAnalysisContext analysisContext2;
|
||||
|
||||
/**
|
||||
* Specifies if [assertErrors] should check for [HintCode.UNUSED_ELEMENT] and
|
||||
* [HintCode.UNUSED_FIELD].
|
||||
*/
|
||||
bool enableUnusedElement = false;
|
||||
|
||||
/**
|
||||
* Specifies if [assertErrors] should check for [HintCode.UNUSED_LOCAL_VARIABLE].
|
||||
*/
|
||||
bool enableUnusedLocalVariable = false;
|
||||
|
||||
AnalysisContext get analysisContext => analysisContext2;
|
||||
|
||||
/**
|
||||
* Return a type provider that can be used to test the results of resolution.
|
||||
*
|
||||
* @return a type provider
|
||||
* @throws AnalysisException if dart:core cannot be resolved
|
||||
*/
|
||||
TypeProvider get typeProvider => analysisContext2.typeProvider;
|
||||
|
||||
/**
|
||||
* Return a type system that can be used to test the results of resolution.
|
||||
*
|
||||
* @return a type system
|
||||
*/
|
||||
TypeSystem get typeSystem => analysisContext2.typeSystem;
|
||||
|
||||
/**
|
||||
* Add a source file to the content provider. The file path should be absolute.
|
||||
*
|
||||
* @param filePath the path of the file being added
|
||||
* @param contents the contents to be returned by the content provider for the specified file
|
||||
* @return the source object representing the added file
|
||||
*/
|
||||
Source addNamedSource(String filePath, String contents) {
|
||||
Source source = cacheSource(filePath, contents);
|
||||
ChangeSet changeSet = new ChangeSet();
|
||||
changeSet.addedSource(source);
|
||||
analysisContext2.applyChanges(changeSet);
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a source file to the content provider.
|
||||
*
|
||||
* @param contents the contents to be returned by the content provider for the specified file
|
||||
* @return the source object representing the added file
|
||||
*/
|
||||
Source addSource(String contents) => addNamedSource("/test.dart", contents);
|
||||
|
||||
/**
|
||||
* Assert that the number of errors reported against the given source matches the number of errors
|
||||
* that are given and that they have the expected error codes. The order in which the errors were
|
||||
* gathered is ignored.
|
||||
*
|
||||
* @param source the source against which the errors should have been reported
|
||||
* @param expectedErrorCodes the error codes of the errors that should have been reported
|
||||
* @throws AnalysisException if the reported errors could not be computed
|
||||
* @throws AssertionFailedError if a different number of errors have been reported than were
|
||||
* expected
|
||||
*/
|
||||
void assertErrors(Source source,
|
||||
[List<ErrorCode> expectedErrorCodes = ErrorCode.EMPTY_LIST]) {
|
||||
GatheringErrorListener errorListener = new GatheringErrorListener();
|
||||
for (AnalysisError error in analysisContext2.computeErrors(source)) {
|
||||
expect(error.source, source);
|
||||
ErrorCode errorCode = error.errorCode;
|
||||
if (!enableUnusedElement &&
|
||||
(errorCode == HintCode.UNUSED_ELEMENT ||
|
||||
errorCode == HintCode.UNUSED_FIELD)) {
|
||||
continue;
|
||||
}
|
||||
if (!enableUnusedLocalVariable &&
|
||||
(errorCode == HintCode.UNUSED_CATCH_CLAUSE ||
|
||||
errorCode == HintCode.UNUSED_CATCH_STACK ||
|
||||
errorCode == HintCode.UNUSED_LOCAL_VARIABLE)) {
|
||||
continue;
|
||||
}
|
||||
errorListener.onError(error);
|
||||
}
|
||||
errorListener.assertErrorsWithCodes(expectedErrorCodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that [code] verifies, but has errors with the given error codes.
|
||||
*
|
||||
* Like [assertErrors], but takes a string of source code.
|
||||
*/
|
||||
// TODO(rnystrom): Use this in more tests that have the same structure.
|
||||
void assertErrorsInCode(String code, List<ErrorCode> errors) {
|
||||
Source source = addSource(code);
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, errors);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that [code] has errors with the given error codes.
|
||||
*
|
||||
* Like [assertErrors], but takes a string of source code.
|
||||
*/
|
||||
void assertErrorsInUnverifiedCode(String code, List<ErrorCode> errors) {
|
||||
Source source = addSource(code);
|
||||
computeLibrarySourceErrors(source);
|
||||
assertErrors(source, errors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that no errors have been reported against the given source.
|
||||
*
|
||||
* @param source the source against which no errors should have been reported
|
||||
* @throws AnalysisException if the reported errors could not be computed
|
||||
* @throws AssertionFailedError if any errors have been reported
|
||||
*/
|
||||
void assertNoErrors(Source source) {
|
||||
assertErrors(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that [code] has no errors or warnings.
|
||||
*/
|
||||
// TODO(rnystrom): Use this in more tests that have the same structure.
|
||||
void assertNoErrorsInCode(String code) {
|
||||
Source source = addSource(code);
|
||||
computeLibrarySourceErrors(source);
|
||||
assertNoErrors(source);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache the source file content in the source factory but don't add the source to the analysis
|
||||
* context. The file path should be absolute.
|
||||
*
|
||||
* @param filePath the path of the file being cached
|
||||
* @param contents the contents to be returned by the content provider for the specified file
|
||||
* @return the source object representing the cached file
|
||||
*/
|
||||
Source cacheSource(String filePath, String contents) {
|
||||
Source source = new FileBasedSource(FileUtilities2.createFile(filePath));
|
||||
analysisContext2.setContents(source, contents);
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the contents of the given [source] to the given [contents].
|
||||
*/
|
||||
void changeSource(Source source, String contents) {
|
||||
analysisContext2.setContents(source, contents);
|
||||
ChangeSet changeSet = new ChangeSet();
|
||||
changeSet.changedSource(source);
|
||||
analysisContext2.applyChanges(changeSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes errors for the given [librarySource].
|
||||
* This assumes that the given [librarySource] and its parts have already
|
||||
* been added to the content provider using the method [addNamedSource].
|
||||
*/
|
||||
void computeLibrarySourceErrors(Source librarySource) {
|
||||
analysisContext.computeErrors(librarySource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a library element that represents a library named `"test"` containing a single
|
||||
* empty compilation unit.
|
||||
*
|
||||
* @return the library element that was created
|
||||
*/
|
||||
LibraryElementImpl createDefaultTestLibrary() =>
|
||||
createTestLibrary(AnalysisContextFactory.contextWithCore(), "test");
|
||||
|
||||
/**
|
||||
* Create a library element that represents a library with the given name containing a single
|
||||
* empty compilation unit.
|
||||
*
|
||||
* @param libraryName the name of the library to be created
|
||||
* @return the library element that was created
|
||||
*/
|
||||
LibraryElementImpl createTestLibrary(
|
||||
AnalysisContext context, String libraryName,
|
||||
[List<String> typeNames]) {
|
||||
String fileName = "$libraryName.dart";
|
||||
FileBasedSource definingCompilationUnitSource =
|
||||
createNamedSource(fileName);
|
||||
List<CompilationUnitElement> sourcedCompilationUnits;
|
||||
if (typeNames == null) {
|
||||
sourcedCompilationUnits = CompilationUnitElement.EMPTY_LIST;
|
||||
} else {
|
||||
int count = typeNames.length;
|
||||
sourcedCompilationUnits = new List<CompilationUnitElement>(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
String typeName = typeNames[i];
|
||||
ClassElementImpl type =
|
||||
new ClassElementImpl.forNode(AstFactory.identifier3(typeName));
|
||||
String fileName = "$typeName.dart";
|
||||
CompilationUnitElementImpl compilationUnit =
|
||||
new CompilationUnitElementImpl(fileName);
|
||||
compilationUnit.source = createNamedSource(fileName);
|
||||
compilationUnit.librarySource = definingCompilationUnitSource;
|
||||
compilationUnit.types = <ClassElement>[type];
|
||||
sourcedCompilationUnits[i] = compilationUnit;
|
||||
}
|
||||
}
|
||||
CompilationUnitElementImpl compilationUnit =
|
||||
new CompilationUnitElementImpl(fileName);
|
||||
compilationUnit.librarySource =
|
||||
compilationUnit.source = definingCompilationUnitSource;
|
||||
LibraryElementImpl library = new LibraryElementImpl.forNode(
|
||||
context, AstFactory.libraryIdentifier2([libraryName]));
|
||||
library.definingCompilationUnit = compilationUnit;
|
||||
library.parts = sourcedCompilationUnits;
|
||||
return library;
|
||||
}
|
||||
|
||||
Expression findTopLevelConstantExpression(
|
||||
CompilationUnit compilationUnit, String name) =>
|
||||
findTopLevelDeclaration(compilationUnit, name).initializer;
|
||||
|
||||
VariableDeclaration findTopLevelDeclaration(
|
||||
CompilationUnit compilationUnit, String name) {
|
||||
for (CompilationUnitMember member in compilationUnit.declarations) {
|
||||
if (member is TopLevelVariableDeclaration) {
|
||||
for (VariableDeclaration variable in member.variables.variables) {
|
||||
if (variable.name.name == name) {
|
||||
return variable;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
// Not found
|
||||
}
|
||||
|
||||
/**
|
||||
* In the rare cases we want to group several tests into single "test_" method, so need a way to
|
||||
* reset test instance to reuse it.
|
||||
*/
|
||||
void reset() {
|
||||
analysisContext2 = AnalysisContextFactory.contextWithCore();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the analysis context to have the given options applied.
|
||||
*
|
||||
* @param options the analysis options to be applied to the context
|
||||
*/
|
||||
void resetWithOptions(AnalysisOptions options) {
|
||||
analysisContext2 =
|
||||
AnalysisContextFactory.contextWithCoreAndOptions(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a library and all of its parts, resolve the contents of the library and the contents of
|
||||
* the parts. This assumes that the sources for the library and its parts have already been added
|
||||
* to the content provider using the method [addNamedSource].
|
||||
*
|
||||
* @param librarySource the source for the compilation unit that defines the library
|
||||
* @return the element representing the resolved library
|
||||
* @throws AnalysisException if the analysis could not be performed
|
||||
*/
|
||||
LibraryElement resolve2(Source librarySource) =>
|
||||
analysisContext2.computeLibraryElement(librarySource);
|
||||
|
||||
/**
|
||||
* Return the resolved compilation unit corresponding to the given source in the given library.
|
||||
*
|
||||
* @param source the source of the compilation unit to be returned
|
||||
* @param library the library in which the compilation unit is to be resolved
|
||||
* @return the resolved compilation unit
|
||||
* @throws Exception if the compilation unit could not be resolved
|
||||
*/
|
||||
CompilationUnit resolveCompilationUnit(
|
||||
Source source, LibraryElement library) =>
|
||||
analysisContext2.resolveCompilationUnit(source, library);
|
||||
|
||||
CompilationUnit resolveSource(String sourceText) =>
|
||||
resolveSource2("/test.dart", sourceText);
|
||||
|
||||
CompilationUnit resolveSource2(String fileName, String sourceText) {
|
||||
Source source = addNamedSource(fileName, sourceText);
|
||||
LibraryElement library = analysisContext.computeLibraryElement(source);
|
||||
return analysisContext.resolveCompilationUnit(source, library);
|
||||
}
|
||||
|
||||
Source resolveSources(List<String> sourceTexts) {
|
||||
for (int i = 0; i < sourceTexts.length; i++) {
|
||||
CompilationUnit unit =
|
||||
resolveSource2("/lib${i + 1}.dart", sourceTexts[i]);
|
||||
// reference the source if this is the last source
|
||||
if (i + 1 == sourceTexts.length) {
|
||||
return unit.element.source;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void resolveWithAndWithoutExperimental(
|
||||
List<String> strSources,
|
||||
List<ErrorCode> codesWithoutExperimental,
|
||||
List<ErrorCode> codesWithExperimental) {
|
||||
// Setup analysis context as non-experimental
|
||||
AnalysisOptionsImpl options = new AnalysisOptionsImpl();
|
||||
// options.enableDeferredLoading = false;
|
||||
resetWithOptions(options);
|
||||
// Analysis and assertions
|
||||
Source source = resolveSources(strSources);
|
||||
assertErrors(source, codesWithoutExperimental);
|
||||
verify([source]);
|
||||
// Setup analysis context as experimental
|
||||
reset();
|
||||
// Analysis and assertions
|
||||
source = resolveSources(strSources);
|
||||
assertErrors(source, codesWithExperimental);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
void resolveWithErrors(List<String> strSources, List<ErrorCode> codes) {
|
||||
// Analysis and assertions
|
||||
Source source = resolveSources(strSources);
|
||||
assertErrors(source, codes);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
@override
|
||||
void setUp() {
|
||||
ElementFactory.flushStaticState();
|
||||
super.setUp();
|
||||
reset();
|
||||
}
|
||||
|
||||
@override
|
||||
void tearDown() {
|
||||
analysisContext2 = null;
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that all of the identifiers in the compilation units associated with
|
||||
* the given [sources] have been resolved.
|
||||
*/
|
||||
void verify(List<Source> sources) {
|
||||
ResolutionVerifier verifier = new ResolutionVerifier();
|
||||
for (Source source in sources) {
|
||||
List<Source> libraries = analysisContext2.getLibrariesContaining(source);
|
||||
for (Source library in libraries) {
|
||||
analysisContext2
|
||||
.resolveCompilationUnit2(source, library)
|
||||
.accept(verifier);
|
||||
}
|
||||
}
|
||||
verifier.assertResolved();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param code the code that assigns the value to the variable "v", no matter how. We check that
|
||||
* "v" has expected static and propagated type.
|
||||
*/
|
||||
void assertPropagatedAssignedType(String code, DartType expectedStaticType,
|
||||
DartType expectedPropagatedType) {
|
||||
SimpleIdentifier identifier = findMarkedIdentifier(code, "v = ");
|
||||
expect(identifier.staticType, same(expectedStaticType));
|
||||
expect(identifier.propagatedType, same(expectedPropagatedType));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param code the code that iterates using variable "v". We check that
|
||||
* "v" has expected static and propagated type.
|
||||
*/
|
||||
void assertPropagatedIterationType(String code, DartType expectedStaticType,
|
||||
DartType expectedPropagatedType) {
|
||||
SimpleIdentifier identifier = findMarkedIdentifier(code, "v in ");
|
||||
expect(identifier.staticType, same(expectedStaticType));
|
||||
expect(identifier.propagatedType, same(expectedPropagatedType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the static and propagated types of the expression marked with "; // marker" comment.
|
||||
*
|
||||
* @param code source code to analyze, with the expression to check marked with "// marker".
|
||||
* @param expectedStaticType if non-null, check actual static type is equal to this.
|
||||
* @param expectedPropagatedType if non-null, check actual static type is equal to this.
|
||||
* @throws Exception
|
||||
*/
|
||||
void assertTypeOfMarkedExpression(String code, DartType expectedStaticType,
|
||||
DartType expectedPropagatedType) {
|
||||
SimpleIdentifier identifier = findMarkedIdentifier(code, "; // marker");
|
||||
if (expectedStaticType != null) {
|
||||
expect(identifier.staticType, expectedStaticType);
|
||||
}
|
||||
expect(identifier.propagatedType, expectedPropagatedType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a source object representing a file with the given [fileName] and
|
||||
* give it an empty content. Return the source that was created.
|
||||
*/
|
||||
FileBasedSource createNamedSource(String fileName) {
|
||||
FileBasedSource source =
|
||||
new FileBasedSource(FileUtilities2.createFile(fileName));
|
||||
analysisContext2.setContents(source, "");
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the `SimpleIdentifier` marked by `marker`. The source code must have no
|
||||
* errors and be verifiable.
|
||||
*
|
||||
* @param code source code to analyze.
|
||||
* @param marker marker identifying sought after expression in source code.
|
||||
* @return expression marked by the marker.
|
||||
* @throws Exception
|
||||
*/
|
||||
SimpleIdentifier findMarkedIdentifier(String code, String marker) {
|
||||
try {
|
||||
Source source = addSource(code);
|
||||
LibraryElement library = resolve2(source);
|
||||
assertNoErrors(source);
|
||||
verify([source]);
|
||||
CompilationUnit unit = resolveCompilationUnit(source, library);
|
||||
// Could generalize this further by making [SimpleIdentifier.class] a
|
||||
// parameter.
|
||||
return EngineTestCase.findNode(
|
||||
unit, code, marker, (node) => node is SimpleIdentifier);
|
||||
} catch (exception) {
|
||||
// Is there a better exception to throw here? The point is that an
|
||||
// assertion failure here should be a failure, in both "test_*" and
|
||||
// "fail_*" tests. However, an assertion failure is success for the
|
||||
// purpose of "fail_*" tests, so without catching them here "fail_*" tests
|
||||
// can succeed by failing for the wrong reason.
|
||||
throw new JavaException("Unexexpected assertion failure: $exception");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An AST visitor used to verify that all of the nodes in an AST structure that
|
||||
* should have been resolved were resolved.
|
||||
*/
|
||||
class ResolutionVerifier extends RecursiveAstVisitor<Object> {
|
||||
/**
|
||||
* A set containing nodes that are known to not be resolvable and should
|
||||
* therefore not cause the test to fail.
|
||||
*/
|
||||
final Set<AstNode> _knownExceptions;
|
||||
|
||||
/**
|
||||
* A list containing all of the AST nodes that were not resolved.
|
||||
*/
|
||||
List<AstNode> _unresolvedNodes = new List<AstNode>();
|
||||
|
||||
/**
|
||||
* A list containing all of the AST nodes that were resolved to an element of
|
||||
* the wrong type.
|
||||
*/
|
||||
List<AstNode> _wrongTypedNodes = new List<AstNode>();
|
||||
|
||||
/**
|
||||
* Initialize a newly created verifier to verify that all of the identifiers
|
||||
* in the visited AST structures that are expected to have been resolved have
|
||||
* an element associated with them. Nodes in the set of [_knownExceptions] are
|
||||
* not expected to have been resolved, even if they normally would have been
|
||||
* expected to have been resolved.
|
||||
*/
|
||||
ResolutionVerifier([this._knownExceptions]);
|
||||
|
||||
/**
|
||||
* Assert that all of the visited identifiers were resolved.
|
||||
*/
|
||||
void assertResolved() {
|
||||
if (!_unresolvedNodes.isEmpty || !_wrongTypedNodes.isEmpty) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
if (!_unresolvedNodes.isEmpty) {
|
||||
buffer.write("Failed to resolve ");
|
||||
buffer.write(_unresolvedNodes.length);
|
||||
buffer.writeln(" nodes:");
|
||||
_printNodes(buffer, _unresolvedNodes);
|
||||
}
|
||||
if (!_wrongTypedNodes.isEmpty) {
|
||||
buffer.write("Resolved ");
|
||||
buffer.write(_wrongTypedNodes.length);
|
||||
buffer.writeln(" to the wrong type of element:");
|
||||
_printNodes(buffer, _wrongTypedNodes);
|
||||
}
|
||||
fail(buffer.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Object visitAnnotation(Annotation node) {
|
||||
node.visitChildren(this);
|
||||
ElementAnnotation elementAnnotation = node.elementAnnotation;
|
||||
if (elementAnnotation == null) {
|
||||
if (_knownExceptions == null || !_knownExceptions.contains(node)) {
|
||||
_unresolvedNodes.add(node);
|
||||
}
|
||||
} else if (elementAnnotation is! ElementAnnotation) {
|
||||
_wrongTypedNodes.add(node);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Object visitBinaryExpression(BinaryExpression node) {
|
||||
node.visitChildren(this);
|
||||
if (!node.operator.isUserDefinableOperator) {
|
||||
return null;
|
||||
}
|
||||
DartType operandType = node.leftOperand.staticType;
|
||||
if (operandType == null || operandType.isDynamic) {
|
||||
return null;
|
||||
}
|
||||
return _checkResolved(
|
||||
node, node.staticElement, (node) => node is MethodElement);
|
||||
}
|
||||
|
||||
@override
|
||||
Object visitCommentReference(CommentReference node) => null;
|
||||
|
||||
@override
|
||||
Object visitCompilationUnit(CompilationUnit node) {
|
||||
node.visitChildren(this);
|
||||
return _checkResolved(
|
||||
node, node.element, (node) => node is CompilationUnitElement);
|
||||
}
|
||||
|
||||
@override
|
||||
Object visitExportDirective(ExportDirective node) =>
|
||||
_checkResolved(node, node.element, (node) => node is ExportElement);
|
||||
|
||||
@override
|
||||
Object visitFunctionDeclaration(FunctionDeclaration node) {
|
||||
node.visitChildren(this);
|
||||
if (node.element is LibraryElement) {
|
||||
_wrongTypedNodes.add(node);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
|
||||
node.visitChildren(this);
|
||||
// TODO(brianwilkerson) If we start resolving function expressions, then
|
||||
// conditionally check to see whether the node was resolved correctly.
|
||||
return null;
|
||||
//checkResolved(node, node.getElement(), FunctionElement.class);
|
||||
}
|
||||
|
||||
@override
|
||||
Object visitImportDirective(ImportDirective node) {
|
||||
// Not sure how to test the combinators given that it isn't an error if the
|
||||
// names are not defined.
|
||||
_checkResolved(node, node.element, (node) => node is ImportElement);
|
||||
SimpleIdentifier prefix = node.prefix;
|
||||
if (prefix == null) {
|
||||
return null;
|
||||
}
|
||||
return _checkResolved(
|
||||
prefix, prefix.staticElement, (node) => node is PrefixElement);
|
||||
}
|
||||
|
||||
@override
|
||||
Object visitIndexExpression(IndexExpression node) {
|
||||
node.visitChildren(this);
|
||||
DartType targetType = node.realTarget.staticType;
|
||||
if (targetType == null || targetType.isDynamic) {
|
||||
return null;
|
||||
}
|
||||
return _checkResolved(
|
||||
node, node.staticElement, (node) => node is MethodElement);
|
||||
}
|
||||
|
||||
@override
|
||||
Object visitLibraryDirective(LibraryDirective node) =>
|
||||
_checkResolved(node, node.element, (node) => node is LibraryElement);
|
||||
|
||||
@override
|
||||
Object visitNamedExpression(NamedExpression node) =>
|
||||
node.expression.accept(this);
|
||||
|
||||
@override
|
||||
Object visitPartDirective(PartDirective node) => _checkResolved(
|
||||
node, node.element, (node) => node is CompilationUnitElement);
|
||||
|
||||
@override
|
||||
Object visitPartOfDirective(PartOfDirective node) =>
|
||||
_checkResolved(node, node.element, (node) => node is LibraryElement);
|
||||
|
||||
@override
|
||||
Object visitPostfixExpression(PostfixExpression node) {
|
||||
node.visitChildren(this);
|
||||
if (!node.operator.isUserDefinableOperator) {
|
||||
return null;
|
||||
}
|
||||
DartType operandType = node.operand.staticType;
|
||||
if (operandType == null || operandType.isDynamic) {
|
||||
return null;
|
||||
}
|
||||
return _checkResolved(
|
||||
node, node.staticElement, (node) => node is MethodElement);
|
||||
}
|
||||
|
||||
@override
|
||||
Object visitPrefixedIdentifier(PrefixedIdentifier node) {
|
||||
SimpleIdentifier prefix = node.prefix;
|
||||
prefix.accept(this);
|
||||
DartType prefixType = prefix.staticType;
|
||||
if (prefixType == null || prefixType.isDynamic) {
|
||||
return null;
|
||||
}
|
||||
return _checkResolved(node, node.staticElement, null);
|
||||
}
|
||||
|
||||
@override
|
||||
Object visitPrefixExpression(PrefixExpression node) {
|
||||
node.visitChildren(this);
|
||||
if (!node.operator.isUserDefinableOperator) {
|
||||
return null;
|
||||
}
|
||||
DartType operandType = node.operand.staticType;
|
||||
if (operandType == null || operandType.isDynamic) {
|
||||
return null;
|
||||
}
|
||||
return _checkResolved(
|
||||
node, node.staticElement, (node) => node is MethodElement);
|
||||
}
|
||||
|
||||
@override
|
||||
Object visitPropertyAccess(PropertyAccess node) {
|
||||
Expression target = node.realTarget;
|
||||
target.accept(this);
|
||||
DartType targetType = target.staticType;
|
||||
if (targetType == null || targetType.isDynamic) {
|
||||
return null;
|
||||
}
|
||||
return node.propertyName.accept(this);
|
||||
}
|
||||
|
||||
@override
|
||||
Object visitSimpleIdentifier(SimpleIdentifier node) {
|
||||
if (node.name == "void") {
|
||||
return null;
|
||||
}
|
||||
if (node.staticType != null &&
|
||||
node.staticType.isDynamic &&
|
||||
node.staticElement == null) {
|
||||
return null;
|
||||
}
|
||||
AstNode parent = node.parent;
|
||||
if (parent is MethodInvocation) {
|
||||
MethodInvocation invocation = parent;
|
||||
if (identical(invocation.methodName, node)) {
|
||||
Expression target = invocation.realTarget;
|
||||
DartType targetType = target == null ? null : target.staticType;
|
||||
if (targetType == null || targetType.isDynamic) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return _checkResolved(node, node.staticElement, null);
|
||||
}
|
||||
|
||||
Object _checkResolved(
|
||||
AstNode node, Element element, Predicate<Element> predicate) {
|
||||
if (element == null) {
|
||||
if (_knownExceptions == null || !_knownExceptions.contains(node)) {
|
||||
_unresolvedNodes.add(node);
|
||||
}
|
||||
} else if (predicate != null) {
|
||||
if (!predicate(element)) {
|
||||
_wrongTypedNodes.add(node);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
String _getFileName(AstNode node) {
|
||||
// TODO (jwren) there are two copies of this method, one here and one in
|
||||
// StaticTypeVerifier, they should be resolved into a single method
|
||||
if (node != null) {
|
||||
AstNode root = node.root;
|
||||
if (root is CompilationUnit) {
|
||||
CompilationUnit rootCU = root;
|
||||
if (rootCU.element != null) {
|
||||
return rootCU.element.source.fullName;
|
||||
} else {
|
||||
return "<unknown file- CompilationUnit.getElement() returned null>";
|
||||
}
|
||||
} else {
|
||||
return "<unknown file- CompilationUnit.getRoot() is not a CompilationUnit>";
|
||||
}
|
||||
}
|
||||
return "<unknown file- ASTNode is null>";
|
||||
}
|
||||
|
||||
void _printNodes(StringBuffer buffer, List<AstNode> nodes) {
|
||||
for (AstNode identifier in nodes) {
|
||||
buffer.write(" ");
|
||||
buffer.write(identifier.toString());
|
||||
buffer.write(" (");
|
||||
buffer.write(_getFileName(identifier));
|
||||
buffer.write(" : ");
|
||||
buffer.write(identifier.offset);
|
||||
buffer.writeln(")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shared infrastructure for [StaticTypeAnalyzer2Test] and
|
||||
* [StrongModeStaticTypeAnalyzer2Test].
|
||||
*/
|
||||
class StaticTypeAnalyzer2TestShared extends ResolverTestCase {
|
||||
String testCode;
|
||||
Source testSource;
|
||||
CompilationUnit testUnit;
|
||||
|
||||
/**
|
||||
* Looks up the identifier with [name] and validates that its type type
|
||||
* stringifies to [type] and that its generics match the given stringified
|
||||
* output.
|
||||
*/
|
||||
expectFunctionType(String name, String type,
|
||||
{String elementTypeParams: '[]',
|
||||
String typeParams: '[]',
|
||||
String typeArgs: '[]',
|
||||
String typeFormals: '[]'}) {
|
||||
SimpleIdentifier identifier = findIdentifier(name);
|
||||
// Element is either ExecutableElement or ParameterElement.
|
||||
var element = identifier.staticElement;
|
||||
FunctionTypeImpl functionType = identifier.staticType;
|
||||
expect(functionType.toString(), type);
|
||||
expect(element.typeParameters.toString(), elementTypeParams);
|
||||
expect(functionType.typeParameters.toString(), typeParams);
|
||||
expect(functionType.typeArguments.toString(), typeArgs);
|
||||
expect(functionType.typeFormals.toString(), typeFormals);
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up the identifier with [name] and validates its static [type].
|
||||
*
|
||||
* If [type] is a string, validates that the identifier's static type
|
||||
* stringifies to that text. Otherwise, [type] is used directly a [Matcher]
|
||||
* to match the type.
|
||||
*
|
||||
* If [propagatedType] is given, also validate's the identifier's propagated
|
||||
* type.
|
||||
*/
|
||||
void expectIdentifierType(String name, type, [propagatedType]) {
|
||||
SimpleIdentifier identifier = findIdentifier(name);
|
||||
_expectType(identifier.staticType, type);
|
||||
if (propagatedType != null) {
|
||||
_expectType(identifier.propagatedType, propagatedType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up the initializer for the declaration containing [identifier] and
|
||||
* validates its static [type].
|
||||
*
|
||||
* If [type] is a string, validates that the identifier's static type
|
||||
* stringifies to that text. Otherwise, [type] is used directly a [Matcher]
|
||||
* to match the type.
|
||||
*
|
||||
* If [propagatedType] is given, also validate's the identifier's propagated
|
||||
* type.
|
||||
*/
|
||||
void expectInitializerType(String name, type, [propagatedType]) {
|
||||
SimpleIdentifier identifier = findIdentifier(name);
|
||||
VariableDeclaration declaration =
|
||||
identifier.getAncestor((node) => node is VariableDeclaration);
|
||||
Expression initializer = declaration.initializer;
|
||||
_expectType(initializer.staticType, type);
|
||||
if (propagatedType != null) {
|
||||
_expectType(initializer.propagatedType, propagatedType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that [type] matches [expected].
|
||||
*
|
||||
* If [expected] is a string, validates that the type stringifies to that
|
||||
* text. Otherwise, [expected] is used directly a [Matcher] to match the type.
|
||||
*/
|
||||
_expectType(DartType type, expected) {
|
||||
if (expected is String) {
|
||||
expect(type.toString(), expected);
|
||||
} else {
|
||||
expect(type, expected);
|
||||
}
|
||||
}
|
||||
|
||||
SimpleIdentifier findIdentifier(String search) {
|
||||
SimpleIdentifier identifier = EngineTestCase.findNode(
|
||||
testUnit, testCode, search, (node) => node is SimpleIdentifier);
|
||||
return identifier;
|
||||
}
|
||||
|
||||
void resolveTestUnit(String code) {
|
||||
testCode = code;
|
||||
testSource = addSource(testCode);
|
||||
LibraryElement library = resolve2(testSource);
|
||||
assertNoErrors(testSource);
|
||||
verify([testSource]);
|
||||
testUnit = resolveCompilationUnit(testSource, library);
|
||||
}
|
||||
}
|
1762
pkg/analyzer/test/generated/simple_resolver_test.dart
Normal file
1762
pkg/analyzer/test/generated/simple_resolver_test.dart
Normal file
File diff suppressed because it is too large
Load diff
1619
pkg/analyzer/test/generated/static_type_analyzer_test.dart
Normal file
1619
pkg/analyzer/test/generated/static_type_analyzer_test.dart
Normal file
File diff suppressed because it is too large
Load diff
|
@ -12,7 +12,7 @@ import 'package:unittest/unittest.dart';
|
|||
|
||||
import '../reflective_tests.dart';
|
||||
import '../utils.dart';
|
||||
import 'resolver_test.dart';
|
||||
import 'resolver_test_case.dart';
|
||||
|
||||
main() {
|
||||
initializeTestEnvironment();
|
||||
|
|
|
@ -10,7 +10,7 @@ import 'package:unittest/unittest.dart';
|
|||
|
||||
import '../reflective_tests.dart';
|
||||
import '../utils.dart';
|
||||
import 'resolver_test.dart';
|
||||
import 'resolver_test_case.dart';
|
||||
|
||||
main() {
|
||||
initializeTestEnvironment();
|
||||
|
|
2280
pkg/analyzer/test/generated/strong_mode_test.dart
Normal file
2280
pkg/analyzer/test/generated/strong_mode_test.dart
Normal file
File diff suppressed because it is too large
Load diff
|
@ -19,7 +19,7 @@ import 'package:plugin/manager.dart';
|
|||
import 'package:plugin/plugin.dart';
|
||||
import 'package:unittest/unittest.dart';
|
||||
|
||||
import 'resolver_test.dart';
|
||||
import 'analysis_context_factory.dart';
|
||||
|
||||
/**
|
||||
* The class `EngineTestCase` defines utility methods for making assertions.
|
||||
|
|
|
@ -18,8 +18,8 @@ import 'package:analyzer/src/generated/testing/element_factory.dart';
|
|||
import 'package:analyzer/src/generated/testing/test_type_provider.dart';
|
||||
import 'package:unittest/unittest.dart';
|
||||
|
||||
import '../../../generated/resolver_test.dart'
|
||||
show TestTypeProvider, AnalysisContextHelper;
|
||||
import '../../../generated/analysis_context_factory.dart'
|
||||
show AnalysisContextHelper;
|
||||
import '../../../generated/test_support.dart';
|
||||
import '../../../reflective_tests.dart';
|
||||
import '../../../utils.dart';
|
||||
|
|
|
@ -25,7 +25,7 @@ import 'package:analyzer/src/summary/resynthesize.dart';
|
|||
import 'package:analyzer/src/summary/summarize_elements.dart';
|
||||
import 'package:unittest/unittest.dart';
|
||||
|
||||
import '../../generated/resolver_test.dart';
|
||||
import '../../generated/resolver_test_case.dart';
|
||||
import '../../reflective_tests.dart';
|
||||
import 'summary_common.dart' show canonicalize;
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ import 'package:analyzer/src/summary/summarize_elements.dart'
|
|||
as summarize_elements;
|
||||
import 'package:unittest/unittest.dart';
|
||||
|
||||
import '../../generated/resolver_test.dart';
|
||||
import '../../generated/resolver_test_case.dart';
|
||||
import '../../reflective_tests.dart';
|
||||
import 'summary_common.dart';
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ import 'package:analyzer/src/summary/summarize_elements.dart'
|
|||
as summarize_elements;
|
||||
import 'package:unittest/unittest.dart';
|
||||
|
||||
import '../../generated/resolver_test.dart';
|
||||
import '../../generated/analysis_context_factory.dart';
|
||||
|
||||
/**
|
||||
* The public namespaces of the sdk are computed once so that we don't bog
|
||||
|
|
|
@ -27,7 +27,7 @@ import 'package:analyzer/task/general.dart';
|
|||
import 'package:analyzer/task/model.dart';
|
||||
import 'package:unittest/unittest.dart';
|
||||
|
||||
import '../../generated/resolver_test.dart';
|
||||
import '../../generated/resolver_test_case.dart';
|
||||
import '../../generated/test_support.dart';
|
||||
import '../../reflective_tests.dart';
|
||||
import '../../utils.dart';
|
||||
|
|
Loading…
Reference in a new issue