Index: packages/analyzer/test/generated/incremental_resolver_test.dart |
diff --git a/packages/analyzer/test/generated/incremental_resolver_test.dart b/packages/analyzer/test/generated/incremental_resolver_test.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..eaef1654096c5abf7885ace7545f039c8b4dc6f2 |
--- /dev/null |
+++ b/packages/analyzer/test/generated/incremental_resolver_test.dart |
@@ -0,0 +1,4895 @@ |
+// Copyright (c) 2014, 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. |
+ |
+library engine.incremental_resolver_test; |
+ |
+import 'package:analyzer/src/context/cache.dart' as task; |
+import 'package:analyzer/src/generated/ast.dart'; |
+import 'package:analyzer/src/generated/element.dart'; |
+import 'package:analyzer/src/generated/engine.dart'; |
+import 'package:analyzer/src/generated/error.dart'; |
+import 'package:analyzer/src/generated/incremental_logger.dart' as log; |
+import 'package:analyzer/src/generated/incremental_resolution_validator.dart'; |
+import 'package:analyzer/src/generated/incremental_resolver.dart'; |
+import 'package:analyzer/src/generated/java_engine.dart'; |
+import 'package:analyzer/src/generated/parser.dart'; |
+import 'package:analyzer/src/generated/resolver.dart'; |
+import 'package:analyzer/src/generated/scanner.dart'; |
+import 'package:analyzer/src/generated/source_io.dart'; |
+import 'package:analyzer/src/generated/testing/ast_factory.dart'; |
+import 'package:analyzer/src/generated/testing/element_factory.dart'; |
+import 'package:analyzer/task/dart.dart'; |
+import 'package:unittest/unittest.dart'; |
+ |
+import '../reflective_tests.dart'; |
+import 'parser_test.dart'; |
+import 'resolver_test.dart'; |
+import 'test_support.dart'; |
+ |
+main() { |
+ initializeTestEnvironment(); |
+ runReflectiveTests(DeclarationMatcherTest); |
+ runReflectiveTests(IncrementalResolverTest); |
+ runReflectiveTests(PoorMansIncrementalResolutionTest); |
+ runReflectiveTests(ResolutionContextBuilderTest); |
+} |
+ |
+void initializeTestEnvironment() {} |
+ |
+void _assertEqualError(AnalysisError incrError, AnalysisError fullError) { |
+ if (incrError.errorCode != fullError.errorCode || |
+ incrError.source != fullError.source || |
+ incrError.offset != fullError.offset || |
+ incrError.length != fullError.length || |
+ incrError.message != fullError.message) { |
+ StringBuffer buffer = new StringBuffer(); |
+ buffer.writeln('Found error does not match expected error:'); |
+ if (incrError.errorCode == fullError.errorCode) { |
+ buffer.write(' errorCode = '); |
+ buffer.write(fullError.errorCode.uniqueName); |
+ } else { |
+ buffer.write(' Expected errorCode = '); |
+ buffer.write(fullError.errorCode.uniqueName); |
+ buffer.write(' found '); |
+ buffer.write(incrError.errorCode.uniqueName); |
+ } |
+ buffer.writeln(); |
+ if (incrError.source == fullError.source) { |
+ buffer.write(' source = '); |
+ buffer.write(fullError.source); |
+ } else { |
+ buffer.write(' Expected source = '); |
+ buffer.write(fullError.source); |
+ buffer.write(' found '); |
+ buffer.write(incrError.source); |
+ } |
+ buffer.writeln(); |
+ if (incrError.offset == fullError.offset) { |
+ buffer.write(' offset = '); |
+ buffer.write(fullError.offset); |
+ } else { |
+ buffer.write(' Expected offset = '); |
+ buffer.write(fullError.offset); |
+ buffer.write(' found '); |
+ buffer.write(incrError.offset); |
+ } |
+ buffer.writeln(); |
+ if (incrError.length == fullError.length) { |
+ buffer.write(' length = '); |
+ buffer.write(fullError.length); |
+ } else { |
+ buffer.write(' Expected length = '); |
+ buffer.write(fullError.length); |
+ buffer.write(' found '); |
+ buffer.write(incrError.length); |
+ } |
+ buffer.writeln(); |
+ if (incrError.message == fullError.message) { |
+ buffer.write(' message = '); |
+ buffer.write(fullError.message); |
+ } else { |
+ buffer.write(' Expected message = '); |
+ buffer.write(fullError.message); |
+ buffer.write(' found '); |
+ buffer.write(incrError.message); |
+ } |
+ fail(buffer.toString()); |
+ } |
+} |
+ |
+void _assertEqualErrors( |
+ List<AnalysisError> incrErrors, List<AnalysisError> fullErrors) { |
+ expect(incrErrors, hasLength(fullErrors.length)); |
+ if (incrErrors.isNotEmpty) { |
+ incrErrors.sort((a, b) => a.offset - b.offset); |
+ } |
+ if (fullErrors.isNotEmpty) { |
+ fullErrors.sort((a, b) => a.offset - b.offset); |
+ } |
+ int length = incrErrors.length; |
+ for (int i = 0; i < length; i++) { |
+ AnalysisError incrError = incrErrors[i]; |
+ AnalysisError fullError = fullErrors[i]; |
+ _assertEqualError(incrError, fullError); |
+ } |
+} |
+ |
+@reflectiveTest |
+class DeclarationMatcherTest extends ResolverTestCase { |
+ void setUp() { |
+ super.setUp(); |
+ test_resolveApiChanges = true; |
+ } |
+ |
+ void test_false_class_annotation_accessor_edit() { |
+ _assertDoesNotMatch( |
+ r''' |
+const my_annotationA = const Object(); |
+const my_annotationB = const Object(); |
+@my_annotationA |
+class A { |
+} |
+''', |
+ r''' |
+const my_annotationA = const Object(); |
+const my_annotationB = const Object(); |
+@my_annotationB |
+class A { |
+} |
+'''); |
+ } |
+ |
+ void test_false_class_annotation_constructor_edit() { |
+ _assertDoesNotMatch( |
+ r''' |
+class MyAnnotationA { |
+ const MyAnnotationA(); |
+} |
+class MyAnnotationB { |
+ const MyAnnotationB(); |
+} |
+@MyAnnotationA() |
+class A { |
+} |
+''', |
+ r''' |
+class MyAnnotationA { |
+ const MyAnnotationA(); |
+} |
+class MyAnnotationB { |
+ const MyAnnotationB(); |
+} |
+@MyAnnotationB() |
+class A { |
+} |
+'''); |
+ } |
+ |
+ void test_false_class_annotations_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+const my_annotation = const Object(); |
+class A { |
+} |
+''', |
+ r''' |
+const my_annotation = const Object(); |
+@my_annotation |
+class A { |
+} |
+'''); |
+ } |
+ |
+ void test_false_class_annotations_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+const my_annotation = const Object(); |
+@my_annotation |
+class A { |
+} |
+''', |
+ r''' |
+const my_annotation = const Object(); |
+class A { |
+} |
+'''); |
+ } |
+ |
+ void test_false_class_list_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A {} |
+class B {} |
+''', |
+ r''' |
+class A {} |
+class B {} |
+class C {} |
+'''); |
+ } |
+ |
+ void test_false_class_list_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A {} |
+class B {} |
+class C {} |
+''', |
+ r''' |
+class A {} |
+class B {} |
+'''); |
+ } |
+ |
+ void test_false_class_typeParameters_bounds_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A {} |
+class B<T> { |
+ T f; |
+} |
+''', |
+ r''' |
+class A {} |
+class B<T extends A> { |
+ T f; |
+} |
+'''); |
+ } |
+ |
+ void test_false_class_typeParameters_bounds_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A {} |
+class B<T extends A> { |
+ T f; |
+} |
+''', |
+ r''' |
+class A {} |
+class B<T> { |
+ T f; |
+} |
+'''); |
+ } |
+ |
+ void test_false_classMemberAccessor_list_add() { |
+ _assertDoesNotMatchOK( |
+ r''' |
+class A { |
+ get a => 1; |
+ get b => 2; |
+} |
+''', |
+ r''' |
+class A { |
+ get a => 1; |
+ get b => 2; |
+ get c => 3; |
+} |
+'''); |
+ } |
+ |
+ void test_false_classMemberAccessor_list_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ get a => 1; |
+ get b => 2; |
+ get c => 3; |
+} |
+''', |
+ r''' |
+class A { |
+ get a => 1; |
+ get b => 2; |
+} |
+'''); |
+ } |
+ |
+ void test_false_classMemberAccessor_wasGetter() { |
+ _assertDoesNotMatchOK( |
+ r''' |
+class A { |
+ get a => 1; |
+} |
+''', |
+ r''' |
+class A { |
+ set a(x) {} |
+} |
+'''); |
+ } |
+ |
+ void test_false_classMemberAccessor_wasInstance() { |
+ _assertDoesNotMatchOK( |
+ r''' |
+class A { |
+ get a => 1; |
+} |
+''', |
+ r''' |
+class A { |
+ static get a => 1; |
+} |
+'''); |
+ } |
+ |
+ void test_false_classMemberAccessor_wasSetter() { |
+ _assertDoesNotMatchOK( |
+ r''' |
+class A { |
+ set a(x) {} |
+} |
+''', |
+ r''' |
+class A { |
+ get a => 1; |
+} |
+'''); |
+ } |
+ |
+ void test_false_classMemberAccessor_wasStatic() { |
+ _assertDoesNotMatchOK( |
+ r''' |
+class A { |
+ static get a => 1; |
+} |
+''', |
+ r''' |
+class A { |
+ get a => 1; |
+} |
+'''); |
+ } |
+ |
+ void test_false_classTypeAlias_list_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+class M {} |
+class A = Object with M; |
+''', |
+ r''' |
+class M {} |
+class A = Object with M; |
+class B = Object with M; |
+'''); |
+ } |
+ |
+ void test_false_classTypeAlias_list_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+class M {} |
+class A = Object with M; |
+class B = Object with M; |
+''', |
+ r''' |
+class M {} |
+class A = Object with M; |
+'''); |
+ } |
+ |
+ void test_false_classTypeAlias_typeParameters_bounds_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+class M<T> {} |
+class A {} |
+class B<T> = Object with M<T>; |
+''', |
+ r''' |
+class M<T> {} |
+class A {} |
+class B<T extends A> = Object with M<T>; |
+'''); |
+ } |
+ |
+ void test_false_classTypeAlias_typeParameters_bounds_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+class M<T> {} |
+class A {} |
+class B<T extends A> = Object with M<T>; |
+''', |
+ r''' |
+class M<T> {} |
+class A {} |
+class B<T> = Object with M<T>; |
+'''); |
+ } |
+ |
+ void test_false_constructor_keywordConst_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ A(); |
+} |
+''', |
+ r''' |
+class A { |
+ const A(); |
+} |
+'''); |
+ } |
+ |
+ void test_false_constructor_keywordConst_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ const A(); |
+} |
+''', |
+ r''' |
+class A { |
+ A(); |
+} |
+'''); |
+ } |
+ |
+ void test_false_constructor_keywordFactory_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ A(); |
+ A.foo() { |
+ return new A(); |
+ } |
+} |
+''', |
+ r''' |
+class A { |
+ A(); |
+ factory A.foo() { |
+ return new A(); |
+ } |
+} |
+'''); |
+ } |
+ |
+ void test_false_constructor_keywordFactory_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ A(); |
+ factory A.foo() { |
+ return new A(); |
+ } |
+} |
+''', |
+ r''' |
+class A { |
+ A(); |
+ A.foo() { |
+ return new A(); |
+ } |
+} |
+'''); |
+ } |
+ |
+ void test_false_constructor_parameters_list_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ A(); |
+} |
+''', |
+ r''' |
+class A { |
+ A(int p); |
+} |
+'''); |
+ } |
+ |
+ void test_false_constructor_parameters_list_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ A(int p); |
+} |
+''', |
+ r''' |
+class A { |
+ A(); |
+} |
+'''); |
+ } |
+ |
+ void test_false_constructor_parameters_type_edit() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ A(int p); |
+} |
+''', |
+ r''' |
+class A { |
+ A(String p); |
+} |
+'''); |
+ } |
+ |
+ void test_false_constructor_unnamed_add_hadParameters() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+} |
+''', |
+ r''' |
+class A { |
+ A(int p) {} |
+} |
+'''); |
+ } |
+ |
+ void test_false_constructor_unnamed_remove_hadParameters() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ A(int p) {} |
+} |
+''', |
+ r''' |
+class A { |
+} |
+'''); |
+ } |
+ |
+ void test_false_defaultFieldFormalParameterElement_wasSimple() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ int field; |
+ A(int field); |
+} |
+''', |
+ r''' |
+class A { |
+ int field; |
+ A([this.field = 0]); |
+} |
+'''); |
+ } |
+ |
+ void test_false_enum_constants_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+enum E {A, B} |
+''', |
+ r''' |
+enum E {A, B, C} |
+'''); |
+ } |
+ |
+ void test_false_enum_constants_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+enum E {A, B, C} |
+''', |
+ r''' |
+enum E {A, B} |
+'''); |
+ } |
+ |
+ void test_false_export_hide_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+export 'dart:async' hide Future; |
+''', |
+ r''' |
+export 'dart:async' hide Future, Stream; |
+'''); |
+ } |
+ |
+ void test_false_export_hide_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+export 'dart:async' hide Future, Stream; |
+''', |
+ r''' |
+export 'dart:async' hide Future; |
+'''); |
+ } |
+ |
+ void test_false_export_list_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+export 'dart:async'; |
+''', |
+ r''' |
+export 'dart:async'; |
+export 'dart:math'; |
+'''); |
+ } |
+ |
+ void test_false_export_list_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+export 'dart:async'; |
+export 'dart:math'; |
+''', |
+ r''' |
+export 'dart:async'; |
+'''); |
+ } |
+ |
+ void test_false_export_show_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+export 'dart:async' show Future; |
+''', |
+ r''' |
+export 'dart:async' show Future, Stream; |
+'''); |
+ } |
+ |
+ void test_false_export_show_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+export 'dart:async' show Future, Stream; |
+''', |
+ r''' |
+export 'dart:async' show Future; |
+'''); |
+ } |
+ |
+ void test_false_extendsClause_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A {} |
+class B {} |
+''', |
+ r''' |
+class A {} |
+class B extends A {} |
+'''); |
+ } |
+ |
+ void test_false_extendsClause_different() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A {} |
+class B {} |
+class C extends A {} |
+''', |
+ r''' |
+class A {} |
+class B {} |
+class C extends B {} |
+'''); |
+ } |
+ |
+ void test_false_extendsClause_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A {} |
+class B extends A{} |
+''', |
+ r''' |
+class A {} |
+class B {} |
+'''); |
+ } |
+ |
+ void test_false_field_list_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+class T { |
+ int A = 1; |
+ int C = 3; |
+} |
+''', |
+ r''' |
+class T { |
+ int A = 1; |
+ int B = 2; |
+ int C = 3; |
+} |
+'''); |
+ } |
+ |
+ void test_false_field_list_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+class T { |
+ int A = 1; |
+ int B = 2; |
+ int C = 3; |
+} |
+''', |
+ r''' |
+class T { |
+ int A = 1; |
+ int C = 3; |
+} |
+'''); |
+ } |
+ |
+ void test_false_field_modifier_isConst() { |
+ _assertDoesNotMatch( |
+ r''' |
+class T { |
+ static final A = 1; |
+} |
+''', |
+ r''' |
+class T { |
+ static const A = 1; |
+} |
+'''); |
+ } |
+ |
+ void test_false_field_modifier_isFinal() { |
+ _assertDoesNotMatch( |
+ r''' |
+class T { |
+ int A = 1; |
+} |
+''', |
+ r''' |
+class T { |
+ final int A = 1; |
+} |
+'''); |
+ } |
+ |
+ void test_false_field_modifier_isStatic() { |
+ _assertDoesNotMatch( |
+ r''' |
+class T { |
+ int A = 1; |
+} |
+''', |
+ r''' |
+class T { |
+ static int A = 1; |
+} |
+'''); |
+ } |
+ |
+ void test_false_field_modifier_wasConst() { |
+ _assertDoesNotMatch( |
+ r''' |
+class T { |
+ static const A = 1; |
+} |
+''', |
+ r''' |
+class T { |
+ static final A = 1; |
+} |
+'''); |
+ } |
+ |
+ void test_false_field_modifier_wasFinal() { |
+ _assertDoesNotMatch( |
+ r''' |
+class T { |
+ final int A = 1; |
+} |
+''', |
+ r''' |
+class T { |
+ int A = 1; |
+} |
+'''); |
+ } |
+ |
+ void test_false_field_modifier_wasStatic() { |
+ _assertDoesNotMatch( |
+ r''' |
+class T { |
+ static int A = 1; |
+} |
+''', |
+ r''' |
+class T { |
+ int A = 1; |
+} |
+'''); |
+ } |
+ |
+ void test_false_field_type_differentArgs() { |
+ _assertDoesNotMatch( |
+ r''' |
+class T { |
+ List<int> A; |
+} |
+''', |
+ r''' |
+class T { |
+ List<String> A; |
+} |
+'''); |
+ } |
+ |
+ void test_false_fieldFormalParameter_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ final field; |
+ A(field); |
+} |
+''', |
+ r''' |
+class A { |
+ final field; |
+ A(this.field); |
+} |
+'''); |
+ } |
+ |
+ void test_false_fieldFormalParameter_add_function() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ final field; |
+ A(field(a)); |
+} |
+''', |
+ r''' |
+class A { |
+ final field; |
+ A(this.field(a)); |
+} |
+'''); |
+ } |
+ |
+ void test_false_fieldFormalParameter_differentField() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ final aaa; |
+ final bbb; |
+ A(this.aaa, this.bbb); |
+} |
+''', |
+ r''' |
+class A { |
+ final aaa; |
+ final bbb; |
+ A(this.bbb, this.aaa); |
+} |
+'''); |
+ } |
+ |
+ void test_false_fieldFormalParameter_parameters_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ final field; |
+ A(this.field(a)); |
+} |
+''', |
+ r''' |
+class A { |
+ final field; |
+ A(this.field(a, b)); |
+} |
+'''); |
+ } |
+ |
+ void test_false_fieldFormalParameter_parameters_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ final field; |
+ A(this.field(a, b)); |
+} |
+''', |
+ r''' |
+class A { |
+ final field; |
+ A(this.field(a)); |
+} |
+'''); |
+ } |
+ |
+ void test_false_fieldFormalParameter_parameters_typeEdit() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ final field; |
+ A(this.field(int p)); |
+} |
+''', |
+ r''' |
+class A { |
+ final field; |
+ A(this.field(String p)); |
+} |
+'''); |
+ } |
+ |
+ void test_false_fieldFormalParameter_remove_default() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ final field; |
+ A([this.field = 0]); |
+} |
+''', |
+ r''' |
+class A { |
+ final field; |
+ A([field = 0]); |
+} |
+'''); |
+ } |
+ |
+ void test_false_fieldFormalParameter_remove_function() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ final field; |
+ A(this.field(a)); |
+} |
+''', |
+ r''' |
+class A { |
+ final field; |
+ A(field(a)); |
+} |
+'''); |
+ } |
+ |
+ void test_false_fieldFormalParameter_remove_normal() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ final field; |
+ A(this.field); |
+} |
+''', |
+ r''' |
+class A { |
+ final field; |
+ A(field); |
+} |
+'''); |
+ } |
+ |
+ void test_false_fieldFormalParameter_typeAdd() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ final fff; |
+ A(this.fff); |
+} |
+''', |
+ r''' |
+class A { |
+ final fff; |
+ A(int this.fff); |
+} |
+'''); |
+ } |
+ |
+ void test_false_fieldFormalParameter_typeEdit() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ final fff; |
+ A(int this.fff); |
+} |
+''', |
+ r''' |
+class A { |
+ final fff; |
+ A(String this.fff); |
+} |
+'''); |
+ } |
+ |
+ void test_false_fieldFormalParameter_typeRemove() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ final fff; |
+ A(int this.fff); |
+} |
+''', |
+ r''' |
+class A { |
+ final fff; |
+ A(this.fff); |
+} |
+'''); |
+ } |
+ |
+ void test_false_fieldFormalParameterElement_wasSimple() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ int field; |
+ A(int field); |
+} |
+''', |
+ r''' |
+class A { |
+ int field; |
+ A(this.field); |
+} |
+'''); |
+ } |
+ |
+ void test_false_final_type_different() { |
+ _assertDoesNotMatch( |
+ r''' |
+class T { |
+ int A; |
+} |
+''', |
+ r''' |
+class T { |
+ String A; |
+} |
+'''); |
+ } |
+ |
+ void test_false_function_async_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+main() {} |
+''', |
+ r''' |
+main() async {} |
+'''); |
+ } |
+ |
+ void test_false_function_async_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+main() async {} |
+''', |
+ r''' |
+main() {} |
+'''); |
+ } |
+ |
+ void test_false_function_generator_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+main() async {} |
+''', |
+ r''' |
+main() async* {} |
+'''); |
+ } |
+ |
+ void test_false_function_generator_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+main() async* {} |
+''', |
+ r''' |
+main() async {} |
+'''); |
+ } |
+ |
+ void test_false_functionTypeAlias_list_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+typedef A(int pa); |
+typedef B(String pb); |
+''', |
+ r''' |
+typedef A(int pa); |
+typedef B(String pb); |
+typedef C(pc); |
+'''); |
+ } |
+ |
+ void test_false_functionTypeAlias_list_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+typedef A(int pa); |
+typedef B(String pb); |
+typedef C(pc); |
+''', |
+ r''' |
+typedef A(int pa); |
+typedef B(String pb); |
+'''); |
+ } |
+ |
+ void test_false_functionTypeAlias_parameters_list_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+typedef A(a); |
+''', |
+ r''' |
+typedef A(a, b); |
+'''); |
+ } |
+ |
+ void test_false_functionTypeAlias_parameters_list_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+typedef A(a, b); |
+''', |
+ r''' |
+typedef A(a); |
+'''); |
+ } |
+ |
+ void test_false_functionTypeAlias_parameters_type_edit() { |
+ _assertDoesNotMatch( |
+ r''' |
+typedef A(int p); |
+''', |
+ r''' |
+typedef A(String p); |
+'''); |
+ } |
+ |
+ void test_false_functionTypeAlias_returnType_edit() { |
+ _assertDoesNotMatch( |
+ r''' |
+typedef int A(); |
+''', |
+ r''' |
+typedef String A(); |
+'''); |
+ } |
+ |
+ void test_false_functionTypeAlias_typeParameters_bounds_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A {} |
+typedef F<T>(); |
+''', |
+ r''' |
+class A {} |
+typedef F<T extends A>(); |
+'''); |
+ } |
+ |
+ void test_false_functionTypeAlias_typeParameters_bounds_edit() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A {} |
+class B {} |
+typedef F<T extends A>(); |
+''', |
+ r''' |
+class A {} |
+typedef F<T extends B>(); |
+'''); |
+ } |
+ |
+ void test_false_functionTypeAlias_typeParameters_bounds_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A {} |
+typedef F<T extends A>(); |
+''', |
+ r''' |
+class A {} |
+typedef F<T>(); |
+'''); |
+ } |
+ |
+ void test_false_functionTypeAlias_typeParameters_list_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+typedef F<A>(); |
+''', |
+ r''' |
+typedef F<A, B>(); |
+'''); |
+ } |
+ |
+ void test_false_functionTypeAlias_typeParameters_list_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+typedef F<A, B>(); |
+''', |
+ r''' |
+typedef F<A>(); |
+'''); |
+ } |
+ |
+ void test_false_FunctionTypedFormalParameter_parameters_list_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+main(int callback(int a)) { |
+} |
+''', |
+ r''' |
+main(int callback(int a, String b)) { |
+} |
+'''); |
+ } |
+ |
+ void test_false_FunctionTypedFormalParameter_parameters_list_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+main(int callback(int a, String b)) { |
+} |
+''', |
+ r''' |
+main(int callback(int a)) { |
+} |
+'''); |
+ } |
+ |
+ void test_false_FunctionTypedFormalParameter_parameterType() { |
+ _assertDoesNotMatch( |
+ r''' |
+main(int callback(int p)) { |
+} |
+''', |
+ r''' |
+main(int callback(String p)) { |
+} |
+'''); |
+ } |
+ |
+ void test_false_FunctionTypedFormalParameter_returnType() { |
+ _assertDoesNotMatch( |
+ r''' |
+main(int callback()) { |
+} |
+''', |
+ r''' |
+main(String callback()) { |
+} |
+'''); |
+ } |
+ |
+ void test_false_FunctionTypedFormalParameter_wasSimple() { |
+ _assertDoesNotMatch( |
+ r''' |
+main(int callback) { |
+} |
+''', |
+ r''' |
+main(int callback(int a, String b)) { |
+} |
+'''); |
+ } |
+ |
+ void test_false_getter_body_add() { |
+ _assertDoesNotMatchOK( |
+ r''' |
+class A { |
+ int get foo; |
+} |
+''', |
+ r''' |
+class A { |
+ int get foo => 0; |
+} |
+'''); |
+ } |
+ |
+ void test_false_getter_body_remove() { |
+ _assertDoesNotMatchOK( |
+ r''' |
+class A { |
+ int get foo => 0; |
+} |
+''', |
+ r''' |
+class A { |
+ int get foo; |
+} |
+'''); |
+ } |
+ |
+ void test_false_implementsClause_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A {} |
+class B {} |
+''', |
+ r''' |
+class A {} |
+class B implements A {} |
+'''); |
+ } |
+ |
+ void test_false_implementsClause_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A {} |
+class B implements A {} |
+''', |
+ r''' |
+class A {} |
+class B {} |
+'''); |
+ } |
+ |
+ void test_false_implementsClause_reorder() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A {} |
+class B {} |
+class C implements A, B {} |
+''', |
+ r''' |
+class A {} |
+class B {} |
+class C implements B, A {} |
+'''); |
+ } |
+ |
+ void test_false_import_hide_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+import 'dart:async' hide Future; |
+''', |
+ r''' |
+import 'dart:async' hide Future, Stream; |
+'''); |
+ } |
+ |
+ void test_false_import_hide_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+import 'dart:async' hide Future, Stream; |
+''', |
+ r''' |
+import 'dart:async' hide Future; |
+'''); |
+ } |
+ |
+ void test_false_import_list_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+import 'dart:async'; |
+''', |
+ r''' |
+import 'dart:async'; |
+import 'dart:math'; |
+'''); |
+ } |
+ |
+ void test_false_import_list_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+import 'dart:async'; |
+import 'dart:math'; |
+''', |
+ r''' |
+import 'dart:async'; |
+'''); |
+ } |
+ |
+ void test_false_import_prefix_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+import 'dart:async'; |
+''', |
+ r''' |
+import 'dart:async' as async; |
+'''); |
+ } |
+ |
+ void test_false_import_prefix_edit() { |
+ _assertDoesNotMatch( |
+ r''' |
+import 'dart:async' as oldPrefix; |
+''', |
+ r''' |
+import 'dart:async' as newPrefix; |
+'''); |
+ } |
+ |
+ void test_false_import_prefix_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+import 'dart:async' as async; |
+''', |
+ r''' |
+import 'dart:async'; |
+'''); |
+ } |
+ |
+ void test_false_import_show_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+import 'dart:async' show Future; |
+''', |
+ r''' |
+import 'dart:async' show Future, Stream; |
+'''); |
+ } |
+ |
+ void test_false_import_show_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+import 'dart:async' show Future, Stream; |
+''', |
+ r''' |
+import 'dart:async' show Future; |
+'''); |
+ } |
+ |
+ void test_false_method_annotation_edit() { |
+ _assertDoesNotMatchOK( |
+ r''' |
+const my_annotationA = const Object(); |
+const my_annotationB = const Object(); |
+class A { |
+ @my_annotationA |
+ void m() {} |
+} |
+''', |
+ r''' |
+const my_annotationA = const Object(); |
+const my_annotationB = const Object(); |
+class A { |
+ @my_annotationB |
+ void m() {} |
+} |
+'''); |
+ } |
+ |
+ void test_false_method_annotations_add() { |
+ _assertDoesNotMatchOK( |
+ r''' |
+const my_annotation = const Object(); |
+class A { |
+ void m() {} |
+} |
+''', |
+ r''' |
+const my_annotation = const Object(); |
+class A { |
+ @my_annotation |
+ void m() {} |
+} |
+'''); |
+ } |
+ |
+ void test_false_method_annotations_remove() { |
+ _assertDoesNotMatchOK( |
+ r''' |
+const my_annotation = const Object(); |
+class A { |
+ @my_annotation |
+ void m() {} |
+} |
+''', |
+ r''' |
+const my_annotation = const Object(); |
+class A { |
+ void m() {} |
+} |
+'''); |
+ } |
+ |
+ void test_false_method_async_add() { |
+ _assertDoesNotMatchOK( |
+ r''' |
+class A { |
+ m() {} |
+} |
+''', |
+ r''' |
+class A { |
+ m() async {} |
+} |
+'''); |
+ } |
+ |
+ void test_false_method_async_remove() { |
+ _assertDoesNotMatchOK( |
+ r''' |
+class A { |
+ m() async {} |
+} |
+''', |
+ r''' |
+class A { |
+ m() {} |
+} |
+'''); |
+ } |
+ |
+ void test_false_method_body_add() { |
+ _assertDoesNotMatchOK( |
+ r''' |
+class A { |
+ void foo(); |
+} |
+''', |
+ r''' |
+class A { |
+ void foo() {} |
+} |
+'''); |
+ } |
+ |
+ void test_false_method_body_remove() { |
+ _assertDoesNotMatchOK( |
+ r''' |
+class A { |
+ void foo() {} |
+} |
+''', |
+ r''' |
+class A { |
+ void foo(); |
+} |
+'''); |
+ } |
+ |
+ void test_false_method_generator_add() { |
+ _assertDoesNotMatchOK( |
+ r''' |
+class A { |
+ m() async {} |
+} |
+''', |
+ r''' |
+class A { |
+ m() async* {} |
+} |
+'''); |
+ } |
+ |
+ void test_false_method_generator_remove() { |
+ _assertDoesNotMatchOK( |
+ r''' |
+class A { |
+ m() async* {} |
+} |
+''', |
+ r''' |
+class A { |
+ m() async {} |
+} |
+'''); |
+ } |
+ |
+ void test_false_method_list_add() { |
+ _assertDoesNotMatchOK( |
+ r''' |
+class A { |
+ a() {} |
+ b() {} |
+} |
+''', |
+ r''' |
+class A { |
+ a() {} |
+ b() {} |
+ c() {} |
+} |
+'''); |
+ } |
+ |
+ void test_false_method_list_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A { |
+ a() {} |
+ b() {} |
+ c() {} |
+} |
+''', |
+ r''' |
+class A { |
+ a() {} |
+ b() {} |
+} |
+'''); |
+ } |
+ |
+ void test_false_method_parameters_type_edit() { |
+ _assertDoesNotMatchOK( |
+ r''' |
+class A { |
+ m(int p) { |
+ } |
+} |
+''', |
+ r''' |
+class A { |
+ m(String p) { |
+ } |
+} |
+'''); |
+ } |
+ |
+ void test_false_method_parameters_type_edit_insertImportPrefix() { |
+ _assertDoesNotMatchOK( |
+ r''' |
+import 'dart:async' as a; |
+ |
+class C { |
+ void foo(Future f) {} |
+} |
+ |
+class Future {} |
+ |
+bar(C c, a.Future f) { |
+ c.foo(f); |
+} |
+''', |
+ r''' |
+import 'dart:async' as a; |
+ |
+class C { |
+ void foo(a.Future f) {} |
+} |
+ |
+class Future {} |
+ |
+bar(C c, a.Future f) { |
+ c.foo(f); |
+} |
+'''); |
+ } |
+ |
+ void test_false_method_returnType_edit() { |
+ _assertDoesNotMatchOK( |
+ r''' |
+class A { |
+ int m() {} |
+} |
+''', |
+ r''' |
+class A { |
+ String m() {} |
+} |
+'''); |
+ } |
+ |
+ void test_false_part_list_add() { |
+ addNamedSource('/unitA.dart', 'part of lib; class A {}'); |
+ addNamedSource('/unitB.dart', 'part of lib; class B {}'); |
+ _assertDoesNotMatch( |
+ r''' |
+library lib; |
+part 'unitA.dart'; |
+''', |
+ r''' |
+library lib; |
+part 'unitA.dart'; |
+part 'unitB.dart'; |
+'''); |
+ } |
+ |
+ void test_false_part_list_remove() { |
+ addNamedSource('/unitA.dart', 'part of lib; class A {}'); |
+ addNamedSource('/unitB.dart', 'part of lib; class B {}'); |
+ _assertDoesNotMatch( |
+ r''' |
+library lib; |
+part 'unitA.dart'; |
+part 'unitB.dart'; |
+''', |
+ r''' |
+library lib; |
+part 'unitA.dart'; |
+'''); |
+ } |
+ |
+ void test_false_SimpleFormalParameter_named_differentName() { |
+ _assertDoesNotMatch( |
+ r''' |
+main({int oldName}) { |
+} |
+''', |
+ r''' |
+main({int newName}) { |
+} |
+'''); |
+ } |
+ |
+ void test_false_SimpleFormalParameter_namedDefault_addValue() { |
+ _assertDoesNotMatch( |
+ r''' |
+main({int p}) { |
+} |
+''', |
+ r''' |
+main({int p: 2}) { |
+} |
+'''); |
+ } |
+ |
+ void test_false_SimpleFormalParameter_namedDefault_differentValue() { |
+ _assertDoesNotMatch( |
+ r''' |
+main({int p: 1}) { |
+} |
+''', |
+ r''' |
+main({int p: 2}) { |
+} |
+'''); |
+ } |
+ |
+ void test_false_SimpleFormalParameter_namedDefault_removeValue() { |
+ _assertDoesNotMatch( |
+ r''' |
+main({int p: 1}) { |
+} |
+''', |
+ r''' |
+main({int p}) { |
+} |
+'''); |
+ } |
+ |
+ void test_false_SimpleFormalParameter_optionalDefault_addValue() { |
+ _assertDoesNotMatch( |
+ r''' |
+main([int p]) { |
+} |
+''', |
+ r''' |
+main([int p = 2]) { |
+} |
+'''); |
+ } |
+ |
+ void test_false_SimpleFormalParameter_optionalDefault_differentValue() { |
+ _assertDoesNotMatch( |
+ r''' |
+main([int p = 1]) { |
+} |
+''', |
+ r''' |
+main([int p = 2]) { |
+} |
+'''); |
+ } |
+ |
+ void test_false_SimpleFormalParameter_optionalDefault_removeValue() { |
+ _assertDoesNotMatch( |
+ r''' |
+main([int p = 1]) { |
+} |
+''', |
+ r''' |
+main([int p]) { |
+} |
+'''); |
+ } |
+ |
+ void test_false_topLevelAccessor_list_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+get a => 1; |
+get b => 2; |
+''', |
+ r''' |
+get a => 1; |
+get b => 2; |
+get c => 3; |
+'''); |
+ } |
+ |
+ void test_false_topLevelAccessor_list_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+get a => 1; |
+get b => 2; |
+get c => 3; |
+''', |
+ r''' |
+get a => 1; |
+get b => 2; |
+'''); |
+ } |
+ |
+ void test_false_topLevelAccessor_wasGetter() { |
+ _assertDoesNotMatch( |
+ r''' |
+get a => 1; |
+''', |
+ r''' |
+set a(x) {} |
+'''); |
+ } |
+ |
+ void test_false_topLevelAccessor_wasSetter() { |
+ _assertDoesNotMatch( |
+ r''' |
+set a(x) {} |
+''', |
+ r''' |
+get a => 1; |
+'''); |
+ } |
+ |
+ void test_false_topLevelFunction_list_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+a() {} |
+b() {} |
+''', |
+ r''' |
+a() {} |
+b() {} |
+c() {} |
+'''); |
+ } |
+ |
+ void test_false_topLevelFunction_list_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+a() {} |
+b() {} |
+c() {} |
+''', |
+ r''' |
+a() {} |
+b() {} |
+'''); |
+ } |
+ |
+ void test_false_topLevelFunction_parameters_list_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+main(int a, int b) { |
+} |
+''', |
+ r''' |
+main(int a, int b, int c) { |
+} |
+'''); |
+ } |
+ |
+ void test_false_topLevelFunction_parameters_list_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+main(int a, int b, int c) { |
+} |
+''', |
+ r''' |
+main(int a, int b) { |
+} |
+'''); |
+ } |
+ |
+ void test_false_topLevelFunction_parameters_type_edit() { |
+ _assertDoesNotMatch( |
+ r''' |
+main(int a, int b, int c) { |
+} |
+''', |
+ r''' |
+main(int a, String b, int c) { |
+} |
+'''); |
+ } |
+ |
+ void test_false_topLevelFunction_returnType_edit() { |
+ _assertDoesNotMatch( |
+ r''' |
+int a() {} |
+''', |
+ r''' |
+String a() {} |
+'''); |
+ } |
+ |
+ void test_false_topLevelVariable_list_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+const int A = 1; |
+const int C = 3; |
+''', |
+ r''' |
+const int A = 1; |
+const int B = 2; |
+const int C = 3; |
+'''); |
+ } |
+ |
+ void test_false_topLevelVariable_list_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+const int A = 1; |
+const int B = 2; |
+const int C = 3; |
+''', |
+ r''' |
+const int A = 1; |
+const int C = 3; |
+'''); |
+ } |
+ |
+ void test_false_topLevelVariable_modifier_isConst() { |
+ _assertDoesNotMatch( |
+ r''' |
+final int A = 1; |
+''', |
+ r''' |
+const int A = 1; |
+'''); |
+ } |
+ |
+ void test_false_topLevelVariable_modifier_isFinal() { |
+ _assertDoesNotMatch( |
+ r''' |
+int A = 1; |
+''', |
+ r''' |
+final int A = 1; |
+'''); |
+ } |
+ |
+ void test_false_topLevelVariable_modifier_wasConst() { |
+ _assertDoesNotMatch( |
+ r''' |
+const int A = 1; |
+''', |
+ r''' |
+final int A = 1; |
+'''); |
+ } |
+ |
+ void test_false_topLevelVariable_modifier_wasFinal() { |
+ _assertDoesNotMatch( |
+ r''' |
+final int A = 1; |
+''', |
+ r''' |
+int A = 1; |
+'''); |
+ } |
+ |
+ void test_false_topLevelVariable_synthetic_wasGetter() { |
+ _assertDoesNotMatch( |
+ r''' |
+int get A => 1; |
+''', |
+ r''' |
+final int A = 1; |
+'''); |
+ } |
+ |
+ void test_false_topLevelVariable_type_different() { |
+ _assertDoesNotMatch( |
+ r''' |
+int A; |
+''', |
+ r''' |
+String A; |
+'''); |
+ } |
+ |
+ void test_false_topLevelVariable_type_differentArgs() { |
+ _assertDoesNotMatch( |
+ r''' |
+List<int> A; |
+''', |
+ r''' |
+List<String> A; |
+'''); |
+ } |
+ |
+ void test_false_type_noTypeArguments_hadTypeArguments() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A<T> {} |
+A<int> main() { |
+} |
+''', |
+ r''' |
+class A<T> {} |
+A main() { |
+} |
+'''); |
+ } |
+ |
+ void test_false_withClause_add() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A {} |
+class B {} |
+''', |
+ r''' |
+class A {} |
+class B extends Object with A {} |
+'''); |
+ } |
+ |
+ void test_false_withClause_remove() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A {} |
+class B extends Object with A {} |
+''', |
+ r''' |
+class A {} |
+class B {} |
+'''); |
+ } |
+ |
+ void test_false_withClause_reorder() { |
+ _assertDoesNotMatch( |
+ r''' |
+class A {} |
+class B {} |
+class C extends Object with A, B {} |
+''', |
+ r''' |
+class A {} |
+class B {} |
+class C extends Object with B, A {} |
+'''); |
+ } |
+ |
+ void test_true_class_annotations_same() { |
+ _assertMatches( |
+ r''' |
+const my_annotation = const Object(); |
+@my_annotation |
+class A { |
+} |
+''', |
+ r''' |
+const my_annotation = const Object(); |
+@my_annotation |
+class A { |
+} |
+'''); |
+ } |
+ |
+ void test_true_class_list_reorder() { |
+ _assertMatches( |
+ r''' |
+class A {} |
+class B {} |
+class C {} |
+''', |
+ r''' |
+class C {} |
+class A {} |
+class B {} |
+'''); |
+ } |
+ |
+ void test_true_class_list_same() { |
+ _assertMatches( |
+ r''' |
+class A {} |
+class B {} |
+class C {} |
+''', |
+ r''' |
+class A {} |
+class B {} |
+class C {} |
+'''); |
+ } |
+ |
+ void test_true_class_typeParameters_same() { |
+ _assertMatches( |
+ r''' |
+class A<T> {} |
+''', |
+ r''' |
+class A<T> {} |
+'''); |
+ } |
+ |
+ void test_true_classMemberAccessor_getterSetter() { |
+ _assertMatches( |
+ r''' |
+class A { |
+ int _test; |
+ get test => _test; |
+ set test(v) { |
+ _test = v; |
+ } |
+} |
+''', |
+ r''' |
+class A { |
+ int _test; |
+ get test => _test; |
+ set test(v) { |
+ _test = v; |
+ } |
+} |
+'''); |
+ } |
+ |
+ void test_true_classMemberAccessor_list_reorder() { |
+ _assertMatches( |
+ r''' |
+class A { |
+ get a => 1; |
+ get b => 2; |
+ get c => 3; |
+} |
+''', |
+ r''' |
+class A { |
+ get c => 3; |
+ get a => 1; |
+ get b => 2; |
+} |
+'''); |
+ } |
+ |
+ void test_true_classMemberAccessor_list_same() { |
+ _assertMatches( |
+ r''' |
+class A { |
+ get a => 1; |
+ get b => 2; |
+ get c => 3; |
+} |
+''', |
+ r''' |
+class A { |
+ get a => 1; |
+ get b => 2; |
+ get c => 3; |
+} |
+'''); |
+ } |
+ |
+ void test_true_classTypeAlias_list_reorder() { |
+ _assertMatches( |
+ r''' |
+class M {} |
+class A = Object with M; |
+class B = Object with M; |
+class C = Object with M; |
+''', |
+ r''' |
+class M {} |
+class C = Object with M; |
+class A = Object with M; |
+class B = Object with M; |
+'''); |
+ } |
+ |
+ void test_true_classTypeAlias_list_same() { |
+ _assertMatches( |
+ r''' |
+class M {} |
+class A = Object with M; |
+class B = Object with M; |
+class C = Object with M; |
+''', |
+ r''' |
+class M {} |
+class A = Object with M; |
+class B = Object with M; |
+class C = Object with M; |
+'''); |
+ } |
+ |
+ void test_true_classTypeAlias_typeParameters_same() { |
+ _assertMatches( |
+ r''' |
+class M<T> {} |
+class A<T> {} |
+class B<T> = A<T> with M<T>; |
+''', |
+ r''' |
+class M<T> {} |
+class A<T> {} |
+class B<T> = A<T> with M<T>; |
+'''); |
+ } |
+ |
+ void test_true_constructor_body_add() { |
+ _assertMatches( |
+ r''' |
+class A { |
+ A(int p); |
+} |
+''', |
+ r''' |
+class A { |
+ A(int p) {} |
+} |
+'''); |
+ } |
+ |
+ void test_true_constructor_body_remove() { |
+ _assertMatches( |
+ r''' |
+class A { |
+ A(int p) {} |
+} |
+''', |
+ r''' |
+class A { |
+ A(int p); |
+} |
+'''); |
+ } |
+ |
+ void test_true_constructor_named_same() { |
+ _assertMatches( |
+ r''' |
+class A { |
+ A.name(int p); |
+} |
+''', |
+ r''' |
+class A { |
+ A.name(int p); |
+} |
+'''); |
+ } |
+ |
+ void test_true_constructor_unnamed_add_noParameters() { |
+ _assertMatches( |
+ r''' |
+class A { |
+} |
+''', |
+ r''' |
+class A { |
+ A() {} |
+} |
+'''); |
+ } |
+ |
+ void test_true_constructor_unnamed_remove_noParameters() { |
+ _assertMatches( |
+ r''' |
+class A { |
+ A() {} |
+} |
+''', |
+ r''' |
+class A { |
+} |
+'''); |
+ } |
+ |
+ void test_true_constructor_unnamed_same() { |
+ _assertMatches( |
+ r''' |
+class A { |
+ A(int p); |
+} |
+''', |
+ r''' |
+class A { |
+ A(int p); |
+} |
+'''); |
+ } |
+ |
+ void test_true_defaultFieldFormalParameterElement() { |
+ _assertMatches( |
+ r''' |
+class A { |
+ int field; |
+ A([this.field = 0]); |
+} |
+''', |
+ r''' |
+class A { |
+ int field; |
+ A([this.field = 0]); |
+} |
+'''); |
+ } |
+ |
+ void test_true_enum_constants_reorder() { |
+ _assertMatches( |
+ r''' |
+enum E {A, B, C} |
+''', |
+ r''' |
+enum E {C, A, B} |
+'''); |
+ } |
+ |
+ void test_true_enum_list_reorder() { |
+ _assertMatches( |
+ r''' |
+enum A {A1, A2, A3} |
+enum B {B1, B2, B3} |
+enum C {C1, C2, C3} |
+''', |
+ r''' |
+enum C {C1, C2, C3} |
+enum A {A1, A2, A3} |
+enum B {B1, B2, B3} |
+'''); |
+ } |
+ |
+ void test_true_enum_list_same() { |
+ _assertMatches( |
+ r''' |
+enum A {A1, A2, A3} |
+enum B {B1, B2, B3} |
+enum C {C1, C2, C3} |
+''', |
+ r''' |
+enum A {A1, A2, A3} |
+enum B {B1, B2, B3} |
+enum C {C1, C2, C3} |
+'''); |
+ } |
+ |
+ void test_true_executable_same_hasLabel() { |
+ _assertMatches( |
+ r''' |
+main() { |
+ label: return 42; |
+} |
+''', |
+ r''' |
+main() { |
+ label: return 42; |
+} |
+'''); |
+ } |
+ |
+ void test_true_executable_same_hasLocalVariable() { |
+ _assertMatches( |
+ r''' |
+main() { |
+ int a = 42; |
+} |
+''', |
+ r''' |
+main() { |
+ int a = 42; |
+} |
+'''); |
+ } |
+ |
+ void test_true_export_hide_reorder() { |
+ _assertMatches( |
+ r''' |
+export 'dart:async' hide Future, Stream; |
+''', |
+ r''' |
+export 'dart:async' hide Stream, Future; |
+'''); |
+ } |
+ |
+ void test_true_export_list_reorder() { |
+ _assertMatches( |
+ r''' |
+export 'dart:async'; |
+export 'dart:math'; |
+''', |
+ r''' |
+export 'dart:math'; |
+export 'dart:async'; |
+'''); |
+ } |
+ |
+ void test_true_export_list_same() { |
+ _assertMatches( |
+ r''' |
+export 'dart:async'; |
+export 'dart:math'; |
+''', |
+ r''' |
+export 'dart:async'; |
+export 'dart:math'; |
+'''); |
+ } |
+ |
+ void test_true_export_show_reorder() { |
+ _assertMatches( |
+ r''' |
+export 'dart:async' show Future, Stream; |
+''', |
+ r''' |
+export 'dart:async' show Stream, Future; |
+'''); |
+ } |
+ |
+ void test_true_extendsClause_same() { |
+ _assertMatches( |
+ r''' |
+class A {} |
+class B extends A {} |
+''', |
+ r''' |
+class A {} |
+class B extends A {} |
+'''); |
+ } |
+ |
+ void test_true_field_list_reorder() { |
+ _assertMatches( |
+ r''' |
+class T { |
+ int A = 1; |
+ int B = 2; |
+ int C = 3; |
+} |
+''', |
+ r''' |
+class T { |
+ int C = 3; |
+ int A = 1; |
+ int B = 2; |
+} |
+'''); |
+ } |
+ |
+ void test_true_field_list_same() { |
+ _assertMatches( |
+ r''' |
+class T { |
+ int A = 1; |
+ int B = 2; |
+ int C = 3; |
+} |
+''', |
+ r''' |
+class T { |
+ int A = 1; |
+ int B = 2; |
+ int C = 3; |
+} |
+'''); |
+ } |
+ |
+ void test_true_fieldFormalParameter() { |
+ _assertMatches( |
+ r''' |
+class A { |
+ int field; |
+ A(this.field); |
+} |
+''', |
+ r''' |
+class A { |
+ int field; |
+ A(this.field); |
+} |
+'''); |
+ } |
+ |
+ void test_true_fieldFormalParameter_changeName_wasUnresolvedField() { |
+ _assertMatches( |
+ r''' |
+class A { |
+ final fff; |
+ A(this.unresolved); |
+} |
+''', |
+ r''' |
+class A { |
+ final fff; |
+ A(this.fff); |
+} |
+'''); |
+ } |
+ |
+ void test_true_fieldFormalParameter_function() { |
+ _assertMatches( |
+ r''' |
+class A { |
+ final field; |
+ A(this.field(int a, String b)); |
+} |
+''', |
+ r''' |
+class A { |
+ final field; |
+ A(this.field(int a, String b)); |
+} |
+'''); |
+ } |
+ |
+ void test_true_functionTypeAlias_list_reorder() { |
+ _assertMatches( |
+ r''' |
+typedef A(int pa); |
+typedef B(String pb); |
+typedef C(pc); |
+''', |
+ r''' |
+typedef C(pc); |
+typedef A(int pa); |
+typedef B(String pb); |
+'''); |
+ } |
+ |
+ void test_true_functionTypeAlias_list_same() { |
+ _assertMatches( |
+ r''' |
+typedef String A(int pa); |
+typedef int B(String pb); |
+typedef C(pc); |
+''', |
+ r''' |
+typedef String A(int pa); |
+typedef int B(String pb); |
+typedef C(pc); |
+'''); |
+ } |
+ |
+ void test_true_functionTypeAlias_typeParameters_list_same() { |
+ _assertMatches( |
+ r''' |
+typedef F<A, B, C>(); |
+''', |
+ r''' |
+typedef F<A, B, C>(); |
+'''); |
+ } |
+ |
+ void test_true_FunctionTypedFormalParameter() { |
+ _assertMatches( |
+ r''' |
+main(int callback(int a, String b)) { |
+} |
+''', |
+ r''' |
+main(int callback(int a, String b)) { |
+} |
+'''); |
+ } |
+ |
+ void test_true_implementsClause_same() { |
+ _assertMatches( |
+ r''' |
+class A {} |
+class B implements A {} |
+''', |
+ r''' |
+class A {} |
+class B implements A {} |
+'''); |
+ } |
+ |
+ void test_true_import_hide_reorder() { |
+ _assertMatches( |
+ r''' |
+import 'dart:async' hide Future, Stream; |
+''', |
+ r''' |
+import 'dart:async' hide Stream, Future; |
+'''); |
+ } |
+ |
+ void test_true_import_list_reorder() { |
+ _assertMatches( |
+ r''' |
+import 'dart:async'; |
+import 'dart:math'; |
+''', |
+ r''' |
+import 'dart:math'; |
+import 'dart:async'; |
+'''); |
+ } |
+ |
+ void test_true_import_list_same() { |
+ _assertMatches( |
+ r''' |
+import 'dart:async'; |
+import 'dart:math'; |
+''', |
+ r''' |
+import 'dart:async'; |
+import 'dart:math'; |
+'''); |
+ } |
+ |
+ void test_true_import_prefix() { |
+ _assertMatches( |
+ r''' |
+import 'dart:async' as async; |
+''', |
+ r''' |
+import 'dart:async' as async; |
+'''); |
+ } |
+ |
+ void test_true_import_show_reorder() { |
+ _assertMatches( |
+ r''' |
+import 'dart:async' show Future, Stream; |
+''', |
+ r''' |
+import 'dart:async' show Stream, Future; |
+'''); |
+ } |
+ |
+ void test_true_method_annotation_accessor_same() { |
+ _assertMatches( |
+ r''' |
+const my_annotation = const Object(); |
+class A { |
+ @my_annotation |
+ void m() {} |
+} |
+''', |
+ r''' |
+const my_annotation = const Object(); |
+class A { |
+ @my_annotation |
+ void m() {} |
+} |
+'''); |
+ } |
+ |
+ void test_true_method_annotation_constructor_same() { |
+ _assertMatches( |
+ r''' |
+class MyAnnotation { |
+ const MyAnnotation(); |
+} |
+class A { |
+ @MyAnnotation() |
+ void m() {} |
+} |
+''', |
+ r''' |
+class MyAnnotation { |
+ const MyAnnotation(); |
+} |
+class A { |
+ @MyAnnotation() |
+ void m() {} |
+} |
+'''); |
+ } |
+ |
+ void test_true_method_async() { |
+ _assertMatches( |
+ r''' |
+class A { |
+ m() async {} |
+} |
+''', |
+ r''' |
+class A { |
+ m() async {} |
+} |
+'''); |
+ } |
+ |
+ void test_true_method_list_reorder() { |
+ _assertMatches( |
+ r''' |
+class A { |
+ a() {} |
+ b() {} |
+ c() {} |
+} |
+''', |
+ r''' |
+class A { |
+ c() {} |
+ a() {} |
+ b() {} |
+} |
+'''); |
+ } |
+ |
+ void test_true_method_list_same() { |
+ _assertMatches( |
+ r''' |
+class A { |
+ a() {} |
+ b() {} |
+ c() {} |
+} |
+''', |
+ r''' |
+class A { |
+ a() {} |
+ b() {} |
+ c() {} |
+} |
+'''); |
+ } |
+ |
+ void test_true_method_operator_minus() { |
+ _assertMatches( |
+ r''' |
+class A { |
+ operator -(other) {} |
+} |
+''', |
+ r''' |
+class A { |
+ operator -(other) {} |
+} |
+'''); |
+ } |
+ |
+ void test_true_method_operator_minusUnary() { |
+ _assertMatches( |
+ r''' |
+class A { |
+ operator -() {} |
+} |
+''', |
+ r''' |
+class A { |
+ operator -() {} |
+} |
+'''); |
+ } |
+ |
+ void test_true_method_operator_plus() { |
+ _assertMatches( |
+ r''' |
+class A { |
+ operator +(other) {} |
+} |
+''', |
+ r''' |
+class A { |
+ operator +(other) {} |
+} |
+'''); |
+ } |
+ |
+ void test_true_method_parameters_type_functionType() { |
+ _assertMatches( |
+ r''' |
+typedef F(); |
+class A { |
+ m(F p) {} |
+} |
+''', |
+ r''' |
+typedef F(); |
+class A { |
+ m(F p) {} |
+} |
+'''); |
+ } |
+ |
+ void test_true_method_parameters_type_sameImportPrefix() { |
+ _assertMatches( |
+ r''' |
+import 'dart:async' as a; |
+ |
+bar(a.Future f) { |
+ print(f); |
+} |
+''', |
+ r''' |
+import 'dart:async' as a; |
+ |
+bar(a.Future ff) { |
+ print(ff); |
+} |
+'''); |
+ } |
+ |
+ void test_true_part_list_reorder() { |
+ addNamedSource('/unitA.dart', 'part of lib; class A {}'); |
+ addNamedSource('/unitB.dart', 'part of lib; class B {}'); |
+ _assertMatches( |
+ r''' |
+library lib; |
+part 'unitA.dart'; |
+part 'unitB.dart'; |
+''', |
+ r''' |
+library lib; |
+part 'unitB.dart'; |
+part 'unitA.dart'; |
+'''); |
+ } |
+ |
+ void test_true_part_list_same() { |
+ addNamedSource('/unitA.dart', 'part of lib; class A {}'); |
+ addNamedSource('/unitB.dart', 'part of lib; class B {}'); |
+ _assertMatches( |
+ r''' |
+library lib; |
+part 'unitA.dart'; |
+part 'unitB.dart'; |
+''', |
+ r''' |
+library lib; |
+part 'unitA.dart'; |
+part 'unitB.dart'; |
+'''); |
+ } |
+ |
+ void test_true_SimpleFormalParameter_optional_differentName() { |
+ _assertMatches( |
+ r''' |
+main([int oldName]) { |
+} |
+''', |
+ r''' |
+main([int newName]) { |
+} |
+'''); |
+ } |
+ |
+ void test_true_SimpleFormalParameter_optionalDefault_differentName() { |
+ _assertMatches( |
+ r''' |
+main([int oldName = 1]) { |
+} |
+''', |
+ r''' |
+main([int newName = 1]) { |
+} |
+'''); |
+ } |
+ |
+ void test_true_SimpleFormalParameter_required_differentName() { |
+ _assertMatches( |
+ r''' |
+main(int oldName) { |
+} |
+''', |
+ r''' |
+main(int newName) { |
+} |
+'''); |
+ } |
+ |
+ void test_true_topLevelAccessor_list_reorder() { |
+ _assertMatches( |
+ r''' |
+set a(x) {} |
+set b(x) {} |
+set c(x) {} |
+''', |
+ r''' |
+set c(x) {} |
+set a(x) {} |
+set b(x) {} |
+'''); |
+ } |
+ |
+ void test_true_topLevelAccessor_list_same() { |
+ _assertMatches( |
+ r''' |
+get a => 1; |
+get b => 2; |
+get c => 3; |
+''', |
+ r''' |
+get a => 1; |
+get b => 2; |
+get c => 3; |
+'''); |
+ } |
+ |
+ void test_true_topLevelFunction_list_reorder() { |
+ _assertMatches( |
+ r''' |
+a() {} |
+b() {} |
+c() {} |
+''', |
+ r''' |
+c() {} |
+a() {} |
+b() {} |
+'''); |
+ } |
+ |
+ void test_true_topLevelFunction_list_same() { |
+ _assertMatches( |
+ r''' |
+a() {} |
+b() {} |
+c() {} |
+''', |
+ r''' |
+a() {} |
+b() {} |
+c() {} |
+'''); |
+ } |
+ |
+ void test_true_topLevelVariable_list_reorder() { |
+ _assertMatches( |
+ r''' |
+const int A = 1; |
+const int B = 2; |
+const int C = 3; |
+''', |
+ r''' |
+const int C = 3; |
+const int A = 1; |
+const int B = 2; |
+'''); |
+ } |
+ |
+ void test_true_topLevelVariable_list_same() { |
+ _assertMatches( |
+ r''' |
+const int A = 1; |
+const int B = 2; |
+const int C = 3; |
+''', |
+ r''' |
+const int A = 1; |
+const int B = 2; |
+const int C = 3; |
+'''); |
+ } |
+ |
+ void test_true_topLevelVariable_type_sameArgs() { |
+ _assertMatches( |
+ r''' |
+Map<int, String> A; |
+''', |
+ r''' |
+Map<int, String> A; |
+'''); |
+ } |
+ |
+ void test_true_type_dynamic() { |
+ _assertMatches( |
+ r''' |
+dynamic a() {} |
+''', |
+ r''' |
+dynamic a() {} |
+'''); |
+ } |
+ |
+ void test_true_type_hasImportPrefix() { |
+ _assertMatches( |
+ r''' |
+import 'dart:async' as async; |
+async.Future F; |
+''', |
+ r''' |
+import 'dart:async' as async; |
+async.Future F; |
+'''); |
+ } |
+ |
+ void test_true_type_noTypeArguments_implyAllDynamic() { |
+ _assertMatches( |
+ r''' |
+class A<T> {} |
+A main() { |
+} |
+''', |
+ r''' |
+class A<T> {} |
+A main() { |
+} |
+'''); |
+ } |
+ |
+ void test_true_type_void() { |
+ _assertMatches( |
+ r''' |
+void a() {} |
+''', |
+ r''' |
+void a() {} |
+'''); |
+ } |
+ |
+ void test_true_withClause_same() { |
+ _assertMatches( |
+ r''' |
+class A {} |
+class B extends Object with A {} |
+''', |
+ r''' |
+class A {} |
+class B extends Object with A {} |
+'''); |
+ } |
+ |
+ void _assertDoesNotMatch(String oldContent, String newContent) { |
+ _assertMatchKind(DeclarationMatchKind.MISMATCH, oldContent, newContent); |
+ } |
+ |
+ void _assertDoesNotMatchOK(String oldContent, String newContent) { |
+ _assertMatchKind(DeclarationMatchKind.MISMATCH_OK, oldContent, newContent); |
+ } |
+ |
+ void _assertMatches(String oldContent, String newContent) { |
+ _assertMatchKind(DeclarationMatchKind.MATCH, oldContent, newContent); |
+ } |
+ |
+ void _assertMatchKind( |
+ DeclarationMatchKind expectMatch, String oldContent, String newContent) { |
+ Source source = addSource(oldContent); |
+ LibraryElement library = resolve2(source); |
+ CompilationUnit oldUnit = resolveCompilationUnit(source, library); |
+ // parse |
+ CompilationUnit newUnit = ParserTestCase.parseCompilationUnit(newContent); |
+ // build elements |
+ { |
+ ElementHolder holder = new ElementHolder(); |
+ ElementBuilder builder = new ElementBuilder(holder); |
+ newUnit.accept(builder); |
+ } |
+ // match |
+ DeclarationMatcher matcher = new DeclarationMatcher(); |
+ DeclarationMatchKind matchKind = matcher.matches(newUnit, oldUnit.element); |
+ expect(matchKind, same(expectMatch)); |
+ } |
+} |
+ |
+@reflectiveTest |
+class IncrementalResolverTest extends ResolverTestCase { |
+ Source source; |
+ String code; |
+ LibraryElement library; |
+ CompilationUnit unit; |
+ |
+ @override |
+ void reset() { |
+ if (AnalysisEngine.instance.useTaskModel) { |
+ analysisContext2 = AnalysisContextFactory.contextWithCore(); |
+ } else { |
+ analysisContext2 = AnalysisContextFactory.oldContextWithCore(); |
+ } |
+ } |
+ |
+ @override |
+ void resetWithOptions(AnalysisOptions options) { |
+ if (AnalysisEngine.instance.useTaskModel) { |
+ analysisContext2 = |
+ AnalysisContextFactory.contextWithCoreAndOptions(options); |
+ } else { |
+ analysisContext2 = |
+ AnalysisContextFactory.oldContextWithCoreAndOptions(options); |
+ } |
+ } |
+ |
+ void setUp() { |
+ super.setUp(); |
+ test_resolveApiChanges = true; |
+ log.logger = log.NULL_LOGGER; |
+ } |
+ |
+ void test_classMemberAccessor_body() { |
+ _resolveUnit(r''' |
+class A { |
+ int get test { |
+ return 1 + 2; |
+ } |
+}'''); |
+ _resolve(_editString('+', '*'), _isFunctionBody); |
+ } |
+ |
+ void test_constructor_body() { |
+ _resolveUnit(r''' |
+class A { |
+ int f; |
+ A(int a, int b) { |
+ f = a + b; |
+ } |
+}'''); |
+ _resolve(_editString('+', '*'), _isFunctionBody); |
+ } |
+ |
+ void test_constructor_fieldInitializer_add() { |
+ _resolveUnit(r''' |
+class A { |
+ int f; |
+ A(int a, int b); |
+}'''); |
+ _resolve(_editString(');', ') : f = a + b;'), _isClassMember); |
+ } |
+ |
+ void test_constructor_fieldInitializer_edit() { |
+ _resolveUnit(r''' |
+class A { |
+ int f; |
+ A(int a, int b) : f = a + b { |
+ int a = 42; |
+ } |
+}'''); |
+ _resolve(_editString('+', '*'), _isExpression); |
+ } |
+ |
+ void test_constructor_label_add() { |
+ _resolveUnit(r''' |
+class A { |
+ A() { |
+ return 42; |
+ } |
+} |
+'''); |
+ _resolve(_editString('return', 'label: return'), _isBlock); |
+ } |
+ |
+ void test_constructor_localVariable_add() { |
+ _resolveUnit(r''' |
+class A { |
+ A() { |
+ 42; |
+ } |
+} |
+'''); |
+ _resolve(_editString('42;', 'var res = 42;'), _isBlock); |
+ } |
+ |
+ void test_constructor_superConstructorInvocation() { |
+ _resolveUnit(r''' |
+class A { |
+ A(int p); |
+} |
+class B extends A { |
+ B(int a, int b) : super(a + b); |
+} |
+'''); |
+ _resolve(_editString('+', '*'), _isExpression); |
+ } |
+ |
+ void test_fieldFormalParameter() { |
+ _resolveUnit(r''' |
+class A { |
+ int xy; |
+ A(this.x); |
+}'''); |
+ _resolve(_editString('this.x', 'this.xy'), _isDeclaration); |
+ } |
+ |
+ void test_function_localFunction_add() { |
+ _resolveUnit(r''' |
+int main() { |
+ return 0; |
+} |
+callIt(f) {} |
+'''); |
+ _resolve(_editString('return 0;', 'callIt((p) {});'), _isBlock); |
+ } |
+ |
+ void test_functionBody_body() { |
+ _resolveUnit(r''' |
+main(int a, int b) { |
+ return a + b; |
+}'''); |
+ _resolve(_editString('+', '*'), _isFunctionBody); |
+ } |
+ |
+ void test_functionBody_expression() { |
+ _resolveUnit(r''' |
+main(int a, int b) => a + b; |
+'''); |
+ _resolve(_editString('+', '*'), _isExpression); |
+ } |
+ |
+ void test_functionBody_statement() { |
+ _resolveUnit(r''' |
+main(int a, int b) { |
+ return a + b; |
+}'''); |
+ _resolve(_editString('+', '*'), _isStatement); |
+ } |
+ |
+ void test_method_body() { |
+ _resolveUnit(r''' |
+class A { |
+ m(int a, int b) { |
+ return a + b; |
+ } |
+}'''); |
+ _resolve(_editString('+', '*'), _isFunctionBody); |
+ } |
+ |
+ void test_method_label_add() { |
+ _resolveUnit(r''' |
+class A { |
+ int m(int a, int b) { |
+ return a + b; |
+ } |
+} |
+'''); |
+ _resolve(_editString('return', 'label: return'), _isBlock); |
+ } |
+ |
+ void test_method_localFunction_add() { |
+ _resolveUnit(r''' |
+class A { |
+ int m() { |
+ return 0; |
+ } |
+} |
+callIt(f) {} |
+'''); |
+ _resolve(_editString('return 0;', 'callIt((p) {});'), _isBlock); |
+ } |
+ |
+ void test_method_localVariable_add() { |
+ _resolveUnit(r''' |
+class A { |
+ int m(int a, int b) { |
+ return a + b; |
+ } |
+} |
+'''); |
+ _resolve( |
+ _editString( |
+ ' return a + b;', |
+ r''' |
+ int res = a + b; |
+ return res; |
+'''), |
+ _isBlock); |
+ } |
+ |
+ void test_method_parameter_rename() { |
+ _resolveUnit(r''' |
+class A { |
+ int m(int a, int b, int c) { |
+ return a + b + c; |
+ } |
+} |
+'''); |
+ _resolve( |
+ _editString( |
+ r'''(int a, int b, int c) { |
+ return a + b + c;''', |
+ r'''(int a, int second, int c) { |
+ return a + second + c;'''), |
+ _isDeclaration); |
+ } |
+ |
+ void test_superInvocation() { |
+ _resolveUnit(r''' |
+class A { |
+ foo(p) {} |
+} |
+class B extends A { |
+ bar() { |
+ super.foo(1 + 2); |
+ } |
+}'''); |
+ _resolve(_editString('+', '*'), _isFunctionBody); |
+ } |
+ |
+ void test_topLevelAccessor_body() { |
+ _resolveUnit(r''' |
+int get test { |
+ return 1 + 2; |
+}'''); |
+ _resolve(_editString('+', '*'), _isFunctionBody); |
+ } |
+ |
+ void test_topLevelFunction_label_add() { |
+ _resolveUnit(r''' |
+int main(int a, int b) { |
+ return a + b; |
+} |
+'''); |
+ _resolve(_editString(' return', 'label: return a + b;'), _isBlock); |
+ } |
+ |
+ void test_topLevelFunction_label_remove() { |
+ _resolveUnit(r''' |
+int main(int a, int b) { |
+ label: return a + b; |
+} |
+'''); |
+ _resolve(_editString('label: ', ''), _isBlock); |
+ } |
+ |
+ void test_topLevelFunction_localVariable_add() { |
+ _resolveUnit(r''' |
+int main(int a, int b) { |
+ return a + b; |
+} |
+'''); |
+ _resolve( |
+ _editString( |
+ ' return a + b;', |
+ r''' |
+ int res = a + b; |
+ return res; |
+'''), |
+ _isBlock); |
+ } |
+ |
+ void test_topLevelFunction_localVariable_remove() { |
+ _resolveUnit(r''' |
+int main(int a, int b) { |
+ int res = a * b; |
+ return a + b; |
+} |
+'''); |
+ _resolve(_editString('int res = a * b;', ''), _isBlock); |
+ } |
+ |
+ void test_topLevelFunction_parameter_inFunctionTyped_rename() { |
+ _resolveUnit(r''' |
+test(f(int a, int b)) { |
+} |
+'''); |
+ _resolve(_editString('test(f(int a', 'test(f2(int a2'), _isDeclaration); |
+ } |
+ |
+ void test_topLevelFunction_parameter_rename() { |
+ _resolveUnit(r''' |
+int main(int a, int b) { |
+ return a + b; |
+} |
+'''); |
+ _resolve( |
+ _editString( |
+ r'''(int a, int b) { |
+ return a + b;''', |
+ r'''(int first, int b) { |
+ return first + b;'''), |
+ _isDeclaration); |
+ } |
+ |
+ void test_topLevelVariable_initializer() { |
+ _resolveUnit(r''' |
+int C = 1 + 2; |
+'''); |
+ _resolve(_editString('+', '*'), _isExpression); |
+ } |
+ |
+ void test_updateElementOffset() { |
+ _resolveUnit(r''' |
+class A { |
+ int am(String ap) { |
+ int av = 1; |
+ return av; |
+ } |
+} |
+main(int a, int b) { |
+ return a + b; |
+} |
+class B { |
+ int bm(String bp) { |
+ int bv = 1; |
+ return bv; |
+ } |
+} |
+'''); |
+ _resolve(_editString('+', ' + '), _isStatement); |
+ } |
+ |
+ _Edit _editString(String search, String replacement, [int length]) { |
+ int offset = code.indexOf(search); |
+ expect(offset, isNot(-1)); |
+ if (length == null) { |
+ length = search.length; |
+ } |
+ return new _Edit(offset, length, replacement); |
+ } |
+ |
+ /** |
+ * Applies [edit] to [code], find the [AstNode] specified by [predicate] |
+ * and incrementally resolves it. |
+ * |
+ * Then resolves the new code from scratch and validates that results of |
+ * the incremental resolution and non-incremental resolutions are the same. |
+ */ |
+ void _resolve(_Edit edit, Predicate<AstNode> predicate) { |
+ int offset = edit.offset; |
+ // parse "newCode" |
+ String newCode = code.substring(0, offset) + |
+ edit.replacement + |
+ code.substring(offset + edit.length); |
+ CompilationUnit newUnit = _parseUnit(newCode); |
+ // replace the node |
+ AstNode oldNode = _findNodeAt(unit, offset, predicate); |
+ AstNode newNode = _findNodeAt(newUnit, offset, predicate); |
+ { |
+ bool success = NodeReplacer.replace(oldNode, newNode); |
+ expect(success, isTrue); |
+ } |
+ // update tokens |
+ { |
+ int delta = edit.replacement.length - edit.length; |
+ _shiftTokens(unit.beginToken, offset, delta); |
+ } |
+ // do incremental resolution |
+ int updateOffset = edit.offset; |
+ int updateEndOld = updateOffset + edit.length; |
+ int updateOldNew = updateOffset + edit.replacement.length; |
+ IncrementalResolver resolver; |
+ if (AnalysisEngine.instance.useTaskModel) { |
+ LibrarySpecificUnit lsu = new LibrarySpecificUnit(source, source); |
+ task.AnalysisCache cache = analysisContext2.analysisCache; |
+ resolver = new IncrementalResolver( |
+ null, |
+ cache.get(source), |
+ cache.get(lsu), |
+ unit.element, |
+ updateOffset, |
+ updateEndOld, |
+ updateOldNew); |
+ } else { |
+ resolver = new IncrementalResolver( |
+ (analysisContext2 as AnalysisContextImpl) |
+ .getReadableSourceEntryOrNull(source), |
+ null, |
+ null, |
+ unit.element, |
+ updateOffset, |
+ updateEndOld, |
+ updateOldNew); |
+ } |
+ bool success = resolver.resolve(newNode); |
+ expect(success, isTrue); |
+ List<AnalysisError> newErrors = analysisContext.computeErrors(source); |
+ // resolve "newCode" from scratch |
+ CompilationUnit fullNewUnit; |
+ { |
+ source = addSource(newCode); |
+ _runTasks(); |
+ LibraryElement library = resolve2(source); |
+ fullNewUnit = resolveCompilationUnit(source, library); |
+ } |
+ try { |
+ assertSameResolution(unit, fullNewUnit); |
+ } on IncrementalResolutionMismatch catch (mismatch) { |
+ fail(mismatch.message); |
+ } |
+ // errors |
+ List<AnalysisError> newFullErrors = |
+ analysisContext.getErrors(source).errors; |
+ _assertEqualErrors(newErrors, newFullErrors); |
+ // prepare for the next cycle |
+ code = newCode; |
+ } |
+ |
+ void _resolveUnit(String code) { |
+ this.code = code; |
+ source = addSource(code); |
+ library = resolve2(source); |
+ unit = resolveCompilationUnit(source, library); |
+ _runTasks(); |
+ } |
+ |
+ void _runTasks() { |
+ AnalysisResult result = analysisContext.performAnalysisTask(); |
+ while (result.changeNotices != null) { |
+ result = analysisContext.performAnalysisTask(); |
+ } |
+ } |
+ |
+ static AstNode _findNodeAt( |
+ CompilationUnit oldUnit, int offset, Predicate<AstNode> predicate) { |
+ NodeLocator locator = new NodeLocator(offset); |
+ AstNode node = locator.searchWithin(oldUnit); |
+ return node.getAncestor(predicate); |
+ } |
+ |
+ static bool _isBlock(AstNode node) => node is Block; |
+ |
+ static bool _isClassMember(AstNode node) => node is ClassMember; |
+ |
+ static bool _isDeclaration(AstNode node) => node is Declaration; |
+ |
+ static bool _isExpression(AstNode node) => node is Expression; |
+ |
+ static bool _isFunctionBody(AstNode node) => node is FunctionBody; |
+ |
+ static bool _isStatement(AstNode node) => node is Statement; |
+ |
+ static CompilationUnit _parseUnit(String code) { |
+ var errorListener = new BooleanErrorListener(); |
+ var reader = new CharSequenceReader(code); |
+ var scanner = new Scanner(null, reader, errorListener); |
+ var token = scanner.tokenize(); |
+ var parser = new Parser(null, errorListener); |
+ return parser.parseCompilationUnit(token); |
+ } |
+ |
+ static void _shiftTokens(Token token, int afterOffset, int delta) { |
+ while (token.type != TokenType.EOF) { |
+ if (token.offset >= afterOffset) { |
+ token.applyDelta(delta); |
+ } |
+ token = token.next; |
+ } |
+ } |
+} |
+ |
+/** |
+ * The test for [poorMansIncrementalResolution] function and its integration |
+ * into [AnalysisContext]. |
+ */ |
+@reflectiveTest |
+class PoorMansIncrementalResolutionTest extends ResolverTestCase { |
+ Source source; |
+ String code; |
+ LibraryElement oldLibrary; |
+ CompilationUnit oldUnit; |
+ CompilationUnitElement oldUnitElement; |
+ |
+ void fail_updateErrors_removeExisting_duplicateMethodDeclaration() { |
+ // TODO(scheglov) We fail to remove the second "foo" declaration. |
+ // So, we still have the same duplicate declaration problem. |
+ _resolveUnit(r''' |
+class A { |
+ void foo() {} |
+ void foo() {} |
+} |
+'''); |
+ _updateAndValidate(r''' |
+class A { |
+ void foo() {} |
+ void foo2() {} |
+} |
+'''); |
+ } |
+ |
+ @override |
+ void setUp() { |
+ AnalysisEngine.instance.useTaskModel = true; |
+ super.setUp(); |
+ _resetWithIncremental(true); |
+ } |
+ |
+ @override |
+ void tearDown() { |
+ super.tearDown(); |
+ AnalysisEngine.instance.useTaskModel = false; |
+ } |
+ |
+ void test_computeConstants() { |
+ _resolveUnit(r''' |
+int f() => 0; |
+main() { |
+ const x = f(); |
+ print(x + 1); |
+} |
+'''); |
+ _updateAndValidate(r''' |
+int f() => 0; |
+main() { |
+ const x = f(); |
+ print(x + 2); |
+} |
+'''); |
+ } |
+ |
+ void test_dartDoc_beforeField() { |
+ _resolveUnit(r''' |
+class A { |
+ /** |
+ * A field [field] of type [int] in class [A]. |
+ */ |
+ int field; |
+} |
+'''); |
+ _updateAndValidate(r''' |
+class A { |
+ /** |
+ * A field [field] of the type [int] in the class [A]. |
+ * Updated, with a reference to the [String] type. |
+ */ |
+ int field; |
+} |
+'''); |
+ } |
+ |
+ void test_dartDoc_clumsy_addReference() { |
+ _resolveUnit(r''' |
+/** |
+ * aaa bbbb |
+ */ |
+main() { |
+} |
+'''); |
+ _updateAndValidate(r''' |
+/** |
+ * aaa [main] bbbb |
+ */ |
+main() { |
+} |
+'''); |
+ } |
+ |
+ void test_dartDoc_clumsy_removeReference() { |
+ _resolveUnit(r''' |
+/** |
+ * aaa [main] bbbb |
+ */ |
+main() { |
+} |
+'''); |
+ _updateAndValidate(r''' |
+/** |
+ * aaa bbbb |
+ */ |
+main() { |
+} |
+'''); |
+ } |
+ |
+ void test_dartDoc_clumsy_updateText_beforeKeywordToken() { |
+ _resolveUnit(r''' |
+/** |
+ * A comment with the [int] type reference. |
+ */ |
+class A {} |
+'''); |
+ _updateAndValidate(r''' |
+/** |
+ * A comment with the [int] type reference. |
+ * Plus reference to [A] itself. |
+ */ |
+class A {} |
+'''); |
+ } |
+ |
+ void test_dartDoc_clumsy_updateText_insert() { |
+ _resolveUnit(r''' |
+/** |
+ * A function [main] with a parameter [p] of type [int]. |
+ */ |
+main(int p) { |
+ unresolvedFunctionProblem(); |
+} |
+/** |
+ * Other comment with [int] reference. |
+ */ |
+foo() {} |
+'''); |
+ _updateAndValidate(r''' |
+/** |
+ * A function [main] with a parameter [p] of type [int]. |
+ * Inserted text with [String] reference. |
+ */ |
+main(int p) { |
+ unresolvedFunctionProblem(); |
+} |
+/** |
+ * Other comment with [int] reference. |
+ */ |
+foo() {} |
+'''); |
+ } |
+ |
+ void test_dartDoc_clumsy_updateText_remove() { |
+ _resolveUnit(r''' |
+/** |
+ * A function [main] with a parameter [p] of type [int]. |
+ * Some text with [String] reference to remove. |
+ */ |
+main(int p) { |
+} |
+/** |
+ * Other comment with [int] reference. |
+ */ |
+foo() {} |
+'''); |
+ _updateAndValidate(r''' |
+/** |
+ * A function [main] with a parameter [p] of type [int]. |
+ */ |
+main(int p) { |
+} |
+/** |
+ * Other comment with [int] reference. |
+ */ |
+foo() {} |
+'''); |
+ } |
+ |
+ void test_dartDoc_elegant_addReference() { |
+ _resolveUnit(r''' |
+/// aaa bbb |
+main() { |
+ return 1; |
+} |
+'''); |
+ _updateAndValidate(r''' |
+/// aaa [main] bbb |
+/// ccc [int] ddd |
+main() { |
+ return 1; |
+} |
+'''); |
+ } |
+ |
+ void test_dartDoc_elegant_removeReference() { |
+ _resolveUnit(r''' |
+/// aaa [main] bbb |
+/// ccc [int] ddd |
+main() { |
+ return 1; |
+} |
+'''); |
+ _updateAndValidate(r''' |
+/// aaa bbb |
+main() { |
+ return 1; |
+} |
+'''); |
+ } |
+ |
+ void test_dartDoc_elegant_updateText_insertToken() { |
+ _resolveUnit(r''' |
+/// A |
+/// [int] |
+class Test { |
+} |
+'''); |
+ _updateAndValidate(r''' |
+/// A |
+/// |
+/// [int] |
+class Test { |
+} |
+'''); |
+ } |
+ |
+ void test_dartDoc_elegant_updateText_removeToken() { |
+ _resolveUnit(r''' |
+/// A |
+/// |
+/// [int] |
+class Test { |
+} |
+'''); |
+ _updateAndValidate(r''' |
+/// A |
+/// [int] |
+class Test { |
+} |
+'''); |
+ } |
+ |
+ void test_endOfLineComment_add_beforeKeywordToken() { |
+ _resolveUnit(r''' |
+main() { |
+ var v = 42; |
+} |
+'''); |
+ _updateAndValidate(r''' |
+main() { |
+ // some comment |
+ var v = 42; |
+} |
+'''); |
+ } |
+ |
+ void test_endOfLineComment_add_beforeStringToken() { |
+ _resolveUnit(r''' |
+main() { |
+ print(0); |
+} |
+'''); |
+ _updateAndValidate(r''' |
+main() { |
+ // some comment |
+ print(0); |
+} |
+'''); |
+ } |
+ |
+ void test_endOfLineComment_edit() { |
+ _resolveUnit(r''' |
+main() { |
+ // some comment |
+ print(0); |
+} |
+'''); |
+ _updateAndValidate(r''' |
+main() { |
+ // edited comment text |
+ print(0); |
+} |
+'''); |
+ } |
+ |
+ void test_endOfLineComment_localFunction_inTopLevelVariable() { |
+ _resolveUnit(r''' |
+typedef int Binary(one, two, three); |
+ |
+int Global = f((a, b, c) { |
+ return 0; // Some comment |
+}); |
+'''); |
+ _updateAndValidate(r''' |
+typedef int Binary(one, two, three); |
+ |
+int Global = f((a, b, c) { |
+ return 0; // Some comment |
+}); |
+'''); |
+ } |
+ |
+ void test_endOfLineComment_outBody_add() { |
+ _resolveUnit(r''' |
+main() { |
+ Object x; |
+ x.foo(); |
+} |
+'''); |
+ _updateAndValidate( |
+ r''' |
+// 000 |
+main() { |
+ Object x; |
+ x.foo(); |
+} |
+''', |
+ expectedSuccess: false); |
+ } |
+ |
+ void test_endOfLineComment_outBody_remove() { |
+ _resolveUnit(r''' |
+// 000 |
+main() { |
+ Object x; |
+ x.foo(); |
+} |
+'''); |
+ _updateAndValidate( |
+ r''' |
+main() { |
+ Object x; |
+ x.foo(); |
+} |
+''', |
+ expectedSuccess: false); |
+ } |
+ |
+ void test_endOfLineComment_outBody_update() { |
+ _resolveUnit(r''' |
+// 000 |
+main() { |
+ Object x; |
+ x.foo(); |
+} |
+'''); |
+ _updateAndValidate( |
+ r''' |
+// 10 |
+main() { |
+ Object x; |
+ x.foo(); |
+} |
+''', |
+ expectedSuccess: false); |
+ } |
+ |
+ void test_endOfLineComment_remove() { |
+ _resolveUnit(r''' |
+main() { |
+ // some comment |
+ print(0); |
+} |
+'''); |
+ _updateAndValidate(r''' |
+main() { |
+ print(0); |
+} |
+'''); |
+ } |
+ |
+ void test_false_constConstructor_initializer() { |
+ _resolveUnit(r''' |
+class C { |
+ final int x; |
+ const C(this.x); |
+ const C.foo() : x = 0; |
+} |
+main() { |
+ const {const C(0): 0, const C.foo(): 1}; |
+} |
+'''); |
+ _updateAndValidate( |
+ r''' |
+class C { |
+ final int x; |
+ const C(this.x); |
+ const C.foo() : x = 1; |
+} |
+main() { |
+ const {const C(0): 0, const C.foo(): 1}; |
+} |
+''', |
+ expectedSuccess: false); |
+ } |
+ |
+ void test_false_expressionBody() { |
+ _resolveUnit(r''' |
+class A { |
+ final f = (() => 1)(); |
+} |
+'''); |
+ _updateAndValidate( |
+ r''' |
+class A { |
+ final f = (() => 2)(); |
+} |
+''', |
+ expectedSuccess: false); |
+ } |
+ |
+ void test_false_topLevelFunction_name() { |
+ _resolveUnit(r''' |
+a() {} |
+b() {} |
+'''); |
+ _updateAndValidate( |
+ r''' |
+a() {} |
+bb() {} |
+''', |
+ expectedSuccess: false); |
+ } |
+ |
+ void test_false_unbalancedCurlyBrackets_inNew() { |
+ _resolveUnit(r''' |
+class A { |
+ aaa() { |
+ if (true) { |
+ 1; |
+ } |
+ } |
+ |
+ bbb() { |
+ print(0123456789); |
+ } |
+}'''); |
+ _updateAndValidate( |
+ r''' |
+class A { |
+ aaa() { |
+ 1; |
+ } |
+ } |
+ |
+ bbb() { |
+ print(0123456789); |
+ } |
+}''', |
+ expectedSuccess: false); |
+ } |
+ |
+ void test_false_unbalancedCurlyBrackets_inOld() { |
+ _resolveUnit(r''' |
+class A { |
+ aaa() { |
+ 1; |
+ } |
+ } |
+ |
+ bbb() { |
+ print(0123456789); |
+ } |
+}'''); |
+ _updateAndValidate( |
+ r''' |
+class A { |
+ aaa() { |
+ if (true) { |
+ 1; |
+ } |
+ } |
+ |
+ bbb() { |
+ print(0123456789); |
+ } |
+}''', |
+ expectedSuccess: false); |
+ } |
+ |
+ void test_fieldClassField_propagatedType() { |
+ _resolveUnit(r''' |
+class A { |
+ static const A b = const B(); |
+ const A(); |
+} |
+ |
+class B extends A { |
+ const B(); |
+} |
+ |
+main() { |
+ print(12); |
+ A.b; |
+} |
+'''); |
+ _updateAndValidate(r''' |
+class A { |
+ static const A b = const B(); |
+ const A(); |
+} |
+ |
+class B extends A { |
+ const B(); |
+} |
+ |
+main() { |
+ print(123); |
+ A.b; |
+} |
+'''); |
+ } |
+ |
+ void test_inBody_expression() { |
+ _resolveUnit(r''' |
+class A { |
+ m() { |
+ print(1); |
+ } |
+} |
+'''); |
+ _updateAndValidate(r''' |
+class A { |
+ m() { |
+ print(2 + 3); |
+ } |
+} |
+'''); |
+ } |
+ |
+ void test_inBody_insertStatement() { |
+ _resolveUnit(r''' |
+main() { |
+ print(1); |
+} |
+'''); |
+ _updateAndValidate(r''' |
+main() { |
+ print(0); |
+ print(1); |
+} |
+'''); |
+ } |
+ |
+ void test_inBody_tokenToNode() { |
+ _resolveUnit(r''' |
+main() { |
+ var v = 42; |
+ print(v); |
+} |
+'''); |
+ _updateAndValidate(r''' |
+main() { |
+ int v = 42; |
+ print(v); |
+} |
+'''); |
+ } |
+ |
+ void test_multiple_emptyLine() { |
+ _resolveUnit(r''' |
+class A { |
+ m() { |
+ return true; |
+ } |
+}'''); |
+ for (int i = 0; i < 6; i++) { |
+ if (i.isEven) { |
+ _updateAndValidate( |
+ r''' |
+class A { |
+ m() { |
+ return true; |
+ |
+ } |
+}''', |
+ compareWithFull: false); |
+ } else { |
+ _updateAndValidate( |
+ r''' |
+class A { |
+ m() { |
+ return true; |
+ } |
+}''', |
+ compareWithFull: false); |
+ } |
+ } |
+ } |
+ |
+ void test_multiple_expression() { |
+ _resolveUnit(r''' |
+main() { |
+ print(1); |
+}'''); |
+ for (int i = 0; i < 6; i++) { |
+ if (i.isEven) { |
+ _updateAndValidate( |
+ r''' |
+main() { |
+ print(12); |
+}''', |
+ compareWithFull: false); |
+ } else { |
+ _updateAndValidate( |
+ r''' |
+main() { |
+ print(1); |
+}''', |
+ compareWithFull: false); |
+ } |
+ } |
+ } |
+ |
+ void test_true_emptyLine_betweenClassMembers_insert() { |
+ _resolveUnit(r''' |
+class A { |
+ a() {} |
+ b() {} |
+} |
+'''); |
+ _updateAndValidate(r''' |
+class A { |
+ a() {} |
+ |
+ b() {} |
+} |
+'''); |
+ } |
+ |
+ void test_true_emptyLine_betweenClassMembers_remove() { |
+ _resolveUnit(r''' |
+class A { |
+ a() {} |
+ |
+ b() {} |
+} |
+'''); |
+ _updateAndValidate(r''' |
+class A { |
+ a() {} |
+ b() {} |
+} |
+'''); |
+ } |
+ |
+ void test_true_emptyLine_betweenCompilationUnitMembers_insert() { |
+ _resolveUnit(r''' |
+a() {} |
+b() {} |
+'''); |
+ _updateAndValidate(r''' |
+a() {} |
+ |
+b() {} |
+'''); |
+ } |
+ |
+ void test_true_emptyLine_betweenCompilationUnitMembers_remove() { |
+ _resolveUnit(r''' |
+a() { |
+ print(1) |
+} |
+ |
+b() { |
+ foo(42); |
+} |
+foo(String p) {} |
+'''); |
+ _updateAndValidate(r''' |
+a() { |
+ print(1) |
+} |
+b() { |
+ foo(42); |
+} |
+foo(String p) {} |
+'''); |
+ } |
+ |
+ void test_true_todoHint() { |
+ _resolveUnit(r''' |
+main() { |
+ print(1); |
+} |
+foo() { |
+ // TODO |
+} |
+'''); |
+ List<AnalysisError> oldErrors = analysisContext.computeErrors(source); |
+ _updateAndValidate(r''' |
+main() { |
+ print(2); |
+} |
+foo() { |
+ // TODO |
+} |
+'''); |
+ List<AnalysisError> newErrors = analysisContext.computeErrors(source); |
+ _assertEqualErrors(newErrors, oldErrors); |
+ } |
+ |
+ void test_true_wholeConstructor() { |
+ _resolveUnit(r''' |
+class A { |
+ A(int a) { |
+ print(a); |
+ } |
+} |
+'''); |
+ _updateAndValidate(r''' |
+class A { |
+ A(int b) { |
+ print(b); |
+ } |
+} |
+'''); |
+ } |
+ |
+ void test_true_wholeConstructor_addInitializer() { |
+ _resolveUnit(r''' |
+class A { |
+ int field; |
+ A(); |
+} |
+'''); |
+ _updateAndValidate(r''' |
+class A { |
+ int field; |
+ A() : field = 5; |
+} |
+'''); |
+ } |
+ |
+ void test_true_wholeFunction() { |
+ _resolveUnit(r''' |
+foo() {} |
+main(int a) { |
+ print(a); |
+} |
+'''); |
+ _updateAndValidate(r''' |
+foo() {} |
+main(int b) { |
+ print(b); |
+} |
+'''); |
+ } |
+ |
+ void test_true_wholeFunction_firstTokenInUnit() { |
+ _resolveUnit(r''' |
+main(int a) { |
+ print(a); |
+} |
+'''); |
+ _updateAndValidate(r''' |
+main(int b) { |
+ print(b); |
+} |
+'''); |
+ } |
+ |
+ void test_true_wholeMethod() { |
+ _resolveUnit(r''' |
+class A { |
+ main(int a) { |
+ print(a); |
+ } |
+} |
+'''); |
+ _updateAndValidate(r''' |
+class A { |
+ main(int b) { |
+ print(b); |
+ } |
+} |
+'''); |
+ } |
+ |
+ void test_unusedHint_add_wasUsedOnlyInPart() { |
+ Source partSource = addNamedSource( |
+ '/my_unit.dart', |
+ r''' |
+part of lib; |
+ |
+f(A a) { |
+ a._foo(); |
+} |
+'''); |
+ _resolveUnit(r''' |
+library lib; |
+part 'my_unit.dart'; |
+class A { |
+ _foo() { |
+ print(1); |
+ } |
+} |
+'''); |
+ _runTasks(); |
+ // perform incremental resolution |
+ _resetWithIncremental(true); |
+ analysisContext2.setContents( |
+ partSource, |
+ r''' |
+part of lib; |
+ |
+f(A a) { |
+// a._foo(); |
+} |
+'''); |
+ // no hints right now, because we delay hints computing |
+ { |
+ List<AnalysisError> errors = analysisContext.getErrors(source).errors; |
+ expect(errors, isEmpty); |
+ } |
+ // a new hint should be added |
+ List<AnalysisError> errors = analysisContext.computeErrors(source); |
+ expect(errors, hasLength(1)); |
+ expect(errors[0].errorCode.type, ErrorType.HINT); |
+ // the same hint should be reported using a ChangeNotice |
+ bool noticeFound = false; |
+ AnalysisResult result = analysisContext2.performAnalysisTask(); |
+ for (ChangeNotice notice in result.changeNotices) { |
+ if (notice.source == source) { |
+ expect(notice.errors, contains(errors[0])); |
+ noticeFound = true; |
+ } |
+ } |
+ expect(noticeFound, isTrue); |
+ } |
+ |
+ void test_unusedHint_false_stillUsedInPart() { |
+ addNamedSource( |
+ '/my_unit.dart', |
+ r''' |
+part of lib; |
+ |
+f(A a) { |
+ a._foo(); |
+} |
+'''); |
+ _resolveUnit(r''' |
+library lib; |
+part 'my_unit.dart'; |
+class A { |
+ _foo() { |
+ print(1); |
+ } |
+} |
+'''); |
+ // perform incremental resolution |
+ _resetWithIncremental(true); |
+ analysisContext2.setContents( |
+ source, |
+ r''' |
+library lib; |
+part 'my_unit.dart'; |
+class A { |
+ _foo() { |
+ print(12); |
+ } |
+} |
+'''); |
+ // no hints |
+ List<AnalysisError> errors = analysisContext.getErrors(source).errors; |
+ expect(errors, isEmpty); |
+ } |
+ |
+ void test_updateErrors_addNew_hint1() { |
+ _resolveUnit(r''' |
+int main() { |
+ return 42; |
+} |
+'''); |
+ _updateAndValidate(r''' |
+int main() { |
+} |
+'''); |
+ } |
+ |
+ void test_updateErrors_addNew_hint2() { |
+ _resolveUnit(r''' |
+main() { |
+ int v = 0; |
+ print(v); |
+} |
+'''); |
+ _updateAndValidate(r''' |
+main() { |
+ int v = 0; |
+} |
+'''); |
+ } |
+ |
+ void test_updateErrors_addNew_parse() { |
+ _resolveUnit(r''' |
+main() { |
+ print(42); |
+} |
+'''); |
+ _updateAndValidate(r''' |
+main() { |
+ print(42) |
+} |
+'''); |
+ } |
+ |
+ void test_updateErrors_addNew_resolve() { |
+ _resolveUnit(r''' |
+main() { |
+ foo(); |
+} |
+foo() {} |
+'''); |
+ _updateAndValidate(r''' |
+main() { |
+ bar(); |
+} |
+foo() {} |
+'''); |
+ } |
+ |
+ void test_updateErrors_addNew_resolve2() { |
+ _resolveUnit(r''' |
+// this comment is important to reproduce the problem |
+main() { |
+ int vvv = 42; |
+ print(vvv); |
+} |
+'''); |
+ _updateAndValidate(r''' |
+// this comment is important to reproduce the problem |
+main() { |
+ int vvv = 42; |
+ print(vvv2); |
+} |
+'''); |
+ } |
+ |
+ void test_updateErrors_addNew_scan() { |
+ _resolveUnit(r''' |
+main() { |
+ 1; |
+} |
+'''); |
+ _updateAndValidate(r''' |
+main() { |
+ 1e; |
+} |
+'''); |
+ } |
+ |
+ void test_updateErrors_addNew_verify() { |
+ _resolveUnit(r''' |
+main() { |
+ foo(0); |
+} |
+foo(int p) {} |
+'''); |
+ _updateAndValidate(r''' |
+main() { |
+ foo('abc'); |
+} |
+foo(int p) {} |
+'''); |
+ } |
+ |
+ void test_updateErrors_removeExisting_hint() { |
+ _resolveUnit(r''' |
+int main() { |
+} |
+'''); |
+ _updateAndValidate(r''' |
+int main() { |
+ return 42; |
+} |
+'''); |
+ } |
+ |
+ void test_updateErrors_removeExisting_verify() { |
+ _resolveUnit(r''' |
+f1() { |
+ print(1) |
+} |
+f2() { |
+ print(22) |
+} |
+f3() { |
+ print(333) |
+} |
+'''); |
+ _updateAndValidate(r''' |
+f1() { |
+ print(1) |
+} |
+f2() { |
+ print(22); |
+} |
+f3() { |
+ print(333) |
+} |
+'''); |
+ } |
+ |
+ void test_updateErrors_shiftExisting() { |
+ _resolveUnit(r''' |
+f1() { |
+ print(1) |
+} |
+f2() { |
+ print(2); |
+} |
+f3() { |
+ print(333) |
+} |
+'''); |
+ _updateAndValidate(r''' |
+f1() { |
+ print(1) |
+} |
+f2() { |
+ print(22); |
+} |
+f3() { |
+ print(333) |
+} |
+'''); |
+ } |
+ |
+ void test_whitespace_getElementAt() { |
+ _resolveUnit(r''' |
+class A {} |
+class B extends A {} |
+'''); |
+ { |
+ ClassElement typeA = oldUnitElement.getType('A'); |
+ expect(oldUnitElement.getElementAt(typeA.nameOffset), typeA); |
+ } |
+ { |
+ ClassElement typeB = oldUnitElement.getType('B'); |
+ expect(oldUnitElement.getElementAt(typeB.nameOffset), typeB); |
+ } |
+ _updateAndValidate(r''' |
+class A {} |
+ |
+class B extends A {} |
+'''); |
+ // getElementAt() caches results, it should be notified when offset |
+ // are changed. |
+ { |
+ ClassElement typeA = oldUnitElement.getType('A'); |
+ expect(oldUnitElement.getElementAt(typeA.nameOffset), typeA); |
+ } |
+ { |
+ ClassElement typeB = oldUnitElement.getType('B'); |
+ expect(oldUnitElement.getElementAt(typeB.nameOffset), typeB); |
+ } |
+ } |
+ |
+ void _assertEqualLineInfo(LineInfo incrLineInfo, LineInfo fullLineInfo) { |
+ for (int offset = 0; offset < 1000; offset++) { |
+ LineInfo_Location incrLocation = incrLineInfo.getLocation(offset); |
+ LineInfo_Location fullLocation = fullLineInfo.getLocation(offset); |
+ if (incrLocation.lineNumber != fullLocation.lineNumber || |
+ incrLocation.columnNumber != fullLocation.columnNumber) { |
+ fail('At offset $offset ' + |
+ '(${incrLocation.lineNumber}, ${incrLocation.columnNumber})' + |
+ ' != ' + |
+ '(${fullLocation.lineNumber}, ${fullLocation.columnNumber})'); |
+ } |
+ } |
+ } |
+ |
+ /** |
+ * Reset the analysis context to have the 'incremental' option set to the |
+ * given value. |
+ */ |
+ void _resetWithIncremental(bool enable) { |
+ AnalysisOptionsImpl analysisOptions = new AnalysisOptionsImpl(); |
+ analysisOptions.incremental = enable; |
+ analysisOptions.incrementalApi = enable; |
+// log.logger = log.PRINT_LOGGER; |
+ log.logger = log.NULL_LOGGER; |
+ analysisContext2.analysisOptions = analysisOptions; |
+ } |
+ |
+ void _resolveUnit(String code) { |
+ this.code = code; |
+ source = addSource(code); |
+ oldLibrary = resolve2(source); |
+ oldUnit = resolveCompilationUnit(source, oldLibrary); |
+ oldUnitElement = oldUnit.element; |
+ } |
+ |
+ void _runTasks() { |
+ AnalysisResult result = analysisContext.performAnalysisTask(); |
+ while (result.changeNotices != null) { |
+ result = analysisContext.performAnalysisTask(); |
+ } |
+ } |
+ |
+ void _updateAndValidate(String newCode, |
+ {bool expectedSuccess: true, bool compareWithFull: true}) { |
+ // Run any pending tasks tasks. |
+ _runTasks(); |
+ // Update the source - currently this may cause incremental resolution. |
+ // Then request the updated resolved unit. |
+ _resetWithIncremental(true); |
+ analysisContext2.setContents(source, newCode); |
+ CompilationUnit newUnit = resolveCompilationUnit(source, oldLibrary); |
+ List<AnalysisError> newErrors = analysisContext.computeErrors(source); |
+ LineInfo newLineInfo = analysisContext.getLineInfo(source); |
+ // check for expected failure |
+ if (!expectedSuccess) { |
+ expect(newUnit.element, isNot(same(oldUnitElement))); |
+ return; |
+ } |
+ // The existing CompilationUnit[Element] should be updated. |
+ expect(newUnit, same(oldUnit)); |
+ expect(newUnit.element, same(oldUnitElement)); |
+ expect(analysisContext.parseCompilationUnit(source), same(oldUnit)); |
+ // The only expected pending task should return the same resolved |
+ // "newUnit", so all clients will get it using the usual way. |
+ AnalysisResult analysisResult = analysisContext.performAnalysisTask(); |
+ ChangeNotice notice = analysisResult.changeNotices[0]; |
+ expect(notice.resolvedDartUnit, same(newUnit)); |
+ // Resolve "newCode" from scratch. |
+ if (compareWithFull) { |
+ _resetWithIncremental(false); |
+ changeSource(source, newCode); |
+ _runTasks(); |
+ LibraryElement library = resolve2(source); |
+ CompilationUnit fullNewUnit = resolveCompilationUnit(source, library); |
+ // Validate tokens. |
+ _assertEqualTokens(newUnit, fullNewUnit); |
+ // Validate LineInfo |
+ _assertEqualLineInfo(newLineInfo, analysisContext.getLineInfo(source)); |
+ // Validate that "incremental" and "full" units have the same resolution. |
+ try { |
+ assertSameResolution(newUnit, fullNewUnit, validateTypes: true); |
+ } on IncrementalResolutionMismatch catch (mismatch) { |
+ fail(mismatch.message); |
+ } |
+ List<AnalysisError> newFullErrors = |
+ analysisContext.getErrors(source).errors; |
+ _assertEqualErrors(newErrors, newFullErrors); |
+ } |
+ } |
+ |
+ static void _assertEqualToken(Token incrToken, Token fullToken) { |
+// print('[${incrToken.offset}] |$incrToken| vs. [${fullToken.offset}] |$fullToken|'); |
+ expect(incrToken.type, fullToken.type); |
+ expect(incrToken.offset, fullToken.offset); |
+ expect(incrToken.length, fullToken.length); |
+ expect(incrToken.lexeme, fullToken.lexeme); |
+ } |
+ |
+ static void _assertEqualTokens( |
+ CompilationUnit incrUnit, CompilationUnit fullUnit) { |
+ Token incrToken = incrUnit.beginToken; |
+ Token fullToken = fullUnit.beginToken; |
+ while (incrToken.type != TokenType.EOF && fullToken.type != TokenType.EOF) { |
+ _assertEqualToken(incrToken, fullToken); |
+ // comments |
+ { |
+ Token incrComment = incrToken.precedingComments; |
+ Token fullComment = fullToken.precedingComments; |
+ while (true) { |
+ if (fullComment == null) { |
+ expect(incrComment, isNull); |
+ break; |
+ } |
+ expect(incrComment, isNotNull); |
+ _assertEqualToken(incrComment, fullComment); |
+ incrComment = incrComment.next; |
+ fullComment = fullComment.next; |
+ } |
+ } |
+ // next tokens |
+ incrToken = incrToken.next; |
+ fullToken = fullToken.next; |
+ } |
+ } |
+} |
+ |
+@reflectiveTest |
+class ResolutionContextBuilderTest extends EngineTestCase { |
+ GatheringErrorListener listener = new GatheringErrorListener(); |
+ |
+ void test_scopeFor_ClassDeclaration() { |
+ Scope scope = _scopeFor(_createResolvedClassDeclaration()); |
+ EngineTestCase.assertInstanceOf( |
+ (obj) => obj is LibraryScope, LibraryScope, scope); |
+ } |
+ |
+ void test_scopeFor_ClassTypeAlias() { |
+ Scope scope = _scopeFor(_createResolvedClassTypeAlias()); |
+ EngineTestCase.assertInstanceOf( |
+ (obj) => obj is LibraryScope, LibraryScope, scope); |
+ } |
+ |
+ void test_scopeFor_CompilationUnit() { |
+ Scope scope = _scopeFor(_createResolvedCompilationUnit()); |
+ EngineTestCase.assertInstanceOf( |
+ (obj) => obj is LibraryScope, LibraryScope, scope); |
+ } |
+ |
+ void test_scopeFor_ConstructorDeclaration() { |
+ Scope scope = _scopeFor(_createResolvedConstructorDeclaration()); |
+ EngineTestCase.assertInstanceOf( |
+ (obj) => obj is ClassScope, ClassScope, scope); |
+ } |
+ |
+ void test_scopeFor_ConstructorDeclaration_parameters() { |
+ Scope scope = _scopeFor(_createResolvedConstructorDeclaration().parameters); |
+ EngineTestCase.assertInstanceOf( |
+ (obj) => obj is FunctionScope, FunctionScope, scope); |
+ } |
+ |
+ void test_scopeFor_FunctionDeclaration() { |
+ Scope scope = _scopeFor(_createResolvedFunctionDeclaration()); |
+ EngineTestCase.assertInstanceOf( |
+ (obj) => obj is LibraryScope, LibraryScope, scope); |
+ } |
+ |
+ void test_scopeFor_FunctionDeclaration_parameters() { |
+ Scope scope = _scopeFor( |
+ _createResolvedFunctionDeclaration().functionExpression.parameters); |
+ EngineTestCase.assertInstanceOf( |
+ (obj) => obj is FunctionScope, FunctionScope, scope); |
+ } |
+ |
+ void test_scopeFor_FunctionTypeAlias() { |
+ Scope scope = _scopeFor(_createResolvedFunctionTypeAlias()); |
+ EngineTestCase.assertInstanceOf( |
+ (obj) => obj is LibraryScope, LibraryScope, scope); |
+ } |
+ |
+ void test_scopeFor_FunctionTypeAlias_parameters() { |
+ Scope scope = _scopeFor(_createResolvedFunctionTypeAlias().parameters); |
+ EngineTestCase.assertInstanceOf( |
+ (obj) => obj is FunctionTypeScope, FunctionTypeScope, scope); |
+ } |
+ |
+ void test_scopeFor_MethodDeclaration() { |
+ Scope scope = _scopeFor(_createResolvedMethodDeclaration()); |
+ EngineTestCase.assertInstanceOf( |
+ (obj) => obj is ClassScope, ClassScope, scope); |
+ } |
+ |
+ void test_scopeFor_MethodDeclaration_body() { |
+ Scope scope = _scopeFor(_createResolvedMethodDeclaration().body); |
+ EngineTestCase.assertInstanceOf( |
+ (obj) => obj is FunctionScope, FunctionScope, scope); |
+ } |
+ |
+ void test_scopeFor_notInCompilationUnit() { |
+ try { |
+ _scopeFor(AstFactory.identifier3("x")); |
+ fail("Expected AnalysisException"); |
+ } on AnalysisException { |
+ // Expected |
+ } |
+ } |
+ |
+ void test_scopeFor_null() { |
+ try { |
+ _scopeFor(null); |
+ fail("Expected AnalysisException"); |
+ } on AnalysisException { |
+ // Expected |
+ } |
+ } |
+ |
+ void test_scopeFor_unresolved() { |
+ try { |
+ _scopeFor(AstFactory.compilationUnit()); |
+ fail("Expected AnalysisException"); |
+ } on AnalysisException { |
+ // Expected |
+ } |
+ } |
+ |
+ ClassDeclaration _createResolvedClassDeclaration() { |
+ CompilationUnit unit = _createResolvedCompilationUnit(); |
+ String className = "C"; |
+ ClassDeclaration classNode = AstFactory.classDeclaration( |
+ null, className, AstFactory.typeParameterList(), null, null, null); |
+ unit.declarations.add(classNode); |
+ ClassElement classElement = ElementFactory.classElement2(className); |
+ classNode.name.staticElement = classElement; |
+ (unit.element as CompilationUnitElementImpl).types = <ClassElement>[ |
+ classElement |
+ ]; |
+ return classNode; |
+ } |
+ |
+ ClassTypeAlias _createResolvedClassTypeAlias() { |
+ CompilationUnit unit = _createResolvedCompilationUnit(); |
+ String className = "C"; |
+ ClassTypeAlias classNode = AstFactory.classTypeAlias( |
+ className, AstFactory.typeParameterList(), null, null, null, null); |
+ unit.declarations.add(classNode); |
+ ClassElement classElement = ElementFactory.classElement2(className); |
+ classNode.name.staticElement = classElement; |
+ (unit.element as CompilationUnitElementImpl).types = <ClassElement>[ |
+ classElement |
+ ]; |
+ return classNode; |
+ } |
+ |
+ CompilationUnit _createResolvedCompilationUnit() { |
+ CompilationUnit unit = AstFactory.compilationUnit(); |
+ LibraryElementImpl library = |
+ ElementFactory.library(AnalysisContextFactory.contextWithCore(), "lib"); |
+ unit.element = library.definingCompilationUnit; |
+ return unit; |
+ } |
+ |
+ ConstructorDeclaration _createResolvedConstructorDeclaration() { |
+ ClassDeclaration classNode = _createResolvedClassDeclaration(); |
+ String constructorName = "f"; |
+ ConstructorDeclaration constructorNode = AstFactory.constructorDeclaration( |
+ AstFactory.identifier3(constructorName), |
+ null, |
+ AstFactory.formalParameterList(), |
+ null); |
+ classNode.members.add(constructorNode); |
+ ConstructorElement constructorElement = |
+ ElementFactory.constructorElement2(classNode.element, null); |
+ constructorNode.element = constructorElement; |
+ (classNode.element as ClassElementImpl).constructors = <ConstructorElement>[ |
+ constructorElement |
+ ]; |
+ return constructorNode; |
+ } |
+ |
+ FunctionDeclaration _createResolvedFunctionDeclaration() { |
+ CompilationUnit unit = _createResolvedCompilationUnit(); |
+ String functionName = "f"; |
+ FunctionDeclaration functionNode = AstFactory.functionDeclaration( |
+ null, null, functionName, AstFactory.functionExpression()); |
+ unit.declarations.add(functionNode); |
+ FunctionElement functionElement = |
+ ElementFactory.functionElement(functionName); |
+ functionNode.name.staticElement = functionElement; |
+ (unit.element as CompilationUnitElementImpl).functions = <FunctionElement>[ |
+ functionElement |
+ ]; |
+ return functionNode; |
+ } |
+ |
+ FunctionTypeAlias _createResolvedFunctionTypeAlias() { |
+ CompilationUnit unit = _createResolvedCompilationUnit(); |
+ FunctionTypeAlias aliasNode = AstFactory.typeAlias( |
+ AstFactory.typeName4("A"), |
+ "F", |
+ AstFactory.typeParameterList(), |
+ AstFactory.formalParameterList()); |
+ unit.declarations.add(aliasNode); |
+ SimpleIdentifier aliasName = aliasNode.name; |
+ FunctionTypeAliasElement aliasElement = |
+ new FunctionTypeAliasElementImpl.forNode(aliasName); |
+ aliasName.staticElement = aliasElement; |
+ (unit.element as CompilationUnitElementImpl).typeAliases = |
+ <FunctionTypeAliasElement>[aliasElement]; |
+ return aliasNode; |
+ } |
+ |
+ MethodDeclaration _createResolvedMethodDeclaration() { |
+ ClassDeclaration classNode = _createResolvedClassDeclaration(); |
+ String methodName = "f"; |
+ MethodDeclaration methodNode = AstFactory.methodDeclaration( |
+ null, |
+ null, |
+ null, |
+ null, |
+ AstFactory.identifier3(methodName), |
+ AstFactory.formalParameterList()); |
+ classNode.members.add(methodNode); |
+ MethodElement methodElement = |
+ ElementFactory.methodElement(methodName, null); |
+ methodNode.name.staticElement = methodElement; |
+ (classNode.element as ClassElementImpl).methods = <MethodElement>[ |
+ methodElement |
+ ]; |
+ return methodNode; |
+ } |
+ |
+ Scope _scopeFor(AstNode node) { |
+ return ResolutionContextBuilder.contextFor(node, listener).scope; |
+ } |
+} |
+ |
+class _Edit { |
+ final int offset; |
+ final int length; |
+ final String replacement; |
+ _Edit(this.offset, this.length, this.replacement); |
+} |