Skip to content

Commit 08205fd

Browse files
johnniwinthercommit-bot@chromium.org
authored andcommitted
[cfe] Add implicit as and type arguments to static_type_test
+ add test for issue 37439 showing Change-Id: I3b42a5a05df5a89f5bd8255a3f305a2c2caa0176 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/112087 Reviewed-by: Dmitry Stefantsov <dmitryas@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
1 parent 7283827 commit 08205fd

File tree

4 files changed

+102
-10
lines changed

4 files changed

+102
-10
lines changed

pkg/front_end/lib/src/testing/id.dart

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ enum IdKind {
3434
/// certain offset. This is used in [NodeId].
3535
moveNext,
3636

37+
/// Id used for the implicit as expression inserted by the compiler.
38+
implicitAs,
39+
3740
/// Id used for the statement at certain offset. This is used in [NodeId].
3841
stmt,
3942

@@ -96,6 +99,8 @@ class IdValue {
9699
return '$currentPrefix$value';
97100
case IdKind.moveNext:
98101
return '$moveNextPrefix$value';
102+
case IdKind.implicitAs:
103+
return '$implicitAsPrefix$value';
99104
case IdKind.stmt:
100105
return '$stmtPrefix$value';
101106
case IdKind.error:
@@ -113,6 +118,7 @@ class IdValue {
113118
static const String iteratorPrefix = "iterator: ";
114119
static const String currentPrefix = "current: ";
115120
static const String moveNextPrefix = "moveNext: ";
121+
static const String implicitAsPrefix = "as: ";
116122
static const String stmtPrefix = "stmt: ";
117123
static const String errorPrefix = "error: ";
118124

@@ -159,6 +165,9 @@ class IdValue {
159165
} else if (text.startsWith(moveNextPrefix)) {
160166
id = new NodeId(offset, IdKind.moveNext);
161167
expected = text.substring(moveNextPrefix.length);
168+
} else if (text.startsWith(implicitAsPrefix)) {
169+
id = new NodeId(offset, IdKind.implicitAs);
170+
expected = text.substring(implicitAsPrefix.length);
162171
} else if (text.startsWith(stmtPrefix)) {
163172
id = new NodeId(offset, IdKind.stmt);
164173
expected = text.substring(stmtPrefix.length);
@@ -340,17 +349,19 @@ abstract class DataRegistry<T> {
340349
///
341350
/// Checks for duplicate data for [id].
342351
void registerValue(Uri uri, int offset, Id id, T value, Object object) {
343-
if (actualMap.containsKey(id)) {
344-
ActualData<T> existingData = actualMap[id];
345-
report(uri, offset, "Duplicate id ${id}, value=$value, object=$object");
346-
report(
347-
uri,
348-
offset,
349-
"Duplicate id ${id}, value=${existingData.value}, "
350-
"object=${existingData.object}");
351-
fail("Duplicate id $id.");
352-
}
353352
if (value != null) {
353+
if (actualMap.containsKey(id)) {
354+
// TODO(johnniwinther): Maybe let the test supply a way to merge
355+
// multiple data on the same id?
356+
ActualData<T> existingData = actualMap[id];
357+
report(uri, offset, "Duplicate id ${id}, value=$value, object=$object");
358+
report(
359+
uri,
360+
offset,
361+
"Duplicate id ${id}, value=${existingData.value}, "
362+
"object=${existingData.object}");
363+
fail("Duplicate id $id.");
364+
}
354365
actualMap[id] = new ActualData<T>(id, value, uri, offset, object);
355366
}
356367
}

pkg/front_end/lib/src/testing/id_extractor.dart

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,14 @@ abstract class DataExtractor<T> extends Visitor with DataRegistry<T> {
136136
NodeId createSwitchCaseId(SwitchCase node) =>
137137
new NodeId(node.expressionOffsets.first, IdKind.node);
138138

139+
NodeId createImplicitAsId(AsExpression node) {
140+
if (node.fileOffset == TreeNode.noOffset) {
141+
// TODO(johnniwinther): Find out why we something have no offset.
142+
return null;
143+
}
144+
return new NodeId(node.fileOffset, IdKind.implicitAs);
145+
}
146+
139147
void run(Node root) {
140148
root.accept(this);
141149
}
@@ -376,4 +384,55 @@ abstract class DataExtractor<T> extends Visitor with DataRegistry<T> {
376384
}
377385
super.visitThisExpression(node);
378386
}
387+
388+
@override
389+
visitAwaitExpression(AwaitExpression node) {
390+
computeForNode(node, computeDefaultNodeId(node));
391+
super.visitAwaitExpression(node);
392+
}
393+
394+
@override
395+
visitConstructorInvocation(ConstructorInvocation node) {
396+
// Skip synthetic constructor invocations like for enum constants.
397+
// TODO(johnniwinther): Can [skipNodeWithNoOffset] be removed when dart2js
398+
// no longer test with cfe constants?
399+
computeForNode(
400+
node, computeDefaultNodeId(node, skipNodeWithNoOffset: true));
401+
super.visitConstructorInvocation(node);
402+
}
403+
404+
@override
405+
visitStaticGet(StaticGet node) {
406+
computeForNode(node, computeDefaultNodeId(node));
407+
super.visitStaticGet(node);
408+
}
409+
410+
@override
411+
visitStaticSet(StaticSet node) {
412+
computeForNode(node, createUpdateId(node));
413+
super.visitStaticSet(node);
414+
}
415+
416+
@override
417+
visitStaticInvocation(StaticInvocation node) {
418+
computeForNode(node, createInvokeId(node));
419+
super.visitStaticInvocation(node);
420+
}
421+
422+
@override
423+
visitAsExpression(AsExpression node) {
424+
if (node.isTypeError) {
425+
computeForNode(node, createImplicitAsId(node));
426+
} else {
427+
computeForNode(node, computeDefaultNodeId(node));
428+
}
429+
return super.visitAsExpression(node);
430+
}
431+
432+
@override
433+
visitArguments(Arguments node) {
434+
computeForNode(
435+
node, computeDefaultNodeId(node, skipNodeWithNoOffset: true));
436+
return super.visitArguments(node);
437+
}
379438
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
class A {}
6+
7+
class B extends A {}
8+
9+
Future<T> func1<T extends A>(T t) async {
10+
// TODO(37439): We should infer 'T' instead of '<bottom>'.
11+
return /*invoke: <bottom>*/ func2/*<<bottom>>*/(/*as: <bottom>*/ /*T*/ t);
12+
}
13+
14+
T func2<T extends A>(T t) => /*T*/ t;
15+
16+
main() async {
17+
/*B*/ await /*invoke: Future<B>*/ func1/*<B>*/(/*B*/ B());
18+
}

pkg/front_end/test/static_types/static_type_test.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ class StaticTypeDataExtractor extends CfeDataExtractor<String> {
5151
if (node is Expression) {
5252
DartType type = node.getStaticType(_environment);
5353
return typeToText(type);
54+
} else if (node is Arguments) {
55+
if (node.types.isNotEmpty) {
56+
return '<${node.types.map(typeToText).join(',')}>';
57+
}
5458
}
5559
return null;
5660
}

0 commit comments

Comments
 (0)