Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 6848cb7

Browse files
johnniwintherCommit Queue
authored and
Commit Queue
committed
[parser] Compute isConstructor before beginMethod
This moves the computation of which a method-like declaration is a constructor to before the listener call to beginMethod. This paves the way for creating a beginXConstructor call that fully separates listener handling of constructors and methods. To avoid changes in the parsed AST, the computation deliberately matches the existing result, even though this is intertwined with error recovery. Change-Id: I34ba68f9690e842a6c8baa26d9ba4b651230ad76 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/461040 Reviewed-by: Jens Johansen <jensj@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
1 parent 77b3c43 commit 6848cb7

15 files changed

+744
-14
lines changed

‎pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart‎

Lines changed: 105 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5507,6 +5507,78 @@ class Parser {
55075507
return token;
55085508
}
55095509

5510+
/// Returns `true` if a method-like declaration is determined to be a
5511+
/// constructor.
5512+
///
5513+
/// [name] is the token for the (first) name of the declaration or the
5514+
/// `operator` token if [isOperator] is `true`.
5515+
///
5516+
/// [getOrSet] is the token for `get` or `set` if this occurred prior to the
5517+
/// [name].
5518+
///
5519+
/// [enclosingDeclarationName] is the name of the enclosing class, mixin,
5520+
/// enum, extension or extension type.
5521+
bool _isConstructor(
5522+
Token name,
5523+
Token? getOrSet,
5524+
String? enclosingDeclarationName,
5525+
bool isOperator,
5526+
) {
5527+
// TODO(johnniwinther): Update this to match what we want and not what we
5528+
// happened to do during error recovery.
5529+
Token afterName;
5530+
if (name.isKeywordOrIdentifier) {
5531+
afterName = name.next!;
5532+
} else {
5533+
// Recovery (identifier is synthesized)
5534+
afterName = name;
5535+
}
5536+
if (afterName.isA(TokenType.PERIOD)) {
5537+
// This is only legal for constructors.
5538+
return true;
5539+
}
5540+
5541+
if (isOperator) {
5542+
if (afterName.isOperator) {
5543+
afterName = afterName.next!;
5544+
} else if (isUnaryMinus(afterName)) {
5545+
afterName = afterName.next!.next!;
5546+
}
5547+
}
5548+
if (afterName.isA(TokenType.BANG)) {
5549+
// Recovery
5550+
afterName = afterName.next!;
5551+
}
5552+
if (afterName.isA(TokenType.LT)) {
5553+
if (afterName.endGroup != null) {
5554+
afterName = afterName.endGroup!.next!;
5555+
if (afterName.isA(TokenType.EQ)) {
5556+
// Recovery
5557+
afterName = afterName.next!;
5558+
}
5559+
}
5560+
}
5561+
5562+
if (afterName.isA(TokenType.OPEN_PAREN)) {
5563+
Token afterParen = afterName.endGroup!.next!;
5564+
if (afterParen.isA(TokenType.COLON)) {
5565+
return true;
5566+
}
5567+
} else if (afterName.isA(TokenType.COLON)) {
5568+
return true;
5569+
}
5570+
5571+
if (getOrSet != null) {
5572+
return false;
5573+
}
5574+
5575+
if (name.lexeme == enclosingDeclarationName) {
5576+
return true;
5577+
}
5578+
5579+
return false;
5580+
}
5581+
55105582
Token parseMethod(
55115583
Token beforeStart,
55125584
Token? abstractToken,
@@ -5556,6 +5628,13 @@ class Parser {
55565628
}
55575629
}
55585630

