Refactor handling of library prefixes.

Closes #13632

BUG=
R=karlklose@google.com

Review URL: https://codereview.chromium.org//1227353002.
This commit is contained in:
Johnni Winther
2015-07-09 16:28:06 +02:00
parent cf4eca0975
commit 6b36c8acc6
6 changed files with 66 additions and 39 deletions
+56 -11
View File
@@ -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) {
+3
View File
@@ -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}'.");
-2
View File
@@ -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 [
-17
View File
@@ -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.