Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 14998df

Browse files
scheglovcommit-bot@chromium.org
authored andcommitted
Fix unlinked API signature for const/static out-of-order.
Saw a crash in logs, was able to reproduce. Change-Id: I2632c9ec7c3c34e6498f74e17507505128664418 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/190400 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent 8bd3088 commit 14998df

File tree

3 files changed

+123
-59
lines changed

3 files changed

+123
-59
lines changed

pkg/analyzer/lib/src/dart/analysis/unlinked_api_signature.dart

Lines changed: 81 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,38 @@ class _UnitApiSignatureComputer {
2020
static const int _kindConstructorDeclaration = 1;
2121
static const int _kindFieldDeclaration = 2;
2222
static const int _kindMethodDeclaration = 3;
23+
static const int _nullNode = 0;
24+
static const int _nullToken = 0;
2325

2426
final ApiSignature signature = ApiSignature();
2527

26-
void addClassOrMixin(ClassOrMixinDeclaration node) {
27-
addTokens(node.beginToken, node.leftBracket);
28+
void compute(CompilationUnit unit) {
29+
signature.addFeatureSet(unit.featureSet);
30+
31+
signature.addInt(unit.directives.length);
32+
unit.directives.forEach(_addNode);
33+
34+
signature.addInt(unit.declarations.length);
35+
for (var declaration in unit.declarations) {
36+
if (declaration is ClassOrMixinDeclaration) {
37+
_addClassOrMixin(declaration);
38+
} else if (declaration is FunctionDeclaration) {
39+
var functionExpression = declaration.functionExpression;
40+
_addTokens(
41+
declaration.beginToken,
42+
(functionExpression.parameters ?? declaration.name).endToken,
43+
);
44+
_addFunctionBodyModifiers(functionExpression.body);
45+
} else if (declaration is TopLevelVariableDeclaration) {
46+
_topLevelVariableDeclaration(declaration);
47+
} else {
48+
_addNode(declaration);
49+
}
50+
}
51+
}
52+
53+
void _addClassOrMixin(ClassOrMixinDeclaration node) {
54+
_addTokens(node.beginToken, node.leftBracket);
2855

2956
bool hasConstConstructor = node.members
3057
.any((m) => m is ConstructorDeclaration && m.constKeyword != null);
@@ -33,67 +60,68 @@ class _UnitApiSignatureComputer {
3360
for (var member in node.members) {
3461
if (member is ConstructorDeclaration) {
3562
signature.addInt(_kindConstructorDeclaration);
36-
addTokens(member.beginToken, member.parameters.endToken);
63+
_addTokens(member.beginToken, member.parameters.endToken);
3764
if (member.constKeyword != null) {
38-
addNodeList(member.initializers);
65+
_addNodeList(member.initializers);
3966
}
40-
addNode(member.redirectedConstructor);
67+
_addNode(member.redirectedConstructor);
4168
} else if (member is FieldDeclaration) {
4269
signature.addInt(_kindFieldDeclaration);
43-
var variableList = member.fields;
44-
addVariables(
45-
member,
46-
variableList,
47-
!member.isStatic && variableList.isFinal && hasConstConstructor,
48-
);
70+
_fieldDeclaration(member, hasConstConstructor);
4971
} else if (member is MethodDeclaration) {
5072
signature.addInt(_kindMethodDeclaration);
51-
addTokens(
73+
_addTokens(
5274
member.beginToken,
5375
(member.parameters ?? member.name).endToken,
5476
);
5577
signature.addBool(member.body is EmptyFunctionBody);
56-
addFunctionBodyModifiers(member.body);
78+
_addFunctionBodyModifiers(member.body);
5779
} else {
5880
throw UnimplementedError('(${member.runtimeType}) $member');
5981
}
6082
}
6183

62-
addToken(node.rightBracket);
84+
_addToken(node.rightBracket);
6385
}
6486

65-
void addFunctionBodyModifiers(FunctionBody? node) {
87+
void _addFunctionBodyModifiers(FunctionBody? node) {
6688
if (node != null) {
6789
signature.addBool(node.isSynchronous);
6890
signature.addBool(node.isGenerator);
6991
}
7092
}
7193

72-
void addNode(AstNode? node) {
94+
void _addNode(AstNode? node) {
7395
if (node != null) {
74-
addTokens(node.beginToken, node.endToken);
96+
_addTokens(node.beginToken, node.endToken);
97+
} else {
98+
signature.addInt(_nullNode);
7599
}
76100
}
77101

78-
void addNodeList(List<AstNode> nodes) {
102+
void _addNodeList(List<AstNode> nodes) {
79103
for (var node in nodes) {
80-
addNode(node);
104+
_addNode(node);
81105
}
82106
}
83107

84-
void addToken(Token token) {
85-
signature.addString(token.lexeme);
108+
void _addToken(Token? token) {
109+
if (token != null) {
110+
signature.addString(token.lexeme);
111+
} else {
112+
signature.addInt(_nullToken);
113+
}
86114
}
87115

88116
/// Appends tokens from [begin] (including), to [end] (also including).
89-
void addTokens(Token begin, Token end) {
117+
void _addTokens(Token begin, Token end) {
90118
if (begin is CommentToken) {
91119
begin = begin.parent!;
92120
}
93121

94122
Token? token = begin;
95123
while (token != null) {
96-
addToken(token);
124+
_addToken(token);
97125

98126
if (token == end) {
99127
break;
@@ -110,48 +138,42 @@ class _UnitApiSignatureComputer {
110138
}
111139
}
112140

113-
void addVariables(
114-
AstNode node,
115-
VariableDeclarationList variableList,
116-
bool includeInitializers,
117-
) {
118-
if (variableList.type == null ||
141+
void _fieldDeclaration(FieldDeclaration node, bool hasConstConstructor) {
142+
_addToken(node.abstractKeyword);
143+
_addToken(node.covariantKeyword);
144+
_addToken(node.externalKeyword);
145+
_addToken(node.staticKeyword);
146+
_addNodeList(node.metadata);
147+
148+
var variableList = node.fields;
149+
var includeInitializers = variableList.type == null ||
119150
variableList.isConst ||
120-
includeInitializers) {
121-
addTokens(node.beginToken, node.endToken);
122-
} else {
123-
addTokens(node.beginToken, variableList.type!.endToken);
151+
hasConstConstructor && !node.isStatic && variableList.isFinal;
152+
_variableList(variableList, includeInitializers);
153+
}
124154

125-
signature.addInt(variableList.variables.length);
126-
for (var variable in variableList.variables) {
127-
addTokens(variable.beginToken, variable.name.endToken);
128-
signature.addBool(variable.initializer != null);
129-
addToken(variable.endToken.next!); // `,` or `;`
130-
}
131-
}
155+
void _topLevelVariableDeclaration(TopLevelVariableDeclaration node) {
156+
_addToken(node.externalKeyword);
157+
_addNodeList(node.metadata);
158+
159+
var variableList = node.variables;
160+
var includeInitializers = variableList.type == null || variableList.isConst;
161+
_variableList(variableList, includeInitializers);
132162
}
133163

134-
void compute(CompilationUnit unit) {
135-
signature.addFeatureSet(unit.featureSet);
164+
void _variableList(VariableDeclarationList node, bool includeInitializers) {
165+
_addToken(node.keyword);
166+
_addToken(node.lateKeyword);
167+
_addNode(node.type);
136168

137-
signature.addInt(unit.directives.length);
138-
unit.directives.forEach(addNode);
169+
var variables = node.variables;
170+
signature.addInt(variables.length);
139171

140-
signature.addInt(unit.declarations.length);
141-
for (var declaration in unit.declarations) {
142-
if (declaration is ClassOrMixinDeclaration) {
143-
addClassOrMixin(declaration);
144-
} else if (declaration is FunctionDeclaration) {
145-
var functionExpression = declaration.functionExpression;
146-
addTokens(
147-
declaration.beginToken,
148-
(functionExpression.parameters ?? declaration.name).endToken,
149-
);
150-
addFunctionBodyModifiers(functionExpression.body);
151-
} else if (declaration is TopLevelVariableDeclaration) {
152-
addVariables(declaration, declaration.variables, false);
153-
} else {
154-
addNode(declaration);
172+
for (var variable in variables) {
173+
_addNode(variable.name);
174+
signature.addBool(variable.initializer != null);
175+
if (includeInitializers) {
176+
_addNode(variable.initializer);
155177
}
156178
}
157179
}

pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,22 @@ class A {
3939
''');
4040
}
4141

42+
test_change_field_outOfOrderStaticConst() async {
43+
await resolveTestCode(r'''
44+
class A {
45+
static f = Object();
46+
}
47+
''');
48+
49+
driverFor(testFilePath).changeFile(testFilePath);
50+
await resolveTestCode(r'''
51+
class A {
52+
const
53+
static f = Object();
54+
}
55+
''');
56+
}
57+
4258
test_change_field_staticFinal_hasConstConstructor_changeInitializer() async {
4359
useEmptyByteStore();
4460

pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,32 @@ class A {
261261
''');
262262
}
263263

264+
test_class_field_const_add_outOfOrder() {
265+
assertNotSameSignature(r'''
266+
class A {
267+
static f = Object();
268+
}
269+
''', r'''
270+
class A {
271+
const
272+
static f = Object();
273+
}
274+
''');
275+
}
276+
277+
test_class_field_const_add_outOfOrder_hasFinal() {
278+
assertNotSameSignature(r'''
279+
class A {
280+
static final f = Object();
281+
}
282+
''', r'''
283+
class A {
284+
const
285+
static final f = Object();
286+
}
287+
''');
288+
}
289+
264290
test_class_field_final_add() {
265291
assertNotSameSignature(r'''
266292
class C {

0 commit comments

Comments
 (0)