5631+
bool isConstructor = _isConstructor(
5632+
name,
5633+
getOrSet,
5634+
enclosingDeclarationName,
5635+
isOperator,
5636+
);
5637+
55595638
if (staticToken != null) {
55605639
if (isOperator) {
55615640
reportRecoverableError(staticToken, codes.codeStaticOperator);
@@ -5710,20 +5789,26 @@ class Parser {
57105789
}
57115790
asyncState = savedAsyncModifier;
57125791

5713-
bool isConstructor = false;
5714-
if (name.next!.isA(TokenType.PERIOD) || beforeInitializers != null) {
5715-
// This is only legal for constructors.
5716-
isConstructor = true;
5717-
} else if (name.lexeme == enclosingDeclarationName) {
5718-
if (getOrSet != null) {
5719-
// Recovery: The (simple) get/set member name is invalid.
5720-
// Report an error and continue with invalid name
5721-
// (keeping it as a getter/setter).
5722-
reportRecoverableError(name, codes.codeMemberWithSameNameAsClass);
5723-
} else {
5724-
isConstructor = true;
5725-
}
5726-
}
5792+
// TODO(johnniwinther): Remove this when [_isConstructor] is updated.
5793+
assert(
5794+
() {
5795+
bool isConstructor = false;
5796+
if (name.next!.isA(TokenType.PERIOD) ||
5797+
beforeInitializers != null) {
5798+
// This is only legal for constructors.
5799+
isConstructor = true;
5800+
} else if (name.lexeme == enclosingDeclarationName) {
5801+
if (getOrSet != null) {
5802+
// Recovery: The (simple) get/set member name is invalid.
5803+
} else {
5804+
isConstructor = true;
5805+
}
5806+
}
5807+
return isConstructor;
5808+
}() ==
5809+
isConstructor,
5810+
"Unexpected constructor state: $isConstructor.",
5811+
);
57275812

57285813
if (isConstructor) {
57295814
//
@@ -5805,6 +5890,12 @@ class Parser {
58055890
//
58065891
// method
58075892
//
5893+
if (name.lexeme == enclosingDeclarationName && getOrSet != null) {
5894+
// Recovery: The (simple) get/set member name is invalid.
5895+
// Report an error and continue with invalid name
5896+
// (keeping it as a getter/setter).
5897+
reportRecoverableError(name, codes.codeMemberWithSameNameAsClass);
5898+
}
58085899
if (varFinalOrConst != null) {
58095900
assert(varFinalOrConst.isA(Keyword.CONST));
58105901
reportRecoverableError(varFinalOrConst, codes.codeConstMethod);
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class C {
2+
operator unary-() : this();
3+
operator unary- : this();
4+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
library;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:2:12: Error: Unexpected token 'unary'.
6+
// operator unary-() : this();
7+
// ^^^^^
8+
//
9+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:2:3: Error: The name of a constructor must match the name of the enclosing class.
10+
// operator unary-() : this();
11+
// ^^^^^^^^
12+
//
13+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:3:12: Error: Unexpected token 'unary'.
14+
// operator unary- : this();
15+
// ^^^^^
16+
//
17+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:3:17: Error: A method declaration needs an explicit list of parameters.
18+
// Try adding a parameter list to the method declaration.
19+
// operator unary- : this();
20+
// ^
21+
//
22+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:3:3: Error: The name of a constructor must match the name of the enclosing class.
23+
// operator unary- : this();
24+
// ^^^^^^^^
25+
//
26+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:3:17: Error: 'C.-' is already declared in this scope.
27+
// operator unary- : this();
28+
// ^
29+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:2:17: Context: Previous declaration of 'C.-'.
30+
// operator unary-() : this();
31+
// ^
32+
//
33+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:2:23: Error: Couldn't find constructor 'C'.
34+
// operator unary-() : this();
35+
// ^^^^
36+
//
37+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:3:21: Error: Couldn't find constructor 'C'.
38+
// operator unary- : this();
39+
// ^^^^
40+
//
41+
import self as self;
42+
import "dart:core" as core;
43+
44+
class C extends core::Object {
45+
constructor -() → self::C
46+
: final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:2:23: Error: Couldn't find constructor 'C'.
47+
operator unary-() : this();
48+
^^^^"
49+
;
50+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
library;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:2:12: Error: Unexpected token 'unary'.
6+
// operator unary-() : this();
7+
// ^^^^^
8+
//
9+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:2:3: Error: The name of a constructor must match the name of the enclosing class.
10+
// operator unary-() : this();
11+
// ^^^^^^^^
12+
//
13+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:3:12: Error: Unexpected token 'unary'.
14+
// operator unary- : this();
15+
// ^^^^^
16+
//
17+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:3:17: Error: A method declaration needs an explicit list of parameters.
18+
// Try adding a parameter list to the method declaration.
19+
// operator unary- : this();
20+
// ^
21+
//
22+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:3:3: Error: The name of a constructor must match the name of the enclosing class.
23+
// operator unary- : this();
24+
// ^^^^^^^^
25+
//
26+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:3:17: Error: 'C.-' is already declared in this scope.
27+
// operator unary- : this();
28+
// ^
29+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:2:17: Context: Previous declaration of 'C.-'.
30+
// operator unary-() : this();
31+
// ^
32+
//
33+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:2:23: Error: Couldn't find constructor 'C'.
34+
// operator unary-() : this();
35+
// ^^^^
36+
//
37+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:3:21: Error: Couldn't find constructor 'C'.
38+
// operator unary- : this();
39+
// ^^^^
40+
//
41+
import self as self;
42+
import "dart:core" as core;
43+
44+
class C extends core::Object {
45+
constructor -() → self::C
46+
: final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:2:23: Error: Couldn't find constructor 'C'.
47+
operator unary-() : this();
48+
^^^^"
49+
;
50+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
library;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:2:12: Error: Unexpected token 'unary'.
6+
// operator unary-() : this();
7+
// ^^^^^
8+
//
9+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:2:3: Error: The name of a constructor must match the name of the enclosing class.
10+
// operator unary-() : this();
11+
// ^^^^^^^^
12+
//
13+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:3:12: Error: Unexpected token 'unary'.
14+
// operator unary- : this();
15+
// ^^^^^
16+
//
17+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:3:17: Error: A method declaration needs an explicit list of parameters.
18+
// Try adding a parameter list to the method declaration.
19+
// operator unary- : this();
20+
// ^
21+
//
22+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:3:3: Error: The name of a constructor must match the name of the enclosing class.
23+
// operator unary- : this();
24+
// ^^^^^^^^
25+
//
26+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:3:17: Error: 'C.-' is already declared in this scope.
27+
// operator unary- : this();
28+
// ^
29+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:2:17: Context: Previous declaration of 'C.-'.
30+
// operator unary-() : this();
31+
// ^
32+
//
33+
import self as self;
34+
import "dart:core" as core;
35+
36+
class C extends core::Object {
37+
constructor -() → self::C
38+
;
39+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
library;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:2:12: Error: Unexpected token 'unary'.
6+
// operator unary-() : this();
7+
// ^^^^^
8+
//
9+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:2:3: Error: The name of a constructor must match the name of the enclosing class.
10+
// operator unary-() : this();
11+
// ^^^^^^^^
12+
//
13+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:3:12: Error: Unexpected token 'unary'.
14+
// operator unary- : this();
15+
// ^^^^^
16+
//
17+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:3:17: Error: A method declaration needs an explicit list of parameters.
18+
// Try adding a parameter list to the method declaration.
19+
// operator unary- : this();
20+
// ^
21+
//
22+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:3:3: Error: The name of a constructor must match the name of the enclosing class.
23+
// operator unary- : this();
24+
// ^^^^^^^^
25+
//
26+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:3:17: Error: 'C.-' is already declared in this scope.
27+
// operator unary- : this();
28+
// ^
29+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:2:17: Context: Previous declaration of 'C.-'.
30+
// operator unary-() : this();
31+
// ^
32+
//
33+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:2:23: Error: Couldn't find constructor 'C'.
34+
// operator unary-() : this();
35+
// ^^^^
36+
//
37+
// pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:3:21: Error: Couldn't find constructor 'C'.
38+
// operator unary- : this();
39+
// ^^^^
40+
//
41+
import self as self;
42+
import "dart:core" as core;
43+
44+
class C extends core::Object {
45+
constructor -() → self::C
46+
: final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/error_recovery/constructor_recovery_operator_unary_minus.dart:2:23: Error: Couldn't find constructor 'C'.
47+
operator unary-() : this();
48+
^^^^"
49+
;
50+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class C {
2+
operator unary-() : this();
3+
operator unary- (): this();
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class C {
2+
operator unary-() : this();
3+
operator unary- (): this();
4+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class C {
2+
C<T>() : this();
3+
C!<T>() : this();
4+
C<T() : this();
5+
C<T>=() : this();
6+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /