mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 22:00:09 +00:00
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:
parent
439dfe0c29
commit
31a0fe292d
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) =>
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue