Issue 33506. Rewrite MethodInvocation into InstanceCreationExpression.

R=brianwilkerson@google.com, paulberry@google.com

Change-Id: I712ab3c79cfe29b2c201b0affc10b33fc0f60d15
Bug: https://github.com/dart-lang/sdk/issues/33506
Reviewed-on: https://dart-review.googlesource.com/68004
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2018-08-02 15:33:11 +00:00 committed by commit-bot@chromium.org
parent 26e087e66b
commit d6189709b8
5 changed files with 179 additions and 19 deletions

View file

@ -633,14 +633,4 @@ class AnalysisHoverTest_UseCFE extends AnalysisHoverTest {
@override
test_instanceCreation_implicit_withTypeArgument() async =>
super.test_instanceCreation_implicit_withTypeArgument();
@failingTest
@override
test_instanceCreation_noKeyword_const() async =>
super.test_instanceCreation_noKeyword_const();
@failingTest
@override
test_instanceCreation_noKeyword_new() async =>
super.test_instanceCreation_noKeyword_new();
}

View file

@ -734,13 +734,6 @@ class LibraryAnalyzer {
new DeclarationResolver(enableKernelDriver: true, applyKernelTypes: true)
.resolve(unit, unitElement);
// TODO(paulberry): need to find a better way to do this.
// See dartbug.com/33506.
// if (_libraryElement.context.analysisOptions.previewDart2) {
// unit.accept(new AstRewriteVisitor(_context.typeSystem, _libraryElement,
// file.source, _typeProvider, AnalysisErrorListener.NULL_LISTENER));
// }
var applierContext = new _ResolutionApplierContext(_resynthesizer,
_typeProvider, _libraryElement, resolution, unit.localDeclarations);
var applier = applierContext.applier;

View file

@ -8,6 +8,7 @@ import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/fasta/resolution_storer.dart';
@ -538,6 +539,10 @@ class ResolutionApplier extends GeneralizingAstVisitor {
_resolveNamedArguments(argumentList, parameters);
}
}
if (invokeElement is ConstructorElement) {
_rewriteInfoInstanceCreation(node, invokeElement, invokeType, resultType);
}
}
@override
@ -763,6 +768,65 @@ class ResolutionApplier extends GeneralizingAstVisitor {
}
}
/// Rewrite AST if the [node] represents an instance creation.
void _rewriteInfoInstanceCreation(
MethodInvocation node,
ConstructorElement invokeElement,
DartType invokeType,
DartType resultType) {
if (node.isCascaded) {
return;
}
Identifier typeIdentifier;
Token constructorIdentifierPeriod;
SimpleIdentifier constructorIdentifier;
var target = node.target;
if (target == null) {
SimpleIdentifier simpleTypeIdentifier = node.methodName;
simpleTypeIdentifier.staticElement = resultType.element;
simpleTypeIdentifier.staticType = resultType;
typeIdentifier = simpleTypeIdentifier;
} else if (target is SimpleIdentifier) {
if (target.staticElement is PrefixElement) {
SimpleIdentifier simpleTypeIdentifier = node.methodName;
simpleTypeIdentifier.staticElement = resultType.element;
simpleTypeIdentifier.staticType = resultType;
typeIdentifier = astFactory.prefixedIdentifier(
target, node.operator, simpleTypeIdentifier);
} else {
typeIdentifier = target;
constructorIdentifierPeriod = node.operator;
constructorIdentifier = node.methodName;
}
} else {
PrefixedIdentifier prefixed = target;
typeIdentifier = prefixed;
constructorIdentifierPeriod = prefixed.period;
constructorIdentifier = node.methodName;
}
var typeName = astFactory.typeName(typeIdentifier, node.typeArguments);
typeName.type = resultType;
var creation = astFactory.instanceCreationExpression(
null,
astFactory.constructorName(
typeName,
constructorIdentifierPeriod,
constructorIdentifier,
),
node.argumentList,
);
creation.staticElement = invokeElement;
creation.staticType = resultType;
NodeReplacer.replace(node, creation);
}
void _storeFunctionType(DartType type, FunctionTypedElementImpl element) {
if (type is FunctionType && element != null) {
DartType Function(DartType) substituteConstituentType;

View file

@ -49,6 +49,13 @@ class AnalysisDriverResolutionTest_Kernel extends AnalysisDriverResolutionTest {
await super.test_invalid_fieldInitializer_this();
}
@override
@failingTest
test_optionalConst_typeArguments() async {
// We should get ConstructorMember, but convert to just ConstructorElement.
await super.test_optionalConst_typeArguments();
}
@override
@failingTest
test_unresolved_assignment_left_indexed1_simple() async {

View file

@ -150,8 +150,6 @@ class AnalysisDriverResolutionTest extends BaseAnalysisDriverTest {
assertElement(name.identifier, expectedElement);
if (useCFE) {
assertType(name.identifier, expectedType);
} else {
expect(name.identifier.staticType, isNull);
}
}
}
@ -193,6 +191,8 @@ class AnalysisDriverResolutionTest extends BaseAnalysisDriverTest {
return node.staticElement;
} else if (node is IndexExpression) {
return node.staticElement;
} else if (node is InstanceCreationExpression) {
return node.staticElement;
} else if (node is PostfixExpression) {
return node.staticElement;
} else if (node is PrefixExpression) {
@ -6716,6 +6716,112 @@ void f<T, U>(T a, U b) {}
}
}
test_optionalConst() async {
addTestFile(r'''
class C {
const C();
const C.named();
}
const a = C(); // ref
const b = C.named(); // ref
''');
await resolveTestFile();
expect(result.errors, isEmpty);
var c = findElement.class_('C');
{
var creation = findNode.instanceCreation('C(); // ref');
assertElement(creation, c.unnamedConstructor);
assertType(creation, 'C');
assertTypeName(creation.constructorName.type, c, 'C');
}
{
var creation = findNode.instanceCreation('C.named(); // ref');
var namedConstructor = c.getNamedConstructor('named');
assertElement(creation, namedConstructor);
assertType(creation, 'C');
assertTypeName(creation.constructorName.type, c, 'C');
assertElement(creation.constructorName.name, namedConstructor);
}
}
test_optionalConst_prefixed() async {
provider.newFile(_p('/test/lib/a.dart'), r'''
class C {
const C();
const C.named();
}
''');
addTestFile(r'''
import 'a.dart' as p;
const a = p.C(); // ref
const b = p.C.named(); // ref
''');
await resolveTestFile();
expect(result.errors, isEmpty);
var import = findElement.import('package:test/a.dart');
var c = import.importedLibrary.getType('C');
{
var creation = findNode.instanceCreation('C(); // ref');
assertElement(creation, c.unnamedConstructor);
assertType(creation, 'C');
assertTypeName(creation.constructorName.type, c, 'C',
expectedPrefix: import.prefix);
}
{
var creation = findNode.instanceCreation('C.named(); // ref');
var namedConstructor = c.getNamedConstructor('named');
assertElement(creation, namedConstructor);
assertType(creation, 'C');
assertTypeName(creation.constructorName.type, c, 'C',
expectedPrefix: import.prefix);
assertElement(creation.constructorName.name, namedConstructor);
}
}
test_optionalConst_typeArguments() async {
addTestFile(r'''
class C<T> {
const C();
const C.named();
}
const a = C<int>(); // ref
const b = C<String>.named(); // ref
''');
await resolveTestFile();
expect(result.errors, isEmpty);
var c = findElement.class_('C');
{
var creation = findNode.instanceCreation('C<int>(); // ref');
assertMember(creation, 'C<int>', c.unnamedConstructor);
assertType(creation, 'C<int>');
assertTypeName(creation.constructorName.type, c, 'C<int>');
assertTypeName(findNode.typeName('int>'), intElement, 'int');
}
{
var creation = findNode.instanceCreation('C<String>.named(); // ref');
var namedConstructor = c.getNamedConstructor('named');
assertMember(creation, 'C<String>', namedConstructor);
assertType(creation, 'C<String>');
assertTypeName(creation.constructorName.type, c, 'C<String>');
assertTypeName(findNode.typeName('String>'), stringElement, 'String');
assertMember(
creation.constructorName.name, 'C<String>', namedConstructor);
}
}
test_outline_invalid_mixin_arguments_tooFew() async {
addTestFile(r'''
class A extends Object with Map<int> {}