Skip to content

Commit

Permalink
[cfe] Add implicit as and type arguments to static_type_test
Browse files Browse the repository at this point in the history
+ 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>
  • Loading branch information
johnniwinther authored and commit-bot@chromium.org committed Aug 7, 2019
1 parent 7283827 commit 08205fd
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 10 deletions.
31 changes: 21 additions & 10 deletions pkg/front_end/lib/src/testing/id.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ enum IdKind {
/// certain offset. This is used in [NodeId].
moveNext,

/// Id used for the implicit as expression inserted by the compiler.
implicitAs,

/// Id used for the statement at certain offset. This is used in [NodeId].
stmt,

Expand Down Expand Up @@ -96,6 +99,8 @@ class IdValue {
return '$currentPrefix$value';
case IdKind.moveNext:
return '$moveNextPrefix$value';
case IdKind.implicitAs:
return '$implicitAsPrefix$value';
case IdKind.stmt:
return '$stmtPrefix$value';
case IdKind.error:
Expand All @@ -113,6 +118,7 @@ class IdValue {
static const String iteratorPrefix = "iterator: ";
static const String currentPrefix = "current: ";
static const String moveNextPrefix = "moveNext: ";
static const String implicitAsPrefix = "as: ";
static const String stmtPrefix = "stmt: ";
static const String errorPrefix = "error: ";

Expand Down Expand Up @@ -159,6 +165,9 @@ class IdValue {
} else if (text.startsWith(moveNextPrefix)) {
id = new NodeId(offset, IdKind.moveNext);
expected = text.substring(moveNextPrefix.length);
} else if (text.startsWith(implicitAsPrefix)) {
id = new NodeId(offset, IdKind.implicitAs);
expected = text.substring(implicitAsPrefix.length);
} else if (text.startsWith(stmtPrefix)) {
id = new NodeId(offset, IdKind.stmt);
expected = text.substring(stmtPrefix.length);
Expand Down Expand Up @@ -340,17 +349,19 @@ abstract class DataRegistry<T> {
///
/// Checks for duplicate data for [id].
void registerValue(Uri uri, int offset, Id id, T value, Object object) {
if (actualMap.containsKey(id)) {
ActualData<T> existingData = actualMap[id];
report(uri, offset, "Duplicate id ${id}, value=$value, object=$object");
report(
uri,
offset,
"Duplicate id ${id}, value=${existingData.value}, "
"object=${existingData.object}");
fail("Duplicate id $id.");
}
if (value != null) {
if (actualMap.containsKey(id)) {
// TODO(johnniwinther): Maybe let the test supply a way to merge
// multiple data on the same id?
ActualData<T> existingData = actualMap[id];
report(uri, offset, "Duplicate id ${id}, value=$value, object=$object");
report(
uri,
offset,
"Duplicate id ${id}, value=${existingData.value}, "
"object=${existingData.object}");
fail("Duplicate id $id.");
}
actualMap[id] = new ActualData<T>(id, value, uri, offset, object);
}
}
Expand Down
59 changes: 59 additions & 0 deletions pkg/front_end/lib/src/testing/id_extractor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,14 @@ abstract class DataExtractor<T> extends Visitor with DataRegistry<T> {
NodeId createSwitchCaseId(SwitchCase node) =>
new NodeId(node.expressionOffsets.first, IdKind.node);

NodeId createImplicitAsId(AsExpression node) {
if (node.fileOffset == TreeNode.noOffset) {
// TODO(johnniwinther): Find out why we something have no offset.
return null;
}
return new NodeId(node.fileOffset, IdKind.implicitAs);
}

void run(Node root) {
root.accept(this);
}
Expand Down Expand Up @@ -376,4 +384,55 @@ abstract class DataExtractor<T> extends Visitor with DataRegistry<T> {
}
super.visitThisExpression(node);
}

@override
visitAwaitExpression(AwaitExpression node) {
computeForNode(node, computeDefaultNodeId(node));
super.visitAwaitExpression(node);
}

@override
visitConstructorInvocation(ConstructorInvocation node) {
// Skip synthetic constructor invocations like for enum constants.
// TODO(johnniwinther): Can [skipNodeWithNoOffset] be removed when dart2js
// no longer test with cfe constants?
computeForNode(
node, computeDefaultNodeId(node, skipNodeWithNoOffset: true));
super.visitConstructorInvocation(node);
}

@override
visitStaticGet(StaticGet node) {
computeForNode(node, computeDefaultNodeId(node));
super.visitStaticGet(node);
}

@override
visitStaticSet(StaticSet node) {
computeForNode(node, createUpdateId(node));
super.visitStaticSet(node);
}

@override
visitStaticInvocation(StaticInvocation node) {
computeForNode(node, createInvokeId(node));
super.visitStaticInvocation(node);
}

@override
visitAsExpression(AsExpression node) {
if (node.isTypeError) {
computeForNode(node, createImplicitAsId(node));
} else {
computeForNode(node, computeDefaultNodeId(node));
}
return super.visitAsExpression(node);
}

@override
visitArguments(Arguments node) {
computeForNode(
node, computeDefaultNodeId(node, skipNodeWithNoOffset: true));
return super.visitArguments(node);
}
}
18 changes: 18 additions & 0 deletions pkg/front_end/test/static_types/data/issue37439.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

class A {}

class B extends A {}

Future<T> func1<T extends A>(T t) async {
// TODO(37439): We should infer 'T' instead of '<bottom>'.
return /*invoke: <bottom>*/ func2/*<<bottom>>*/(/*as: <bottom>*/ /*T*/ t);
}

T func2<T extends A>(T t) => /*T*/ t;

main() async {
/*B*/ await /*invoke: Future<B>*/ func1/*<B>*/(/*B*/ B());
}
4 changes: 4 additions & 0 deletions pkg/front_end/test/static_types/static_type_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ class StaticTypeDataExtractor extends CfeDataExtractor<String> {
if (node is Expression) {
DartType type = node.getStaticType(_environment);
return typeToText(type);
} else if (node is Arguments) {
if (node.types.isNotEmpty) {
return '<${node.types.map(typeToText).join(',')}>';
}
}
return null;
}
Expand Down

0 comments on commit 08205fd

Please sign in to comment.