Skip to content

Commit c25e748

Browse files
stereotype441commit-bot@chromium.org
authored andcommitted
Add links to "why not promoted" error messages.
These links are not live yet, but they will be filled in with documentation explaining subtleties of type promotion in more detail. Bug: #44900 Change-Id: I3e1865597fc5c56495a8108c8a4de98cab0c3e4b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193749 Commit-Queue: Paul Berry <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent 76e41bc commit c25e748

File tree

7 files changed

+84
-32
lines changed

7 files changed

+84
-32
lines changed

pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,9 @@ class DemoteViaExplicitWrite<Variable extends Object, Expression extends Object>
311311

312312
DemoteViaExplicitWrite(this.variable, this.writeExpression);
313313

314+
@override
315+
String get documentationLink => 'http://dart.dev/go/non-promo-write';
316+
314317
@override
315318
String get shortName => 'explicitWrite';
316319

@@ -339,6 +342,9 @@ class DemoteViaForEachVariableWrite<Variable extends Object,
339342

340343
DemoteViaForEachVariableWrite(this.variable, this.node);
341344

345+
@override
346+
String get documentationLink => 'http://dart.dev/go/non-promo-write';
347+
342348
@override
343349
String get shortName => 'explicitWrite';
344350

@@ -2332,6 +2338,11 @@ class NonPromotionHistory<Type> {
23322338

23332339
/// Abstract class representing a reason why something was not promoted.
23342340
abstract class NonPromotionReason {
2341+
/// Link to documentation describing this non-promotion reason; this should be
2342+
/// presented to the user as a source of additional information about the
2343+
/// error.
2344+
String get documentationLink;
2345+
23352346
/// Short text description of this non-promotion reason; intended for ID
23362347
/// testing.
23372348
String get shortName;
@@ -2371,6 +2382,9 @@ class PropertyNotPromoted<Type extends Object> extends NonPromotionReason {
23712382

23722383
PropertyNotPromoted(this.propertyName, this.staticType);
23732384

2385+
@override
2386+
String get documentationLink => 'http://dart.dev/go/non-promo-property';
2387+
23742388
@override
23752389
String get shortName => 'propertyNotPromoted';
23762390

@@ -2606,6 +2620,9 @@ class SsaNode<Variable extends Object, Type extends Object> {
26062620
/// Non-promotion reason describing the situation where an expression was not
26072621
/// promoted due to the fact that it's a reference to `this`.
26082622
class ThisNotPromoted extends NonPromotionReason {
2623+
@override
2624+
String get documentationLink => 'http://dart.dev/go/non-promo-this';
2625+
26092626
@override
26102627
String get shortName => 'thisNotPromoted';
26112628

pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4110,25 +4110,29 @@ const MessageCode messageFieldInitializerOutsideConstructor = const MessageCode(
41104110
tip: r"""Try removing 'this.'.""");
41114111

41124112
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
4113-
const Template<Message Function(String name)> templateFieldNotPromoted =
4114-
const Template<Message Function(String name)>(
4113+
const Template<Message Function(String name, String string)>
4114+
templateFieldNotPromoted =
4115+
const Template<Message Function(String name, String string)>(
41154116
messageTemplate:
41164117
r"""'#name' refers to a property so it couldn't be promoted.""",
4118+
tipTemplate: r"""See #string""",
41174119
withArguments: _withArgumentsFieldNotPromoted);
41184120

41194121
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
4120-
const Code<Message Function(String name)> codeFieldNotPromoted =
4121-
const Code<Message Function(String name)>(
4122+
const Code<Message Function(String name, String string)> codeFieldNotPromoted =
4123+
const Code<Message Function(String name, String string)>(
41224124
"FieldNotPromoted",
41234125
);
41244126

41254127
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
4126-
Message _withArgumentsFieldNotPromoted(String name) {
4128+
Message _withArgumentsFieldNotPromoted(String name, String string) {
41274129
if (name.isEmpty) throw 'No name provided';
41284130
name = demangleMixinApplicationName(name);
4131+
if (string.isEmpty) throw 'No string provided';
41294132
return new Message(codeFieldNotPromoted,
41304133
message: """'${name}' refers to a property so it couldn't be promoted.""",
4131-
arguments: {'name': name});
4134+
tip: """See ${string}""",
4135+
arguments: {'name': name, 'string': string});
41324136
}
41334137

41344138
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -9073,11 +9077,26 @@ const MessageCode messageThisInNullAwareReceiver = const MessageCode(
90739077
tip: r"""Try replacing '?.' with '.'""");
90749078

90759079
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
9076-
const Code<Null> codeThisNotPromoted = messageThisNotPromoted;
9080+
const Template<Message Function(String string)> templateThisNotPromoted =
9081+
const Template<Message Function(String string)>(
9082+
messageTemplate: r"""'this' can't be promoted.""",
9083+
tipTemplate: r"""See #string""",
9084+
withArguments: _withArgumentsThisNotPromoted);
90779085

90789086
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
9079-
const MessageCode messageThisNotPromoted = const MessageCode("ThisNotPromoted",
9080-
message: r"""'this' can't be promoted.""");
9087+
const Code<Message Function(String string)> codeThisNotPromoted =
9088+
const Code<Message Function(String string)>(
9089+
"ThisNotPromoted",
9090+
);
9091+
9092+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
9093+
Message _withArgumentsThisNotPromoted(String string) {
9094+
if (string.isEmpty) throw 'No string provided';
9095+
return new Message(codeThisNotPromoted,
9096+
message: """'this' can't be promoted.""",
9097+
tip: """See ${string}""",
9098+
arguments: {'string': string});
9099+
}
90819100

90829101
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
90839102
const Template<Message Function(String string)>
@@ -9688,29 +9707,33 @@ const MessageCode messageVarReturnType = const MessageCode("VarReturnType",
96889707
r"""Try removing the keyword 'var', or replacing it with the name of the return type.""");
96899708

96909709
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
9691-
const Template<Message Function(String name)>
9710+
const Template<Message Function(String name, String string)>
96929711
templateVariableCouldBeNullDueToWrite =
9693-
const Template<Message Function(String name)>(
9712+
const Template<Message Function(String name, String string)>(
96949713
messageTemplate:
96959714
r"""Variable '#name' could be null due to an intervening write.""",
9696-
tipTemplate: r"""Try null checking the variable after the write.""",
9715+
tipTemplate:
9716+
r"""Try null checking the variable after the write. See #string""",
96979717
withArguments: _withArgumentsVariableCouldBeNullDueToWrite);
96989718

96999719
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
9700-
const Code<Message Function(String name)> codeVariableCouldBeNullDueToWrite =
9701-
const Code<Message Function(String name)>(
9720+
const Code<Message Function(String name, String string)>
9721+
codeVariableCouldBeNullDueToWrite =
9722+
const Code<Message Function(String name, String string)>(
97029723
"VariableCouldBeNullDueToWrite",
97039724
);
97049725

97059726
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
9706-
Message _withArgumentsVariableCouldBeNullDueToWrite(String name) {
9727+
Message _withArgumentsVariableCouldBeNullDueToWrite(
9728+
String name, String string) {
97079729
if (name.isEmpty) throw 'No name provided';
97089730
name = demangleMixinApplicationName(name);
9731+
if (string.isEmpty) throw 'No string provided';
97099732
return new Message(codeVariableCouldBeNullDueToWrite,
97109733
message:
97119734
"""Variable '${name}' could be null due to an intervening write.""",
9712-
tip: """Try null checking the variable after the write.""",
9713-
arguments: {'name': name});
9735+
tip: """Try null checking the variable after the write. See ${string}""",
9736+
arguments: {'name': name, 'string': string});
97149737
}
97159738

97169739
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.

pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5754,6 +5754,9 @@ Matcher _matchVariableModel(
57545754
}
57555755

57565756
class _MockNonPromotionReason extends NonPromotionReason {
5757+
@override
5758+
String get documentationLink => fail('Unexpected call to documentationLink');
5759+
57575760
String get shortName => fail('Unexpected call to shortName');
57585761

57595762
R accept<R, Node extends Object, Expression extends Object,

pkg/analyzer/lib/src/generated/resolver.dart

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3472,7 +3472,7 @@ class _WhyNotPromotedVisitor
34723472
}
34733473
var variableName = reason.variable.name;
34743474
if (variableName == null) return null;
3475-
return _contextMessageForWrite(variableName, writeExpression);
3475+
return _contextMessageForWrite(variableName, writeExpression, reason);
34763476
}
34773477

34783478
@override
@@ -3496,7 +3496,7 @@ class _WhyNotPromotedVisitor
34963496
_dataForTesting!.nonPromotionReasonTargets[identifier] =
34973497
reason.shortName;
34983498
}
3499-
return _contextMessageForWrite(variableName, identifier);
3499+
return _contextMessageForWrite(variableName, identifier, reason);
35003500
} else {
35013501
assert(false, 'Unexpected parts type');
35023502
return null;
@@ -3521,7 +3521,8 @@ class _WhyNotPromotedVisitor
35213521
if (receiverElement is PropertyAccessorElement) {
35223522
propertyReference = receiverElement;
35233523
propertyType = reason.staticType;
3524-
return _contextMessageForProperty(receiverElement, reason.propertyName);
3524+
return _contextMessageForProperty(
3525+
receiverElement, reason.propertyName, reason);
35253526
} else {
35263527
assert(receiverElement == null,
35273528
'Unrecognized property element: ${receiverElement.runtimeType}');
@@ -3533,27 +3534,29 @@ class _WhyNotPromotedVisitor
35333534
DiagnosticMessage? visitThisNotPromoted(ThisNotPromoted reason) {
35343535
return DiagnosticMessageImpl(
35353536
filePath: source.fullName,
3536-
message: "'this' can't be promoted.",
3537+
message: "'this' can't be promoted. See ${reason.documentationLink}",
35373538
offset: _errorEntity.offset,
35383539
length: _errorEntity.length);
35393540
}
35403541

35413542
DiagnosticMessageImpl _contextMessageForProperty(
3542-
PropertyAccessorElement property, String propertyName) {
3543+
PropertyAccessorElement property,
3544+
String propertyName,
3545+
NonPromotionReason reason) {
35433546
return DiagnosticMessageImpl(
35443547
filePath: property.source.fullName,
3545-
message:
3546-
"'$propertyName' refers to a property so it couldn't be promoted.",
3548+
message: "'$propertyName' refers to a property so it couldn't be "
3549+
"promoted. See ${reason.documentationLink}",
35473550
offset: property.nameOffset,
35483551
length: property.nameLength);
35493552
}
35503553

3551-
DiagnosticMessageImpl _contextMessageForWrite(
3552-
String variableName, Expression writeExpression) {
3554+
DiagnosticMessageImpl _contextMessageForWrite(String variableName,
3555+
Expression writeExpression, NonPromotionReason reason) {
35533556
return DiagnosticMessageImpl(
35543557
filePath: source.fullName,
35553558
message: "Variable '$variableName' could be null due to an intervening "
3556-
"write.",
3559+
"write. See ${reason.documentationLink}",
35573560
offset: writeExpression.offset,
35583561
length: writeExpression.length);
35593562
}

pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5151,7 +5151,7 @@ class _WhyNotPromotedVisitor
51515151
}
51525152
int offset = reason.writeExpression.fileOffset;
51535153
return templateVariableCouldBeNullDueToWrite
5154-
.withArguments(reason.variable.name)
5154+
.withArguments(reason.variable.name, reason.documentationLink)
51555155
.withLocation(inferrer.helper.uri, offset, noLength);
51565156
}
51575157

@@ -5160,7 +5160,7 @@ class _WhyNotPromotedVisitor
51605160
DemoteViaForEachVariableWrite<VariableDeclaration, Node> reason) {
51615161
int offset = (reason.node as TreeNode).fileOffset;
51625162
return templateVariableCouldBeNullDueToWrite
5163-
.withArguments(reason.variable.name)
5163+
.withArguments(reason.variable.name, reason.documentationLink)
51645164
.withLocation(inferrer.helper.uri, offset, noLength);
51655165
}
51665166

@@ -5183,7 +5183,7 @@ class _WhyNotPromotedVisitor
51835183
propertyReference = member;
51845184
propertyType = reason.staticType;
51855185
return templateFieldNotPromoted
5186-
.withArguments(reason.propertyName)
5186+
.withArguments(reason.propertyName, reason.documentationLink)
51875187
.withLocation(member.fileUri, member.fileOffset, noLength);
51885188
} else {
51895189
return null;
@@ -5192,6 +5192,8 @@ class _WhyNotPromotedVisitor
51925192

51935193
@override
51945194
LocatedMessage visitThisNotPromoted(ThisNotPromoted reason) {
5195-
return messageThisNotPromoted.withoutLocation();
5195+
return templateThisNotPromoted
5196+
.withArguments(reason.documentationLink)
5197+
.withoutLocation();
51965198
}
51975199
}

pkg/front_end/messages.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4656,13 +4656,15 @@ MultipleVarianceModifiers:
46564656

46574657
VariableCouldBeNullDueToWrite:
46584658
template: "Variable '#name' could be null due to an intervening write."
4659-
tip: "Try null checking the variable after the write."
4659+
tip: "Try null checking the variable after the write. See #string"
46604660

46614661
FieldNotPromoted:
46624662
template: "'#name' refers to a property so it couldn't be promoted."
4663+
tip: "See #string"
46634664

46644665
ThisNotPromoted:
46654666
template: "'this' can't be promoted."
4667+
tip: "See #string"
46664668

46674669
NullablePropertyAccessError:
46684670
template: "Property '#name' cannot be accessed on '#type' because it is potentially null."

pkg/front_end/test/spell_checking_list_code.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,7 @@ prebuilt
882882
preexisted
883883
preexisting
884884
preorder
885+
presented
885886
presubmit
886887
prev
887888
prime
@@ -892,6 +893,7 @@ proc
892893
producers
893894
product
894895
progresses
896+
promo
895897
proof
896898
prop
897899
propose

0 commit comments

Comments
 (0)