Split resolver_test.dart into smaller files.

R=brianwilkerson@google.com

Review URL: https://codereview.chromium.org/1782463002 .
This commit is contained in:
Bob Nystrom 2016-03-09 10:42:09 -08:00
parent 00e6b92e20
commit 8defa5f77c
27 changed files with 14160 additions and 13921 deletions

View file

@ -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].

View file

@ -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() {

View 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);
}
}

View file

@ -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]);
}
}

View file

@ -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();

View file

@ -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() {

View file

@ -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() {

File diff suppressed because it is too large Load diff

View file

@ -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();

File diff suppressed because it is too large Load diff

View file

@ -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() {

File diff suppressed because it is too large Load diff

View file

@ -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() {

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View 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);
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -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();

View file

@ -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();

File diff suppressed because it is too large Load diff

View file

@ -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.

View file

@ -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';

View file

@ -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;

View file

@ -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';

View file

@ -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

View file

@ -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';