Refactor handling of library prefixes.
Closes #13632 BUG= R=karlklose@google.com Review URL: https://codereview.chromium.org//1227353002.
This commit is contained in:
@@ -46,7 +46,12 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
||||
Scope scope;
|
||||
ClassElement currentClass;
|
||||
ExpressionStatement currentExpressionStatement;
|
||||
|
||||
/// `true` if a [Send] or [SendSet] is visited as the prefix of member access.
|
||||
/// For instance `Class` in `Class.staticField` or `prefix.Class` in
|
||||
/// `prefix.Class.staticMethod()`.
|
||||
bool sendIsMemberAccess = false;
|
||||
|
||||
StatementScope statementScope;
|
||||
int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION
|
||||
| ElementCategory.IMPLIES_TYPE;
|
||||
@@ -1332,7 +1337,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
||||
if (leftResult.isConstant && rightResult.isConstant) {
|
||||
bool isValidConstant;
|
||||
ConstantExpression leftConstant = leftResult.constant;
|
||||
ConstantExpression rightConstant = leftResult.constant;
|
||||
ConstantExpression rightConstant = rightResult.constant;
|
||||
DartType knownLeftType = leftConstant.getKnownType(coreTypes);
|
||||
DartType knownRightType = rightConstant.getKnownType(coreTypes);
|
||||
switch (operator.kind) {
|
||||
@@ -1770,12 +1775,54 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle qualified [Send] where the receiver resolves to a [prefix],
|
||||
/// like `prefix.toplevelFunction()` or `prefix.Class.staticField` where
|
||||
/// `prefix` is a library prefix.
|
||||
ResolutionResult handleLibraryPrefixSend(
|
||||
Send node, PrefixElement prefix, Name name) {
|
||||
Element member = prefix.lookupLocalMember(name.text);
|
||||
if (member == null) {
|
||||
registry.registerThrowNoSuchMethod();
|
||||
Element error = reportAndCreateErroneousElement(
|
||||
node, name.text, MessageKind.NO_SUCH_LIBRARY_MEMBER,
|
||||
{'libraryName': prefix.name, 'memberName': name});
|
||||
registry.useElement(node, error);
|
||||
return new ElementResult(error);
|
||||
} else {
|
||||
return handleResolvedSend(node, name, member);
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle a [Send] that resolves to a [prefix]. Like `prefix` in
|
||||
/// `prefix.Class` or `prefix` in `prefix()`, the latter being a compile time
|
||||
/// error.
|
||||
ResolutionResult handleLibraryPrefix(
|
||||
Send node,
|
||||
Name name,
|
||||
PrefixElement prefix) {
|
||||
if ((ElementCategory.PREFIX & allowedCategory) == 0) {
|
||||
compiler.reportError(
|
||||
node,
|
||||
MessageKind.PREFIX_AS_EXPRESSION,
|
||||
{'prefix': name});
|
||||
return const NoneResult();
|
||||
}
|
||||
if (prefix.isDeferred) {
|
||||
// TODO(johnniwinther): Remove this when deferred access is detected
|
||||
// through a [SendStructure].
|
||||
registry.useElement(node.selector, prefix);
|
||||
}
|
||||
registry.useElement(node, prefix);
|
||||
return new ElementResult(prefix);
|
||||
}
|
||||
|
||||
|
||||
/// Handle qualified [Send] where the receiver resolves to an [Element], like
|
||||
/// `a.b` where `a` is a local, field, class, or prefix, etc.
|
||||
ResolutionResult handleResolvedQualifiedSend(
|
||||
Send node, Name name, Element element) {
|
||||
if (element.isPrefix) {
|
||||
return oldVisitSend(node);
|
||||
return handleLibraryPrefixSend(node, element, name);
|
||||
} else if (element.isClass) {
|
||||
return handleStaticMemberAccess(node, name, element);
|
||||
}
|
||||
@@ -1909,15 +1956,13 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
||||
Name name,
|
||||
AmbiguousElement element) {
|
||||
|
||||
compiler.reportError(
|
||||
node, element.messageKind, element.messageArguments);
|
||||
element.diagnose(enclosingElement, compiler);
|
||||
|
||||
ErroneousElement error = new ErroneousElementX(
|
||||
element.messageKind,
|
||||
element.messageArguments,
|
||||
ErroneousElement error = reportAndCreateErroneousElement(
|
||||
node,
|
||||
name.text,
|
||||
enclosingElement);
|
||||
element.messageKind,
|
||||
element.messageArguments);
|
||||
element.diagnose(enclosingElement, compiler);
|
||||
registry.registerThrowNoSuchMethod();
|
||||
|
||||
// TODO(johnniwinther): Support ambiguous access as an [AccessSemantics].
|
||||
AccessSemantics accessSemantics = new StaticAccess.unresolved(error);
|
||||
@@ -2192,7 +2237,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
||||
} else if (element.isTypeVariable) {
|
||||
return oldVisitSend(node);
|
||||
} else if (element.isPrefix) {
|
||||
return oldVisitSend(node);
|
||||
return handleLibraryPrefix(node, name, element);
|
||||
} else if (element.isLocal) {
|
||||
return handleLocalAccess(node, name, element);
|
||||
} else if (element.isStatic || element.isTopLevel) {
|
||||
|
||||
@@ -401,6 +401,9 @@ main() {}""",
|
||||
static const MessageKind NOT_A_PREFIX = const MessageKind(
|
||||
"'#{node}' is not a prefix.");
|
||||
|
||||
static const MessageKind PREFIX_AS_EXPRESSION = const MessageKind(
|
||||
"Library prefix '#{prefix}' is not a valid expression.");
|
||||
|
||||
static const MessageKind CANNOT_FIND_CONSTRUCTOR = const MessageKind(
|
||||
"Cannot find constructor '#{constructorName}'.");
|
||||
|
||||
|
||||
@@ -46,8 +46,6 @@ Language/12_Expressions/30_Identifier_Reference_A02_t01: fail # Issue 21154
|
||||
Language/13_Statements/04_Local_Function_Declaration_A04_t01: MissingCompileTimeError # Issue 21050
|
||||
Language/13_Statements/04_Local_Function_Declaration_A04_t03: MissingCompileTimeError # Issue 21050
|
||||
Language/14_Libraries_and_Scripts/1_Imports_A03_t08: fail # Issue 21171
|
||||
Language/14_Libraries_and_Scripts/1_Imports_A03_t09: fail # Issue 21171
|
||||
Language/14_Libraries_and_Scripts/1_Imports_A03_t10: fail # Issue 21171
|
||||
Language/14_Libraries_and_Scripts/1_Imports_A03_t28: fail # Issue 21171
|
||||
Language/15_Types/4_Interface_Types_A11_t01: crash # Issue 21174
|
||||
Language/15_Types/4_Interface_Types_A11_t02: crash # Issue 21174
|
||||
|
||||
@@ -29,7 +29,7 @@ main() {
|
||||
diagnosticHandler,
|
||||
libraryRoot,
|
||||
packageRoot,
|
||||
['--analyze-only'],
|
||||
['--analyze-all'],
|
||||
{});
|
||||
asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
|
||||
diagnostics.sort();
|
||||
@@ -38,10 +38,10 @@ main() {
|
||||
"memory:library.dart:41:45:'hest' is defined here.:info",
|
||||
"memory:main.dart:0:22:'hest' is imported here.:info",
|
||||
"memory:main.dart:23:46:'hest' is imported here.:info",
|
||||
"memory:main.dart:86:92:Duplicate import of 'hest'.:error"
|
||||
"memory:main.dart:86:92:Duplicate import of 'hest'.:warning",
|
||||
];
|
||||
Expect.listEquals(expected, diagnostics);
|
||||
Expect.isTrue(compiler.compilationFailed);
|
||||
Expect.isFalse(compiler.compilationFailed);
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -749,7 +749,6 @@ const Map<String, List<Test>> SEND_TESTS = const {
|
||||
''',
|
||||
const Visit(VisitKind.VISIT_TOP_LEVEL_GETTER_GET,
|
||||
element: 'getter(o)')),
|
||||
// TODO(johnniwinther): Expect [VISIT_TOP_LEVEL_SETTER_GET] instead.
|
||||
const Test(
|
||||
'''
|
||||
set o(_) {}
|
||||
@@ -764,8 +763,8 @@ const Map<String, List<Test>> SEND_TESTS = const {
|
||||
'''
|
||||
m() => p.o;
|
||||
''',
|
||||
const Visit(VisitKind.VISIT_UNRESOLVED_GET,
|
||||
name: 'o')),
|
||||
const Visit(VisitKind.VISIT_TOP_LEVEL_SETTER_GET,
|
||||
element: 'setter(o)')),
|
||||
// TODO(johnniwinther): Expect [VISIT_TOP_LEVEL_GETTER_SET] instead.
|
||||
const Test(
|
||||
'''
|
||||
@@ -815,7 +814,6 @@ const Map<String, List<Test>> SEND_TESTS = const {
|
||||
const Visit(VisitKind.VISIT_TOP_LEVEL_GETTER_INVOKE,
|
||||
element: 'getter(o)',
|
||||
arguments: '(null,42)')),
|
||||
// TODO(johnniwinther): Expected [VISIT_TOP_LEVEL_SETTER_INVOKE] instead.
|
||||
const Test(
|
||||
'''
|
||||
set o(_) {}
|
||||
@@ -829,8 +827,8 @@ const Map<String, List<Test>> SEND_TESTS = const {
|
||||
set o(_) {}
|
||||
''',
|
||||
'm() { p.o(null, 42); }',
|
||||
const Visit(VisitKind.VISIT_UNRESOLVED_INVOKE,
|
||||
name: 'o',
|
||||
const Visit(VisitKind.VISIT_TOP_LEVEL_SETTER_INVOKE,
|
||||
element: 'setter(o)',
|
||||
arguments: '(null,42)')),
|
||||
],
|
||||
'Top level functions': const [
|
||||
|
||||
@@ -33,10 +33,6 @@ stacktrace_test: Pass, RuntimeError # # Issue 12698
|
||||
stacktrace_rethrow_nonerror_test: Pass, RuntimeError # Issue 12698
|
||||
stacktrace_rethrow_error_test: Pass, RuntimeError # Issue 12698
|
||||
instantiate_type_variable_test/01: CompileTimeError # Issue 13631
|
||||
library_ambiguous_test/00: CompileTimeError # Issue 13632
|
||||
library_ambiguous_test/01: CompileTimeError # Issue 13632
|
||||
library_ambiguous_test/02: CompileTimeError # Issue 13632
|
||||
library_ambiguous_test/03: CompileTimeError # Issue 13632
|
||||
type_variable_conflict_test/01: Fail # Issue 13702
|
||||
type_variable_conflict_test/02: Fail # Issue 13702
|
||||
type_variable_conflict_test/03: Fail # Issue 13702
|
||||
@@ -64,21 +60,12 @@ if_null_assignment_behavior_test/13: Crash # Issue 23491
|
||||
if_null_assignment_behavior_test/14: Crash # Issue 23491
|
||||
nullaware_opt_test: Fail # Fails at e?.f ??= 200;
|
||||
|
||||
conditional_method_invocation_test/11: MissingCompileTimeError # Issue 23611
|
||||
conditional_property_access_test/09: MissingCompileTimeError # Issue 23611
|
||||
conditional_property_assignment_test/20: MissingCompileTimeError # Issue 23611
|
||||
conditional_property_assignment_test/21: MissingCompileTimeError # Issue 23611
|
||||
conditional_property_assignment_test/22: MissingCompileTimeError # Issue 23611
|
||||
if_null_assignment_behavior_test/29: Crash # Issue 23611
|
||||
if_null_assignment_behavior_test/30: Crash # Issue 23611
|
||||
prefix_assignment_test/01: Crash # Issue 23611
|
||||
prefix_assignment_test/02: Crash # Issue 23611
|
||||
prefix_identifier_reference_test/01: MissingCompileTimeError # Issue 23611
|
||||
prefix_identifier_reference_test/02: MissingCompileTimeError # Issue 23611
|
||||
prefix_identifier_reference_test/03: MissingCompileTimeError # Issue 23611
|
||||
prefix_identifier_reference_test/04: Crash # Issue 23611
|
||||
prefix_identifier_reference_test/05: Crash # Issue 23611
|
||||
prefix_unqualified_invocation_test/01: RuntimeError # Issue 23611
|
||||
|
||||
const_error_multiply_initialized_test/02: CompileTimeError # Issue 23618
|
||||
const_error_multiply_initialized_test/04: CompileTimeError # Issue 23618
|
||||
@@ -206,10 +193,6 @@ canonical_const2_test: RuntimeError, OK # Issue 1533
|
||||
bit_operations_test: RuntimeError, OK # Issue 1533
|
||||
expect_test: RuntimeError, OK # Issue 13080
|
||||
|
||||
illegal_invocation_test/01: MissingCompileTimeError # Issue 23611
|
||||
prefix_unqualified_invocation_test/01: MissingCompileTimeError # Issue 23611
|
||||
prefix_unqualified_invocation_test/02: MissingCompileTimeError # Issue 23611
|
||||
|
||||
[ $compiler == dart2js && $runtime == none ]
|
||||
*: Fail, Pass # TODO(ahe): Triage these tests.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user