Compute unlinked API signatures without unlinked summaries.
R=brianwilkerson@google.com, paulberry@google.com
Change-Id: I21c87f60d88716eb9c6b1d5e558bb17156daa598
Reviewed-on: https://dart-review.googlesource.com/74925
Reviewed-by: Paul Berry <paulberry@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 278996c..c032de3 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -92,7 +92,7 @@
/**
* The version of data format, should be incremented on every format change.
*/
- static const int DATA_VERSION = 65;
+ static const int DATA_VERSION = 66;
/**
* The number of exception contexts allowed to write. Once this field is
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index 8e90b2d..8264349 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -14,6 +14,7 @@
import 'package:analyzer/src/dart/analysis/one_phase_summaries_selector.dart';
import 'package:analyzer/src/dart/analysis/referenced_names.dart';
import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
+import 'package:analyzer/src/dart/analysis/unlinked_api_signature.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/engine.dart';
@@ -126,7 +127,6 @@
Set<String> _definedTopLevelNames;
Set<String> _referencedNames;
Set<String> _subtypedNames;
- String _unlinkedKey;
AnalysisDriverUnlinkedUnit _driverUnlinkedUnit;
UnlinkedUnit _unlinked;
List<int> _apiSignature;
@@ -419,27 +419,38 @@
_contentHash = rawFileState.contentHash;
}
- // Prepare the unlinked bundle key.
+ // Prepare keys of unlinked data.
+ String apiSignatureKey;
+ String unlinkedKey;
{
- ApiSignature signature = new ApiSignature();
+ var signature = new ApiSignature();
signature.addUint32List(_fsState._salt);
signature.addString(_contentHash);
- _unlinkedKey = '${signature.toHex()}.unlinked';
+
+ var signatureHex = signature.toHex();
+ apiSignatureKey = '$signatureHex.api_signature';
+ unlinkedKey = '$signatureHex.unlinked';
}
- // Prepare bytes of the unlinked bundle - existing or new.
- List<int> bytes;
- {
- bytes = _fsState._byteStore.get(_unlinkedKey);
- if (bytes == null || bytes.isEmpty) {
- CompilationUnit unit = parse();
- _fsState._logger.run('Create unlinked for $path', () {
- UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit,
+ // Try to get bytes of unlinked data.
+ var apiSignatureBytes = _fsState._byteStore.get(apiSignatureKey);
+ var unlinkedUnitBytes = _fsState._byteStore.get(unlinkedKey);
+
+ // Compute unlinked data that we are missing.
+ if (apiSignatureBytes == null || unlinkedUnitBytes == null) {
+ CompilationUnit unit = parse(AnalysisErrorListener.NULL_LISTENER);
+ _fsState._logger.run('Create unlinked for $path', () {
+ if (apiSignatureBytes == null) {
+ apiSignatureBytes = computeUnlinkedApiSignature(unit);
+ _fsState._byteStore.put(apiSignatureKey, apiSignatureBytes);
+ }
+ if (unlinkedUnitBytes == null) {
+ var unlinkedUnit = serializeAstUnlinked(unit,
serializeInferrableFields: !enableOnePhaseSummaries);
- DefinedNames definedNames = computeDefinedNames(unit);
- List<String> referencedNames = computeReferencedNames(unit).toList();
- List<String> subtypedNames = computeSubtypedNames(unit).toList();
- bytes = new AnalysisDriverUnlinkedUnitBuilder(
+ var definedNames = computeDefinedNames(unit);
+ var referencedNames = computeReferencedNames(unit).toList();
+ var subtypedNames = computeSubtypedNames(unit).toList();
+ unlinkedUnitBytes = new AnalysisDriverUnlinkedUnitBuilder(
unit: unlinkedUnit,
definedTopLevelNames: definedNames.topLevelNames.toList(),
definedClassMemberNames:
@@ -447,13 +458,14 @@
referencedNames: referencedNames,
subtypedNames: subtypedNames)
.toBuffer();
- _fsState._byteStore.put(_unlinkedKey, bytes);
- });
- }
+ _fsState._byteStore.put(unlinkedKey, unlinkedUnitBytes);
+ }
+ });
}
// Read the unlinked bundle.
- _driverUnlinkedUnit = new AnalysisDriverUnlinkedUnit.fromBuffer(bytes);
+ _driverUnlinkedUnit =
+ new AnalysisDriverUnlinkedUnit.fromBuffer(unlinkedUnitBytes);
_unlinked = _driverUnlinkedUnit.unit;
_lineInfo = new LineInfo(_unlinked.lineStarts);
@@ -465,10 +477,9 @@
_topLevelDeclarations = null;
// Prepare API signature.
- List<int> newApiSignature = new Uint8List.fromList(_unlinked.apiSignature);
bool apiSignatureChanged = _apiSignature != null &&
- !_equalByteLists(_apiSignature, newApiSignature);
- _apiSignature = newApiSignature;
+ !_equalByteLists(_apiSignature, apiSignatureBytes);
+ _apiSignature = apiSignatureBytes;
// The API signature changed.
// Flush transitive signatures of affected files.
@@ -684,8 +695,6 @@
final FileState file;
FileStateTestView(this.file);
-
- String get unlinkedKey => file._unlinkedKey;
}
/**
diff --git a/pkg/analyzer/lib/src/dart/analysis/unlinked_api_signature.dart b/pkg/analyzer/lib/src/dart/analysis/unlinked_api_signature.dart
new file mode 100644
index 0000000..e9b3c93
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/analysis/unlinked_api_signature.dart
@@ -0,0 +1,119 @@
+// Copyright (c) 2018, 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.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/summary/api_signature.dart';
+
+/// Return the bytes of the unlinked API signature of the given [unit].
+///
+/// If API signatures of two units are different, they may have different APIs.
+List<int> computeUnlinkedApiSignature(CompilationUnit unit) {
+ var computer = new _UnitApiSignatureComputer();
+ computer.compute(unit);
+ return computer.signature.toByteList();
+}
+
+class _UnitApiSignatureComputer {
+ final signature = new ApiSignature();
+
+ void addClassOrMixin(ClassOrMixinDeclaration node) {
+ addTokens(node.beginToken, node.leftBracket);
+
+ bool hasConstConstructor = node.members
+ .any((m) => m is ConstructorDeclaration && m.constKeyword != null);
+
+ signature.addInt(node.members.length);
+ for (var member in node.members) {
+ if (member is ConstructorDeclaration) {
+ var lastInitializer = member.constKeyword != null &&
+ member.initializers != null &&
+ member.initializers.isNotEmpty
+ ? member.initializers.last
+ : null;
+ addTokens(
+ member.beginToken,
+ (lastInitializer ?? member.parameters ?? member.name).endToken,
+ );
+ } else if (member is FieldDeclaration) {
+ addVariables(member, member.fields, hasConstConstructor);
+ } else if (member is MethodDeclaration) {
+ addTokens(
+ member.beginToken,
+ (member.parameters ?? member.name).endToken,
+ );
+ } else {
+ addNode(member);
+ }
+ }
+
+ addToken(node.rightBracket);
+ }
+
+ void addNode(AstNode node) {
+ addTokens(node.beginToken, node.endToken);
+ }
+
+ void addToken(Token token) {
+ signature.addString(token.lexeme);
+ }
+
+ /// Appends tokens from [begin] (including), to [end] (also including).
+ void addTokens(Token begin, Token end) {
+ if (begin is CommentToken) {
+ begin = (begin as CommentToken).parent;
+ }
+ Token token = begin;
+ while (token != null) {
+ addToken(token);
+ if (token == end) {
+ break;
+ }
+ token = token.next;
+ }
+ }
+
+ void addVariables(
+ AstNode node,
+ VariableDeclarationList variableList,
+ bool includeFinalInitializers,
+ ) {
+ if (variableList.type == null ||
+ variableList.isConst ||
+ variableList.isFinal && includeFinalInitializers) {
+ addTokens(node.beginToken, node.endToken);
+ } else {
+ addTokens(node.beginToken, variableList.type.endToken);
+
+ signature.addInt(variableList.variables.length);
+ for (var variable in variableList.variables) {
+ addTokens(variable.beginToken, variable.name.endToken);
+ addToken(variable.endToken.next); // `,` or `;`
+ }
+ }
+ }
+
+ void compute(CompilationUnit unit) {
+ signature.addInt(unit.directives.length);
+ unit.directives.forEach(addNode);
+
+ signature.addInt(unit.declarations.length);
+ for (var declaration in unit.declarations) {
+ if (declaration is ClassOrMixinDeclaration) {
+ addClassOrMixin(declaration);
+ } else if (declaration is FunctionDeclaration) {
+ var parameters = declaration.functionExpression.parameters;
+ addTokens(
+ declaration.beginToken,
+ (parameters ?? declaration.name).endToken,
+ );
+ } else if (declaration is TopLevelVariableDeclaration) {
+ addVariables(declaration, declaration.variables, false);
+ } else {
+ addNode(declaration);
+ }
+ }
+ }
+}
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index 6ec4d00..f83688a 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -654,22 +654,6 @@
expect(file.apiSignature, signature);
}
- test_store_zeroLengthUnlinked() {
- String path = _p('/test.dart');
- provider.newFile(path, 'class A {}');
-
- // Get the file, prepare unlinked.
- FileState file = fileSystemState.getFileForPath(path);
- expect(file.unlinked, isNotNull);
-
- // Make the unlinked unit in the byte store zero-length, damaged.
- byteStore.put(file.test.unlinkedKey, <int>[]);
-
- // Refresh should not fail, zero bytes in the store are ignored.
- file.refresh();
- expect(file.unlinked, isNotNull);
- }
-
test_subtypedNames() {
String path = _p('/test.dart');
provider.newFile(path, r'''
diff --git a/pkg/analyzer/test/src/dart/analysis/test_all.dart b/pkg/analyzer/test/src/dart/analysis/test_all.dart
index 7c74b6b..f4f9c49 100644
--- a/pkg/analyzer/test/src/dart/analysis/test_all.dart
+++ b/pkg/analyzer/test/src/dart/analysis/test_all.dart
@@ -18,6 +18,7 @@
import 'search_test.dart' as search;
import 'session_helper_test.dart' as session_helper;
import 'session_test.dart' as session;
+import 'unlinked_api_signature_test.dart' as unlinked_api_signature;
import 'uri_converter_test.dart' as uri_converter;
main() {
@@ -36,6 +37,7 @@
search.main();
session_helper.main();
session.main();
+ unlinked_api_signature.main();
uri_converter.main();
}, name: 'analysis');
}
diff --git a/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart b/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart
new file mode 100644
index 0000000..0686064
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart
@@ -0,0 +1,832 @@
+// Copyright (c) 2018, 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.
+
+import 'dart:typed_data';
+
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/dart/analysis/file_state.dart';
+import 'package:analyzer/src/file_system/file_system.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
+import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+import 'package:front_end/src/api_prototype/byte_store.dart';
+import 'package:front_end/src/base/performance_logger.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../context/mock_sdk.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(UnitApiSignatureTest);
+ });
+}
+
+@reflectiveTest
+class UnitApiSignatureTest extends Object with ResourceProviderMixin {
+ FileSystemState fileSystemState;
+
+ Future<Null> assertNotSameSignature(String oldCode, String newCode) async {
+ assertSignature(oldCode, newCode, same: false);
+ }
+
+ Future<Null> assertSameSignature(String oldCode, String newCode) async {
+ assertSignature(oldCode, newCode, same: true);
+ }
+
+ Future<Null> assertSignature(String oldCode, String newCode,
+ {bool same}) async {
+ var path = convertPath('/test.dart');
+
+ newFile(path, content: oldCode);
+ var file = fileSystemState.getFileForPath(path);
+ var lastSignature = file.apiSignature;
+
+ newFile(path, content: newCode);
+ await file.refresh();
+
+ var newSignature = file.apiSignature;
+ if (same) {
+ expect(newSignature, lastSignature);
+ } else {
+ expect(newSignature, isNot(lastSignature));
+ }
+ }
+
+ void setUp() {
+ var sdk = new MockSdk(resourceProvider: resourceProvider);
+ var sourceFactory = new SourceFactory([
+ new DartUriResolver(sdk),
+ new PackageMapUriResolver(resourceProvider, <String, List<Folder>>{
+ 'aaa': [getFolder('/aaa/lib')],
+ 'bbb': [getFolder('/bbb/lib')],
+ }),
+ new ResourceUriResolver(resourceProvider)
+ ], null, resourceProvider);
+ fileSystemState = new FileSystemState(
+ new PerformanceLog(new StringBuffer()),
+ new MemoryByteStore(),
+ new FileContentOverlay(),
+ resourceProvider,
+ sourceFactory,
+ new AnalysisOptionsImpl(),
+ new Uint32List(0));
+ }
+
+ test_class_annotation() async {
+ await assertNotSameSignature(r'''
+const a = 0;
+
+class C {}
+''', r'''
+const a = 0;
+
+@a
+class C {}
+''');
+ }
+
+ test_class_constructor_block_to_empty() async {
+ await assertSameSignature(r'''
+class C {
+ C() {
+ var v = 1;
+ }
+}
+''', r'''
+class C {
+ C();
+}
+''');
+ }
+
+ test_class_constructor_body() async {
+ await assertSameSignature(r'''
+class C {
+ C() {
+ var v = 1;
+ }
+}
+''', r'''
+class C {
+ C() {
+ var v = 2;
+ }
+}
+''');
+ }
+
+ test_class_constructor_empty_to_block() async {
+ await assertSameSignature(r'''
+class C {
+ C();
+}
+''', r'''
+class C {
+ C() {
+ var v = 1;
+ }
+}
+''');
+ }
+
+ test_class_constructor_initializer_const() async {
+ await assertNotSameSignature(r'''
+class C {
+ final int f;
+ const C() : f = 1;
+}
+''', r'''
+class C {
+ final int f;
+ const C() : f = 2;
+}
+''');
+ }
+
+ test_class_constructor_initializer_empty() async {
+ await assertSameSignature(r'''
+class C {
+ C.foo() : ;
+}
+''', r'''
+class C {
+ C.foo() : f;
+}
+''');
+ }
+
+ test_class_constructor_initializer_notConst() async {
+ await assertSameSignature(r'''
+class C {
+ final int f;
+ C.foo() : f = 1;
+ const C.bar();
+}
+''', r'''
+class C {
+ final int f;
+ C.foo() : f = 2;
+ const C.bar();
+}
+''');
+ }
+
+ test_class_constructor_parameters_add() async {
+ await assertNotSameSignature(r'''
+class C {
+ C(int a);
+}
+''', r'''
+class C {
+ C(int a, int b);
+}
+''');
+ }
+
+ test_class_constructor_parameters_remove() async {
+ await assertNotSameSignature(r'''
+class C {
+ C(int a, int b);
+}
+''', r'''
+class C {
+ C(int a);
+}
+''');
+ }
+
+ test_class_constructor_parameters_rename() async {
+ await assertNotSameSignature(r'''
+class C {
+ C(int a);
+}
+''', r'''
+class C {
+ C(int b);
+}
+''');
+ }
+
+ test_class_constructor_parameters_type() async {
+ await assertNotSameSignature(r'''
+class C {
+ C(int p);
+}
+''', r'''
+class C {
+ C(double p);
+}
+''');
+ }
+
+ test_class_extends() async {
+ await assertNotSameSignature(r'''
+class A {}
+class B {}
+''', r'''
+class A {}
+class B extends A {}
+''');
+ }
+
+ test_class_field_withoutType() async {
+ await assertNotSameSignature(r'''
+class C {
+ var a = 1;
+}
+''', r'''
+class C {
+ var a = 2;
+}
+''');
+ }
+
+ test_class_field_withoutType2() async {
+ await assertNotSameSignature(r'''
+class C {
+ var a = 1, b = 2, c, d = 4;
+}
+''', r'''
+class C {
+ var a = 1, b, c = 3, d = 4;
+}
+''');
+ }
+
+ test_class_field_withType() async {
+ await assertSameSignature(r'''
+class C {
+ int a = 1, b, c = 3;
+}
+''', r'''
+class C {
+ int a = 0, b = 2, c;
+}
+''');
+ }
+
+ test_class_field_withType_const() async {
+ await assertNotSameSignature(r'''
+class C {
+ static const int a = 1;
+}
+''', r'''
+class C {
+ static const int a = 2;
+}
+''');
+ }
+
+ test_class_field_withType_final_hasConstConstructor() async {
+ await assertNotSameSignature(r'''
+class C {
+ final int a = 1;
+ const C();
+}
+''', r'''
+class C {
+ final int a = 2;
+ const C();
+}
+''');
+ }
+
+ test_class_field_withType_final_noConstConstructor() async {
+ await assertSameSignature(r'''
+class C {
+ final int a = 1;
+}
+''', r'''
+class C {
+ final int a = 2;
+}
+''');
+ }
+
+ test_class_implements() async {
+ await assertNotSameSignature(r'''
+class A {}
+class B {}
+''', r'''
+class A {}
+class B implements A {}
+''');
+ }
+
+ test_class_method_annotation() async {
+ await assertNotSameSignature(r'''
+const a = 0;
+
+class C {
+ void foo() {}
+}
+''', r'''
+const a = 0;
+
+class C {
+ @a
+ void foo() {}
+}
+''');
+ }
+
+ test_class_method_body_async_to_sync() async {
+ await assertSameSignature(r'''
+class C {
+ Future foo() async {}
+}
+''', r'''
+class C {
+ Future foo() {}
+}
+''');
+ }
+
+ test_class_method_body_block() async {
+ await assertSameSignature(r'''
+class C {
+ int foo() {
+ return 1;
+ }
+}
+''', r'''
+class C {
+ int foo() {
+ return 2;
+ }
+}
+''');
+ }
+
+ test_class_method_body_block_to_expression() async {
+ await assertSameSignature(r'''
+class C {
+ int foo() {
+ return 1;
+ }
+}
+''', r'''
+class C {
+ int foo() => 2;
+}
+''');
+ }
+
+ test_class_method_body_empty_to_block() async {
+ await assertSameSignature(r'''
+class C {
+ int foo();
+}
+''', r'''
+class C {
+ int foo() {
+ var v = 0;
+ }
+}
+''');
+ }
+
+ test_class_method_body_expression() async {
+ await assertSameSignature(r'''
+class C {
+ int foo() => 1;
+}
+''', r'''
+class C {
+ int foo() => 2;
+}
+''');
+ }
+
+ test_class_method_body_sync_to_async() async {
+ await assertSameSignature(r'''
+class C {
+ Future foo() {}
+}
+''', r'''
+class C {
+ Future foo() async {}
+}
+''');
+ }
+
+ test_class_method_getter_body_block_to_expression() async {
+ await assertSameSignature(r'''
+class C {
+ int get foo {
+ return 1;
+ }
+}
+''', r'''
+class C {
+ int get foo => 2;
+}
+''');
+ }
+
+ test_class_method_getter_body_empty_to_expression() async {
+ await assertSameSignature(r'''
+class C {
+ int get foo;
+}
+''', r'''
+class C {
+ int get foo => 2;
+}
+''');
+ }
+
+ test_class_method_parameters_add() async {
+ await assertNotSameSignature(r'''
+class C {
+ foo(int a) {}
+}
+''', r'''
+class C {
+ foo(int a, int b) {}
+}
+''');
+ }
+
+ test_class_method_parameters_remove() async {
+ await assertNotSameSignature(r'''
+class C {
+ foo(int a, int b) {}
+}
+''', r'''
+class C {
+ foo(int a) {}
+}
+''');
+ }
+
+ test_class_method_parameters_rename() async {
+ await assertNotSameSignature(r'''
+class C {
+ void foo(int a) {}
+}
+''', r'''
+class C {
+ void foo(int b) {}
+}
+''');
+ }
+
+ test_class_method_parameters_type() async {
+ await assertNotSameSignature(r'''
+class C {
+ void foo(int p) {}
+}
+''', r'''
+class C {
+ void foo(double p) {}
+}
+''');
+ }
+
+ test_class_method_returnType() async {
+ await assertNotSameSignature(r'''
+class C {
+ int foo() => 0;
+}
+''', r'''
+class C {
+ num foo() => 0;
+}
+''');
+ }
+
+ test_class_method_typeParameters_add() async {
+ await assertNotSameSignature(r'''
+class C {
+ void foo() {}
+}
+''', r'''
+class C {
+ void foo<T>() {}
+}
+''');
+ }
+
+ test_class_method_typeParameters_remove() async {
+ await assertNotSameSignature(r'''
+class C {
+ void foo<T>() {}
+}
+''', r'''
+class C {
+ void foo() {}
+}
+''');
+ }
+
+ test_class_method_typeParameters_rename() async {
+ await assertNotSameSignature(r'''
+class C {
+ void foo<T>() {}
+}
+''', r'''
+class C {
+ void foo<U>() {}
+}
+''');
+ }
+
+ test_class_modifier() async {
+ await assertNotSameSignature(r'''
+class C {}
+''', r'''
+abstract class C {}
+''');
+ }
+
+ test_class_with() async {
+ await assertNotSameSignature(r'''
+class A {}
+class B {}
+class C extends A {}
+''', r'''
+class A {}
+class B {}
+class C extends A with B {}
+''');
+ }
+
+ test_commentAdd() async {
+ await assertSameSignature(r'''
+var a = 1;
+var b = 2;
+var c = 3;
+''', r'''
+var a = 1; // comment
+
+/// comment 1
+/// comment 2
+var b = 2;
+
+/**
+ * Comment
+ */
+var c = 3;
+''');
+ }
+
+ test_commentRemove() async {
+ await assertSameSignature(r'''
+var a = 1; // comment
+
+/// comment 1
+/// comment 2
+var b = 2;
+
+/**
+ * Comment
+ */
+var c = 3;
+''', r'''
+var a = 1;
+var b = 2;
+var c = 3;
+''');
+ }
+
+ test_function_annotation() async {
+ await assertNotSameSignature(r'''
+const a = 0;
+
+void foo() {}
+''', r'''
+const a = 0;
+
+@a
+void foo() {}
+''');
+ }
+
+ test_function_body_async_to_sync() async {
+ await assertSameSignature(r'''
+Future foo() async {}
+''', r'''
+Future foo() {}
+''');
+ }
+
+ test_function_body_block() async {
+ await assertSameSignature(r'''
+int foo() {
+ return 1;
+}
+''', r'''
+int foo() {
+ return 2;
+}
+''');
+ }
+
+ test_function_body_block_to_expression() async {
+ await assertSameSignature(r'''
+int foo() {
+ return 1;
+}
+''', r'''
+int foo() => 2;
+''');
+ }
+
+ test_function_body_expression() async {
+ await assertSameSignature(r'''
+int foo() => 1;
+''', r'''
+int foo() => 2;
+''');
+ }
+
+ test_function_body_sync_to_async() async {
+ await assertSameSignature(r'''
+Future foo() {}
+''', r'''
+Future foo() async {}
+''');
+ }
+
+ test_function_getter_block_to_expression() async {
+ await assertSameSignature(r'''
+int get foo {
+ return 1;
+}
+''', r'''
+int get foo => 2;
+''');
+ }
+
+ test_function_parameters_rename() async {
+ await assertNotSameSignature(r'''
+void foo(int a) {}
+''', r'''
+void foo(int b) {}
+''');
+ }
+
+ test_function_parameters_type() async {
+ await assertNotSameSignature(r'''
+void foo(int p) {}
+''', r'''
+void foo(double p) {}
+''');
+ }
+
+ test_function_returnType() async {
+ await assertNotSameSignature(r'''
+int foo() => 0;
+''', r'''
+num foo() => 0;
+''');
+ }
+
+ test_function_typeParameters_add() async {
+ await assertNotSameSignature(r'''
+void foo() {}
+''', r'''
+void foo<T>() {}
+''');
+ }
+
+ test_function_typeParameters_remove() async {
+ await assertNotSameSignature(r'''
+void foo<T>() {}
+''', r'''
+void foo() {}
+''');
+ }
+
+ test_function_typeParameters_rename() async {
+ await assertNotSameSignature(r'''
+void foo<T>() {}
+''', r'''
+void foo<U>() {}
+''');
+ }
+
+ test_mixin_field_withoutType() async {
+ await assertNotSameSignature(r'''
+mixin M {
+ var a = 1;
+}
+''', r'''
+mixin M {
+ var a = 2;
+}
+''');
+ }
+
+ test_mixin_field_withType() async {
+ await assertSameSignature(r'''
+mixin M {
+ int a = 1, b, c = 3;
+}
+''', r'''
+mixin M {
+ int a = 0, b = 2, c;
+}
+''');
+ }
+
+ test_mixin_implements() async {
+ await assertNotSameSignature(r'''
+class A {}
+mixin M {}
+''', r'''
+class A {}
+mixin M implements A {}
+''');
+ }
+
+ test_mixin_method_body_block() async {
+ await assertSameSignature(r'''
+mixin M {
+ int foo() {
+ return 1;
+ }
+}
+''', r'''
+mixin M {
+ int foo() {
+ return 2;
+ }
+}
+''');
+ }
+
+ test_mixin_method_body_expression() async {
+ await assertSameSignature(r'''
+mixin M {
+ int foo() => 1;
+}
+''', r'''
+mixin M {
+ int foo() => 2;
+}
+''');
+ }
+
+ test_mixin_on() async {
+ await assertNotSameSignature(r'''
+class A {}
+mixin M {}
+''', r'''
+class A {}
+mixin M on A {}
+''');
+ }
+
+ test_topLevelVariable_withoutType() async {
+ await assertNotSameSignature(r'''
+var a = 1;
+''', r'''
+var a = 2;
+''');
+ }
+
+ test_topLevelVariable_withoutType2() async {
+ await assertNotSameSignature(r'''
+var a = 1, b = 2, c, d = 4;;
+''', r'''
+var a = 1, b, c = 3, d = 4;;
+''');
+ }
+
+ test_topLevelVariable_withType() async {
+ await assertSameSignature(r'''
+int a = 1, b, c = 3;
+''', r'''
+int a = 0, b = 2, c;
+''');
+ }
+
+ test_topLevelVariable_withType_const() async {
+ await assertNotSameSignature(r'''
+const int a = 1;
+''', r'''
+const int a = 2;
+''');
+ }
+
+ test_topLevelVariable_withType_final() async {
+ await assertSameSignature(r'''
+final int a = 1;
+''', r'''
+final int a = 2;
+''');
+ }
+
+ test_typedef_generic_parameters_type() async {
+ await assertNotSameSignature(r'''
+typedef F = void Function(int);
+''', r'''
+typedef F = void Function(double);
+''');
+ }
+}