Index: pkg/analysis_server/test/src/utilities/change_builder_dart_test.dart |
diff --git a/pkg/analysis_server/test/src/utilities/change_builder_dart_test.dart b/pkg/analysis_server/test/src/utilities/change_builder_dart_test.dart |
index 8ff8eb511316e216fcddcedf10fd67d3d2f3fb11..a6e05ae0e2f476de85af53feeaa7088b64ccf8be 100644 |
--- a/pkg/analysis_server/test/src/utilities/change_builder_dart_test.dart |
+++ b/pkg/analysis_server/test/src/utilities/change_builder_dart_test.dart |
@@ -12,7 +12,12 @@ import 'package:analyzer/dart/ast/ast.dart'; |
import 'package:analyzer/dart/ast/standard_resolution_map.dart'; |
import 'package:analyzer/dart/element/element.dart'; |
import 'package:analyzer/dart/element/type.dart'; |
+import 'package:analyzer/src/context/source.dart'; |
import 'package:analyzer/src/dart/analysis/driver.dart'; |
+import 'package:analyzer/src/generated/engine.dart'; |
+import 'package:analyzer/src/generated/resolver.dart'; |
+import 'package:analyzer/src/generated/source.dart'; |
+import 'package:analyzer/src/generated/testing/test_type_provider.dart'; |
import 'package:test/test.dart'; |
import 'package:test_reflective_loader/test_reflective_loader.dart'; |
@@ -23,9 +28,34 @@ main() { |
defineReflectiveTests(DartChangeBuilderImplTest); |
defineReflectiveTests(DartEditBuilderImplTest); |
defineReflectiveTests(DartFileEditBuilderImplTest); |
+ defineReflectiveTests(DartLinkedEditBuilderImplTest); |
}); |
} |
+abstract class BuilderTestMixin { |
+ SourceEdit getEdit(DartChangeBuilderImpl builder) { |
+ SourceChange sourceChange = builder.sourceChange; |
+ expect(sourceChange, isNotNull); |
+ List<SourceFileEdit> fileEdits = sourceChange.edits; |
+ expect(fileEdits, hasLength(1)); |
+ SourceFileEdit fileEdit = fileEdits[0]; |
+ expect(fileEdit, isNotNull); |
+ List<SourceEdit> edits = fileEdit.edits; |
+ expect(edits, hasLength(1)); |
+ return edits[0]; |
+ } |
+ |
+ List<SourceEdit> getEdits(DartChangeBuilderImpl builder) { |
+ SourceChange sourceChange = builder.sourceChange; |
+ expect(sourceChange, isNotNull); |
+ List<SourceFileEdit> fileEdits = sourceChange.edits; |
+ expect(fileEdits, hasLength(1)); |
+ SourceFileEdit fileEdit = fileEdits[0]; |
+ expect(fileEdit, isNotNull); |
+ return fileEdit.edits; |
+ } |
+} |
+ |
@reflectiveTest |
class DartChangeBuilderImplTest extends AbstractContextTest { |
@override |
@@ -46,22 +76,11 @@ class DartChangeBuilderImplTest extends AbstractContextTest { |
} |
@reflectiveTest |
-class DartEditBuilderImplTest extends AbstractContextTest { |
+class DartEditBuilderImplTest extends AbstractContextTest |
+ with BuilderTestMixin { |
@override |
bool get enableNewAnalysisDriver => true; |
- SourceEdit getEdit(DartChangeBuilderImpl builder) { |
- SourceChange sourceChange = builder.sourceChange; |
- expect(sourceChange, isNotNull); |
- List<SourceFileEdit> fileEdits = sourceChange.edits; |
- expect(fileEdits, hasLength(1)); |
- SourceFileEdit fileEdit = fileEdits[0]; |
- expect(fileEdit, isNotNull); |
- List<SourceEdit> edits = fileEdit.edits; |
- expect(edits, hasLength(1)); |
- return edits[0]; |
- } |
- |
test_writeClassDeclaration_interfaces() async { |
String path = '/test.dart'; |
addSource(path, 'class A {}'); |
@@ -176,12 +195,19 @@ class DartEditBuilderImplTest extends AbstractContextTest { |
DartChangeBuilderImpl builder = new DartChangeBuilderImpl(driver); |
await builder.addFileEdit(path, 1, (FileEditBuilder builder) { |
builder.addInsertion(0, (EditBuilder builder) { |
- (builder as DartEditBuilder) |
- .writeClassDeclaration('C', superclass: typeB); |
+ (builder as DartEditBuilder).writeClassDeclaration('C', |
+ superclass: typeB, superclassGroupName: 'superclass'); |
}); |
}); |
SourceEdit edit = getEdit(builder); |
expect(edit.replacement, equalsIgnoringWhitespace('class C extends B { }')); |
+ |
+ List<LinkedEditGroup> linkedEditGroups = |
+ builder.sourceChange.linkedEditGroups; |
+ expect(linkedEditGroups, hasLength(1)); |
+ LinkedEditGroup group = linkedEditGroups[0]; |
+ expect(group.length, 1); |
+ expect(group.positions, hasLength(1)); |
} |
test_writeFieldDeclaration_initializerWriter() async { |
@@ -314,6 +340,90 @@ class DartEditBuilderImplTest extends AbstractContextTest { |
expect(position.offset, equals(20)); |
} |
+ test_writeFunctionDeclaration_noReturnType_noParams_body() async { |
+ String path = '/test.dart'; |
+ String content = ''; |
+ addSource(path, content); |
+ |
+ DartChangeBuilderImpl builder = new DartChangeBuilderImpl(driver); |
+ await builder.addFileEdit(path, 1, (FileEditBuilder builder) { |
+ builder.addInsertion(0, (EditBuilder builder) { |
+ (builder as DartEditBuilder).writeFunctionDeclaration('fib', |
+ bodyWriter: () { |
+ builder.write('{ ... }'); |
+ }); |
+ }); |
+ }); |
+ SourceEdit edit = getEdit(builder); |
+ expect(edit.replacement, equalsIgnoringWhitespace('fib() { ... }')); |
+ } |
+ |
+ test_writeFunctionDeclaration_noReturnType_noParams_noBody() async { |
+ String path = '/test.dart'; |
+ String content = ''; |
+ addSource(path, content); |
+ |
+ DartChangeBuilderImpl builder = new DartChangeBuilderImpl(driver); |
+ await builder.addFileEdit(path, 1, (FileEditBuilder builder) { |
+ builder.addInsertion(0, (EditBuilder builder) { |
+ (builder as DartEditBuilder) |
+ .writeFunctionDeclaration('fib', nameGroupName: 'name'); |
+ }); |
+ }); |
+ SourceEdit edit = getEdit(builder); |
+ expect(edit.replacement, equalsIgnoringWhitespace('fib() {}')); |
+ |
+ List<LinkedEditGroup> linkedEditGroups = |
+ builder.sourceChange.linkedEditGroups; |
+ expect(linkedEditGroups, hasLength(1)); |
+ LinkedEditGroup group = linkedEditGroups[0]; |
+ expect(group.length, 3); |
+ expect(group.positions, hasLength(1)); |
+ } |
+ |
+ test_writeFunctionDeclaration_noReturnType_params_noBody() async { |
+ String path = '/test.dart'; |
+ String content = ''; |
+ addSource(path, content); |
+ |
+ DartChangeBuilderImpl builder = new DartChangeBuilderImpl(driver); |
+ await builder.addFileEdit(path, 1, (FileEditBuilder builder) { |
+ builder.addInsertion(0, (EditBuilder builder) { |
+ (builder as DartEditBuilder).writeFunctionDeclaration('fib', |
+ parameterWriter: () { |
+ builder.write('p, q, r'); |
+ }); |
+ }); |
+ }); |
+ SourceEdit edit = getEdit(builder); |
+ expect(edit.replacement, equalsIgnoringWhitespace('fib(p, q, r) {}')); |
+ } |
+ |
+ test_writeFunctionDeclaration_returnType_noParams_noBody() async { |
+ String path = '/test.dart'; |
+ String content = 'class A {}'; |
+ addSource(path, content); |
+ |
+ DartType typeA = await _getType(path, 'A'); |
+ |
+ DartChangeBuilderImpl builder = new DartChangeBuilderImpl(driver); |
+ await builder.addFileEdit(path, 1, (FileEditBuilder builder) { |
+ builder.addInsertion(0, (EditBuilder builder) { |
+ (builder as DartEditBuilder).writeFunctionDeclaration('fib', |
+ returnType: typeA, returnTypeGroupName: 'type'); |
+ }); |
+ }); |
+ SourceEdit edit = getEdit(builder); |
+ expect(edit.replacement, equalsIgnoringWhitespace('A fib() => null;')); |
+ |
+ List<LinkedEditGroup> linkedEditGroups = |
+ builder.sourceChange.linkedEditGroups; |
+ expect(linkedEditGroups, hasLength(1)); |
+ LinkedEditGroup group = linkedEditGroups[0]; |
+ expect(group.length, 1); |
+ expect(group.positions, hasLength(1)); |
+ } |
+ |
test_writeGetterDeclaration_bodyWriter() async { |
String path = '/test.dart'; |
String content = 'class A {}'; |
@@ -399,6 +509,180 @@ class DartEditBuilderImplTest extends AbstractContextTest { |
expect(position.offset, equals(20)); |
} |
+ test_writeLocalVariableDeclaration_noType_initializer() async { |
+ String path = '/test.dart'; |
+ String content = ''' |
+void f() { |
+ |
+}'''; |
+ addSource(path, content); |
+ await driver.getResult(path); |
+ |
+ DartChangeBuilderImpl builder = new DartChangeBuilderImpl(driver); |
+ await builder.addFileEdit(path, 1, (FileEditBuilder builder) { |
+ builder.addInsertion(11, (EditBuilder builder) { |
+ (builder as DartEditBuilder).writeLocalVariableDeclaration('foo', |
+ initializerWriter: () { |
+ builder.write('null'); |
+ }); |
+ }); |
+ }); |
+ SourceEdit edit = getEdit(builder); |
+ expect(edit.replacement, equalsIgnoringWhitespace('var foo = null;')); |
+ } |
+ |
+ test_writeLocalVariableDeclaration_noType_noInitializer() async { |
+ String path = '/test.dart'; |
+ String content = ''' |
+void f() { |
+ |
+}'''; |
+ addSource(path, content); |
+ await driver.getResult(path); |
+ |
+ DartChangeBuilderImpl builder = new DartChangeBuilderImpl(driver); |
+ await builder.addFileEdit(path, 1, (FileEditBuilder builder) { |
+ builder.addInsertion(11, (EditBuilder builder) { |
+ (builder as DartEditBuilder) |
+ .writeLocalVariableDeclaration('foo', nameGroupName: 'name'); |
+ }); |
+ }); |
+ SourceEdit edit = getEdit(builder); |
+ expect(edit.replacement, equalsIgnoringWhitespace('var foo;')); |
+ |
+ List<LinkedEditGroup> linkedEditGroups = |
+ builder.sourceChange.linkedEditGroups; |
+ expect(linkedEditGroups, hasLength(1)); |
+ LinkedEditGroup group = linkedEditGroups[0]; |
+ expect(group.length, 3); |
+ expect(group.positions, hasLength(1)); |
+ } |
+ |
+ test_writeLocalVariableDeclaration_noType_noInitializer_const() async { |
+ String path = '/test.dart'; |
+ String content = ''' |
+void f() { |
+ |
+}'''; |
+ addSource(path, content); |
+ await driver.getResult(path); |
+ |
+ DartChangeBuilderImpl builder = new DartChangeBuilderImpl(driver); |
+ await builder.addFileEdit(path, 1, (FileEditBuilder builder) { |
+ builder.addInsertion(11, (EditBuilder builder) { |
+ (builder as DartEditBuilder) |
+ .writeLocalVariableDeclaration('foo', isConst: true); |
+ }); |
+ }); |
+ SourceEdit edit = getEdit(builder); |
+ expect(edit.replacement, equalsIgnoringWhitespace('const foo;')); |
+ } |
+ |
+ test_writeLocalVariableDeclaration_noType_noInitializer_final() async { |
+ String path = '/test.dart'; |
+ String content = ''' |
+void f() { |
+ |
+}'''; |
+ addSource(path, content); |
+ await driver.getResult(path); |
+ |
+ DartChangeBuilderImpl builder = new DartChangeBuilderImpl(driver); |
+ await builder.addFileEdit(path, 1, (FileEditBuilder builder) { |
+ builder.addInsertion(11, (EditBuilder builder) { |
+ (builder as DartEditBuilder) |
+ .writeLocalVariableDeclaration('foo', isFinal: true); |
+ }); |
+ }); |
+ SourceEdit edit = getEdit(builder); |
+ expect(edit.replacement, equalsIgnoringWhitespace('final foo;')); |
+ } |
+ |
+ test_writeLocalVariableDeclaration_type_initializer() async { |
+ String path = '/test.dart'; |
+ String content = ''' |
+void f() { |
+ |
+} |
+class MyClass {}'''; |
+ addSource(path, content); |
+ CompilationUnit unit = (await driver.getResult(path))?.unit; |
+ |
+ ClassDeclaration A = unit.declarations[1]; |
+ |
+ DartChangeBuilderImpl builder = new DartChangeBuilderImpl(driver); |
+ await builder.addFileEdit(path, 1, (FileEditBuilder builder) { |
+ builder.addInsertion(11, (EditBuilder builder) { |
+ (builder as DartEditBuilder).writeLocalVariableDeclaration('foo', |
+ initializerWriter: () { |
+ builder.write('null'); |
+ }, type: A.element.type); |
+ }); |
+ }); |
+ SourceEdit edit = getEdit(builder); |
+ expect(edit.replacement, equalsIgnoringWhitespace('MyClass foo = null;')); |
+ } |
+ |
+ test_writeLocalVariableDeclaration_type_noInitializer() async { |
+ String path = '/test.dart'; |
+ String content = ''' |
+void f() { |
+ |
+} |
+class MyClass {}'''; |
+ addSource(path, content); |
+ CompilationUnit unit = (await driver.getResult(path))?.unit; |
+ |
+ ClassDeclaration A = unit.declarations[1]; |
+ |
+ DartChangeBuilderImpl builder = new DartChangeBuilderImpl(driver); |
+ await builder.addFileEdit(path, 1, (FileEditBuilder builder) { |
+ builder.addInsertion(11, (EditBuilder builder) { |
+ (builder as DartEditBuilder).writeLocalVariableDeclaration('foo', |
+ type: A.element.type, typeGroupName: 'type'); |
+ }); |
+ }); |
+ SourceEdit edit = getEdit(builder); |
+ expect(edit.replacement, equalsIgnoringWhitespace('MyClass foo;')); |
+ |
+ List<LinkedEditGroup> linkedEditGroups = |
+ builder.sourceChange.linkedEditGroups; |
+ expect(linkedEditGroups, hasLength(1)); |
+ LinkedEditGroup group = linkedEditGroups[0]; |
+ expect(group.length, 7); |
+ expect(group.positions, hasLength(1)); |
+ } |
+ |
+ test_writeLocalVariableDeclaration_type_noInitializer_final() async { |
+ String path = '/test.dart'; |
+ String content = ''' |
+void f() { |
+ |
+} |
+class MyClass {}'''; |
+ addSource(path, content); |
+ CompilationUnit unit = (await driver.getResult(path))?.unit; |
+ |
+ ClassDeclaration A = unit.declarations[1]; |
+ |
+ DartChangeBuilderImpl builder = new DartChangeBuilderImpl(driver); |
+ await builder.addFileEdit(path, 1, (FileEditBuilder builder) { |
+ builder.addInsertion(11, (EditBuilder builder) { |
+ (builder as DartEditBuilder).writeLocalVariableDeclaration('foo', |
+ isFinal: true, type: A.element.type, typeGroupName: 'type'); |
+ }); |
+ }); |
+ SourceEdit edit = getEdit(builder); |
+ expect(edit.replacement, equalsIgnoringWhitespace('final MyClass foo;')); |
+ |
+ List<LinkedEditGroup> linkedEditGroups = |
+ builder.sourceChange.linkedEditGroups; |
+ expect(linkedEditGroups, hasLength(1)); |
+ LinkedEditGroup group = linkedEditGroups[0]; |
+ expect(group.length, 7); |
+ expect(group.positions, hasLength(1)); |
+ } |
+ |
test_writeOverrideOfInheritedMember() async { |
String path = '/test.dart'; |
String content = ''' |
@@ -426,10 +710,39 @@ A add(A a) { |
}''')); |
} |
+ test_writeParameterMatchingArgument() async { |
+ String path = '/test.dart'; |
+ String content = r''' |
+f() {} |
+g() { |
+ f(new A()); |
+} |
+class A {} |
+'''; |
+ addSource(path, content); |
+ CompilationUnit unit = (await driver.getResult(path))?.unit; |
+ FunctionDeclaration g = unit.declarations[1]; |
+ BlockFunctionBody body = g.functionExpression.body; |
+ ExpressionStatement statement = body.block.statements[0]; |
+ MethodInvocation invocation = statement.expression; |
+ Expression argument = invocation.argumentList.arguments[0]; |
+ |
+ DartChangeBuilderImpl builder = new DartChangeBuilderImpl(driver); |
+ await builder.addFileEdit(path, 1, (FileEditBuilder builder) { |
+ builder.addInsertion(2, (EditBuilder builder) { |
+ (builder as DartEditBuilder) |
+ .writeParameterMatchingArgument(argument, 0, new Set<String>()); |
+ }); |
+ }); |
+ SourceEdit edit = getEdit(builder); |
+ expect(edit.replacement, equalsIgnoringWhitespace('A a')); |
+ } |
+ |
test_writeParameters_named() async { |
String path = '/test.dart'; |
String content = 'f(int i, {String s}) {}'; |
addSource(path, content); |
+ |
CompilationUnit unit = (await driver.getResult(path))?.unit; |
FunctionDeclaration f = unit.declarations[0]; |
FormalParameterList parameters = f.functionExpression.parameters; |
@@ -507,8 +820,7 @@ f(int i, String s) { |
}); |
}); |
SourceEdit edit = getEdit(builder); |
- expect( |
- edit.replacement, equalsIgnoringWhitespace('(String s, [int index])')); |
+ expect(edit.replacement, equalsIgnoringWhitespace('String s, {int index}')); |
} |
test_writeParametersMatchingArguments_required() async { |
@@ -532,7 +844,7 @@ f(int i, String s) { |
}); |
}); |
SourceEdit edit = getEdit(builder); |
- expect(edit.replacement, equalsIgnoringWhitespace('(String s, int i)')); |
+ expect(edit.replacement, equalsIgnoringWhitespace('String s, int i')); |
} |
test_writeParameterSource() async { |
@@ -804,10 +1116,36 @@ f(int i, String s) { |
} |
@reflectiveTest |
-class DartFileEditBuilderImplTest extends AbstractContextTest { |
+class DartFileEditBuilderImplTest extends AbstractContextTest |
+ with BuilderTestMixin { |
@override |
bool get enableNewAnalysisDriver => true; |
+ TypeProvider get typeProvider { |
+ AnalysisContext context = AnalysisEngine.instance.createAnalysisContext(); |
+ context.sourceFactory = new SourceFactoryImpl([new DartUriResolver(sdk)]); |
+ return new TestTypeProvider(context); |
+ } |
+ |
+ test_convertFunctionFromSyncToAsync() async { |
+ String path = '/test.dart'; |
+ addSource(path, 'String f() {}'); |
+ |
+ CompilationUnit unit = (await driver.getResult(path))?.unit; |
+ FunctionDeclaration function = unit.declarations[0]; |
+ FunctionBody body = function.functionExpression.body; |
+ |
+ DartChangeBuilderImpl builder = new DartChangeBuilderImpl(driver); |
+ await builder.addFileEdit(path, 1, (FileEditBuilder builder) { |
+ (builder as DartFileEditBuilder) |
+ .convertFunctionFromSyncToAsync(body, typeProvider); |
+ }); |
+ List<SourceEdit> edits = getEdits(builder); |
+ expect(edits, hasLength(2)); |
+ expect(edits[0].replacement, equalsIgnoringWhitespace('async')); |
+ expect(edits[1].replacement, equalsIgnoringWhitespace('Future<String>')); |
+ } |
+ |
test_createEditBuilder() async { |
String path = '/test.dart'; |
addSource(path, 'library test;'); |
@@ -825,4 +1163,46 @@ class DartFileEditBuilderImplTest extends AbstractContextTest { |
expect(sourceEdit.replacement, isEmpty); |
}); |
} |
+ |
+ test_replaceTypeWithFuture() async { |
+ String path = '/test.dart'; |
+ addSource(path, 'String f() {}'); |
+ |
+ CompilationUnit unit = (await driver.getResult(path))?.unit; |
+ FunctionDeclaration function = unit.declarations[0]; |
+ TypeAnnotation type = function.returnType; |
+ |
+ DartChangeBuilderImpl builder = new DartChangeBuilderImpl(driver); |
+ await builder.addFileEdit(path, 1, (FileEditBuilder builder) { |
+ (builder as DartFileEditBuilder) |
+ .replaceTypeWithFuture(type, typeProvider); |
+ }); |
+ SourceEdit edit = getEdit(builder); |
+ expect(edit.replacement, equalsIgnoringWhitespace('Future<String>')); |
+ } |
+} |
+ |
+@reflectiveTest |
+class DartLinkedEditBuilderImplTest extends AbstractContextTest { |
+ @override |
+ bool get enableNewAnalysisDriver => true; |
+ |
+ test_addSuperTypesAsSuggestions() async { |
+ String path = '/test.dart'; |
+ addSource( |
+ path, |
+ ''' |
+class A {} |
+class B extends A {} |
+class C extends B {} |
+'''); |
+ CompilationUnit unit = (await driver.getResult(path))?.unit; |
+ ClassDeclaration classC = unit.declarations[2]; |
+ DartLinkedEditBuilderImpl builder = new DartLinkedEditBuilderImpl(null); |
+ builder.addSuperTypesAsSuggestions(classC.element.type); |
+ List<LinkedEditSuggestion> suggestions = builder.suggestions; |
+ expect(suggestions, hasLength(4)); |
+ expect(suggestions.map((s) => s.value), |
+ unorderedEquals(['Object', 'A', 'B', 'C'])); |
+ } |
} |