diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart index c4c3d2955750..459327bdcfd5 100644 --- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart +++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart @@ -398,7 +398,8 @@ class BodyBuilder extends ScopeListener pushQualifiedReference(beginToken.next, periodBeforeName); if (arguments != null) { push(arguments); - endNewExpression(beginToken); + buildConstructorReferenceInvocation( + beginToken, beginToken.offset, Constness.explicitConst); push(popForValue()); } else { String name = pop(); @@ -2660,6 +2661,12 @@ class BodyBuilder extends ScopeListener constantContext = ConstantContext.inferred; } + @override + void beginImplicitCreationExpression(Token token) { + debugEvent("beginImplicitCreationExpression"); + super.push(constantContext); + } + @override void endConstLiteral(Token token) { debugEvent("endConstLiteral"); @@ -2671,7 +2678,12 @@ class BodyBuilder extends ScopeListener @override void endNewExpression(Token token) { debugEvent("NewExpression"); - Token nameToken = token.next; + buildConstructorReferenceInvocation( + token.next, token.offset, Constness.explicitNew); + } + + void buildConstructorReferenceInvocation( + Token nameToken, int offset, Constness constness) { Arguments arguments = pop(); String name = pop(); List typeArguments = pop(); @@ -2697,27 +2709,26 @@ class BodyBuilder extends ScopeListener ConstantContext savedConstantContext = pop(); if (type is TypeDeclarationBuilder) { Expression expression = buildConstructorInvocation( - type, - nameToken, - arguments, - name, - typeArguments, - token.charOffset, - optional("const", token) || optional("@", token) - ? Constness.explicitConst - : Constness.explicitNew); + type, nameToken, arguments, name, typeArguments, offset, constness); push(deferredPrefix != null ? wrapInDeferredCheck(expression, deferredPrefix, checkOffset) : expression); } else if (type is ErrorAccessor) { push(type.buildError(arguments)); } else { - push(throwNoSuchMethodError(forest.literalNull(token), + push(throwNoSuchMethodError(storeOffset(forest.literalNull(null), offset), debugName(getNodeName(type), name), arguments, nameToken.charOffset)); } constantContext = savedConstantContext; } + @override + void endImplicitCreationExpression(Token token) { + debugEvent("ImplicitCreationExpression"); + buildConstructorReferenceInvocation( + token, token.offset, Constness.implicit); + } + @override Expression buildConstructorInvocation( TypeDeclarationBuilder type, @@ -2816,7 +2827,8 @@ class BodyBuilder extends ScopeListener @override void endConstExpression(Token token) { debugEvent("endConstExpression"); - endNewExpression(token); + buildConstructorReferenceInvocation( + token.next, token.offset, Constness.explicitConst); } @override diff --git a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart index 353a65419bef..6e9fb7626141 100644 --- a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart +++ b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart @@ -951,6 +951,16 @@ class ForwardingListener implements Listener { listener?.handleDottedName(count, firstIdentifier); } + @override + void beginImplicitCreationExpression(Token token) { + listener?.beginImplicitCreationExpression(token); + } + + @override + void endImplicitCreationExpression(Token token) { + listener?.endImplicitCreationExpression(token); + } + @override void handleEmptyStatement(Token token) { listener?.handleEmptyStatement(token); diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart index e71259cbc5c6..19ed1b1b2f40 100644 --- a/pkg/front_end/lib/src/fasta/parser/listener.dart +++ b/pkg/front_end/lib/src/fasta/parser/listener.dart @@ -516,6 +516,12 @@ class Listener { logEvent("DottedName"); } + void beginImplicitCreationExpression(Token token) {} + + void endImplicitCreationExpression(Token token) { + logEvent("ImplicitCreationExpression"); + } + void beginInitializedIdentifier(Token token) {} void endInitializedIdentifier(Token nameToken) { diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart index 0b381b6164c4..cee75f20cda9 100644 --- a/pkg/front_end/lib/src/fasta/parser/parser.dart +++ b/pkg/front_end/lib/src/fasta/parser/parser.dart @@ -4566,9 +4566,24 @@ class Parser { token.next, POSTFIX_PRECEDENCE, allowCascades); listener.handleUnaryPrefixAssignmentExpression(operator); return token; - } else { - return parsePrimary(token, IdentifierContext.expression); + } else if (token.next.isIdentifier) { + Token identifier = token.next; + if (optional(".", identifier.next)) { + identifier = identifier.next.next; + } + if (identifier.isIdentifier) { + // Looking at `identifier ('.' identifier)?`. + if (optional("<", identifier.next)) { + BeginToken typeArguments = identifier.next; + Token endTypeArguments = typeArguments.endGroup; + if (endTypeArguments != null && + optional(".", endTypeArguments.next)) { + return parseImplicitCreationExpression(token); + } + } + } } + return parsePrimary(token, IdentifierContext.expression); } Token parseArgumentOrIndexStar(Token token, Token typeArguments) { @@ -4981,6 +4996,15 @@ class Parser { return token; } + Token parseImplicitCreationExpression(Token token) { + Token begin = token; + listener.beginImplicitCreationExpression(token); + token = parseConstructorReference(token); + token = parseRequiredArguments(token); + listener.endImplicitCreationExpression(begin); + return token; + } + /// This method parses a list or map literal that is known to start with the /// keyword 'const'. /// diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status index af4595d9c4cd..73d503144a8d 100644 --- a/tests/language_2/language_2_kernel.status +++ b/tests/language_2/language_2_kernel.status @@ -115,11 +115,6 @@ identical_const_test/01: MissingCompileTimeError identical_const_test/02: MissingCompileTimeError identical_const_test/03: MissingCompileTimeError identical_const_test/04: MissingCompileTimeError -implicit_creation/implicit_const_context_constructor_generic_named_test: CompileTimeError -implicit_creation/implicit_const_context_prefix_constructor_generic_named_test: CompileTimeError -implicit_creation/implicit_new_constructor_generic_named_test: CompileTimeError -implicit_creation/implicit_new_or_const_generic_test: CompileTimeError -implicit_creation/implicit_new_prefix_constructor_generic_named_test: CompileTimeError implicit_this_test/01: MissingCompileTimeError implicit_this_test/04: MissingCompileTimeError issue31596_override_test/07: MissingCompileTimeError @@ -667,7 +662,6 @@ generic_no_such_method_dispatcher_test: CompileTimeError # Issue 31533 generic_tearoff_test: CompileTimeError generic_tearoff_test: RuntimeError if_null_evaluation_order_test: Pass -implicit_creation/implicit_new_constructor_generic_test: Pass initializing_formal_type_annotation_test/01: MissingCompileTimeError initializing_formal_type_annotation_test/02: MissingCompileTimeError instantiate_tearoff_of_call_test: CompileTimeError @@ -1010,7 +1004,6 @@ getter_override_test/01: MissingCompileTimeError # Issue 32613: override check i getter_override_test/02: MissingCompileTimeError # Issue 32613: override check is missing in CFE. hello_dart_test: Skip # Incompatible flag: --compile_all implicit_closure_test: Skip # Incompatible flag: --use_slow_path -implicit_creation/implicit_new_constructor_generic_test: Pass implicit_downcast_during_assignment_test: Pass # Correctly passes. implicit_downcast_during_combiner_test: Pass # Correctly passes. implicit_downcast_during_compound_assignment_test: Pass # Correctly passes.