Remember import prefix name for static references.

Bug:
Change-Id: Ib71a9cc8e6c65d597f24c20c0260f7f37ef3674f
Reviewed-on: https://dart-review.googlesource.com/28541
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
This commit is contained in:
Konstantin Shcheglov 2017-12-16 05:09:35 +00:00 committed by commit-bot@chromium.org
parent 439dfe0c29
commit 31a0fe292d
11 changed files with 289 additions and 86 deletions

View file

@ -438,7 +438,7 @@ class LibraryAnalyzer {
ResolutionApplier _createResolutionApplier(
ElementImpl context, CollectedResolution resolution) {
return new _ResolutionApplierContext(
_resynthesizer, _typeProvider, resolution, context)
_resynthesizer, _typeProvider, _libraryElement, resolution, context)
.applier;
}
@ -1011,6 +1011,7 @@ class _NameOrSource {
class _ResolutionApplierContext implements TypeContext {
final KernelResynthesizer resynthesizer;
final TypeProvider typeProvider;
final LibraryElement libraryElement;
final CollectedResolution resolution;
@override
@ -1028,8 +1029,8 @@ class _ResolutionApplierContext implements TypeContext {
ResolutionApplier applier;
_ResolutionApplierContext(
this.resynthesizer, this.typeProvider, this.resolution, this.context) {
_ResolutionApplierContext(this.resynthesizer, this.typeProvider,
this.libraryElement, this.resolution, this.context) {
for (Element element = context;
element != null;
element = element.enclosingElement) {
@ -1110,6 +1111,15 @@ class _ResolutionApplierContext implements TypeContext {
element = memberElement;
}
}
} else if (referencedNode is kernel.ImportPrefixNode) {
assert(referencedNode.name != null);
for (var import in libraryElement.imports) {
if (import.prefix?.name == referencedNode.name) {
element = import.prefix;
break;
}
}
assert(element != null);
} else if (referencedNode is kernel.NullNode) {
element = null;
} else if (referencedNode == null) {
@ -1213,7 +1223,9 @@ class _ResolutionApplierContext implements TypeContext {
@override
DartType translateType(kernel.DartType kernelType) {
if (kernelType is kernel.FunctionReferenceDartType) {
if (kernelType is kernel.NullType) {
return null;
} else if (kernelType is kernel.FunctionReferenceDartType) {
kernel.VariableDeclaration variable = kernelType.function.variable;
FunctionElement element = declarationToElement[variable];
return element.type;

View file

@ -802,6 +802,10 @@ abstract class TypeContext {
/// [ResolutionStorer]) to an analyzer AST, and also checks file offsets to
/// verify that the types are applied to the correct subexpressions.
class ValidatingResolutionApplier extends ResolutionApplier {
/// The offset that is used when the actual offset is not know.
/// The applier should not validate this offset.
static const UNKNOWN_OFFSET = -2;
/// Indicates whether debug messages should be printed.
static const bool _debug = false;
@ -865,7 +869,7 @@ class ValidatingResolutionApplier extends ResolutionApplier {
'No reference information for $entity at $entityOffset');
}
int elementOffset = _referencedElementOffsets[_referencedElementIndex];
if (entityOffset != elementOffset) {
if (elementOffset != UNKNOWN_OFFSET && entityOffset != elementOffset) {
throw new StateError(
'Expected element reference for analyzer offset $entityOffset; '
'got one for kernel offset $elementOffset');
@ -882,9 +886,10 @@ class ValidatingResolutionApplier extends ResolutionApplier {
if (_typeIndex >= _types.length) {
throw new StateError('No type information for $entity at $entityOffset');
}
if (entityOffset != _typeOffsets[_typeIndex]) {
int typeOffset = _typeOffsets[_typeIndex];
if (typeOffset != UNKNOWN_OFFSET && entityOffset != typeOffset) {
throw new StateError('Expected a type for $entity at $entityOffset; '
'got one for kernel offset ${_typeOffsets[_typeIndex]}');
'got one for kernel offset $typeOffset');
}
return super._getTypeFor(entity);
}

View file

@ -24,6 +24,20 @@ class FunctionReferenceDartType implements DartType {
}
}
/// The reference to the import prefix with the [name].
class ImportPrefixNode implements TreeNode {
final String name;
ImportPrefixNode(this.name);
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
@override
String toString() {
return '(prefix-$name)';
}
}
/// The type of [DartType] node that is used as a marker for using `null`
/// as the [FunctionType] for index assignment.
class IndexAssignNullFunctionType implements DartType {
@ -192,9 +206,28 @@ class NullNode implements TreeNode {
}
}
/// The type of [DartType] node that is used as a marker for `null`.
///
/// It is used for import prefix identifiers, which are resolved to elements,
/// but don't have any types.
class NullType implements DartType {
const NullType();
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
@override
String toString() {
return '(null-type)';
}
}
/// Type inference listener that records inferred types for later use by
/// [ResolutionApplier].
class ResolutionStorer extends TypeInferenceListener {
/// The offset that is used when the actual offset is not know.
/// The consumer of information should not validate this offset.
static const UNKNOWN_OFFSET = -2;
final List<TreeNode> _declarations;
final List<Node> _references;
final List<DartType> _types;
@ -494,8 +527,18 @@ class ResolutionStorer extends TypeInferenceListener {
}
@override
bool staticAssignEnter(Expression expression, int targetOffset,
Class targetClass, Expression write, DartType typeContext) {
bool staticAssignEnter(
Expression expression,
String prefixName,
int targetOffset,
Class targetClass,
Expression write,
DartType typeContext) {
// if there was an import prefix, record it.
if (prefixName != null) {
_recordReference(new ImportPrefixNode(prefixName), UNKNOWN_OFFSET);
_recordType(const NullType(), UNKNOWN_OFFSET);
}
// If the static target is explicit (and is a class), record it.
if (targetClass != null) {
_recordReference(targetClass, targetOffset);
@ -505,7 +548,7 @@ class ResolutionStorer extends TypeInferenceListener {
_deferReference(write.fileOffset);
_deferType(write.fileOffset);
return super.staticAssignEnter(
expression, targetOffset, targetClass, write, typeContext);
expression, prefixName, targetOffset, targetClass, write, typeContext);
}
@override
@ -524,15 +567,20 @@ class ResolutionStorer extends TypeInferenceListener {
}
@override
bool staticGetEnter(StaticGet expression, int targetOffset, Class targetClass,
DartType typeContext) {
bool staticGetEnter(StaticGet expression, String prefixName, int targetOffset,
Class targetClass, DartType typeContext) {
// if there was an import prefix, record it.
if (prefixName != null) {
_recordReference(new ImportPrefixNode(prefixName), UNKNOWN_OFFSET);
_recordType(const NullType(), UNKNOWN_OFFSET);
}
// If the static target is explicit (and is a class), record it.
if (targetClass != null) {
_recordReference(targetClass, targetOffset);
_recordType(targetClass.rawType, targetOffset);
}
return super
.staticGetEnter(expression, targetOffset, targetClass, typeContext);
return super.staticGetEnter(
expression, prefixName, targetOffset, targetClass, typeContext);
}
@override
@ -543,8 +591,13 @@ class ResolutionStorer extends TypeInferenceListener {
}
@override
bool staticInvocationEnter(StaticInvocation expression, int targetOffset,
Class targetClass, DartType typeContext) {
bool staticInvocationEnter(StaticInvocation expression, String prefixName,
int targetOffset, Class targetClass, DartType typeContext) {
// if there was an import prefix, record it.
if (prefixName != null) {
_recordReference(new ImportPrefixNode(prefixName), UNKNOWN_OFFSET);
_recordType(const NullType(), UNKNOWN_OFFSET);
}
// If the static target is explicit (and is a class), record it.
if (targetClass != null) {
_recordReference(targetClass, targetOffset);
@ -568,7 +621,7 @@ class ResolutionStorer extends TypeInferenceListener {
_deferType(expression.fileOffset);
_deferType(expression.arguments.fileOffset);
return super.staticInvocationEnter(
expression, targetOffset, targetClass, typeContext);
expression, prefixName, targetOffset, targetClass, typeContext);
}
@override
@ -596,6 +649,16 @@ class ResolutionStorer extends TypeInferenceListener {
@override
void thisExpressionExit(ThisExpression expression, DartType inferredType) {}
bool typeLiteralEnter(@override TypeLiteral expression, String prefixName,
DartType typeContext) {
// if there was an import prefix, record it.
if (prefixName != null) {
_recordReference(new ImportPrefixNode(prefixName), UNKNOWN_OFFSET);
_recordType(const NullType(), UNKNOWN_OFFSET);
}
return super.typeLiteralEnter(expression, prefixName, typeContext);
}
void typeLiteralExit(TypeLiteral expression, DartType inferredType) {
_recordReference(expression.type, expression.fileOffset);
super.typeLiteralExit(expression, inferredType);

View file

@ -209,13 +209,6 @@ class TypePropagationTest_Kernel extends TypePropagationTest_Driver {
await super.test_initializer_dereference();
}
@override
@failingTest
test_invocation_target_prefixed() async {
// Bad state: Expected element reference for analyzer offset 43; got one for kernel offset 50
await super.test_invocation_target_prefixed();
}
@override
@failingTest
test_is_conditional() async {
@ -342,13 +335,6 @@ class TypePropagationTest_Kernel extends TypePropagationTest_Driver {
await super.test_mergePropagatedTypesAtJoinPoint_4();
}
@override
@failingTest
test_objectAccessInference_disabled_for_library_prefix() async {
// Bad state: Expected element reference for analyzer offset 43; got one for kernel offset 50
await super.test_objectAccessInference_disabled_for_library_prefix();
}
@override
@failingTest
test_objectAccessInference_enabled_for_cascades() async {
@ -356,13 +342,6 @@ class TypePropagationTest_Kernel extends TypePropagationTest_Driver {
await super.test_objectAccessInference_enabled_for_cascades();
}
@override
@failingTest
test_objectMethodInference_disabled_for_library_prefix() async {
// Bad state: Expected element reference for analyzer offset 43; got one for kernel offset 50
await super.test_objectMethodInference_disabled_for_library_prefix();
}
@override
@failingTest
test_objectMethodInference_enabled_for_cascades() async {

View file

@ -3569,6 +3569,101 @@ class C {
expect(identifier.staticType, typeProvider.intType);
}
test_prefixedIdentifier_importPrefix_className() async {
var libPath = _p('/test/lib/lib.dart');
provider.newFile(libPath, '''
class MyClass {}
typedef void MyFunctionTypeAlias();
int myTopVariable;
int myTopFunction() => 0;
int get myGetter => 0;
void set mySetter(int _) {}
''');
addTestFile(r'''
import 'lib.dart' as my;
main() {
my.MyClass;
my.MyFunctionTypeAlias;
my.myTopVariable;
my.myTopFunction;
my.myTopFunction();
my.myGetter;
my.mySetter = 0;
}
''');
AnalysisResult result = await driver.getResult(testFile);
// TODO(scheglov) Uncomment and fix "unused imports" hint.
// expect(result.errors, isEmpty);
var unitElement = result.unit.element;
ImportElement myImport = unitElement.library.imports[0];
PrefixElement myPrefix = myImport.prefix;
var typeProvider = unitElement.context.typeProvider;
var myLibrary = myImport.importedLibrary;
var myUnit = myLibrary.definingCompilationUnit;
var myClass = myUnit.types.single;
var myFunctionTypeAlias = myUnit.functionTypeAliases.single;
var myTopVariable = myUnit.topLevelVariables[0];
var myTopFunction = myUnit.functions.single;
var myGetter = myUnit.topLevelVariables[1].getter;
var mySetter = myUnit.topLevelVariables[2].setter;
expect(myTopVariable.name, 'myTopVariable');
expect(myGetter.displayName, 'myGetter');
expect(mySetter.displayName, 'mySetter');
List<Statement> statements = _getMainStatements(result);
void assertPrefix(SimpleIdentifier identifier) {
expect(identifier.staticElement, same(myPrefix));
expect(identifier.staticType, isNull);
}
void assertPrefixedIdentifier(
int statementIndex, Element expectedElement, DartType expectedType) {
ExpressionStatement statement = statements[statementIndex];
PrefixedIdentifier prefixed = statement.expression;
assertPrefix(prefixed.prefix);
expect(prefixed.identifier.staticElement, same(expectedElement));
expect(prefixed.identifier.staticType, expectedType);
}
assertPrefixedIdentifier(0, myClass, typeProvider.typeType);
assertPrefixedIdentifier(1, myFunctionTypeAlias, typeProvider.typeType);
assertPrefixedIdentifier(2, myTopVariable.getter, typeProvider.intType);
{
ExpressionStatement statement = statements[3];
PrefixedIdentifier prefixed = statement.expression;
assertPrefix(prefixed.prefix);
expect(prefixed.identifier.staticElement, same(myTopFunction));
expect(prefixed.identifier.staticType, isNotNull);
}
{
ExpressionStatement statement = statements[4];
MethodInvocation invocation = statement.expression;
assertPrefix(invocation.target);
expect(invocation.methodName.staticElement, same(myTopFunction));
expect(invocation.methodName.staticType, isNotNull);
}
assertPrefixedIdentifier(5, myGetter, typeProvider.intType);
{
ExpressionStatement statement = statements[6];
AssignmentExpression assignment = statement.expression;
PrefixedIdentifier left = assignment.leftHandSide;
assertPrefix(left.prefix);
expect(left.identifier.staticElement, same(mySetter));
expect(left.identifier.staticType, typeProvider.intType);
}
}
test_prefixExpression_local() async {
String content = r'''
main() {
@ -5104,6 +5199,11 @@ typedef void F(int p);
fail('Not found main() in ${result.unit}');
return null;
}
/**
* Return the [provider] specific path for the given Posix [path].
*/
String _p(String path) => provider.convertPath(path);
}
@reflectiveTest

View file

@ -1236,7 +1236,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
charOffset, "Not a constant expression.");
}
return new TypeDeclarationAccessor(
this, charOffset, builder, name, token);
this, prefix, charOffset, builder, name, token);
} else if (builder.isLocal) {
if (constantExpressionRequired &&
!builder.isConst &&
@ -1285,7 +1285,8 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
return new ThisPropertyAccessor(this, token, n, getter, setter);
} else if (builder.isRegularMethod) {
assert(builder.isStatic || builder.isTopLevel);
return new StaticAccessor(this, token, builder.target, null);
return new StaticAccessor(this, token, builder.target, null,
prefixName: prefix?.name);
} else if (builder is PrefixBuilder) {
if (constantExpressionRequired && builder.deferred) {
deprecated_addCompileTimeError(
@ -1309,8 +1310,9 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
} else if (builder.isField && !builder.isFinal) {
setter = builder;
}
StaticAccessor accessor =
new StaticAccessor.fromBuilder(this, builder, token, setter);
StaticAccessor accessor = new StaticAccessor.fromBuilder(
this, builder, token, setter,
prefix: prefix);
if (constantExpressionRequired) {
Member readTarget = accessor.readTarget;
if (!(readTarget is Field && readTarget.isConst ||
@ -2343,6 +2345,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
{bool isConst: false,
int charOffset: -1,
Member initialTarget,
String prefixName,
int targetOffset: -1,
Class targetClass}) {
initialTarget ??= target;
@ -2376,7 +2379,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
..fileOffset = charOffset;
} else {
return new ShadowStaticInvocation(
targetOffset, targetClass, target, arguments,
prefixName, targetOffset, targetClass, target, arguments,
isConst: isConst)
..fileOffset = charOffset;
}
@ -3611,8 +3614,9 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
@override
StaticGet makeStaticGet(Member readTarget, Token token,
{int targetOffset: -1, Class targetClass}) {
return new ShadowStaticGet(targetOffset, targetClass, readTarget)
{String prefixName, int targetOffset: -1, Class targetClass}) {
return new ShadowStaticGet(
prefixName, targetOffset, targetClass, readTarget)
..fileOffset = offsetForToken(token);
}
}

View file

@ -114,6 +114,7 @@ abstract class BuilderHelper {
{bool isConst,
int charOffset,
Member initialTarget,
String prefixName,
int targetOffset: -1,
Class targetClass});
@ -131,7 +132,7 @@ abstract class BuilderHelper {
List<TypeParameter> typeParameters);
StaticGet makeStaticGet(Member readTarget, Token token,
{int targetOffset: -1, Class targetClass});
{String prefixName, int targetOffset: -1, Class targetClass});
dynamic deprecated_addCompileTimeError(int charOffset, String message);
@ -739,15 +740,15 @@ class PropertyAccessor extends kernel.PropertyAccessor with FastaAccessor {
class StaticAccessor extends kernel.StaticAccessor with FastaAccessor {
StaticAccessor(
BuilderHelper helper, Token token, Member readTarget, Member writeTarget,
{int targetOffset: -1, Class targetClass})
: super(
helper, targetOffset, targetClass, readTarget, writeTarget, token) {
{String prefixName, int targetOffset: -1, Class targetClass})
: super(helper, prefixName, targetOffset, targetClass, readTarget,
writeTarget, token) {
assert(readTarget != null || writeTarget != null);
}
factory StaticAccessor.fromBuilder(
BuilderHelper helper, Builder builder, Token token, Builder builderSetter,
{int targetOffset: -1, Class targetClass}) {
{PrefixBuilder prefix, int targetOffset: -1, Class targetClass}) {
if (builder is AccessErrorBuilder) {
AccessErrorBuilder error = builder;
builder = error.builder;
@ -766,7 +767,9 @@ class StaticAccessor extends kernel.StaticAccessor with FastaAccessor {
}
}
return new StaticAccessor(helper, token, getter, setter,
targetOffset: targetOffset, targetClass: targetClass);
prefixName: prefix?.name,
targetOffset: targetOffset,
targetClass: targetClass);
}
String get plainNameForRead => (readTarget ?? writeTarget).name.name;
@ -786,6 +789,7 @@ class StaticAccessor extends kernel.StaticAccessor with FastaAccessor {
} else {
return helper.buildStaticInvocation(readTarget, arguments,
charOffset: offset,
prefixName: prefixName,
targetOffset: targetOffset,
targetClass: targetClass);
}
@ -795,7 +799,7 @@ class StaticAccessor extends kernel.StaticAccessor with FastaAccessor {
@override
ShadowComplexAssignment startComplexAssignment(Expression rhs) =>
new ShadowStaticAssignment(targetOffset, targetClass, rhs);
new ShadowStaticAssignment(prefixName, targetOffset, targetClass, rhs);
}
class LoadLibraryAccessor extends kernel.LoadLibraryAccessor
@ -1013,14 +1017,23 @@ class ParenthesizedExpression extends ReadOnlyAccessor {
}
class TypeDeclarationAccessor extends ReadOnlyAccessor {
/// The import prefix preceding the [declaration] reference, or `null` if
/// the reference is not prefixed.
final PrefixBuilder prefix;
/// The offset at which the [declaration] is referenced by this accessor,
/// or `-1` if the reference is implicit.
final int declarationReferenceOffset;
final TypeDeclarationBuilder declaration;
TypeDeclarationAccessor(BuilderHelper helper, this.declarationReferenceOffset,
this.declaration, String plainNameForRead, Token token)
TypeDeclarationAccessor(
BuilderHelper helper,
this.prefix,
this.declarationReferenceOffset,
this.declaration,
String plainNameForRead,
Token token)
: super(helper, null, plainNameForRead, token);
Expression get expression {
@ -1036,7 +1049,7 @@ class TypeDeclarationAccessor extends ReadOnlyAccessor {
..fileOffset = offset;
} else {
super.expression = new ShadowTypeLiteral(
buildType(null, nonInstanceAccessIsError: true))
prefix?.name, buildType(null, nonInstanceAccessIsError: true))
..fileOffset = offsetForToken(token);
}
}

View file

@ -669,6 +669,10 @@ class SuperIndexAccessor extends Accessor {
}
class StaticAccessor extends Accessor {
/// The name of the import prefix preceding the [targetClass], [readTarget],
/// or [writeTarget], or `null` if the reference is not prefixed.
String prefixName;
/// If [targetClass] is not `null`, the offset at which the explicit
/// reference to it is; otherwise `-1`.
int targetOffset;
@ -681,8 +685,8 @@ class StaticAccessor extends Accessor {
Member readTarget;
Member writeTarget;
StaticAccessor(BuilderHelper helper, this.targetOffset, this.targetClass,
this.readTarget, this.writeTarget, Token token)
StaticAccessor(BuilderHelper helper, this.prefixName, this.targetOffset,
this.targetClass, this.readTarget, this.writeTarget, Token token)
: super(helper, token);
Expression _makeRead(ShadowComplexAssignment complexAssignment) {
@ -690,7 +694,9 @@ class StaticAccessor extends Accessor {
return makeInvalidRead();
} else {
var read = helper.makeStaticGet(readTarget, token,
targetOffset: targetOffset, targetClass: targetClass);
prefixName: prefixName,
targetOffset: targetOffset,
targetClass: targetClass);
complexAssignment?.read = read;
return read;
}

View file

@ -1734,15 +1734,20 @@ abstract class ShadowStatement extends Statement {
/// Concrete shadow object representing an assignment to a static variable.
class ShadowStaticAssignment extends ShadowComplexAssignment {
/// The name of the import prefix preceding the [_targetClass], or the target
/// [Procedure]; or `null` if the reference is not prefixed.
final String _prefixName;
/// If [_targetClass] is not `null`, the offset at which the explicit
/// reference to it is; otherwise `-1`.
int _targetOffset;
final int _targetOffset;
/// The [Class] that was explicitly referenced to get the target [Procedure],
/// or `null` if the class is implicit.
Class _targetClass;
final Class _targetClass;
ShadowStaticAssignment(this._targetOffset, this._targetClass, Expression rhs)
ShadowStaticAssignment(
this._prefixName, this._targetOffset, this._targetClass, Expression rhs)
: super(rhs);
@override
@ -1754,8 +1759,8 @@ class ShadowStaticAssignment extends ShadowComplexAssignment {
@override
DartType _inferExpression(
ShadowTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
typeNeeded = inferrer.listener.staticAssignEnter(
desugared, _targetOffset, _targetClass, this.write, typeContext) ||
typeNeeded = inferrer.listener.staticAssignEnter(desugared, _prefixName,
_targetOffset, _targetClass, this.write, typeContext) ||
typeNeeded;
DartType readType;
var read = this.read;
@ -1785,22 +1790,27 @@ class ShadowStaticAssignment extends ShadowComplexAssignment {
/// Concrete shadow object representing a read of a static variable in kernel
/// form.
class ShadowStaticGet extends StaticGet implements ShadowExpression {
/// The name of the import prefix preceding the [_targetClass], or the target
/// [Procedure]; or `null` if the reference is not prefixed.
final String _prefixName;
/// If [_targetClass] is not `null`, the offset at which the explicit
/// reference to it is; otherwise `-1`.
int _targetOffset;
final int _targetOffset;
/// The [Class] that was explicitly referenced to get the target [Procedure],
/// or `null` if the class is implicit.
Class _targetClass;
final Class _targetClass;
ShadowStaticGet(this._targetOffset, this._targetClass, Member target)
ShadowStaticGet(
this._prefixName, this._targetOffset, this._targetClass, Member target)
: super(target);
@override
DartType _inferExpression(
ShadowTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
typeNeeded = inferrer.listener
.staticGetEnter(this, _targetOffset, _targetClass, typeContext) ||
typeNeeded = inferrer.listener.staticGetEnter(
this, _prefixName, _targetOffset, _targetClass, typeContext) ||
typeNeeded;
var target = this.target;
if (target is ShadowField && target._inferenceNode != null) {
@ -1820,16 +1830,20 @@ class ShadowStaticGet extends StaticGet implements ShadowExpression {
/// Shadow object for [StaticInvocation].
class ShadowStaticInvocation extends StaticInvocation
implements ShadowExpression {
/// The name of the import prefix preceding the [_targetClass], or the target
/// [Procedure]; or `null` if the reference is not prefixed.
final String _prefixName;
/// If [_targetClass] is not `null`, the offset at which the explicit
/// reference to it is; otherwise `-1`.
int _targetOffset;
final int _targetOffset;
/// The [Class] that was explicitly referenced to get the target [Procedure],
/// or `null` if the class is implicit.
Class _targetClass;
final Class _targetClass;
ShadowStaticInvocation(this._targetOffset, this._targetClass,
Procedure target, Arguments arguments,
ShadowStaticInvocation(this._prefixName, this._targetOffset,
this._targetClass, Procedure target, Arguments arguments,
{bool isConst: false})
: super(target, arguments, isConst: isConst);
@ -1837,7 +1851,7 @@ class ShadowStaticInvocation extends StaticInvocation
DartType _inferExpression(
ShadowTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
typeNeeded = inferrer.listener.staticInvocationEnter(
this, _targetOffset, _targetClass, typeContext) ||
this, _prefixName, _targetOffset, _targetClass, typeContext) ||
typeNeeded;
var calleeType = target.function.functionType;
var inferredType = inferrer.inferInvocation(typeContext, typeNeeded,
@ -2243,13 +2257,18 @@ class ShadowTypeInferrer extends TypeInferrerImpl {
/// Shadow object for [TypeLiteral].
class ShadowTypeLiteral extends TypeLiteral implements ShadowExpression {
ShadowTypeLiteral(DartType type) : super(type);
/// The name of the import prefix preceding the referenced type literal;
/// or `null` if the reference is not prefixed.
final String prefixName;
ShadowTypeLiteral(this.prefixName, DartType type) : super(type);
@override
DartType _inferExpression(
ShadowTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
typeNeeded =
inferrer.listener.typeLiteralEnter(this, typeContext) || typeNeeded;
inferrer.listener.typeLiteralEnter(this, prefixName, typeContext) ||
typeNeeded;
var inferredType = typeNeeded ? inferrer.coreTypes.typeClass.rawType : null;
inferrer.listener.typeLiteralExit(this, inferredType);
return inferredType;

View file

@ -394,8 +394,13 @@ class TypeInferenceListener
void returnStatementExit(ReturnStatement statement) =>
genericStatementExit('returnStatement', statement);
bool staticAssignEnter(Expression expression, int targetOffset,
Class targetClass, Expression write, DartType typeContext) =>
bool staticAssignEnter(
Expression expression,
String prefixName,
int targetOffset,
Class targetClass,
Expression write,
DartType typeContext) =>
genericExpressionEnter("staticAssign", expression, typeContext);
void staticAssignExit(
@ -407,15 +412,15 @@ class TypeInferenceListener
DartType inferredType) =>
genericExpressionExit("staticAssign", expression, inferredType);
bool staticGetEnter(StaticGet expression, int targetOffset, Class targetClass,
DartType typeContext) =>
bool staticGetEnter(StaticGet expression, String prefixName, int targetOffset,
Class targetClass, DartType typeContext) =>
genericExpressionEnter("staticGet", expression, typeContext);
void staticGetExit(StaticGet expression, DartType inferredType) =>
genericExpressionExit("staticGet", expression, inferredType);
bool staticInvocationEnter(StaticInvocation expression, int targetOffset,
Class targetClass, DartType typeContext) =>
bool staticInvocationEnter(StaticInvocation expression, String prefixName,
int targetOffset, Class targetClass, DartType typeContext) =>
genericExpressionEnter("staticInvocation", expression, typeContext);
void staticInvocationExit(
@ -481,7 +486,8 @@ class TypeInferenceListener
void tryFinallyExit(TryFinally statement) =>
genericStatementExit('tryFinally', statement);
bool typeLiteralEnter(TypeLiteral expression, DartType typeContext) =>
bool typeLiteralEnter(
TypeLiteral expression, String prefixName, DartType typeContext) =>
genericExpressionEnter("typeLiteral", expression, typeContext);
void typeLiteralExit(TypeLiteral expression, DartType inferredType) =>

View file

@ -52,9 +52,7 @@ inference/future_then_explicit_future: Fail
inference/generic_functions_return_typedef: Fail
inference/generic_methods_basic_downward_inference: Crash
inference/generic_methods_downwards_inference_fold: Crash
inference/generic_methods_infer_generic_instantiation: Crash
inference/generic_methods_infer_js_builtin: Fail
inference/generic_methods_nested_generic_instantiation: Crash
inference/infer_correctly_on_multiple_variables_declared_together: Crash
inference/infer_from_complex_expressions_if_outer_most_value_is_precise: Crash
inference/infer_local_function_referenced_before_declaration: Crash
@ -112,7 +110,6 @@ rasta/issue_000070: Crash
rasta/malformed_function: Crash
rasta/mandatory_parameter_initializer: Crash
rasta/parser_error: Crash
rasta/previsit_deferred: Crash
rasta/static: Crash
rasta/super: Crash
rasta/super_initializer: Crash
@ -149,5 +146,4 @@ runtime_checks_new/for_in_call_kinds: Crash
statements: Crash
super_rasta_copy: Crash
type_variable_as_super: Crash
type_variable_prefix: Crash
uninitialized_fields: Crash