blob: 3f6d6536ee097af4b7f4f35e66965121933a6fac [file] [log] [blame]
// Copyright (c) 2015, 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 test.src.serialization.elements_test;
import 'dart:convert';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/element_handle.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/resolver.dart'
show Namespace, TypeProvider;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/idl.dart';
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 '../../reflective_tests.dart';
import 'summary_common.dart' show canonicalize;
main() {
groupSep = ' | ';
runReflectiveTests(ResynthTest);
}
@reflectiveTest
class ResynthTest extends ResolverTestCase {
Set<Source> otherLibrarySources = new Set<Source>();
bool constantInitializersAreInvalid = false;
/**
* Determine the analysis options that should be used for this test.
*/
AnalysisOptionsImpl get options =>
new AnalysisOptionsImpl()..enableGenericMethods = true;
void addLibrary(String uri) {
otherLibrarySources.add(analysisContext2.sourceFactory.forUri(uri));
}
void addLibrarySource(String filePath, String contents) {
otherLibrarySources.add(addNamedSource(filePath, contents));
}
void checkLibrary(String text,
{bool allowErrors: false, bool dumpSummaries: false}) {
Source source = addSource(text);
LibraryElementImpl original = resolve2(source);
LibraryElementImpl resynthesized = resynthesizeLibraryElement(
encodeLibrary(original,
allowErrors: allowErrors, dumpSummaries: dumpSummaries),
source.uri.toString(),
original);
checkLibraryElements(original, resynthesized);
}
void checkLibraryElements(
LibraryElementImpl original, LibraryElementImpl resynthesized) {
compareElements(resynthesized, original, '(library)');
expect(resynthesized.displayName, original.displayName);
expect(original.enclosingElement, isNull);
expect(resynthesized.enclosingElement, isNull);
expect(resynthesized.hasExtUri, original.hasExtUri);
compareCompilationUnitElements(resynthesized.definingCompilationUnit,
original.definingCompilationUnit);
expect(resynthesized.parts.length, original.parts.length);
for (int i = 0; i < resynthesized.parts.length; i++) {
compareCompilationUnitElements(resynthesized.parts[i], original.parts[i]);
}
expect(resynthesized.imports.length, original.imports.length);
for (int i = 0; i < resynthesized.imports.length; i++) {
compareImportElements(resynthesized.imports[i], original.imports[i],
'import ${original.imports[i].uri}');
}
expect(resynthesized.exports.length, original.exports.length);
for (int i = 0; i < resynthesized.exports.length; i++) {
compareExportElements(resynthesized.exports[i], original.exports[i],
'export ${original.exports[i].uri}');
}
expect(resynthesized.nameLength, original.nameLength);
compareNamespaces(resynthesized.publicNamespace, original.publicNamespace,
'(public namespace)');
compareNamespaces(resynthesized.exportNamespace, original.exportNamespace,
'(export namespace)');
if (original.entryPoint == null) {
expect(resynthesized.entryPoint, isNull);
} else {
expect(resynthesized.entryPoint, isNotNull);
compareFunctionElements(
resynthesized.entryPoint, original.entryPoint, '(entry point)');
}
// The libraries `dart:core` and `dart:async` cannot create their
// `loadLibrary` functions until after both are created.
if (original.name != 'dart.core' && original.name != 'dart.async') {
compareExecutableElements(
resynthesized.loadLibraryFunction as ExecutableElementImpl,
original.loadLibraryFunction as ExecutableElementImpl,
'(loadLibraryFunction)');
}
}
/**
* Verify that the [resynthesizer] didn't do any unnecessary work when
* resynthesizing [library].
*/
void checkMinimalResynthesisWork(
_TestSummaryResynthesizer resynthesizer, LibraryElement library) {
// Check that no other summaries needed to be resynthesized to resynthesize
// the library element.
expect(resynthesizer.resynthesisCount, 1);
// Check that the only linked summary consulted was that for [uri].
expect(resynthesizer.linkedSummariesRequested, hasLength(1));
expect(resynthesizer.linkedSummariesRequested.first,
library.source.uri.toString());
// Check that the only unlinked summaries consulted were those for the
// library in question.
Set<String> expectedCompilationUnitUris = library.units
.map((CompilationUnitElement unit) => unit.source.uri.toString())
.toSet();
for (String requestedUri in resynthesizer.unlinkedSummariesRequested) {
expect(expectedCompilationUnitUris, contains(requestedUri));
}
}
void checkPossibleLocalElements(Element resynthesized, Element original) {
if (original is! LocalElement && resynthesized is! LocalElement) {
return;
}
// TODO(scheglov) add support for parameters
if (original is ParameterElement && resynthesized is ParameterElement) {
return;
}
if (original is LocalElement && resynthesized is LocalElement) {
expect(resynthesized.visibleRange, original.visibleRange);
} else {
fail('Incompatible local elements '
'${resynthesized.runtimeType} vs. ${original.runtimeType}');
}
}
void checkPossibleMember(
Element resynthesized, Element original, String desc) {
Element resynthesizedNonHandle = resynthesized is ElementHandle
? resynthesized.actualElement
: resynthesized;
if (original is Member) {
expect(resynthesizedNonHandle, new isInstanceOf<Member>(), reason: desc);
if (resynthesizedNonHandle is Member) {
List<DartType> resynthesizedTypeArguments =
resynthesizedNonHandle.definingType.typeArguments;
List<DartType> originalTypeArguments =
original.definingType.typeArguments;
expect(
resynthesizedTypeArguments, hasLength(originalTypeArguments.length),
reason: desc);
for (int i = 0; i < originalTypeArguments.length; i++) {
compareTypeImpls(resynthesizedTypeArguments[i],
originalTypeArguments[i], '$desc type argument $i');
}
}
} else {
expect(
resynthesizedNonHandle, isNot(new isInstanceOf<ConstructorMember>()),
reason: desc);
}
}
void compareClassElements(
ClassElementImpl resynthesized, ClassElementImpl original, String desc) {
compareElements(resynthesized, original, desc);
expect(resynthesized.fields.length, original.fields.length,
reason: '$desc fields.length');
for (int i = 0; i < resynthesized.fields.length; i++) {
String name = original.fields[i].name;
compareFieldElements(
resynthesized.fields[i], original.fields[i], '$desc.field $name');
}
compareTypes(
resynthesized.supertype, original.supertype, '$desc supertype');
expect(resynthesized.interfaces.length, original.interfaces.length);
for (int i = 0; i < resynthesized.interfaces.length; i++) {
compareTypes(resynthesized.interfaces[i], original.interfaces[i],
'$desc interface ${original.interfaces[i].name}');
}
expect(resynthesized.mixins.length, original.mixins.length);
for (int i = 0; i < resynthesized.mixins.length; i++) {
compareTypes(resynthesized.mixins[i], original.mixins[i],
'$desc mixin ${original.mixins[i].name}');
}
expect(resynthesized.typeParameters.length, original.typeParameters.length);
for (int i = 0; i < resynthesized.typeParameters.length; i++) {
compareTypeParameterElements(
resynthesized.typeParameters[i],
original.typeParameters[i],
'$desc type parameter ${original.typeParameters[i].name}');
}
expect(resynthesized.constructors.length, original.constructors.length,
reason: '$desc constructors.length');
for (int i = 0; i < resynthesized.constructors.length; i++) {
compareConstructorElements(
resynthesized.constructors[i],
original.constructors[i],
'$desc constructor ${original.constructors[i].name}');
}
expect(resynthesized.accessors.length, original.accessors.length);
for (int i = 0; i < resynthesized.accessors.length; i++) {
comparePropertyAccessorElements(
resynthesized.accessors[i],
original.accessors[i],
'$desc accessor ${original.accessors[i].name}');
}
expect(resynthesized.methods.length, original.methods.length);
for (int i = 0; i < resynthesized.methods.length; i++) {
compareMethodElements(resynthesized.methods[i], original.methods[i],
'$desc.${original.methods[i].name}');
}
compareTypes(resynthesized.type, original.type, desc);
}
void compareCompilationUnitElements(CompilationUnitElementImpl resynthesized,
CompilationUnitElementImpl original) {
String desc = 'Compilation unit ${original.source.uri}';
compareUriReferencedElements(resynthesized, original, desc);
expect(resynthesized.source, original.source);
expect(resynthesized.librarySource, original.librarySource);
expect(resynthesized.types.length, original.types.length);
for (int i = 0; i < resynthesized.types.length; i++) {
compareClassElements(
resynthesized.types[i], original.types[i], original.types[i].name);
}
expect(resynthesized.topLevelVariables.length,
original.topLevelVariables.length);
for (int i = 0; i < resynthesized.topLevelVariables.length; i++) {
String name = resynthesized.topLevelVariables[i].name;
compareTopLevelVariableElements(
resynthesized.topLevelVariables[i],
original.topLevelVariables
.singleWhere((TopLevelVariableElement e) => e.name == name),
'variable $name');
}
expect(resynthesized.functions.length, original.functions.length);
for (int i = 0; i < resynthesized.functions.length; i++) {
compareFunctionElements(resynthesized.functions[i], original.functions[i],
'function ${original.functions[i].name}');
}
expect(resynthesized.functionTypeAliases.length,
original.functionTypeAliases.length);
for (int i = 0; i < resynthesized.functionTypeAliases.length; i++) {
compareFunctionTypeAliasElements(
resynthesized.functionTypeAliases[i],
original.functionTypeAliases[i],
original.functionTypeAliases[i].name);
}
expect(resynthesized.enums.length, original.enums.length);
for (int i = 0; i < resynthesized.enums.length; i++) {
compareClassElements(
resynthesized.enums[i], original.enums[i], original.enums[i].name);
}
expect(resynthesized.accessors.length, original.accessors.length);
for (int i = 0; i < resynthesized.accessors.length; i++) {
String name = resynthesized.accessors[i].name;
if (original.accessors[i].isGetter) {
comparePropertyAccessorElements(
resynthesized.accessors[i],
original.accessors
.singleWhere((PropertyAccessorElement e) => e.name == name),
'getter $name');
} else {
comparePropertyAccessorElements(
resynthesized.accessors[i],
original.accessors
.singleWhere((PropertyAccessorElement e) => e.name == name),
'setter $name');
}
}
// Note: no need to test CompilationUnitElementImpl._offsetToElementMap
// since it is built on demand when needed (see
// CompilationUnitElementImpl.getElementAt])
}
void compareConstAstLists(
List<Object> rItems, List<Object> oItems, String desc) {
if (rItems == null && oItems == null) {
return;
}
expect(rItems != null && oItems != null, isTrue);
expect(rItems, hasLength(oItems.length));
for (int i = 0; i < oItems.length; i++) {
Object rItem = rItems[i];
Object oItem = oItems[i];
if (rItem is Expression && oItem is Expression) {
compareConstAsts(rItem, oItem, desc);
} else if (rItem is TypeName && oItem is TypeName) {
compareConstAsts(rItem.name, oItem.name, desc);
} else if (rItem is InterpolationString && oItem is InterpolationString) {
expect(rItem.value, oItem.value);
} else if (rItem is InterpolationExpression &&
oItem is InterpolationExpression) {
compareConstAsts(rItem.expression, oItem.expression, desc);
} else if (rItem is MapLiteralEntry && oItem is MapLiteralEntry) {
compareConstAsts(rItem.key, oItem.key, desc);
compareConstAsts(rItem.value, oItem.value, desc);
} else if (oItem is ConstructorFieldInitializer &&
rItem is ConstructorFieldInitializer) {
compareConstAsts(rItem.fieldName, oItem.fieldName, desc);
if (constantInitializersAreInvalid) {
_assertUnresolvedIdentifier(rItem.expression, desc);
} else {
compareConstAsts(rItem.expression, oItem.expression, desc);
}
} else if (oItem is SuperConstructorInvocation &&
rItem is SuperConstructorInvocation) {
compareElements(rItem.staticElement, oItem.staticElement, desc);
compareConstAsts(rItem.constructorName, oItem.constructorName, desc);
compareConstAstLists(
rItem.argumentList.arguments, oItem.argumentList.arguments, desc);
} else if (oItem is RedirectingConstructorInvocation &&
rItem is RedirectingConstructorInvocation) {
compareElements(rItem.staticElement, oItem.staticElement, desc);
compareConstAsts(rItem.constructorName, oItem.constructorName, desc);
compareConstAstLists(
rItem.argumentList.arguments, oItem.argumentList.arguments, desc);
} else {
fail('$desc Incompatible item types: '
'${rItem.runtimeType} vs. ${oItem.runtimeType}');
}
}
}
void compareConstAsts(AstNode r, AstNode o, String desc) {
if (o == null) {
expect(r, isNull, reason: desc);
} else {
expect(r, isNotNull, reason: desc);
// ConstantAstCloner does not copy static types, and constant values
// computer does not use static types. So, we don't set them during
// resynthesis and should not check them here.
if (o is ParenthesizedExpression) {
// We don't resynthesize parenthesis, so just ignore it.
compareConstAsts(r, o.expression, desc);
} else if (o is SimpleIdentifier && r is SimpleIdentifier) {
expect(r.name, o.name, reason: desc);
compareElements(r.staticElement, o.staticElement, desc);
} else if (o is PrefixedIdentifier && r is SimpleIdentifier) {
// We often don't resynthesize prefixed identifiers.
// We use simple identifiers with correct elements.
compareConstAsts(r, o.identifier, desc);
} else if (o is PrefixedIdentifier && r is PrefixedIdentifier) {
compareConstAsts(r.prefix, o.prefix, desc);
compareConstAsts(r.identifier, o.identifier, desc);
} else if (o is PropertyAccess && r is PropertyAccess) {
compareConstAsts(r.target, o.target, desc);
expect(r.propertyName.name, o.propertyName.name, reason: desc);
compareElements(
r.propertyName.staticElement, o.propertyName.staticElement, desc);
} else if (o is PropertyAccess && r is SimpleIdentifier) {
// We don't resynthesize property access.
// We use simple identifiers with correct elements.
compareConstAsts(r, o.propertyName, desc);
} else if (o is NullLiteral) {
expect(r, new isInstanceOf<NullLiteral>(), reason: desc);
} else if (o is BooleanLiteral && r is BooleanLiteral) {
expect(r.value, o.value, reason: desc);
} else if (o is IntegerLiteral && r is IntegerLiteral) {
expect(r.value, o.value, reason: desc);
} else if (o is DoubleLiteral && r is DoubleLiteral) {
if (r.value != null &&
r.value.isNaN &&
o.value != null &&
o.value.isNaN) {
// NaN is not comparable.
} else {
expect(r.value, o.value, reason: desc);
}
} else if (o is StringInterpolation && r is StringInterpolation) {
compareConstAstLists(r.elements, o.elements, desc);
} else if (o is StringLiteral && r is StringLiteral) {
// We don't keep all the tokens of AdjacentStrings.
// So, we can compare only their values.
expect(r.stringValue, o.stringValue, reason: desc);
} else if (o is SymbolLiteral && r is SymbolLiteral) {
// We don't keep all the tokens of symbol literals.
// So, we can compare only their values.
expect(r.components.map((t) => t.lexeme).join('.'),
o.components.map((t) => t.lexeme).join('.'),
reason: desc);
} else if (o is NamedExpression && r is NamedExpression) {
expect(r.name.label.name, o.name.label.name, reason: desc);
compareConstAsts(r.expression, o.expression, desc);
} else if (o is BinaryExpression && r is BinaryExpression) {
expect(r.operator.lexeme, o.operator.lexeme, reason: desc);
compareConstAsts(r.leftOperand, o.leftOperand, desc);
compareConstAsts(r.rightOperand, o.rightOperand, desc);
} else if (o is PrefixExpression && r is PrefixExpression) {
expect(r.operator.lexeme, o.operator.lexeme, reason: desc);
compareConstAsts(r.operand, o.operand, desc);
} else if (o is ConditionalExpression && r is ConditionalExpression) {
compareConstAsts(r.condition, o.condition, desc);
compareConstAsts(r.thenExpression, o.thenExpression, desc);
compareConstAsts(r.elseExpression, o.elseExpression, desc);
} else if (o is ListLiteral && r is ListLiteral) {
compareConstAstLists(
r.typeArguments?.arguments, o.typeArguments?.arguments, desc);
compareConstAstLists(r.elements, o.elements, desc);
} else if (o is MapLiteral && r is MapLiteral) {
compareConstAstLists(
r.typeArguments?.arguments, o.typeArguments?.arguments, desc);
compareConstAstLists(r.entries, o.entries, desc);
} else if (o is InstanceCreationExpression &&
r is InstanceCreationExpression) {
compareElements(r.staticElement, o.staticElement, desc);
ConstructorName oConstructor = o.constructorName;
ConstructorName rConstructor = r.constructorName;
expect(oConstructor, isNotNull, reason: desc);
expect(rConstructor, isNotNull, reason: desc);
compareConstructorElements(
rConstructor.staticElement, oConstructor.staticElement, desc);
TypeName oType = oConstructor.type;
TypeName rType = rConstructor.type;
expect(oType, isNotNull, reason: desc);
expect(rType, isNotNull, reason: desc);
compareConstAsts(rType.name, oType.name, desc);
compareConstAsts(rConstructor.name, oConstructor.name, desc);
compareConstAstLists(rType.typeArguments?.arguments,
oType.typeArguments?.arguments, desc);
compareConstAstLists(
r.argumentList.arguments, o.argumentList.arguments, desc);
} else if (o is AnnotationImpl && r is AnnotationImpl) {
expect(o.atSign.lexeme, r.atSign.lexeme, reason: desc);
Identifier rName = r.name;
Identifier oName = o.name;
if (oName is PrefixedIdentifier && o.constructorName != null) {
// E.g. `@prefix.cls.ctor`. This gets resynthesized as `@cls.ctor`,
// with `cls.ctor` represented as a PrefixedIdentifier.
expect(rName, new isInstanceOf<PrefixedIdentifier>(), reason: desc);
if (rName is PrefixedIdentifier) {
compareConstAsts(rName.prefix, oName.identifier, desc);
expect(rName.period.lexeme, '.', reason: desc);
compareConstAsts(rName.identifier, o.constructorName, desc);
expect(r.period, isNull, reason: desc);
expect(r.constructorName, isNull, reason: desc);
}
} else {
compareConstAsts(r.name, o.name, desc);
expect(r.period?.lexeme, o.period?.lexeme, reason: desc);
compareConstAsts(r.constructorName, o.constructorName, desc);
}
compareConstAstLists(
r.arguments?.arguments, o.arguments?.arguments, desc);
Element expectedElement = o.element;
if (oName is PrefixedIdentifier && o.constructorName != null) {
// Due to dartbug.com/25706, [o.element] incorrectly points to the
// class rather than the named constructor. Hack around this.
// TODO(paulberry): when dartbug.com/25706 is fixed, remove this.
expectedElement = (expectedElement as ClassElement)
.getNamedConstructor(o.constructorName.name);
expect(expectedElement, isNotNull, reason: desc);
}
compareElements(r.element, expectedElement, desc);
// elementAnnotation should be null; it is only used in the full AST.
expect(o.elementAnnotation, isNull);
expect(r.elementAnnotation, isNull);
} else {
fail('Not implemented for ${r.runtimeType} vs. ${o.runtimeType}');
}
}
}
void compareConstructorElements(ConstructorElement resynthesized,
ConstructorElement original, String desc) {
if (original == null && resynthesized == null) {
return;
}
compareExecutableElements(resynthesized, original, desc);
if (original.isConst) {
ConstructorElementImpl resynthesizedImpl =
getActualElement(resynthesized, desc);
ConstructorElementImpl originalImpl = getActualElement(original, desc);
compareConstAstLists(resynthesizedImpl.constantInitializers,
originalImpl.constantInitializers, desc);
}
if (original.redirectedConstructor == null) {
expect(resynthesized.redirectedConstructor, isNull, reason: desc);
} else {
compareConstructorElements(resynthesized.redirectedConstructor,
original.redirectedConstructor, '$desc redirectedConstructor');
}
checkPossibleMember(resynthesized, original, desc);
}
void compareElementAnnotations(ElementAnnotationImpl resynthesized,
ElementAnnotationImpl original, String desc) {
expect(resynthesized.element, isNotNull, reason: desc);
expect(resynthesized.element.kind, original.element.kind, reason: desc);
expect(resynthesized.element.location, original.element.location,
reason: desc);
expect(resynthesized.compilationUnit, isNotNull, reason: desc);
expect(resynthesized.compilationUnit.location,
original.compilationUnit.location,
reason: desc);
expect(resynthesized.annotationAst, isNotNull, reason: desc);
compareConstAsts(resynthesized.annotationAst, original.annotationAst, desc);
}
void compareElements(Element resynthesized, Element original, String desc) {
ElementImpl rImpl = getActualElement(resynthesized, desc);
ElementImpl oImpl = getActualElement(original, desc);
if (oImpl == null && rImpl == null) {
return;
}
if (oImpl is PrefixElement) {
// TODO(scheglov) prefixes cannot be resynthesized
return;
}
expect(original, isNotNull);
expect(resynthesized, isNotNull);
expect(rImpl.runtimeType, oImpl.runtimeType);
expect(resynthesized.kind, original.kind);
expect(resynthesized.location, original.location, reason: desc);
expect(resynthesized.name, original.name);
expect(resynthesized.nameOffset, original.nameOffset, reason: desc);
expect(resynthesized.documentationComment, original.documentationComment,
reason: desc);
expect(resynthesized.docRange, original.docRange, reason: desc);
compareMetadata(resynthesized.metadata, original.metadata, desc);
// Modifiers are a pain to test via handles. So just test them via the
// actual element.
for (Modifier modifier in Modifier.values) {
bool got = rImpl.hasModifier(modifier);
bool want = oImpl.hasModifier(modifier);
expect(got, want,
reason: 'Mismatch in $desc.$modifier: got $got, want $want');
}
// Validate members.
if (oImpl is Member) {
expect(rImpl, new isInstanceOf<Member>(), reason: desc);
} else {
expect(rImpl, isNot(new isInstanceOf<Member>()), reason: desc);
}
}
void compareExecutableElements(ExecutableElement resynthesized,
ExecutableElement original, String desc) {
compareElements(resynthesized, original, desc);
expect(resynthesized.parameters.length, original.parameters.length);
for (int i = 0; i < resynthesized.parameters.length; i++) {
compareParameterElements(
resynthesized.parameters[i],
original.parameters[i],
'$desc parameter ${original.parameters[i].name}');
}
compareTypes(
resynthesized.returnType, original.returnType, '$desc return type');
compareTypes(resynthesized.type, original.type, desc);
expect(resynthesized.typeParameters.length, original.typeParameters.length);
for (int i = 0; i < resynthesized.typeParameters.length; i++) {
compareTypeParameterElements(
resynthesized.typeParameters[i],
original.typeParameters[i],
'$desc type parameter ${original.typeParameters[i].name}');
}
if (original is! Member) {
List<FunctionElement> rFunctions = resynthesized.functions;
List<FunctionElement> oFunctions = original.functions;
expect(rFunctions, hasLength(oFunctions.length));
for (int i = 0; i < oFunctions.length; i++) {
compareFunctionElements(rFunctions[i], oFunctions[i],
'$desc local function ${oFunctions[i].name}');
}
}
if (original is! Member) {
List<LocalVariableElement> rVariables = resynthesized.localVariables;
List<LocalVariableElement> oVariables = original.localVariables;
expect(rVariables, hasLength(oVariables.length));
for (int i = 0; i < oVariables.length; i++) {
compareVariableElements(rVariables[i], oVariables[i],
'$desc local variable ${oVariables[i].name}');
}
}
}
void compareExportElements(ExportElementImpl resynthesized,
ExportElementImpl original, String desc) {
compareUriReferencedElements(resynthesized, original, desc);
expect(resynthesized.exportedLibrary.location,
original.exportedLibrary.location);
expect(resynthesized.combinators.length, original.combinators.length);
for (int i = 0; i < resynthesized.combinators.length; i++) {
compareNamespaceCombinators(
resynthesized.combinators[i], original.combinators[i]);
}
}
void compareFieldElements(
FieldElementImpl resynthesized, FieldElementImpl original, String desc) {
comparePropertyInducingElements(resynthesized, original, desc);
}
void compareFunctionElements(
FunctionElement resynthesized, FunctionElement original, String desc) {
compareExecutableElements(resynthesized, original, desc);
checkPossibleLocalElements(resynthesized, original);
}
void compareFunctionTypeAliasElements(
FunctionTypeAliasElementImpl resynthesized,
FunctionTypeAliasElementImpl original,
String desc) {
compareElements(resynthesized, original, desc);
expect(resynthesized.parameters.length, original.parameters.length);
for (int i = 0; i < resynthesized.parameters.length; i++) {
compareParameterElements(
resynthesized.parameters[i],
original.parameters[i],
'$desc parameter ${original.parameters[i].name}');
}
compareTypes(
resynthesized.returnType, original.returnType, '$desc return type');
compareTypes(resynthesized.type, original.type, desc);
expect(resynthesized.typeParameters.length, original.typeParameters.length);
for (int i = 0; i < resynthesized.typeParameters.length; i++) {
compareTypeParameterElements(
resynthesized.typeParameters[i],
original.typeParameters[i],
'$desc type parameter ${original.typeParameters[i].name}');
}
}
void compareImportElements(ImportElementImpl resynthesized,
ImportElementImpl original, String desc) {
compareUriReferencedElements(resynthesized, original, desc);
expect(resynthesized.importedLibrary.location,
original.importedLibrary.location);
expect(resynthesized.prefixOffset, original.prefixOffset);
if (original.prefix == null) {
expect(resynthesized.prefix, isNull);
} else {
comparePrefixElements(
resynthesized.prefix, original.prefix, original.prefix.name);
}
expect(resynthesized.combinators.length, original.combinators.length);
for (int i = 0; i < resynthesized.combinators.length; i++) {
compareNamespaceCombinators(
resynthesized.combinators[i], original.combinators[i]);
}
}
void compareMetadata(List<ElementAnnotation> resynthesized,
List<ElementAnnotation> original, String desc) {
expect(resynthesized, hasLength(original.length), reason: desc);
for (int i = 0; i < original.length; i++) {
compareElementAnnotations(
resynthesized[i], original[i], '$desc annotation $i');
}
}
void compareMethodElements(MethodElementImpl resynthesized,
MethodElementImpl original, String desc) {
// TODO(paulberry): do we need to deal with
// MultiplyInheritedMethodElementImpl?
compareExecutableElements(resynthesized, original, desc);
}
void compareNamespaceCombinators(
NamespaceCombinator resynthesized, NamespaceCombinator original) {
if (original is ShowElementCombinatorImpl &&
resynthesized is ShowElementCombinatorImpl) {
expect(resynthesized.shownNames, original.shownNames);
} else if (original is HideElementCombinatorImpl &&
resynthesized is HideElementCombinatorImpl) {
expect(resynthesized.hiddenNames, original.hiddenNames);
} else if (resynthesized.runtimeType != original.runtimeType) {
fail(
'Type mismatch: expected ${original.runtimeType}, got ${resynthesized.runtimeType}');
} else {
fail('Unimplemented comparison for ${original.runtimeType}');
}
}
void compareNamespaces(
Namespace resynthesized, Namespace original, String desc) {
Map<String, Element> resynthesizedMap = resynthesized.definedNames;
Map<String, Element> originalMap = original.definedNames;
expect(resynthesizedMap.keys.toSet(), originalMap.keys.toSet(),
reason: desc);
for (String key in originalMap.keys) {
Element resynthesizedElement = resynthesizedMap[key];
Element originalElement = originalMap[key];
compareElements(resynthesizedElement, originalElement, key);
}
}
void compareParameterElements(
ParameterElement resynthesized, ParameterElement original, String desc) {
compareVariableElements(resynthesized, original, desc);
expect(resynthesized.parameters.length, original.parameters.length);
for (int i = 0; i < resynthesized.parameters.length; i++) {
compareParameterElements(
resynthesized.parameters[i],
original.parameters[i],
'$desc parameter ${original.parameters[i].name}');
}
expect(resynthesized.parameterKind, original.parameterKind);
expect(resynthesized.isInitializingFormal, original.isInitializingFormal,
reason: desc);
expect(resynthesized is FieldFormalParameterElementImpl,
original is FieldFormalParameterElementImpl);
if (resynthesized is FieldFormalParameterElementImpl &&
original is FieldFormalParameterElementImpl) {
if (original.field == null) {
expect(resynthesized.field, isNull, reason: '$desc field');
} else {
expect(resynthesized.field, isNotNull, reason: '$desc field');
compareFieldElements(
resynthesized.field, original.field, '$desc field');
}
}
}
void comparePrefixElements(PrefixElementImpl resynthesized,
PrefixElementImpl original, String desc) {
compareElements(resynthesized, original, desc);
}
void comparePropertyAccessorElements(
PropertyAccessorElementImpl resynthesized,
PropertyAccessorElementImpl original,
String desc) {
// TODO(paulberry): do I need to worry about
// MultiplyInheritedPropertyAccessorElementImpl?
compareExecutableElements(resynthesized, original, desc);
expect(resynthesized.variable, isNotNull);
expect(resynthesized.variable.location, original.variable.location);
}
void comparePropertyInducingElements(
PropertyInducingElementImpl resynthesized,
PropertyInducingElementImpl original,
String desc) {
compareVariableElements(resynthesized, original, desc);
compareTypes(resynthesized.propagatedType, original.propagatedType, desc);
if (original.getter == null) {
expect(resynthesized.getter, isNull);
} else {
expect(resynthesized.getter, isNotNull);
expect(resynthesized.getter.location, original.getter.location);
}
if (original.setter == null) {
expect(resynthesized.setter, isNull);
} else {
expect(resynthesized.setter, isNotNull);
expect(resynthesized.setter.location, original.setter.location);
}
}
void compareTopLevelVariableElements(
TopLevelVariableElementImpl resynthesized,
TopLevelVariableElementImpl original,
String desc) {
comparePropertyInducingElements(resynthesized, original, desc);
}
void compareTypeImpls(
TypeImpl resynthesized, TypeImpl original, String desc) {
expect(resynthesized.element.location, original.element.location,
reason: desc);
expect(resynthesized.name, original.name, reason: desc);
}
void compareTypeParameterElements(TypeParameterElementImpl resynthesized,
TypeParameterElementImpl original, String desc) {
compareElements(resynthesized, original, desc);
compareTypes(resynthesized.type, original.type, desc);
compareTypes(resynthesized.bound, original.bound, '$desc bound');
}
void compareTypes(DartType resynthesized, DartType original, String desc) {
if (original == null) {
expect(resynthesized, isNull, reason: desc);
} else if (resynthesized is InterfaceTypeImpl &&
original is InterfaceTypeImpl) {
compareTypeImpls(resynthesized, original, desc);
expect(resynthesized.typeArguments.length, original.typeArguments.length);
for (int i = 0; i < resynthesized.typeArguments.length; i++) {
compareTypes(resynthesized.typeArguments[i], original.typeArguments[i],
'$desc type argument ${original.typeArguments[i].name}');
}
} else if (resynthesized is TypeParameterTypeImpl &&
original is TypeParameterTypeImpl) {
compareTypeImpls(resynthesized, original, desc);
} else if (resynthesized is DynamicTypeImpl &&
original is DynamicTypeImpl) {
expect(resynthesized, same(original));
} else if (resynthesized is UndefinedTypeImpl &&
original is UndefinedTypeImpl) {
expect(resynthesized, same(original));
} else if (resynthesized is FunctionTypeImpl &&
original is FunctionTypeImpl) {
compareTypeImpls(resynthesized, original, desc);
expect(resynthesized.isInstantiated, original.isInstantiated,
reason: desc);
if (original.element.isSynthetic &&
original.element is FunctionTypeAliasElementImpl &&
resynthesized.element is FunctionTypeAliasElementImpl) {
compareFunctionTypeAliasElements(
resynthesized.element, original.element, desc);
}
expect(resynthesized.typeArguments.length, original.typeArguments.length,
reason: desc);
for (int i = 0; i < resynthesized.typeArguments.length; i++) {
compareTypes(resynthesized.typeArguments[i], original.typeArguments[i],
'$desc type argument ${original.typeArguments[i].name}');
}
if (original.typeParameters == null) {
expect(resynthesized.typeParameters, isNull, reason: desc);
} else {
expect(resynthesized.typeParameters, isNotNull, reason: desc);
expect(
resynthesized.typeParameters.length, original.typeParameters.length,
reason: desc);
for (int i = 0; i < resynthesized.typeParameters.length; i++) {
compareTypeParameterElements(resynthesized.typeParameters[i],
original.typeParameters[i], '$desc type parameter $i');
}
}
expect(resynthesized.typeFormals.length, original.typeFormals.length,
reason: desc);
for (int i = 0; i < resynthesized.typeFormals.length; i++) {
compareTypeParameterElements(resynthesized.typeFormals[i],
original.typeFormals[i], '$desc bound type parameter $i');
}
} else if (resynthesized is VoidTypeImpl && original is VoidTypeImpl) {
expect(resynthesized, same(original));
} else if (resynthesized is DynamicTypeImpl &&
original is UndefinedTypeImpl) {
// TODO(scheglov) In the strong mode constant variable like
// `var V = new Unresolved()` gets `UndefinedTypeImpl`, and it gets
// `DynamicTypeImpl` in the spec mode.
} else if (resynthesized.runtimeType != original.runtimeType) {
fail('Type mismatch: expected ${original.runtimeType},'
' got ${resynthesized.runtimeType} ($desc)');
} else {
fail('Unimplemented comparison for ${original.runtimeType}');
}
}
void compareUriReferencedElements(UriReferencedElementImpl resynthesized,
UriReferencedElementImpl original, String desc) {
compareElements(resynthesized, original, desc);
expect(resynthesized.uri, original.uri);
expect(resynthesized.uriOffset, original.uriOffset, reason: desc);
expect(resynthesized.uriEnd, original.uriEnd, reason: desc);
}
void compareVariableElements(
VariableElement resynthesized, VariableElement original, String desc) {
compareElements(resynthesized, original, desc);
compareTypes(resynthesized.type, original.type, desc);
VariableElementImpl originalActual = getActualElement(original, desc);
if (originalActual is ConstVariableElement) {
VariableElementImpl resynthesizedActual =
getActualElement(resynthesized, desc);
Expression initializer = resynthesizedActual.constantInitializer;
if (constantInitializersAreInvalid) {
_assertUnresolvedIdentifier(initializer, desc);
} else {
compareConstAsts(initializer, originalActual.constantInitializer,
'$desc initializer');
}
}
checkPossibleMember(resynthesized, original, desc);
checkPossibleLocalElements(resynthesized, original);
}
/**
* Serialize the given [library] into a summary. Then create a
* [_TestSummaryResynthesizer] which can deserialize it, along with any
* references it makes to `dart:core`.
*
* Errors will lead to a test failure unless [allowErrors] is `true`.
*/
_TestSummaryResynthesizer encodeLibrary(LibraryElementImpl library,
{bool allowErrors: false, bool dumpSummaries: false}) {
if (!allowErrors) {
assertNoErrors(library.source);
}
addLibrary('dart:core');
return encodeLibraryElement(library, dumpSummaries: dumpSummaries);
}
/**
* Convert the library element [library] into a summary, and then create a
* [_TestSummaryResynthesizer] which can deserialize it.
*
* Caller is responsible for checking the library for errors, and adding any
* dependent libraries using [addLibrary].
*/
_TestSummaryResynthesizer encodeLibraryElement(LibraryElementImpl library,
{bool dumpSummaries: false}) {
Map<String, UnlinkedUnit> unlinkedSummaries = <String, UnlinkedUnit>{};
LinkedLibrary getLinkedSummaryFor(LibraryElement lib) {
LibrarySerializationResult serialized = serializeLibrary(
lib, typeProvider, analysisContext.analysisOptions.strongMode);
for (int i = 0; i < serialized.unlinkedUnits.length; i++) {
unlinkedSummaries[serialized.unitUris[i]] =
new UnlinkedUnit.fromBuffer(serialized.unlinkedUnits[i].toBuffer());
}
return new LinkedLibrary.fromBuffer(serialized.linked.toBuffer());
}
Map<String, LinkedLibrary> linkedSummaries = <String, LinkedLibrary>{
library.source.uri.toString(): getLinkedSummaryFor(library)
};
for (Source source in otherLibrarySources) {
LibraryElement original = resolve2(source);
String uri = source.uri.toString();
linkedSummaries[uri] = getLinkedSummaryFor(original);
}
if (dumpSummaries) {
unlinkedSummaries.forEach((String path, UnlinkedUnit unit) {
print('Unlinked $path: ${JSON.encode(canonicalize(unit))}');
});
linkedSummaries.forEach((String path, LinkedLibrary lib) {
print('Linked $path: ${JSON.encode(canonicalize(lib))}');
});
}
return new _TestSummaryResynthesizer(
null,
analysisContext,
analysisContext.typeProvider,
analysisContext.sourceFactory,
unlinkedSummaries,
linkedSummaries,
options.strongMode);
}
fail_library_hasExtUri() {
checkLibrary('import "dart-ext:doesNotExist.dart";');
}
ElementImpl getActualElement(Element element, String desc) {
if (element == null) {
return null;
} else if (element is ElementImpl) {
return element;
} else if (element is ElementHandle) {
Element actualElement = element.actualElement;
// A handle should never point to a member, because if it did, then
// "is Member" checks on the handle would produce the wrong result.
expect(actualElement, isNot(new isInstanceOf<Member>()), reason: desc);
return getActualElement(actualElement, desc);
} else if (element is Member) {
return getActualElement(element.baseElement, desc);
} else {
fail('Unexpected type for resynthesized ($desc):'
' ${element.runtimeType}');
return null;
}
}
/**
* Resynthesize the library element associated with [uri] using
* [resynthesizer], and verify that it only had to consult one summary in
* order to do so. [original] is consulted merely to verify that no
* unnecessary resynthesis work was performed.
*/
LibraryElementImpl resynthesizeLibraryElement(
_TestSummaryResynthesizer resynthesizer,
String uri,
LibraryElement original) {
LibraryElementImpl resynthesized = resynthesizer.getLibraryElement(uri);
checkMinimalResynthesisWork(resynthesizer, original);
return resynthesized;
}
@override
void setUp() {
super.setUp();
resetWithOptions(options);
}
test_class_abstract() {
checkLibrary('abstract class C {}');
}
test_class_alias() {
checkLibrary('class C = D with E, F; class D {} class E {} class F {}');
}
test_class_alias_abstract() {
checkLibrary('abstract class C = D with E; class D {} class E {}');
}
test_class_alias_documented() {
checkLibrary('''
// Extra comment so doc comment offset != 0
/**
* Docs
*/
class C = D with E;
class D {}
class E {}''');
}
test_class_alias_with_forwarding_constructors() {
addLibrarySource(
'/a.dart',
'''
class Base {
Base._priv();
Base();
Base.noArgs();
Base.requiredArg(x);
Base.positionalArg([x]);
Base.namedArg({x});
factory Base.fact() => null;
factory Base.fact2() = Base.noArgs;
}
''');
checkLibrary('''
import "a.dart";
class M {}
class MixinApp = Base with M;
''');
}
test_class_alias_with_forwarding_constructors_type_substitution() {
checkLibrary('''
class Base<T> {
Base.ctor(T t, List<T> l);
}
class M {}
class MixinApp = Base with M;
''');
}
test_class_alias_with_forwarding_constructors_type_substitution_complex() {
checkLibrary('''
class Base<T> {
Base.ctor(T t, List<T> l);
}
class M {}
class MixinApp<U> = Base<List<U>> with M;
''');
}
test_class_alias_with_mixin_members() {
checkLibrary('''
class C = D with E;
class D {}
class E {
int get a => null;
void set b(int i) {}
void f() {}
int x;
}''');
}
test_class_constructor_const() {
checkLibrary('class C { const C(); }');
}
test_class_constructor_const_external() {
checkLibrary('class C { external const C(); }');
}
test_class_constructor_explicit_named() {
checkLibrary('class C { C.foo(); }');
}
test_class_constructor_explicit_type_params() {
checkLibrary('class C<T, U> { C(); }');
}
test_class_constructor_explicit_unnamed() {
checkLibrary('class C { C(); }');
}
test_class_constructor_external() {
checkLibrary('class C { external C(); }');
}
test_class_constructor_factory() {
checkLibrary('class C { factory C() => null; }');
}
test_class_constructor_field_formal_dynamic_dynamic() {
checkLibrary('class C { dynamic x; C(dynamic this.x); }');
}
test_class_constructor_field_formal_dynamic_typed() {
checkLibrary('class C { dynamic x; C(int this.x); }');
}
test_class_constructor_field_formal_dynamic_untyped() {
checkLibrary('class C { dynamic x; C(this.x); }');
}
test_class_constructor_field_formal_multiple_matching_fields() {
// This is a compile-time error but it should still analyze consistently.
checkLibrary('class C { C(this.x); int x; String x; }', allowErrors: true);
}
test_class_constructor_field_formal_no_matching_field() {
// This is a compile-time error but it should still analyze consistently.
checkLibrary('class C { C(this.x); }', allowErrors: true);
}
test_class_constructor_field_formal_typed_dynamic() {
checkLibrary('class C { num x; C(dynamic this.x); }', allowErrors: true);
}
test_class_constructor_field_formal_typed_typed() {
checkLibrary('class C { num x; C(int this.x); }');
}
test_class_constructor_field_formal_typed_untyped() {
checkLibrary('class C { num x; C(this.x); }');
}
test_class_constructor_field_formal_untyped_dynamic() {
checkLibrary('class C { var x; C(dynamic this.x); }');
}
test_class_constructor_field_formal_untyped_typed() {
checkLibrary('class C { var x; C(int this.x); }');
}
test_class_constructor_field_formal_untyped_untyped() {
checkLibrary('class C { var x; C(this.x); }');
}
test_class_constructor_fieldFormal_named_noDefault() {
checkLibrary('class C { int x; C({this.x}); }');
}
test_class_constructor_fieldFormal_named_withDefault() {
checkLibrary('class C { int x; C({this.x: 42}); }');
}
test_class_constructor_fieldFormal_optional_noDefault() {
checkLibrary('class C { int x; C([this.x]); }');
}
test_class_constructor_fieldFormal_optional_withDefault() {
checkLibrary('class C { int x; C([this.x = 42]); }');
}
test_class_constructor_implicit() {
checkLibrary('class C {}');
}
test_class_constructor_implicit_type_params() {
checkLibrary('class C<T, U> {}');
}
test_class_constructor_params() {
checkLibrary('class C { C(x, y); }');
}
test_class_constructors() {
checkLibrary('class C { C.foo(); C.bar(); }');
}
test_class_documented() {
checkLibrary('''
// Extra comment so doc comment offset != 0
/**
* Docs
*/
class C {}''');
}
test_class_documented_with_references() {
checkLibrary('''
/**
* Docs referring to [D] and [E]
*/
class C {}
class D {}
class E {}''');
}
test_class_documented_with_windows_line_endings() {
checkLibrary('/**\r\n * Docs\r\n */\r\nclass C {}');
}
test_class_field_const() {
checkLibrary('class C { static const int i = 0; }');
}
test_class_field_implicit_type() {
checkLibrary('class C { var x; }');
}
test_class_field_static() {
checkLibrary('class C { static int i; }');
}
test_class_fields() {
checkLibrary('class C { int i; int j; }');
}
test_class_getter_abstract() {
checkLibrary('abstract class C { int get x; }');
}
test_class_getter_external() {
checkLibrary('class C { external int get x; }');
}
test_class_getter_implicit_return_type() {
checkLibrary('class C { get x => null; }');
}
test_class_getter_static() {
checkLibrary('class C { static int get x => null; }');
}
test_class_getters() {
checkLibrary('class C { int get x => null; get y => null; }');
}
test_class_implicitField_getterFirst() {
checkLibrary('class C { int get x => 0; void set x(int value) {} }');
}
test_class_implicitField_setterFirst() {
checkLibrary('class C { void set x(int value) {} int get x => 0; }');
}
test_class_interfaces() {
checkLibrary('class C implements D, E {} class D {} class E {}');
}
test_class_method_abstract() {
checkLibrary('abstract class C { f(); }');
}
test_class_method_external() {
checkLibrary('class C { external f(); }');
}
test_class_method_params() {
checkLibrary('class C { f(x, y) {} }');
}
test_class_method_static() {
checkLibrary('class C { static f() {} }');
}
test_class_methods() {
checkLibrary('class C { f() {} g() {} }');
}
test_class_mixins() {
checkLibrary('class C extends Object with D, E {} class D {} class E {}');
}
test_class_setter_abstract() {
checkLibrary('abstract class C { void set x(int value); }');
}
test_class_setter_external() {
checkLibrary('class C { external void set x(int value); }');
}
test_class_setter_implicit_param_type() {
checkLibrary('class C { void set x(value) {} }');
}
test_class_setter_implicit_return_type() {
checkLibrary('class C { set x(int value) {} }');
}
test_class_setter_static() {
checkLibrary('class C { static void set x(int value) {} }');
}
test_class_setters() {
checkLibrary('class C { void set x(int value) {} set y(value) {} }');
}
test_class_supertype() {
checkLibrary('class C extends D {} class D {}');
}
test_class_type_parameters() {
checkLibrary('class C<T, U> {}');
}
test_class_type_parameters_bound() {
checkLibrary('class C<T extends Object, U extends D> {} class D {}');
}
test_class_type_parameters_f_bound_complex() {
checkLibrary('class C<T extends List<U>, U> {}');
}
test_class_type_parameters_f_bound_simple() {
checkLibrary('class C<T extends U, U> {}');
}
test_classes() {
checkLibrary('class C {} class D {}');
}
test_const_invalid_field_const() {
constantInitializersAreInvalid = true;
checkLibrary(
r'''
class C {
static const f = 1 + foo();
}
int foo() => 42;
''',
allowErrors: true);
}
test_const_invalid_field_final() {
constantInitializersAreInvalid = true;
checkLibrary(
r'''
class C {
final f = 1 + foo();
}
int foo() => 42;
''',
allowErrors: true);
}
test_const_invalid_topLevel() {
constantInitializersAreInvalid = true;
checkLibrary(
r'''
const v = 1 + foo();
int foo() => 42;
''',
allowErrors: true);
}
test_const_invokeConstructor_generic_named() {
checkLibrary(r'''
class C<K, V> {
const C.named(K k, V v);
}
const V = const C<int, String>.named(1, '222');
''');
}
test_const_invokeConstructor_generic_named_imported() {
addLibrarySource(
'/a.dart',
r'''
class C<K, V> {
const C.named(K k, V v);
}
''');
checkLibrary(r'''
import 'a.dart';
const V = const C<int, String>.named(1, '222');
''');
}
test_const_invokeConstructor_generic_named_imported_withPrefix() {
addLibrarySource(
'/a.dart',
r'''
class C<K, V> {
const C.named(K k, V v);
}
''');
checkLibrary(r'''
import 'a.dart' as p;
const V = const p.C<int, String>.named(1, '222');
''');
}
test_const_invokeConstructor_generic_noTypeArguments() {
checkLibrary(r'''
class C<K, V> {
const C();
}
const V = const C();
''');
}
test_const_invokeConstructor_generic_unnamed() {
checkLibrary(r'''
class C<K, V> {
const C();
}
const V = const C<int, String>();
''');
}
test_const_invokeConstructor_generic_unnamed_imported() {
addLibrarySource(
'/a.dart',
r'''
class C<K, V> {
const C();
}
''');
checkLibrary(r'''
import 'a.dart';
const V = const C<int, String>();
''');
}
test_const_invokeConstructor_generic_unnamed_imported_withPrefix() {
addLibrarySource(
'/a.dart',
r'''
class C<K, V> {
const C();
}
''');
checkLibrary(r'''
import 'a.dart' as p;
const V = const p.C<int, String>();
''');
}
test_const_invokeConstructor_named() {
checkLibrary(r'''
class C {
const C.named(bool a, int b, int c, {String d, double e});
}
const V = const C.named(true, 1, 2, d: 'ccc', e: 3.4);
''');
}
test_const_invokeConstructor_named_imported() {
addLibrarySource(
'/a.dart',
r'''
class C {
const C.named();
}
''');
checkLibrary(r'''
import 'a.dart';
const V = const C.named();
''');
}
test_const_invokeConstructor_named_imported_withPrefix() {
addLibrarySource(
'/a.dart',
r'''
class C {
const C.named();
}
''');
checkLibrary(r'''
import 'a.dart' as p;
const V = const p.C.named();
''');
}
test_const_invokeConstructor_named_unresolved() {
checkLibrary(
r'''
class C {}
const V = const C.named();
''',
allowErrors: true);
}
test_const_invokeConstructor_named_unresolved2() {
checkLibrary(
r'''
const V = const C.named();
''',
allowErrors: true);
}
test_const_invokeConstructor_named_unresolved3() {
addLibrarySource(
'/a.dart',
r'''
class C {
}
''');
checkLibrary(
r'''
import 'a.dart' as p;
const V = const p.C.named();
''',
allowErrors: true);
}
test_const_invokeConstructor_named_unresolved4() {
addLibrarySource('/a.dart', '');
checkLibrary(
r'''
import 'a.dart' as p;
const V = const p.C.named();
''',
allowErrors: true);
}
test_const_invokeConstructor_named_unresolved5() {
checkLibrary(
r'''
const V = const p.C.named();
''',
allowErrors: true);
}
test_const_invokeConstructor_unnamed() {
checkLibrary(r'''
class C {
const C();
}
const V = const C();
''');
}
test_const_invokeConstructor_unnamed_imported() {
addLibrarySource(
'/a.dart',
r'''
class C {
const C();
}
''');
checkLibrary(r'''
import 'a.dart';
const V = const C();
''');
}
test_const_invokeConstructor_unnamed_imported_withPrefix() {
addLibrarySource(
'/a.dart',
r'''
class C {
const C();
}
''');
checkLibrary(r'''
import 'a.dart' as p;
const V = const p.C();
''');
}
test_const_invokeConstructor_unnamed_unresolved() {
checkLibrary(
r'''
const V = const C();
''',
allowErrors: true);
}
test_const_invokeConstructor_unnamed_unresolved2() {
addLibrarySource('/a.dart', '');
checkLibrary(
r'''
import 'a.dart' as p;
const V = const p.C();
''',
allowErrors: true);
}
test_const_invokeConstructor_unnamed_unresolved3() {
checkLibrary(
r'''
const V = const p.C();
''',
allowErrors: true);
}
test_const_length_ofClassConstField() {
checkLibrary(r'''
class C {
static const String F = '';
}
const int v = C.F.length;
''');
}
test_const_length_ofClassConstField_imported() {
addLibrarySource(
'/a.dart',
r'''
class C {
static const String F = '';
}
''');
checkLibrary(r'''
import 'a.dart';
const int v = C.F.length;
''');
}
test_const_length_ofClassConstField_imported_withPrefix() {
addLibrarySource(
'/a.dart',
r'''
class C {
static const String F = '';
}
''');
checkLibrary(r'''
import 'a.dart' as p;
const int v = p.C.F.length;
''');
}
test_const_length_ofStringLiteral() {
checkLibrary(r'''
const v = 'abc'.length;
''');
}
test_const_length_ofTopLevelVariable() {
checkLibrary(r'''
const String S = 'abc';
const v = S.length;
''');
}
test_const_length_ofTopLevelVariable_imported() {
addLibrarySource(
'/a.dart',
r'''
const String S = 'abc';
''');
checkLibrary(r'''
import 'a.dart';
const v = S.length;
''');
}
test_const_length_ofTopLevelVariable_imported_withPrefix() {
addLibrarySource(
'/a.dart',
r'''
const String S = 'abc';
''');
checkLibrary(r'''
import 'a.dart' as p;
const v = p.S.length;
''');
}
test_const_length_staticMethod() {
checkLibrary(r'''
class C {
static int length() => 42;
}
const v = C.length;
''');
}
test_const_parameterDefaultValue_initializingFormal_functionTyped() {
checkLibrary(r'''
class C {
final x;
const C({this.x: foo});
}
int foo() => 42;
''');
}
test_const_parameterDefaultValue_initializingFormal_named() {
checkLibrary(r'''
class C {
final x;
const C({this.x: 1 + 2});
}
''');
}
test_const_parameterDefaultValue_initializingFormal_positional() {
checkLibrary(r'''
class C {
final x;
const C([this.x = 1 + 2]);
}
''');
}
test_const_parameterDefaultValue_normal() {
checkLibrary(r'''
class C {
const C.positional([p = 1 + 2]);
const C.named({p: 1 + 2});
void methodPositional([p = 1 + 2]) {}
void methodPositionalWithoutDefault([p]) {}
void methodNamed({p: 1 + 2}) {}
void methodNamedWithoutDefault({p}) {}
}
''');
}
test_const_reference_staticField() {
checkLibrary(r'''
class C {
static const int F = 42;
}
const V = C.F;
''');
}
test_const_reference_staticField_imported() {
addLibrarySource(
'/a.dart',
r'''
class C {
static const int F = 42;
}
''');
checkLibrary(r'''
import 'a.dart';
const V = C.F;
''');
}
test_const_reference_staticField_imported_withPrefix() {
addLibrarySource(
'/a.dart',
r'''
class C {
static const int F = 42;
}
''');
checkLibrary(r'''
import 'a.dart' as p;
const V = p.C.F;
''');
}
test_const_reference_staticMethod() {
checkLibrary(r'''
class C {
static int m(int a, String b) => 42;
}
const V = C.m;
''');
}
test_const_reference_staticMethod_imported() {
addLibrarySource(
'/a.dart',
r'''
class C {
static int m(int a, String b) => 42;
}
''');
checkLibrary(r'''
import 'a.dart';
const V = C.m;
''');
}
test_const_reference_staticMethod_imported_withPrefix() {
addLibrarySource(
'/a.dart',
r'''
class C {
static int m(int a, String b) => 42;
}
''');
checkLibrary(r'''
import 'a.dart' as p;
const V = p.C.m;
''');
}
test_const_reference_topLevelFunction() {
checkLibrary(r'''
foo() {}
const V = foo;
''');
}
test_const_reference_topLevelFunction_imported() {
addLibrarySource(
'/a.dart',
r'''
foo() {}
''');
checkLibrary(r'''
import 'a.dart';
const V = foo;
''');
}
test_const_reference_topLevelFunction_imported_withPrefix() {
addLibrarySource(
'/a.dart',
r'''
foo() {}
''');
checkLibrary(r'''
import 'a.dart' as p;
const V = p.foo;
''');
}
test_const_reference_topLevelVariable() {
checkLibrary(r'''
const A = 1;
const B = A + 2;
''');
}
test_const_reference_topLevelVariable_imported() {
addLibrarySource(
'/a.dart',
r'''
const A = 1;
''');
checkLibrary(r'''
import 'a.dart';
const B = A + 2;
''');
}
test_const_reference_topLevelVariable_imported_withPrefix() {
addLibrarySource(
'/a.dart',
r'''
const A = 1;
''');
checkLibrary(r'''
import 'a.dart' as p;
const B = p.A + 2;
''');
}
test_const_reference_type() {
checkLibrary(r'''
class C {}
class D<T> {}
enum E {a, b, c}
typedef F(int a, String b);
const vDynamic = dynamic;
const vNull = Null;
const vObject = Object;
const vClass = C;
const vGenericClass = D;
const vEnum = E;
const vFunctionTypeAlias = F;
''');
}
test_const_reference_type_imported() {
addLibrarySource(
'/a.dart',
r'''
class C {}
enum E {a, b, c}
typedef F(int a, String b);
''');
checkLibrary(r'''
import 'a.dart';
const vClass = C;
const vEnum = E;
const vFunctionTypeAlias = F;
''');
}
test_const_reference_type_imported_withPrefix() {
addLibrarySource(
'/a.dart',
r'''
class C {}
enum E {a, b, c}
typedef F(int a, String b);
''');
checkLibrary(r'''
import 'a.dart' as p;
const vClass = p.C;
const vEnum = p.E;
const vFunctionTypeAlias = p.F;
''');
}
test_const_reference_unresolved_prefix0() {
checkLibrary(
r'''
const V = foo;
''',
allowErrors: true);
}
test_const_reference_unresolved_prefix1() {
checkLibrary(
r'''
class C {}
const v = C.foo;
''',
allowErrors: true);
}
test_const_reference_unresolved_prefix2() {
addLibrarySource(
'/foo.dart',
'''
class C {}
''');
checkLibrary(
r'''
import 'foo.dart' as p;
const v = p.C.foo;
''',
allowErrors: true);
}
test_const_topLevel_binary() {
checkLibrary(r'''
const vEqual = 1 == 2;
const vAnd = true && false;
const vOr = false || true;
const vBitXor = 1 ^ 2;
const vBitAnd = 1 & 2;
const vBitOr = 1 | 2;
const vBitShiftLeft = 1 << 2;
const vBitShiftRight = 1 >> 2;
const vAdd = 1 + 2;
const vSubtract = 1 - 2;
const vMiltiply = 1 * 2;
const vDivide = 1 / 2;
const vFloorDivide = 1 ~/ 2;
const vModulo = 1 % 2;
const vGreater = 1 > 2;
const vGreaterEqual = 1 >= 2;
const vLess = 1 < 2;
const vLessEqual = 1 <= 2;
''');
}
test_const_topLevel_conditional() {
checkLibrary(r'''
const vConditional = (1 == 2) ? 11 : 22;
''');
}
test_const_topLevel_identical() {
checkLibrary(r'''
const vIdentical = (1 == 2) ? 11 : 22;
''');
}
test_const_topLevel_literal() {
checkLibrary(r'''
const vNull = null;
const vBoolFalse = false;
const vBoolTrue = true;
const vInt = 1;
const vIntLong = 0x9876543210987654321;
const vDouble = 2.3;
const vString = 'abc';
const vStringConcat = 'aaa' 'bbb';
const vStringInterpolation = 'aaa ${true} ${42} bbb';
const vSymbol = #aaa.bbb.ccc;
''');
}
test_const_topLevel_prefix() {
checkLibrary(r'''
const vNotEqual = 1 != 2;
const vNot = !true;
const vNegate = -1;
const vComplement = ~1;
''');
}
test_const_topLevel_typedList() {
checkLibrary(r'''
const vNull = const <Null>[];
const vDynamic = const <dynamic>[1, 2, 3];
const vInterfaceNoTypeParameters = const <int>[1, 2, 3];
const vInterfaceNoTypeArguments = const <List>[];
const vInterfaceWithTypeArguments = const <List<String>>[];
const vInterfaceWithTypeArguments2 = const <Map<int, List<String>>>[];
''');
}
test_const_topLevel_typedList_imported() {
addLibrarySource('/a.dart', 'class C {}');
checkLibrary(r'''
import 'a.dart';
const v = const <C>[];
''');
}
test_const_topLevel_typedList_importedWithPrefix() {
addLibrarySource('/a.dart', 'class C {}');
checkLibrary(r'''
import 'a.dart' as p;
const v = const <p.C>[];
''');
}
test_const_topLevel_typedMap() {
checkLibrary(r'''
const vDynamic1 = const <dynamic, int>{};
const vDynamic2 = const <int, dynamic>{};
const vInterface = const <int, String>{};
const vInterfaceWithTypeArguments = const <int, List<String>>{};
''');
}
test_const_topLevel_untypedList() {
checkLibrary(r'''
const v = const [1, 2, 3];
''');
}
test_const_topLevel_untypedMap() {
checkLibrary(r'''
const v = const {0: 'aaa', 1: 'bbb', 2: 'ccc'};
''');
}
test_constExpr_pushReference_field_simpleIdentifier() {
checkLibrary('''
class C {
static const a = b;
static const b = null;
}
''');
}
test_constExpr_pushReference_staticMethod_simpleIdentifier() {
checkLibrary('''
class C {
static const a = m;
static m() {}
}
''');
}
test_constructor_documented() {
checkLibrary('''
class C {
/**
* Docs
*/
C();
}''');
}
test_constructor_initializers_field() {
checkLibrary('''
class C {
final x;
const C() : x = 42;
}
''');
}
test_constructor_initializers_field_notConst() {
constantInitializersAreInvalid = true;
checkLibrary(
'''
class C {
final x;
const A() : x = foo();
}
int foo() => 42;
''',
allowErrors: true);
}
test_constructor_initializers_field_withParameter() {
checkLibrary('''
class C {
final x;
const C(int p) : x = 1 + p;
}
''');
}
test_constructor_initializers_superInvocation_named() {
checkLibrary('''
class A {
const A.aaa(int p);
}
class C extends A {
const C() : super.aaa(42);
}
''');
}
test_constructor_initializers_superInvocation_unnamed() {
checkLibrary('''
class A {
const A(int p);
}
class C extends A {
const C.ccc() : super(42);
}
''');
}
test_constructor_initializers_thisInvocation_named() {
checkLibrary('''
class C {
const C() : this.named(1, 'bbb');
const C.named(int a, String b);
}
''');
}
test_constructor_initializers_thisInvocation_unnamed() {
checkLibrary('''
class C {
const C.named() : this(1, 'bbb');
const C(int a, String b);
}
''');
}
test_constructor_redirected_factory_named() {
checkLibrary('''
class C {
factory C() = D.named;
C._();
}
class D extends C {
D.named() : super._();
}
''');
}
test_constructor_redirected_factory_named_generic() {
checkLibrary('''
class C<T, U> {
factory C() = D<U, T>.named;
C._();
}
class D<T, U> extends C<U, T> {
D.named() : super._();
}
''');
}
test_constructor_redirected_factory_named_imported() {
addLibrarySource(
'/foo.dart',
'''
import 'test.dart';
class D extends C {
D.named() : super._();
}
''');
checkLibrary('''
import 'foo.dart';
class C {
factory C() = D.named;
C._();
}
''');
}
test_constructor_redirected_factory_named_imported_generic() {
addLibrarySource(
'/foo.dart',
'''
import 'test.dart';
class D<T, U> extends C<U, T> {
D.named() : super._();
}
''');
checkLibrary('''
import 'foo.dart';
class C<T, U> {
factory C() = D<U, T>.named;
C._();
}
''');
}
test_constructor_redirected_factory_named_prefixed() {
addLibrarySource(
'/foo.dart',
'''
import 'test.dart';
class D extends C {
D.named() : super._();
}
''');
checkLibrary('''
import 'foo.dart' as foo;
class C {
factory C() = foo.D.named;
C._();
}
''');
}
test_constructor_redirected_factory_named_prefixed_generic() {
addLibrarySource(
'/foo.dart',
'''
import 'test.dart';
class D<T, U> extends C<U, T> {
D.named() : super._();
}
''');
checkLibrary('''
import 'foo.dart' as foo;
class C<T, U> {
factory C() = foo.D<U, T>.named;
C._();
}
''');
}
test_constructor_redirected_factory_unnamed() {
checkLibrary('''
class C {
factory C() = D;
C._();
}
class D extends C {
D() : super._();
}
''');
}
test_constructor_redirected_factory_unnamed_generic() {
checkLibrary('''
class C<T, U> {
factory C() = D<U, T>;
C._();
}
class D<T, U> extends C<U, T> {
D() : super._();
}
''');
}
test_constructor_redirected_factory_unnamed_imported() {
addLibrarySource(
'/foo.dart',
'''
import 'test.dart';
class D extends C {
D() : super._();
}
''');
checkLibrary('''
import 'foo.dart';
class C {
factory C() = D;
C._();
}
''');
}
test_constructor_redirected_factory_unnamed_imported_generic() {
addLibrarySource(
'/foo.dart',
'''
import 'test.dart';
class D<T, U> extends C<U, T> {
D() : super._();
}
''');
checkLibrary('''
import 'foo.dart';
class C<T, U> {
factory C() = D<U, T>;
C._();
}
''');
}
test_constructor_redirected_factory_unnamed_prefixed() {
addLibrarySource(
'/foo.dart',
'''
import 'test.dart';
class D extends C {
D() : super._();
}
''');
checkLibrary('''
import 'foo.dart' as foo;
class C {
factory C() = foo.D;
C._();
}
''');
}
test_constructor_redirected_factory_unnamed_prefixed_generic() {
addLibrarySource(
'/foo.dart',
'''
import 'test.dart';
class D<T, U> extends C<U, T> {
D() : super._();
}
''');
checkLibrary('''
import 'foo.dart' as foo;
class C<T, U> {
factory C() = foo.D<U, T>;
C._();
}
''');
}
test_constructor_redirected_thisInvocation_named() {
checkLibrary('''
class C {
C.named();
C() : this.named();
}
''');
}
test_constructor_redirected_thisInvocation_named_generic() {
checkLibrary('''
class C<T> {
C.named();
C() : this.named();
}
''');
}
test_constructor_redirected_thisInvocation_unnamed() {
checkLibrary('''
class C {
C();
C.named() : this();
}
''');
}
test_constructor_redirected_thisInvocation_unnamed_generic() {
checkLibrary('''
class C<T> {
C();
C.named() : this();
}
''');
}
test_core() {
String uri = 'dart:core';
LibraryElementImpl original =
resolve2(analysisContext2.sourceFactory.forUri(uri));
LibraryElementImpl resynthesized = resynthesizeLibraryElement(
encodeLibraryElement(original), uri, original);
checkLibraryElements(original, resynthesized);
}
test_enum_documented() {
checkLibrary('''
// Extra comment so doc comment offset != 0
/**
* Docs
*/
enum E { v }''');
}
test_enum_value_documented() {
checkLibrary('''
enum E {
/**
* Docs
*/
v
}''');
}
test_enum_values() {
checkLibrary('enum E { v1, v2 }');
}
test_enums() {
checkLibrary('enum E1 { v1 } enum E2 { v2 }');
}
test_export_class() {
addLibrarySource('/a.dart', 'class C {}');
checkLibrary('export "a.dart";');
}
test_export_class_type_alias() {
addLibrarySource(
'/a.dart', 'class C {} exends _D with _E; class _D {} class _E {}');
checkLibrary('export "a.dart";');
}
test_export_function() {
addLibrarySource('/a.dart', 'f() {}');
checkLibrary('export "a.dart";');
}
test_export_getter() {
addLibrarySource('/a.dart', 'get f() => null;');
checkLibrary('export "a.dart";');
}
test_export_hide() {
addLibrary('dart:async');
checkLibrary('export "dart:async" hide Stream, Future;');
}
test_export_multiple_combinators() {
addLibrary('dart:async');
checkLibrary('export "dart:async" hide Stream show Future;');
}
test_export_setter() {
addLibrarySource('/a.dart', 'void set f(value) {}');
checkLibrary('export "a.dart";');
}
test_export_show() {
addLibrary('dart:async');
checkLibrary('export "dart:async" show Future, Stream;');
}
test_export_typedef() {
addLibrarySource('/a.dart', 'typedef F();');
checkLibrary('export "a.dart";');
}
test_export_variable() {
addLibrarySource('/a.dart', 'var x;');
checkLibrary('export "a.dart";');
}
test_export_variable_const() {
addLibrarySource('/a.dart', 'const x = 0;');
checkLibrary('export "a.dart";');
}
test_export_variable_final() {
addLibrarySource('/a.dart', 'final x = 0;');
checkLibrary('export "a.dart";');
}
test_exports() {
addLibrarySource('/a.dart', 'library a;');
addLibrarySource('/b.dart', 'library b;');
checkLibrary('export "a.dart"; export "b.dart";');
}
test_field_documented() {
checkLibrary('''
class C {
/**
* Docs
*/
var x;
}''');
}
test_field_formal_param_inferred_type_implicit() {
checkLibrary('class C extends D { var v; C(this.v); }'
' abstract class D { int get v; }');
}
test_field_inferred_type_nonStatic_explicit_initialized() {
checkLibrary('class C { num v = 0; }');
}
test_field_inferred_type_nonStatic_implicit_initialized() {
checkLibrary('class C { var v = 0; }');
}
test_field_inferred_type_nonStatic_implicit_uninitialized() {
checkLibrary(
'class C extends D { var v; } abstract class D { int get v; }');
}
test_field_inferred_type_static_implicit_initialized() {
checkLibrary('class C { static var v = 0; }');
}
test_field_propagatedType_const_noDep() {
checkLibrary('''
class C {
static const x = 0;
}''');
}
test_field_propagatedType_final_dep_inLib() {
addLibrarySource('/a.dart', 'final a = 1;');
checkLibrary('''
import "a.dart";
class C {
final b = a / 2;
}''');
}
test_field_propagatedType_final_dep_inPart() {
addNamedSource('/a.dart', 'part of lib; final a = 1;');
checkLibrary('''
library lib;
part "a.dart";
class C {
final b = a / 2;
}''');
}
test_field_propagatedType_final_noDep_instance() {
checkLibrary('''
class C {
final x = 0;
}''');
}
test_field_propagatedType_final_noDep_static() {
checkLibrary('''
class C {
static final x = 0;
}''');
}
test_function_documented() {
checkLibrary('''
// Extra comment so doc comment offset != 0
/**
* Docs
*/
f() {}''');
}
test_function_entry_point() {
checkLibrary('main() {}');
}
test_function_entry_point_in_export() {
addLibrarySource('/a.dart', 'library a; main() {}');
checkLibrary('export "a.dart";');
}
test_function_entry_point_in_export_hidden() {
addLibrarySource('/a.dart', 'library a; main() {}');
checkLibrary('export "a.dart" hide main;');
}
test_function_entry_point_in_part() {
addNamedSource('/a.dart', 'part of my.lib; main() {}');
checkLibrary('library my.lib; part "a.dart";');
}
test_function_external() {
checkLibrary('external f();');
}
test_function_parameter_kind_named() {
checkLibrary('f({x}) {}');
}
test_function_parameter_kind_positional() {
checkLibrary('f([x]) {}');
}
test_function_parameter_kind_required() {
checkLibrary('f(x) {}');
}
test_function_parameter_parameters() {
checkLibrary('f(g(x, y)) {}');
}
test_function_parameter_return_type() {
checkLibrary('f(int g()) {}');
}
test_function_parameter_return_type_void() {
checkLibrary('f(void g()) {}');
}
test_function_parameter_type() {
checkLibrary('f(int i) {}');
}
test_function_parameters() {
checkLibrary('f(x, y) {}');
}
test_function_return_type() {
checkLibrary('int f() => null;');
}
test_function_return_type_implicit() {
checkLibrary('f() => null;');
}
test_function_return_type_void() {
checkLibrary('void f() {}');
}
test_function_type_parameter() {
resetWithOptions(new AnalysisOptionsImpl()..enableGenericMethods = true);
checkLibrary('T f<T, U>(U u) => null;');
}
test_function_type_parameter_with_function_typed_parameter() {
resetWithOptions(new AnalysisOptionsImpl()..enableGenericMethods = true);
checkLibrary('void f<T, U>(T x(U u)) {}');
}
test_functions() {
checkLibrary('f() {} g() {}');
}
test_generic_gClass_gMethodStatic() {
resetWithOptions(new AnalysisOptionsImpl()..enableGenericMethods = true);
checkLibrary('''
class C<T, U> {
static void m<V, W>(V v, W w) {
void f<X, Y>(V v, W w, X x, Y y) {
}
}
}
''');
}
test_getElement_constructor_named() {
ConstructorElement original = resolve2(addSource('class C { C.named(); }'))
.getType('C')
.getNamedConstructor('named');
expect(original, isNotNull);
ConstructorElement resynthesized = validateGetElement(original);
compareConstructorElements(resynthesized, original, 'C.constructor named');
}
test_getElement_constructor_unnamed() {
ConstructorElement original =
resolve2(addSource('class C { C(); }')).getType('C').unnamedConstructor;
expect(original, isNotNull);
ConstructorElement resynthesized = validateGetElement(original);
compareConstructorElements(resynthesized, original, 'C.constructor');
}
test_getElement_field() {
FieldElement original =
resolve2(addSource('class C { var f; }')).getType('C').getField('f');
expect(original, isNotNull);
FieldElement resynthesized = validateGetElement(original);
compareFieldElements(resynthesized, original, 'C.field f');
}
test_getElement_getter() {
PropertyAccessorElement original =
resolve2(addSource('class C { get f => null; }'))
.getType('C')
.getGetter('f');
expect(original, isNotNull);
PropertyAccessorElement resynthesized = validateGetElement(original);
comparePropertyAccessorElements(resynthesized, original, 'C.getter f');
}
test_getElement_method() {
MethodElement original =
resolve2(addSource('class C { f() {} }')).getType('C').getMethod('f');
expect(original, isNotNull);
MethodElement resynthesized = validateGetElement(original);
compareMethodElements(resynthesized, original, 'C.method f');
}
test_getElement_operator() {
MethodElement original =
resolve2(addSource('class C { operator+(x) => null; }'))
.getType('C')
.getMethod('+');
expect(original, isNotNull);
MethodElement resynthesized = validateGetElement(original);
compareMethodElements(resynthesized, original, 'C.operator+');
}
test_getElement_setter() {
PropertyAccessorElement original =
resolve2(addSource('class C { void set f(value) {} }'))
.getType('C')
.getSetter('f');
expect(original, isNotNull);
PropertyAccessorElement resynthesized = validateGetElement(original);
comparePropertyAccessorElements(resynthesized, original, 'C.setter f');
}
test_getElement_unit() {
Source source = addSource('class C { f() {} }');
CompilationUnitElement original = resolve2(source).definingCompilationUnit;
expect(original, isNotNull);
CompilationUnitElement resynthesized = validateGetElement(original);
compareCompilationUnitElements(resynthesized, original);
}
test_getter_documented() {
checkLibrary('''
// Extra comment so doc comment offset != 0
/**
* Docs
*/
get x => null;''');
}
test_getter_external() {
checkLibrary('external int get x;');
}
test_getter_inferred_type_nonStatic_implicit_return() {
checkLibrary(
'class C extends D { get f => null; } abstract class D { int get f; }');
}
test_getters() {
checkLibrary('int get x => null; get y => null;');
}
test_implicitTopLevelVariable_getterFirst() {
checkLibrary('int get x => 0; void set x(int value) {}');
}
test_implicitTopLevelVariable_setterFirst() {
checkLibrary('void set x(int value) {} int get x => 0;');
}
test_import_deferred() {
addLibrarySource('/a.dart', 'f() {}');
checkLibrary('import "a.dart" deferred as p; main() { p.f(); }');
}
test_import_hide() {
addLibrary('dart:async');
checkLibrary('import "dart:async" hide Stream, Completer; Future f;');
}
test_import_multiple_combinators() {
addLibrary('dart:async');
checkLibrary('import "dart:async" hide Stream show Future; Future f;');
}
test_import_prefixed() {
addLibrarySource('/a.dart', 'library a; class C {}');
checkLibrary('import "a.dart" as a; a.C c;');
}
test_import_show() {
addLibrary('dart:async');
checkLibrary('import "dart:async" show Future, Stream; Future f;');
}
test_imports() {
addLibrarySource('/a.dart', 'library a; class C {}');
addLibrarySource('/b.dart', 'library b; class D {}');
checkLibrary('import "a.dart"; import "b.dart"; C c; D d;');
}
test_inferred_type_is_typedef() {
checkLibrary('typedef int F(String s);'
' class C extends D { var v; }'
' abstract class D { F get v; }');
}
test_inferred_type_refers_to_bound_type_param() {
checkLibrary('class C<T> extends D<int, T> { var v; }'
' abstract class D<U, V> { Map<V, U> get v; }');
}
test_inferred_type_refers_to_function_typed_parameter_type_generic_class() {
checkLibrary('class C<T, U> extends D<U, int> { void f(int x, g) {} }'
' abstract class D<V, W> { void f(int x, W g(V s)); }');
}
test_inferred_type_refers_to_function_typed_parameter_type_other_lib() {
addLibrarySource(
'/a.dart', 'import "b.dart"; abstract class D extends E {}');
addLibrarySource(
'/b.dart', 'abstract class E { void f(int x, int g(String s)); }');
checkLibrary('import "a.dart"; class C extends D { void f(int x, g) {} }');
}
test_inferred_type_refers_to_method_function_typed_parameter_type() {
checkLibrary('class C extends D { void f(int x, g) {} }'
' abstract class D { void f(int x, int g(String s)); }');
}
test_inferred_type_refers_to_setter_function_typed_parameter_type() {
checkLibrary('class C extends D { void set f(g) {} }'
' abstract class D { void set f(int g(String s)); }');
}
test_library() {
checkLibrary('');
}
test_library_documented() {
checkLibrary('''
// Extra comment so doc comment offset != 0
/**
* Docs
*/
library foo;''');
}
test_library_name_with_spaces() {
checkLibrary('library foo . bar ;');
}
test_library_named() {
checkLibrary('library foo.bar;');
}
test_localFunctions() {
checkLibrary(r'''
f() {
f1() {}
{
f2() {}
}
}
''');
}
test_localFunctions_inConstructor() {
checkLibrary(r'''
class C {
C() {
f() {}
}
}
''');
}
test_localFunctions_inMethod() {
checkLibrary(r'''
class C {
m() {
f() {}
}
}
''');
}
test_localFunctions_inTopLevelGetter() {
checkLibrary(r'''
get g {
f() {}
}
''');
}
test_localVariables_inConstructor() {
checkLibrary(r'''
class C {
C() {
int v;
f() {}
}
}
''');
}
test_localVariables_inLocalFunction() {
checkLibrary(r'''
f() {
f1() {
int v1 = 1;
} // 2
f2() {
int v1 = 1;
f3() {
int v2 = 1;
}
}
}
''');
}
test_localVariables_inMethod() {
checkLibrary(r'''
class C {
m() {
int v;
}
}
''');
}
test_localVariables_inTopLevelFunction() {
checkLibrary(r'''
main() {
int v1 = 1;
{
const String v2 = 'bbb';
}
Map<int, List<double>> v3;
}
''');
}
test_localVariables_inTopLevelGetter() {
checkLibrary(r'''
get g {
int v;
}
''');
}
test_main_class() {
checkLibrary('class main {}');
}
test_main_class_alias() {
checkLibrary('class main = C with D; class C {} class D {}');
}
test_main_class_alias_via_export() {
addLibrarySource('/a.dart', 'class main = C with D; class C {} class D {}');
checkLibrary('export "a.dart";');
}
test_main_class_via_export() {
addLibrarySource('/a.dart', 'class main {}');
checkLibrary('export "a.dart";');
}
test_main_getter() {
checkLibrary('get main => null;');
}
test_main_getter_via_export() {
addLibrarySource('/a.dart', 'get main => null;');
checkLibrary('export "a.dart";');
}
test_main_typedef() {
checkLibrary('typedef main();');
}
test_main_typedef_via_export() {
addLibrarySource('/a.dart', 'typedef main();');
checkLibrary('export "a.dart";');
}
test_main_variable() {
checkLibrary('var main;');
}
test_main_variable_via_export() {
addLibrarySource('/a.dart', 'var main;');
checkLibrary('export "a.dart";');
}
test_metadata_classDeclaration() {
checkLibrary('const a = null; @a class C {}');
}
test_metadata_classTypeAlias() {
checkLibrary(
'const a = null; @a class C = D with E; class D {} class E {}');
}
test_metadata_constructor_call_named() {
checkLibrary('class A { const A.named(); } @A.named() class C {}');
}
test_metadata_constructor_call_named_prefixed() {
addLibrarySource('/foo.dart', 'class A { const A.named(); }');
checkLibrary('import "foo.dart" as foo; @foo.A.named() class C {}');
}
test_metadata_constructor_call_unnamed() {
checkLibrary('class A { const A(); } @A() class C {}');
}
test_metadata_constructor_call_unnamed_prefixed() {
addLibrarySource('/foo.dart', 'class A { const A(); }');
checkLibrary('import "foo.dart" as foo; @foo.A() class C {}');
}
test_metadata_constructor_call_with_args() {
checkLibrary('class A { const A(x); } @A(null) class C {}');
}
test_metadata_constructorDeclaration_named() {
checkLibrary('const a = null; class C { @a C.named(); }');
}
test_metadata_constructorDeclaration_unnamed() {
checkLibrary('const a = null; class C { @a C(); }');
}
test_metadata_enumDeclaration() {
checkLibrary('const a = null; @a enum E { v }');
}
test_metadata_exportDirective() {
addLibrarySource('/foo.dart', '');
checkLibrary('@a export "foo.dart"; const a = null;');
}
test_metadata_fieldDeclaration() {
checkLibrary('const a = null; class C { @a int x; }');
}
test_metadata_fieldFormalParameter() {
checkLibrary('const a = null; class C { var x; C(@a this.x); }');
}
test_metadata_fieldFormalParameter_withDefault() {
checkLibrary('const a = null; class C { var x; C([@a this.x = null]); }');
}
test_metadata_functionDeclaration_function() {
checkLibrary('const a = null; @a f() {}');
}
test_metadata_functionDeclaration_getter() {
checkLibrary('const a = null; @a get f => null;');
}
test_metadata_functionDeclaration_setter() {
checkLibrary('const a = null; @a set f(value) {}');
}
test_metadata_functionTypeAlias() {
checkLibrary('const a = null; @a typedef F();');
}
test_metadata_functionTypedFormalParameter() {
checkLibrary('const a = null; f(@a g()) {}');
}
test_metadata_functionTypedFormalParameter_withDefault() {
checkLibrary('const a = null; f([@a g() = null]) {}');
}
test_metadata_importDirective() {
addLibrarySource('/foo.dart', 'const b = null;');
checkLibrary('@a import "foo.dart"; const a = b;');
}
test_metadata_libraryDirective() {
checkLibrary('@a library L; const a = null;');
}
test_metadata_methodDeclaration_getter() {
checkLibrary('const a = null; class C { @a get m => null; }');
}
test_metadata_methodDeclaration_method() {
checkLibrary('const a = null; class C { @a m() {} }');
}
test_metadata_methodDeclaration_setter() {
checkLibrary('const a = null; class C { @a set m(value) {} }');
}
test_metadata_partDirective() {
addNamedSource('/foo.dart', 'part of L;');
checkLibrary('library L; @a part "foo.dart"; const a = null;');
}
test_metadata_prefixed_variable() {
addLibrarySource('/a.dart', 'const b = null;');
checkLibrary('import "a.dart" as a; @a.b class C {}');
}
test_metadata_simpleFormalParameter() {
checkLibrary('const a = null; f(@a x) {}');
}
test_metadata_simpleFormalParameter_withDefault() {
checkLibrary('const a = null; f([@a x = null]) {}');
}
test_metadata_topLevelVariableDeclaration() {
checkLibrary('const a = null; @a int v;');
}
test_metadata_typeParameter_ofClass() {
checkLibrary('const a = null; class C<@a T> {}');
}
test_metadata_typeParameter_ofClassTypeAlias() {
checkLibrary(
'const a = null; class C<@a T> = D with E; class D {} class E {}');
}
test_metadata_typeParameter_ofFunction() {
checkLibrary('const a = null; f<@a T>() {}');
}
test_metadata_typeParameter_ofTypedef() {
checkLibrary('const a = null; typedef F<@a T>();');
}
test_method_documented() {
checkLibrary('''
class C {
/**
* Docs
*/
f() {}
}''');
}
test_method_inferred_type_nonStatic_implicit_param() {
checkLibrary('class C extends D { void f(value) {} }'
' abstract class D { void f(int value); }');
}
test_method_inferred_type_nonStatic_implicit_return() {
checkLibrary(
'class C extends D { f() => null; } abstract class D { int f(); }');
}
test_method_parameter_parameters() {
checkLibrary('class C { f(g(x, y)) {} }');
}
test_method_parameter_parameters_in_generic_class() {
checkLibrary('class C<A, B> { f(A g(B x)) {} }');
}
test_method_parameter_return_type() {
checkLibrary('class C { f(int g()) {} }');
}
test_method_parameter_return_type_void() {
checkLibrary('class C { f(void g()) {} }');
}
test_method_type_parameter() {
resetWithOptions(new AnalysisOptionsImpl()..enableGenericMethods = true);
checkLibrary('class C { T f<T, U>(U u) => null; }');
}
test_method_type_parameter_in_generic_class() {
resetWithOptions(new AnalysisOptionsImpl()..enableGenericMethods = true);
checkLibrary('class C<T, U> { V f<V, W>(T t, U u, W w) => null; }');
}
test_method_type_parameter_with_function_typed_parameter() {
resetWithOptions(new AnalysisOptionsImpl()..enableGenericMethods = true);
checkLibrary('class C { void f<T, U>(T x(U u)) {} }');
}
test_nested_generic_functions_in_generic_class_with_function_typed_params() {
checkLibrary('''
class C<T, U> {
void g<V, W>() {
void h<X, Y>(void p(T t, U u, V v, W w, X x, Y y)) {
}
}
}
''');
}
test_nested_generic_functions_in_generic_class_with_local_variables() {
checkLibrary('''
class C<T, U> {
void g<V, W>() {
void h<X, Y>() {
T t;
U u;
V v;
W w;
X x;
Y y;
}
}
}
''');
}
test_nested_generic_functions_with_function_typed_param() {
checkLibrary('''
void f<T, U>() {
void g<V, W>() {
void h<X, Y>(void p(T t, U u, V v, W w, X x, Y y)) {
}
}
}
''');
}
test_nested_generic_functions_with_local_variables() {
checkLibrary('''
void f<T, U>() {
void g<V, W>() {
void h<X, Y>() {
T t;
U u;
V v;
W w;
X x;
Y y;
}
}
}
''');
}
test_operator() {
checkLibrary('class C { C operator+(C other) => null; }');
}
test_operator_equal() {
checkLibrary('class C { bool operator==(Object other) => false; }');
}
test_operator_external() {
checkLibrary('class C { external C operator+(C other); }');
}
test_operator_greater_equal() {
checkLibrary('class C { bool operator>=(C other) => false; }');
}
test_operator_index() {
checkLibrary('class C { bool operator[](int i) => null; }');
}
test_operator_index_set() {
checkLibrary('class C { void operator[]=(int i, bool v) {} }');
}
test_operator_less_equal() {
checkLibrary('class C { bool operator<=(C other) => false; }');
}
test_parameterTypeNotInferred_constructor() {
// Strong mode doesn't do type inference on constructor parameters, so it's
// ok that we don't store inferred type info for them in summaries.
checkLibrary('''
class C {
C.positional([x = 1]);
C.named({x: 1});
}
''');
}
test_parameterTypeNotInferred_initializingFormal() {
// Strong mode doesn't do type inference on initializing formals, so it's
// ok that we don't store inferred type info for them in summaries.
checkLibrary('''
class C {
var x;
C.positional([this.x = 1]);
C.named({this.x: 1});
}
''');
}
test_parameterTypeNotInferred_staticMethod() {
// Strong mode doesn't do type inference on parameters of static methods,
// so it's ok that we don't store inferred type info for them in summaries.
checkLibrary('''
class C {
static void positional([x = 1]) {}
static void named({x: 1}) {}
}
''');
}
test_parameterTypeNotInferred_topLevelFunction() {
// Strong mode doesn't do type inference on parameters of top level
// functions, so it's ok that we don't store inferred type info for them in
// summaries.
checkLibrary('''
void positional([x = 1]) {}
void named({x: 1}) {}
''');
}
test_parts() {
addNamedSource('/a.dart', 'part of my.lib;');
addNamedSource('/b.dart', 'part of my.lib;');
checkLibrary('library my.lib; part "a.dart"; part "b.dart";');
}
test_setter_documented() {
checkLibrary('''
// Extra comment so doc comment offset != 0
/**
* Docs
*/
void set x(value) {}''');
}
test_setter_external() {
checkLibrary('external void set x(int value);');
}
test_setter_inferred_type_nonStatic_implicit_param() {
checkLibrary('class C extends D { void set f(value) {} }'
' abstract class D { void set f(int value); }');
}
test_setter_inferred_type_static_implicit_return() {
checkLibrary('class C { static set f(int value) {} }');
}
test_setter_inferred_type_top_level_implicit_return() {
checkLibrary('set f(int value) {}');
}
test_setters() {
checkLibrary('void set x(int value) {} set y(value) {}');
}
test_type_arguments_explicit_dynamic_dynamic() {
checkLibrary('Map<dynamic, dynamic> m;');
}
test_type_arguments_explicit_dynamic_int() {
checkLibrary('Map<dynamic, int> m;');
}
test_type_arguments_explicit_String_dynamic() {
checkLibrary('Map<String, dynamic> m;');
}
test_type_arguments_explicit_String_int() {
checkLibrary('Map<String, int> m;');
}
test_type_arguments_implicit() {
checkLibrary('Map m;');
}
test_type_dynamic() {
checkLibrary('dynamic d;');
}
test_type_reference_lib_to_lib() {
checkLibrary('class C {} enum E { v } typedef F(); C c; E e; F f;');
}
test_type_reference_lib_to_part() {
addNamedSource(
'/a.dart', 'part of l; class C {} enum E { v } typedef F();');
checkLibrary('library l; part "a.dart"; C c; E e; F f;');
}
test_type_reference_part_to_lib() {
addNamedSource('/a.dart', 'part of l; C c; E e; F f;');
checkLibrary(
'library l; part "a.dart"; class C {} enum E { v } typedef F();');
}
test_type_reference_part_to_other_part() {
addNamedSource(
'/a.dart', 'part of l; class C {} enum E { v } typedef F();');
addNamedSource('/b.dart', 'part of l; C c; E e; F f;');
checkLibrary('library l; part "a.dart"; part "b.dart";');
}
test_type_reference_part_to_part() {
addNamedSource('/a.dart',
'part of l; class C {} enum E { v } typedef F(); C c; E e; F f;');
checkLibrary('library l; part "a.dart";');
}
test_type_reference_to_class() {
checkLibrary('class C {} C c;');
}
test_type_reference_to_class_with_type_arguments() {
checkLibrary('class C<T, U> {} C<int, String> c;');
}
test_type_reference_to_class_with_type_arguments_implicit() {
checkLibrary('class C<T, U> {} C c;');
}
test_type_reference_to_enum() {
checkLibrary('enum E { v } E e;');
}
test_type_reference_to_import() {
addLibrarySource('/a.dart', 'class C {} enum E { v }; typedef F();');
checkLibrary('import "a.dart"; C c; E e; F f;');
}
test_type_reference_to_import_export() {
addLibrarySource('/a.dart', 'export "b.dart";');
addLibrarySource('/b.dart', 'class C {} enum E { v } typedef F();');
checkLibrary('import "a.dart"; C c; E e; F f;');
}
test_type_reference_to_import_export_export() {
addLibrarySource('/a.dart', 'export "b.dart";');
addLibrarySource('/b.dart', 'export "c.dart";');
addLibrarySource('/c.dart', 'class C {} enum E { v } typedef F();');
checkLibrary('import "a.dart"; C c; E e; F f;');
}
test_type_reference_to_import_export_export_in_subdirs() {
addLibrarySource('/a/a.dart', 'export "b/b.dart";');
addLibrarySource('/a/b/b.dart', 'export "../c/c.dart";');
addLibrarySource('/a/c/c.dart', 'class C {} enum E { v } typedef F();');
checkLibrary('import "a/a.dart"; C c; E e; F f;');
}
test_type_reference_to_import_export_in_subdirs() {
addLibrarySource('/a/a.dart', 'export "b/b.dart";');
addLibrarySource('/a/b/b.dart', 'class C {} enum E { v } typedef F();');
checkLibrary('import "a/a.dart"; C c; E e; F f;');
}
test_type_reference_to_import_part() {
addLibrarySource('/a.dart', 'library l; part "b.dart";');
addNamedSource(
'/b.dart', 'part of l; class C {} enum E { v } typedef F();');
checkLibrary('import "a.dart"; C c; E e; F f;');
}
test_type_reference_to_import_part2() {
addLibrarySource('/a.dart', 'library l; part "p1.dart"; part "p2.dart";');
addNamedSource('/p1.dart', 'part of l; class C1 {}');
addNamedSource('/p2.dart', 'part of l; class C2 {}');
checkLibrary('import "a.dart"; C1 c1; C2 c2;');
}
test_type_reference_to_import_part_in_subdir() {
addLibrarySource('/a/b.dart', 'library l; part "c.dart";');
addNamedSource(
'/a/c.dart', 'part of l; class C {} enum E { v } typedef F();');
checkLibrary('import "a/b.dart"; C c; E e; F f;');
}
test_type_reference_to_import_relative() {
addLibrarySource('/a.dart', 'class C {} enum E { v } typedef F();');
checkLibrary('import "a.dart"; C c; E e; F f;');
}
test_type_reference_to_typedef() {
checkLibrary('typedef F(); F f;');
}
test_type_reference_to_typedef_with_type_arguments() {
checkLibrary('typedef U F<T, U>(T t); F<int, String> f;');
}
test_type_reference_to_typedef_with_type_arguments_implicit() {
checkLibrary('typedef U F<T, U>(T t); F f;');
}
test_type_unresolved() {
checkLibrary('C c;', allowErrors: true);
}
test_type_unresolved_prefixed() {
checkLibrary('import "dart:core" as core; core.C c;', allowErrors: true);
}
test_typedef_documented() {
checkLibrary('''
// Extra comment so doc comment offset != 0
/**
* Docs
*/
typedef F();''');
}
test_typedef_parameter_parameters() {
checkLibrary('typedef F(g(x, y));');
}
test_typedef_parameter_parameters_in_generic_class() {
checkLibrary('typedef F<A, B>(A g(B x));');
}
test_typedef_parameter_return_type() {
checkLibrary('typedef F(int g());');
}
test_typedef_parameter_type() {
checkLibrary('typedef F(int i);');
}
test_typedef_parameter_type_generic() {
checkLibrary('typedef F<T>(T t);');
}
test_typedef_parameters() {
checkLibrary('typedef F(x, y);');
}
test_typedef_return_type() {
checkLibrary('typedef int F();');
}
test_typedef_return_type_generic() {
checkLibrary('typedef T F<T>();');
}
test_typedef_return_type_implicit() {
checkLibrary('typedef F();');
}
test_typedef_return_type_void() {
checkLibrary('typedef void F();');
}
test_typedef_type_parameters() {
checkLibrary('typedef U F<T, U>(T t);');
}
test_typedef_type_parameters_bound() {
checkLibrary('typedef U F<T extends Object, U extends D>(T t); class D {}');
}
test_typedef_type_parameters_f_bound_complex() {
checkLibrary('typedef U F<T extends List<U>, U>(T t);');
}
test_typedef_type_parameters_f_bound_simple() {
checkLibrary('typedef U F<T extends U, U>(T t);');
}
test_typedefs() {
checkLibrary('f() {} g() {}');
}
test_variable_const() {
checkLibrary('const int i = 0;');
}
test_variable_documented() {
checkLibrary('''
// Extra comment so doc comment offset != 0
/**
* Docs
*/
var x;''');
}
test_variable_final() {
checkLibrary('final int x = 0;');
}
test_variable_getterInLib_setterInPart() {
addNamedSource('/a.dart', 'part of my.lib; void set x(int _) {}');
checkLibrary('library my.lib; part "a.dart"; int get x => 42;');
}
test_variable_getterInPart_setterInLib() {
addNamedSource('/a.dart', 'part of my.lib; int get x => 42;');
checkLibrary('library my.lib; part "a.dart"; void set x(int _) {}');
}
test_variable_getterInPart_setterInPart() {
addNamedSource('/a.dart', 'part of my.lib; int get x => 42;');
addNamedSource('/b.dart', 'part of my.lib; void set x(int _) {}');
checkLibrary('library my.lib; part "a.dart"; part "b.dart";');
}
test_variable_implicit_type() {
checkLibrary('var x;');
}
test_variable_inferred_type_implicit_initialized() {
checkLibrary('var v = 0;');
}
test_variable_propagatedType_const_noDep() {
checkLibrary('const i = 0;');
}
test_variable_propagatedType_final_dep_inLib() {
addNamedSource('/a.dart', 'final a = 1;');
checkLibrary('import "a.dart"; final b = a / 2;');
}
test_variable_propagatedType_final_dep_inPart() {
addNamedSource('/a.dart', 'part of lib; final a = 1;');
checkLibrary('library lib; part "a.dart"; final b = a / 2;');
}
test_variable_propagatedType_final_noDep() {
checkLibrary('final i = 0;');
}
test_variable_propagatedType_implicit_dep() {
// The propagated type is defined in a library that is not imported.
addNamedSource('/a.dart', 'class C {}');
addNamedSource('/b.dart', 'import "a.dart"; C f() => null;');
checkLibrary('import "b.dart"; final x = f();');
}
test_variable_setterInPart_getterInPart() {
addNamedSource('/a.dart', 'part of my.lib; void set x(int _) {}');
addNamedSource('/b.dart', 'part of my.lib; int get x => 42;');
checkLibrary('library my.lib; part "a.dart"; part "b.dart";');
}
test_variables() {
checkLibrary('int i; int j;');
}
/**
* Encode the library containing [original] into a summary and then use
* [_TestSummaryResynthesizer.getElement] to retrieve just the original
* element from the resynthesized summary.
*/
Element validateGetElement(Element original) {
_TestSummaryResynthesizer resynthesizer = encodeLibrary(original.library);
ElementLocationImpl location = original.location;
Element result = resynthesizer.getElement(location);
checkMinimalResynthesisWork(resynthesizer, original.library);
// Check that no other summaries needed to be resynthesized to resynthesize
// the library element.
expect(resynthesizer.resynthesisCount, 1);
expect(result.location, location);
return result;
}
void _assertUnresolvedIdentifier(Expression initializer, String desc) {
expect(initializer, new isInstanceOf<SimpleIdentifier>(), reason: desc);
SimpleIdentifier identifier = initializer;
expect(identifier.staticElement, isNull, reason: desc);
}
}
class _TestSummaryResynthesizer extends SummaryResynthesizer {
final Map<String, UnlinkedUnit> unlinkedSummaries;
final Map<String, LinkedLibrary> linkedSummaries;
/**
* The set of uris for which unlinked summaries have been requested using
* [getUnlinkedSummary].
*/
final Set<String> unlinkedSummariesRequested = new Set<String>();
/**
* The set of uris for which linked summaries have been requested using
* [getLinkedSummary].
*/
final Set<String> linkedSummariesRequested = new Set<String>();
_TestSummaryResynthesizer(
SummaryResynthesizer parent,
AnalysisContext context,
TypeProvider typeProvider,
SourceFactory sourceFactory,
this.unlinkedSummaries,
this.linkedSummaries,
bool strongMode)
: super(parent, context, typeProvider, sourceFactory, strongMode);
@override
LinkedLibrary getLinkedSummary(String uri) {
linkedSummariesRequested.add(uri);
LinkedLibrary serializedLibrary = linkedSummaries[uri];
if (serializedLibrary == null) {
fail('Unexpectedly tried to get linked summary for $uri');
}
return serializedLibrary;
}
@override
UnlinkedUnit getUnlinkedSummary(String uri) {
unlinkedSummariesRequested.add(uri);
UnlinkedUnit serializedUnit = unlinkedSummaries[uri];
if (serializedUnit == null) {
fail('Unexpectedly tried to get unlinked summary for $uri');
}
return serializedUnit;
}
@override
bool hasLibrarySummary(String uri) {
return true;
}
}