| // 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. | |
| import 'package:analyzer/source/line_info.dart'; | |
| import 'package:analyzer/source/source_range.dart'; | |
| import 'package:analyzer/src/dart/ast/ast.dart'; | |
| import 'package:analyzer/src/generated/utilities_collection.dart'; | |
| import 'package:test/test.dart'; | |
| import 'package:test_reflective_loader/test_reflective_loader.dart'; | |
| import '../src/diagnostics/parser_diagnostics.dart'; | |
| main() { | |
| defineReflectiveSuite(() { | |
| defineReflectiveTests(EnumSetTest); | |
| defineReflectiveTests(LineInfoTest); | |
| defineReflectiveTests(NodeReplacerTest); | |
| defineReflectiveTests(SourceRangeTest); | |
| }); | |
| } | |
| @reflectiveTest | |
| class EnumSetTest { | |
| void test_it() { | |
| var enumSet = EnumSet<_MyEnum>.empty(); | |
| // Can set `foo`. | |
| enumSet = enumSet.updated(_MyEnum.foo, true); | |
| expect(enumSet[_MyEnum.foo], true); | |
| expect(enumSet[_MyEnum.bar], false); | |
| // Can set `bar`. | |
| enumSet = enumSet.updated(_MyEnum.bar, true); | |
| expect(enumSet[_MyEnum.foo], true); | |
| expect(enumSet[_MyEnum.bar], true); | |
| // Can set `foo` again. | |
| enumSet = enumSet.updated(_MyEnum.foo, true); | |
| expect(enumSet[_MyEnum.foo], true); | |
| expect(enumSet[_MyEnum.bar], true); | |
| // Can clear `foo`. | |
| enumSet = enumSet.updated(_MyEnum.foo, false); | |
| expect(enumSet[_MyEnum.foo], false); | |
| expect(enumSet[_MyEnum.bar], true); | |
| // Can clear `foo` again. | |
| enumSet = enumSet.updated(_MyEnum.foo, false); | |
| expect(enumSet[_MyEnum.foo], false); | |
| expect(enumSet[_MyEnum.bar], true); | |
| // Can clear `bar`. | |
| enumSet = enumSet.updated(_MyEnum.bar, false); | |
| expect(enumSet[_MyEnum.foo], false); | |
| expect(enumSet[_MyEnum.bar], false); | |
| } | |
| } | |
| @reflectiveTest | |
| class LineInfoTest { | |
| void test_creation() { | |
| expect(LineInfo(<int>[0]), isNotNull); | |
| } | |
| void test_creation_empty() { | |
| expect(() { | |
| LineInfo(<int>[]); | |
| }, throwsArgumentError); | |
| } | |
| void test_fromContent_n() { | |
| var content = 'a\nbb\nccc'; | |
| var lineInfo = LineInfo.fromContent(content); | |
| expect(lineInfo.lineStarts, <int>[0, 2, 5]); | |
| expect(LineInfo.getOffsetForLine(0, content), 0); | |
| expect(LineInfo.getOffsetForLine(1, content), 2); | |
| expect(LineInfo.getOffsetForLine(2, content), 5); | |
| } | |
| void test_fromContent_r() { | |
| var content = 'a\rbb\rccc'; | |
| var lineInfo = LineInfo.fromContent(content); | |
| expect(lineInfo.lineStarts, <int>[0, 2, 5]); | |
| expect(LineInfo.getOffsetForLine(0, content), 0); | |
| expect(LineInfo.getOffsetForLine(1, content), 2); | |
| expect(LineInfo.getOffsetForLine(2, content), 5); | |
| } | |
| void test_fromContent_rn() { | |
| var content = 'a\r\nbb\r\nccc'; | |
| var lineInfo = LineInfo.fromContent(content); | |
| expect(lineInfo.lineStarts, <int>[0, 3, 7]); | |
| expect(LineInfo.getOffsetForLine(0, content), 0); | |
| expect(LineInfo.getOffsetForLine(1, content), 3); | |
| expect(LineInfo.getOffsetForLine(2, content), 7); | |
| } | |
| void test_getLocation_firstLine() { | |
| LineInfo info = LineInfo(<int>[0, 12, 34]); | |
| var location = info.getLocation(4); | |
| expect(location.lineNumber, 1); | |
| expect(location.columnNumber, 5); | |
| } | |
| void test_getLocation_lastLine() { | |
| LineInfo info = LineInfo(<int>[0, 12, 34]); | |
| var location = info.getLocation(36); | |
| expect(location.lineNumber, 3); | |
| expect(location.columnNumber, 3); | |
| } | |
| void test_getLocation_middleLine() { | |
| LineInfo info = LineInfo(<int>[0, 12, 34]); | |
| var location = info.getLocation(12); | |
| expect(location.lineNumber, 2); | |
| expect(location.columnNumber, 1); | |
| } | |
| void test_getOffsetForLine_outside_range() { | |
| var content = 'a\r\nbb\r\nccc'; | |
| expect(LineInfo.getOffsetForLine(-1, content), null); | |
| expect(LineInfo.getOffsetForLine(3, content), null); | |
| expect(LineInfo.getOffsetForLine(4, content), null); | |
| } | |
| void test_getOffsetOfLine() { | |
| LineInfo info = LineInfo(<int>[0, 12, 34]); | |
| expect(0, info.getOffsetOfLine(0)); | |
| expect(12, info.getOffsetOfLine(1)); | |
| expect(34, info.getOffsetOfLine(2)); | |
| } | |
| void test_getOffsetOfLineAfter() { | |
| LineInfo info = LineInfo(<int>[0, 12, 34]); | |
| expect(info.getOffsetOfLineAfter(0), 12); | |
| expect(info.getOffsetOfLineAfter(11), 12); | |
| expect(info.getOffsetOfLineAfter(12), 34); | |
| expect(info.getOffsetOfLineAfter(33), 34); | |
| } | |
| } | |
| @reflectiveTest | |
| class NodeReplacerTest extends ParserDiagnosticsTest { | |
| void test_adjacentStrings() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| 'aaa' 'bbb'; | |
| } | |
| '''); | |
| var adjacentStrings = parseResult.findNode.adjacentStrings('aaa'); | |
| _assertReplaceInList( | |
| destination: adjacentStrings, | |
| child: adjacentStrings.strings[0], | |
| replacement: adjacentStrings.strings[1], | |
| ); | |
| } | |
| void test_annotation() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| @prefix.A<int>.named(args) | |
| @prefix.B<double>.named(args) | |
| void f() {} | |
| '''); | |
| _assertReplacementForChildren<Annotation>( | |
| destination: parseResult.findNode.annotation('prefix.A'), | |
| source: parseResult.findNode.annotation('prefix.B'), | |
| childAccessors: [(node) => node.expression], | |
| ); | |
| } | |
| void test_argumentList() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| g(0, 1); | |
| } | |
| '''); | |
| var argumentList = parseResult.findNode.argumentList('(0, 1)'); | |
| _assertReplaceInList( | |
| destination: argumentList, | |
| child: argumentList.arguments2[0], | |
| replacement: argumentList.arguments2[1], | |
| ); | |
| } | |
| void test_asExpression() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| 0 as int; | |
| 1 as int; | |
| } | |
| '''); | |
| _assertReplacementForChildren<AsExpression>( | |
| destination: parseResult.findNode.as_('0 as'), | |
| source: parseResult.findNode.as_('1 as'), | |
| childAccessors: [(node) => node.expression2, (node) => node.type], | |
| ); | |
| } | |
| void test_assertStatement() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| assert(true, 'first'); | |
| assert(true, 'second'); | |
| } | |
| '''); | |
| _assertReplacementForChildren<AssertStatement>( | |
| destination: parseResult.findNode.assertStatement('first'), | |
| source: parseResult.findNode.assertStatement('second'), | |
| childAccessors: [(node) => node.condition2, (node) => node.message2!], | |
| ); | |
| } | |
| void test_assignmentExpression() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| a = 0; | |
| b = 1; | |
| } | |
| '''); | |
| _assertReplacementForChildren<DirectAssignment>( | |
| destination: parseResult.findNode.directAssignment('a ='), | |
| source: parseResult.findNode.directAssignment('b ='), | |
| childAccessors: [(node) => node.target, (node) => node.value], | |
| ); | |
| } | |
| void test_awaitExpression() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() async { | |
| await 0; | |
| await 1; | |
| } | |
| '''); | |
| _assertReplacementForChildren<AwaitExpression>( | |
| destination: parseResult.findNode.awaitExpression('0'), | |
| source: parseResult.findNode.awaitExpression('1'), | |
| childAccessors: [(node) => node.expression2], | |
| ); | |
| } | |
| void test_binaryExpression() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| 0 + 1; | |
| 1 + 2; | |
| } | |
| '''); | |
| _assertReplacementForChildren<BinaryOperatorInvocation>( | |
| destination: parseResult.findNode.binaryOperatorInvocation('0 + 1'), | |
| source: parseResult.findNode.binaryOperatorInvocation('1 + 2'), | |
| childAccessors: [(node) => node.leftOperand, (node) => node.rightOperand], | |
| ); | |
| } | |
| void test_block() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| print(0); | |
| print(1); | |
| } | |
| '''); | |
| var block = parseResult.findNode.block('{'); | |
| _assertReplaceInList( | |
| destination: block, | |
| child: block.statements[0], | |
| replacement: block.statements[1], | |
| ); | |
| } | |
| void test_blockFunctionBody() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| print('fff'); | |
| } | |
| void g() { | |
| print('ggg'); | |
| } | |
| '''); | |
| _assertReplacementForChildren<BlockFunctionBody>( | |
| destination: parseResult.findNode.blockFunctionBody('fff'), | |
| source: parseResult.findNode.blockFunctionBody('ggg'), | |
| childAccessors: [(node) => node.block, (node) => node.block], | |
| ); | |
| } | |
| void test_breakStatement() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| while (true) { | |
| break first; | |
| break second; | |
| } | |
| } | |
| '''); | |
| _assertReplacementForChildren<BreakStatement>( | |
| destination: parseResult.findNode.breakStatement('first'), | |
| source: parseResult.findNode.breakStatement('second'), | |
| childAccessors: [(node) => node.label!], | |
| ); | |
| } | |
| void test_callInvocation() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| (g)<int>(0); | |
| (h)<double>(1); | |
| } | |
| '''); | |
| _assertReplacementForChildren<CallInvocation>( | |
| destination: parseResult.findNode.callInvocation('<int>'), | |
| source: parseResult.findNode.callInvocation('<double>'), | |
| childAccessors: [ | |
| (node) => node.receiver, | |
| (node) => node.typeArguments!, | |
| (node) => node.argumentList, | |
| ], | |
| ); | |
| } | |
| void test_cascadeExpression() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| 0..foo..bar; | |
| 1..foo; | |
| } | |
| '''); | |
| var cascadeExpression = parseResult.findNode.cascade('0'); | |
| _assertReplaceInList( | |
| destination: cascadeExpression, | |
| child: cascadeExpression.sections[0], | |
| replacement: cascadeExpression.sections[1], | |
| ); | |
| _assertReplacementForChildren<CascadeExpression>( | |
| destination: parseResult.findNode.cascade('0'), | |
| source: parseResult.findNode.cascade('1'), | |
| childAccessors: [(node) => node.target2], | |
| ); | |
| } | |
| void test_catchClause() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| try {} on E catch (e, st) {} | |
| try {} on E2 catch (e2, st2) {} | |
| } | |
| '''); | |
| _assertReplacementForChildren<CatchClause>( | |
| destination: parseResult.findNode.catchClause('(e,'), | |
| source: parseResult.findNode.catchClause('(e2,'), | |
| childAccessors: [ | |
| (node) => node.exceptionType!, | |
| (node) => node.exceptionParameter!, | |
| (node) => node.stackTraceParameter!, | |
| (node) => node.body, | |
| ], | |
| ); | |
| } | |
| void test_classTypeAlias() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| /// Comment A. | |
| @myA1 | |
| @myA2 | |
| class A<T> = A0 with M implements I; | |
| /// Comment B. | |
| class B<U> = B0 with N implements J; | |
| '''); | |
| var destination = parseResult.findNode.classTypeAlias('A<T>'); | |
| _assertAnnotatedNode(destination); | |
| _assertReplacementForChildren<ClassTypeAlias>( | |
| destination: destination, | |
| source: parseResult.findNode.classTypeAlias('B<U>'), | |
| childAccessors: [ | |
| (node) => node.documentationComment!, | |
| (node) => node.superclass, | |
| (node) => node.implementsClause!, | |
| (node) => node.typeParameters!, | |
| (node) => node.withClause, | |
| ], | |
| ); | |
| _assertRemovalForNullableChild<ClassTypeAlias>( | |
| destination: destination, | |
| childAccessor: (node) => node.typeParameters, | |
| ); | |
| } | |
| void test_comment() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| /// Has [foo] and [bar]. | |
| void f() {} | |
| '''); | |
| var comment = parseResult.findNode.comment('Has'); | |
| _assertReplaceInList( | |
| destination: comment, | |
| child: comment.references[0], | |
| replacement: comment.references[1], | |
| ); | |
| } | |
| void test_commentReference() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| /// Has [foo] and [bar]. | |
| void f() {} | |
| '''); | |
| _assertReplacementForChildren<CommentReference>( | |
| destination: parseResult.findNode.commentReference('foo'), | |
| source: parseResult.findNode.commentReference('bar'), | |
| childAccessors: [(node) => node.components.single], | |
| ); | |
| } | |
| void test_compilationUnit() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| import 'a.dart'; | |
| import 'b.dart'; | |
| class A {} | |
| class B {} | |
| '''); | |
| var unit = parseResult.findNode.unit; | |
| _assertReplaceInList( | |
| destination: unit, | |
| child: unit.directives[0], | |
| replacement: unit.directives[1], | |
| ); | |
| _assertReplaceInList( | |
| destination: unit, | |
| child: unit.declarations2[0], | |
| replacement: unit.declarations2[1], | |
| ); | |
| } | |
| void test_conditionalExpression() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| true ? 0 : 1; | |
| false ? 2 : 3; | |
| } | |
| '''); | |
| _assertReplacementForChildren<ConditionalExpression>( | |
| destination: parseResult.findNode.conditionalExpression('true'), | |
| source: parseResult.findNode.conditionalExpression('false'), | |
| childAccessors: [ | |
| (node) => node.condition2, | |
| (node) => node.thenExpression2, | |
| (node) => node.elseExpression2, | |
| ], | |
| ); | |
| } | |
| void test_constantPattern() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f(x) async { | |
| if (x case 0) {} | |
| if (x case 1) {} | |
| } | |
| '''); | |
| _assertReplacementForChildren<ConstantPattern>( | |
| destination: | |
| parseResult.findNode.caseClause('0').guardedPattern.pattern | |
| as ConstantPattern, | |
| source: | |
| parseResult.findNode.caseClause('1').guardedPattern.pattern | |
| as ConstantPattern, | |
| childAccessors: [(node) => node.expression2], | |
| ); | |
| } | |
| void test_constructorDeclaration() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| class A { | |
| @myA1 | |
| @myA2 | |
| A.named(int a) : b = 0, c = 1; | |
| } | |
| class B { | |
| B.named(int b); | |
| } | |
| '''); | |
| _assertReplacementForChildren<ConstructorDeclaration>( | |
| destination: parseResult.findNode.constructor('A.named'), | |
| source: parseResult.findNode.constructor('B.named'), | |
| childAccessors: [(node) => node.body, (node) => node.parameters], | |
| ); | |
| _assertAnnotatedNode(parseResult.findNode.constructor('A.named')); | |
| } | |
| void test_constructorDeclaration_factoryRedirectionTarget() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| class A { | |
| factory A() = R; | |
| } | |
| class B { | |
| factory B() = R; | |
| } | |
| '''); | |
| _assertReplacementForChildren<ConstructorDeclaration>( | |
| destination: parseResult.findNode.constructor('factory A'), | |
| source: parseResult.findNode.constructor('factory B'), | |
| childAccessors: [(node) => node.factoryRedirectionTarget!], | |
| ); | |
| } | |
| void test_constructorFieldInitializer() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| class A { | |
| A() : a = 0, b = 1; | |
| } | |
| '''); | |
| _assertReplacementForChildren<ConstructorFieldInitializer>( | |
| destination: parseResult.findNode.constructorFieldInitializer('a ='), | |
| source: parseResult.findNode.constructorFieldInitializer('b ='), | |
| childAccessors: [(node) => node.expression2], | |
| ); | |
| } | |
| void test_constructorInvocation() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| new A(0); | |
| new B(1); | |
| } | |
| '''); | |
| _assertReplacementForChildren<ConstructorInvocation>( | |
| destination: parseResult.findNode.constructorInvocation('A('), | |
| source: parseResult.findNode.constructorInvocation('B('), | |
| childAccessors: [ | |
| (node) => node.constructorReference, | |
| (node) => node.argumentList, | |
| ], | |
| ); | |
| } | |
| void test_constructorReference2() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| new prefix.A.foo(); | |
| new prefix.B.bar(); | |
| } | |
| '''); | |
| _assertReplacementForChildren<ConstructorReference2>( | |
| destination: parseResult.findNode | |
| .constructorInvocation('A.foo') | |
| .constructorReference, | |
| source: parseResult.findNode | |
| .constructorInvocation('B.bar') | |
| .constructorReference, | |
| childAccessors: [(node) => node.typeReference, (node) => node.selector!], | |
| ); | |
| } | |
| void test_continueStatement() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| while (true) { | |
| continue first; | |
| continue second; | |
| } | |
| } | |
| '''); | |
| _assertReplacementForChildren<ContinueStatement>( | |
| destination: parseResult.findNode.continueStatement('first'), | |
| source: parseResult.findNode.continueStatement('second'), | |
| childAccessors: [(node) => node.label!], | |
| ); | |
| } | |
| void test_declaredIdentifier() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| for (int i in []) {} | |
| for (double j in []) {} | |
| } | |
| '''); | |
| _assertReplacementForChildren<DeclaredIdentifier>( | |
| destination: parseResult.findNode.declaredIdentifier('i in'), | |
| source: parseResult.findNode.declaredIdentifier('j in'), | |
| childAccessors: [(node) => node.type!], | |
| ); | |
| } | |
| void test_defaultFormalParameter() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f({int a = 0, double b = 1}) {} | |
| '''); | |
| _assertReplacementForChildren<FormalParameter>( | |
| destination: parseResult.findNode.formalParameter('a ='), | |
| source: parseResult.findNode.formalParameter('b ='), | |
| childAccessors: [(node) => node.type!, (node) => node.defaultClause!], | |
| ); | |
| } | |
| void test_doStatement() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| do { | |
| 0; | |
| } while (true); | |
| do { | |
| 1; | |
| } while (false); | |
| } | |
| '''); | |
| _assertReplacementForChildren<DoStatement>( | |
| destination: parseResult.findNode.doStatement('true'), | |
| source: parseResult.findNode.doStatement('false'), | |
| childAccessors: [(node) => node.body, (node) => node.condition2], | |
| ); | |
| } | |
| void test_enumBody_constants() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| enum E1 {one} | |
| enum E2 {two} | |
| '''); | |
| _assertReplaceInList( | |
| destination: parseResult.findNode.enumDeclaration('enum E1').body, | |
| child: parseResult.findNode.enumConstantDeclaration('one'), | |
| replacement: parseResult.findNode.enumConstantDeclaration('two'), | |
| ); | |
| } | |
| void test_enumBody_members() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| enum E1 {one; void foo() {}} | |
| enum E2 {two; void bar() {}} | |
| '''); | |
| _assertReplaceInList( | |
| destination: parseResult.findNode.enumDeclaration('enum E1').body, | |
| child: parseResult.findNode.methodDeclaration('foo'), | |
| replacement: parseResult.findNode.methodDeclaration('bar'), | |
| ); | |
| } | |
| void test_enumConstantDeclaration() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| enum E { | |
| @myA1 | |
| @myA2 | |
| aaa, | |
| bbb; | |
| } | |
| '''); | |
| _assertAnnotatedNode(parseResult.findNode.enumConstantDeclaration('aaa')); | |
| } | |
| void test_enumDeclaration() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| enum E1<T> with M1 implements I1 {one, two} | |
| enum E2<U> with M2 implements I2 {one, two} | |
| '''); | |
| _assertReplacementForChildren<EnumDeclaration>( | |
| destination: parseResult.findNode.enumDeclaration('enum E1'), | |
| source: parseResult.findNode.enumDeclaration('enum E2'), | |
| childAccessors: [ | |
| (node) => node.withClause!, | |
| (node) => node.implementsClause!, | |
| ], | |
| ); | |
| } | |
| void test_exportDirective() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| @myA1 | |
| @myA2 | |
| export 'a.dart' hide A show B; | |
| // ^^^^ | |
| // [diag.multipleCombinators] At most one 'show' or 'hide' combinator can be used on an import or export directive. | |
| export 'b.dart'; | |
| '''); | |
| var export_a = parseResult.findNode.export('a.dart'); | |
| _assertAnnotatedNode(export_a); | |
| _assertReplaceInList( | |
| destination: export_a, | |
| child: export_a.combinators[0], | |
| replacement: export_a.combinators[1], | |
| ); | |
| _assertReplacementForChildren<ExportDirective>( | |
| destination: parseResult.findNode.export('a.dart'), | |
| source: parseResult.findNode.export('b.dart'), | |
| childAccessors: [(node) => node.uri], | |
| ); | |
| } | |
| void test_expressionFunctionBody() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() => 0; | |
| void g() => 1; | |
| '''); | |
| _assertReplacementForChildren<ExpressionFunctionBody>( | |
| destination: parseResult.findNode.expressionFunctionBody('0'), | |
| source: parseResult.findNode.expressionFunctionBody('1'), | |
| childAccessors: [(node) => node.expression2], | |
| ); | |
| } | |
| void test_expressionStatement() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| 0; | |
| 1; | |
| } | |
| '''); | |
| _assertReplacementForChildren<ExpressionStatement>( | |
| destination: parseResult.findNode.expressionStatement('0'), | |
| source: parseResult.findNode.expressionStatement('1'), | |
| childAccessors: [(node) => node.expression2], | |
| ); | |
| } | |
| void test_extendsClause() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| class A extends A0 {} | |
| class B extends B0 {} | |
| '''); | |
| _assertReplacementForChildren<ExtendsClause>( | |
| destination: parseResult.findNode.extendsClause('A0'), | |
| source: parseResult.findNode.extendsClause('B0'), | |
| childAccessors: [(node) => node.superclass], | |
| ); | |
| } | |
| void test_extensionDeclaration() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| /// Comment A. | |
| @myA1 | |
| @myA2 | |
| extension E<T> on int {} | |
| /// Comment B. | |
| extension F<U> on double {} | |
| '''); | |
| var destination = parseResult.findNode.extensionDeclaration('E<T>'); | |
| _assertAnnotatedNode(destination); | |
| _assertReplacementForChildren<ExtensionDeclaration>( | |
| destination: destination, | |
| source: parseResult.findNode.extensionDeclaration('F<U>'), | |
| childAccessors: [ | |
| (node) => node.documentationComment!, | |
| (node) => node.typeParameters!, | |
| ], | |
| ); | |
| _assertRemovalForNullableChild<ExtensionDeclaration>( | |
| destination: destination, | |
| childAccessor: (node) => node.typeParameters, | |
| ); | |
| } | |
| void test_fieldDeclaration() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| class A { | |
| @myA1 | |
| @myA2 | |
| int foo = 0; | |
| int bar = 0; | |
| } | |
| class B extends B0 {} | |
| '''); | |
| _assertAnnotatedNode(parseResult.findNode.fieldDeclaration('foo')); | |
| _assertReplacementForChildren<FieldDeclaration>( | |
| destination: parseResult.findNode.fieldDeclaration('foo'), | |
| source: parseResult.findNode.fieldDeclaration('bar'), | |
| childAccessors: [(node) => node.fields], | |
| ); | |
| } | |
| void test_fieldFormalParameter() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| class A { | |
| A([int this.foo = 0, double this.bar = 1]); | |
| } | |
| '''); | |
| _assertReplacementForChildren<FieldFormalParameter>( | |
| destination: parseResult.findNode.fieldFormalParameter('foo ='), | |
| source: parseResult.findNode.fieldFormalParameter('bar ='), | |
| childAccessors: [(node) => node.type!, (node) => node.defaultClause!], | |
| ); | |
| } | |
| void test_fieldFormalParameter_functionTyped() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| class A { | |
| A( | |
| @myA1 | |
| @myA2 | |
| int this.foo<T>(int a), | |
| int this.bar<U>(int b), | |
| ); | |
| } | |
| '''); | |
| var foo = parseResult.findNode.fieldFormalParameter('foo'); | |
| _assertFormalParameterMetadata(foo); | |
| _assertReplacementForChildren<FieldFormalParameter>( | |
| destination: parseResult.findNode.fieldFormalParameter('foo'), | |
| source: parseResult.findNode.fieldFormalParameter('bar'), | |
| childAccessors: [ | |
| (node) => node.type!, | |
| (node) => node.functionTypedSuffix!, | |
| ], | |
| ); | |
| } | |
| void test_forEachPartsWithDeclaration() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| for (int a in []) {} | |
| for (int b in []) {} | |
| } | |
| '''); | |
| _assertReplacementForChildren<ForEachPartsWithDeclaration>( | |
| destination: parseResult.findNode.forEachPartsWithDeclaration('a in'), | |
| source: parseResult.findNode.forEachPartsWithDeclaration('b in'), | |
| childAccessors: [(node) => node.loopVariable, (node) => node.iterable2], | |
| ); | |
| } | |
| void test_forEachPartsWithIdentifier() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| for (a in []) {} | |
| for (b in []) {} | |
| } | |
| '''); | |
| _assertReplacementForChildren<ForEachPartsWithIdentifier>( | |
| destination: parseResult.findNode.forEachPartsWithIdentifier('a in'), | |
| source: parseResult.findNode.forEachPartsWithIdentifier('b in'), | |
| childAccessors: [(node) => node.target, (node) => node.iterable2], | |
| ); | |
| } | |
| void test_forEachPartsWithPattern() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| for (var (a) in []) {} | |
| for (var (b) in []) {} | |
| } | |
| '''); | |
| _assertReplacementForChildren<ForEachPartsWithPattern>( | |
| destination: parseResult.findNode.forEachPartsWithPattern('(a)'), | |
| source: parseResult.findNode.forEachPartsWithPattern('(b)'), | |
| childAccessors: [(node) => node.iterable2], | |
| ); | |
| } | |
| void test_forEachStatement_withIdentifier() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f(int a) { | |
| for (a in []) {} | |
| for (b in []) {} | |
| } | |
| '''); | |
| _assertReplacementForChildren<ForStatement>( | |
| destination: parseResult.findNode.forStatement('a in'), | |
| source: parseResult.findNode.forStatement('b in'), | |
| childAccessors: [(node) => node.body, (node) => node.forLoopParts], | |
| ); | |
| } | |
| void test_formalParameterList() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f(int a, int b) {} | |
| '''); | |
| _assertReplaceInList( | |
| destination: parseResult.findNode.formalParameterList('int a'), | |
| child: parseResult.findNode.regularFormalParameter('int a'), | |
| replacement: parseResult.findNode.regularFormalParameter('int b'), | |
| ); | |
| } | |
| void test_forPartsWithDeclarations() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| for (int i = 0; i < 8; i++, i += 2) {} | |
| for (int j = 0; j < 8; j++) {} | |
| } | |
| '''); | |
| var for_i = parseResult.findNode.forPartsWithDeclarations('i = 0'); | |
| _assertReplaceInList( | |
| destination: for_i, | |
| child: for_i.updaters2[0], | |
| replacement: for_i.updaters2[1], | |
| ); | |
| _assertReplacementForChildren<ForPartsWithDeclarations>( | |
| destination: for_i, | |
| source: parseResult.findNode.forPartsWithDeclarations('j = 0'), | |
| childAccessors: [(node) => node.variables, (node) => node.condition2!], | |
| ); | |
| } | |
| void test_forPartsWithExpression() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| for (i = 0; i < 8; i++, i += 2) {} | |
| for (j = 0; j < 8; j++) {} | |
| } | |
| '''); | |
| var for_i = parseResult.findNode.forPartsWithExpression('i = 0'); | |
| _assertReplaceInList( | |
| destination: for_i, | |
| child: for_i.updaters2[0], | |
| replacement: for_i.updaters2[1], | |
| ); | |
| _assertReplacementForChildren<ForPartsWithExpression>( | |
| destination: for_i, | |
| source: parseResult.findNode.forPartsWithExpression('j = 0'), | |
| childAccessors: [ | |
| (node) => node.initialization2!, | |
| (node) => node.condition2!, | |
| ], | |
| ); | |
| } | |
| void test_functionDeclaration() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| @myA1 | |
| @myA2 | |
| int f() => 0; | |
| double g() => 0; | |
| '''); | |
| _assertAnnotatedNode(parseResult.findNode.functionDeclaration('f()')); | |
| _assertReplacementForChildren<FunctionDeclaration>( | |
| destination: parseResult.findNode.functionDeclaration('f()'), | |
| source: parseResult.findNode.functionDeclaration('g()'), | |
| childAccessors: [ | |
| (node) => node.functionExpression, | |
| (node) => node.returnType!, | |
| ], | |
| ); | |
| } | |
| void test_functionDeclarationStatement() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| void g() {} | |
| void h() {} | |
| } | |
| '''); | |
| _assertReplacementForChildren<FunctionDeclarationStatement>( | |
| destination: parseResult.findNode.functionDeclarationStatement('g()'), | |
| source: parseResult.findNode.functionDeclarationStatement('h()'), | |
| childAccessors: [(node) => node.functionDeclaration], | |
| ); | |
| } | |
| void test_functionExpression() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f<T>(int a) { | |
| 0; | |
| } | |
| void g<U>(double b) { | |
| 1; | |
| } | |
| '''); | |
| var destination = parseResult.findNode.functionExpression('T>'); | |
| _assertReplacementForChildren<FunctionExpression>( | |
| destination: destination, | |
| source: parseResult.findNode.functionExpression('U>'), | |
| childAccessors: [ | |
| (node) => node.body, | |
| (node) => node.parameters!, | |
| (node) => node.typeParameters!, | |
| ], | |
| ); | |
| _assertRemovalForNullableChild<FunctionExpression>( | |
| destination: destination, | |
| childAccessor: (node) => node.typeParameters, | |
| ); | |
| } | |
| void test_functionTypeAlias() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| @myA1 | |
| @myA2 | |
| typedef int F<T>(int a); | |
| typedef double G<U>(double b); | |
| '''); | |
| var destination = parseResult.findNode.functionTypeAlias('int F'); | |
| _assertAnnotatedNode(destination); | |
| _assertReplacementForChildren<FunctionTypeAlias>( | |
| destination: destination, | |
| source: parseResult.findNode.functionTypeAlias('double G'), | |
| childAccessors: [ | |
| (node) => node.parameters, | |
| (node) => node.returnType!, | |
| (node) => node.typeParameters!, | |
| ], | |
| ); | |
| _assertRemovalForNullableChild<FunctionTypeAlias>( | |
| destination: destination, | |
| childAccessor: (node) => node.typeParameters, | |
| ); | |
| } | |
| void test_functionTypedFormalParameterSuffix() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f( | |
| int a<T>(int a1), | |
| double b<U>(double b2), | |
| ) {} | |
| '''); | |
| var destination = parseResult.findNode.functionTypedFormalParameterSuffix( | |
| 'T>', | |
| ); | |
| _assertReplacementForChildren<FunctionTypedFormalParameterSuffix>( | |
| destination: destination, | |
| source: parseResult.findNode.functionTypedFormalParameterSuffix('U>'), | |
| childAccessors: [ | |
| (node) => node.typeParameters!, | |
| (node) => node.formalParameters, | |
| ], | |
| ); | |
| _assertRemovalForNullableChild<FunctionTypedFormalParameterSuffix>( | |
| destination: destination, | |
| childAccessor: (node) => node.typeParameters, | |
| ); | |
| } | |
| void test_genericFunctionType() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| typedef A = int Function<T>(int a); | |
| typedef B = double Function<U>(double b); | |
| '''); | |
| var destination = parseResult.findNode.genericFunctionType('Function<T>'); | |
| _assertReplacementForChildren<GenericFunctionType>( | |
| destination: destination, | |
| source: parseResult.findNode.genericFunctionType('Function<U>'), | |
| childAccessors: [ | |
| (node) => node.returnType!, | |
| (node) => node.typeParameters!, | |
| (node) => node.parameters, | |
| ], | |
| ); | |
| _assertRemovalForNullableChild<GenericFunctionType>( | |
| destination: destination, | |
| childAccessor: (node) => node.typeParameters, | |
| ); | |
| } | |
| void test_genericTypeAlias() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| @myA1 | |
| @myA2 | |
| typedef A<T> = int; | |
| typedef B<U> = double; | |
| '''); | |
| var destination = parseResult.findNode.genericTypeAlias('A<T>'); | |
| _assertAnnotatedNode(destination); | |
| _assertReplacementForChildren<GenericTypeAlias>( | |
| destination: destination, | |
| source: parseResult.findNode.genericTypeAlias('B<U>'), | |
| childAccessors: [(node) => node.typeParameters!, (node) => node.type], | |
| ); | |
| _assertRemovalForNullableChild<GenericTypeAlias>( | |
| destination: destination, | |
| childAccessor: (node) => node.typeParameters, | |
| ); | |
| } | |
| void test_hideCombinator() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| import '' hide A, B; | |
| '''); | |
| var node = parseResult.findNode.hideCombinator('hide'); | |
| _assertReplaceInList( | |
| destination: node, | |
| child: node.names[0], | |
| replacement: node.names[1], | |
| ); | |
| } | |
| void test_ifStatement() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| if (true) { | |
| 0; | |
| } else { | |
| 1; | |
| } | |
| if (false) { | |
| 2; | |
| } else { | |
| 3; | |
| } | |
| } | |
| '''); | |
| _assertReplacementForChildren<IfStatement>( | |
| destination: parseResult.findNode.ifStatement('true'), | |
| source: parseResult.findNode.ifStatement('false'), | |
| childAccessors: [ | |
| (node) => node.expression2, | |
| (node) => node.thenStatement, | |
| (node) => node.elseStatement!, | |
| ], | |
| ); | |
| } | |
| void test_implementsClause() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| class A implements I, J {} | |
| '''); | |
| var node = parseResult.findNode.implementsClause('implements'); | |
| _assertReplaceInList( | |
| destination: node, | |
| child: node.interfaces[0], | |
| replacement: node.interfaces[1], | |
| ); | |
| } | |
| void test_importDirective() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| @myA1 | |
| @myA2 | |
| import 'a.dart' hide A show B; | |
| // ^^^^ | |
| // [diag.multipleCombinators] At most one 'show' or 'hide' combinator can be used on an import or export directive. | |
| import 'b.dart'; | |
| '''); | |
| var import_a = parseResult.findNode.import('a.dart'); | |
| _assertAnnotatedNode(import_a); | |
| _assertReplaceInList( | |
| destination: import_a, | |
| child: import_a.combinators[0], | |
| replacement: import_a.combinators[1], | |
| ); | |
| _assertReplacementForChildren<ImportDirective>( | |
| destination: parseResult.findNode.import('a.dart'), | |
| source: parseResult.findNode.import('b.dart'), | |
| childAccessors: [(node) => node.uri], | |
| ); | |
| } | |
| void test_indexExpression() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| a[0]; | |
| b[1]; | |
| } | |
| '''); | |
| _assertReplacementForChildren<ReceiverIndexExpression>( | |
| destination: parseResult.findNode.receiverIndexExpression('[0]'), | |
| source: parseResult.findNode.receiverIndexExpression('[1]'), | |
| childAccessors: [(node) => node.receiver, (node) => node.index], | |
| ); | |
| } | |
| void test_interpolationExpression() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| '$foo $bar'; | |
| } | |
| '''); | |
| _assertReplacementForChildren<InterpolationExpression>( | |
| destination: parseResult.findNode.interpolationExpression('foo'), | |
| source: parseResult.findNode.interpolationExpression('bar'), | |
| childAccessors: [(node) => node.expression2], | |
| ); | |
| } | |
| void test_isExpression() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| 0 is int; | |
| 1 is double; | |
| } | |
| '''); | |
| _assertReplacementForChildren<IsExpression>( | |
| destination: parseResult.findNode.isExpression('0 is'), | |
| source: parseResult.findNode.isExpression('1 is'), | |
| childAccessors: [(node) => node.expression2, (node) => node.type], | |
| ); | |
| } | |
| void test_labeledStatement() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| foo: bar: 0; | |
| baz: 1; | |
| } | |
| '''); | |
| var foo = parseResult.findNode.labeledStatement('foo'); | |
| _assertReplaceInList( | |
| destination: foo, | |
| child: foo.labels[0], | |
| replacement: foo.labels[1], | |
| ); | |
| _assertReplacementForChildren<LabeledStatement>( | |
| destination: foo, | |
| source: parseResult.findNode.labeledStatement('baz'), | |
| childAccessors: [(node) => node.statement], | |
| ); | |
| } | |
| void test_libraryDirective() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| @myA1 | |
| @myA2 | |
| library foo; | |
| '''); | |
| var node = parseResult.findNode.singleLibraryDirective; | |
| _assertAnnotatedNode(node); | |
| _assertReplacementForChildren<LibraryDirective>( | |
| destination: node, | |
| source: node, | |
| childAccessors: [(node) => node.name!], | |
| ); | |
| } | |
| void test_listLiteral() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| <int>[0, 1]; | |
| <double>[]; | |
| } | |
| '''); | |
| var node = parseResult.findNode.listLiteral('[0'); | |
| _assertReplaceInList( | |
| destination: node, | |
| child: node.elements2[0], | |
| replacement: node.elements2[1], | |
| ); | |
| _assertReplacementForChildren<ListLiteral>( | |
| destination: parseResult.findNode.listLiteral('<int>'), | |
| source: parseResult.findNode.listLiteral('<double>'), | |
| childAccessors: [(node) => node.typeArguments!], | |
| ); | |
| } | |
| void test_mapLiteralEntry() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| <int, int>{0: 1, 2: 3}; | |
| } | |
| '''); | |
| _assertReplacementForChildren<MapLiteralEntry>( | |
| destination: parseResult.findNode.mapLiteralEntry('0: 1'), | |
| source: parseResult.findNode.mapLiteralEntry('2: 3'), | |
| childAccessors: [(node) => node.key2, (node) => node.value2], | |
| ); | |
| } | |
| void test_methodDeclaration() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| class A { | |
| @myA1 | |
| @myA2 | |
| int a<T>(int a1) { | |
| 0; | |
| } | |
| double b<U>(double b1) { | |
| 1; | |
| } | |
| } | |
| '''); | |
| var destination = parseResult.findNode.methodDeclaration('a<T>'); | |
| _assertAnnotatedNode(destination); | |
| _assertReplacementForChildren<MethodDeclaration>( | |
| destination: destination, | |
| source: parseResult.findNode.methodDeclaration('b<U>'), | |
| childAccessors: [ | |
| (node) => node.returnType!, | |
| (node) => node.typeParameters!, | |
| (node) => node.parameters!, | |
| (node) => node.body, | |
| ], | |
| ); | |
| _assertRemovalForNullableChild<MethodDeclaration>( | |
| destination: destination, | |
| childAccessor: (node) => node.typeParameters, | |
| ); | |
| } | |
| void test_mixinDeclaration() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| @myA1 | |
| @myA2 | |
| mixin A<T> on A0 implements I { | |
| void a() {} | |
| } | |
| mixin B<U> on B0 implements J { | |
| void b() {} | |
| } | |
| '''); | |
| var destination = parseResult.findNode.mixinDeclaration('A<T>'); | |
| _assertAnnotatedNode(destination); | |
| _assertReplacementForChildren<MixinDeclaration>( | |
| destination: destination, | |
| source: parseResult.findNode.mixinDeclaration('B<U>'), | |
| childAccessors: [ | |
| (node) => node.typeParameters!, | |
| (node) => node.onClause!, | |
| (node) => node.implementsClause!, | |
| (node) => node.body, | |
| ], | |
| ); | |
| _assertRemovalForNullableChild<MixinDeclaration>( | |
| destination: destination, | |
| childAccessor: (node) => node.typeParameters, | |
| ); | |
| } | |
| void test_namedArgument() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| g(foo: 0, bar: 1); | |
| } | |
| '''); | |
| _assertReplacementForChildren<NamedArgument>( | |
| destination: parseResult.findNode.namedArgument('foo'), | |
| source: parseResult.findNode.namedArgument('bar'), | |
| childAccessors: [(node) => node.argumentExpression2], | |
| ); | |
| } | |
| void test_nameWithTypeParameters() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| class A<T> {} | |
| class B<U> {} | |
| '''); | |
| var destination = parseResult.findNode.nameWithTypeParameters('A<T>'); | |
| _assertReplacementForChildren<NameWithTypeParameters>( | |
| destination: destination, | |
| source: parseResult.findNode.nameWithTypeParameters('B<U>'), | |
| childAccessors: [(node) => node.typeParameters!], | |
| ); | |
| _assertRemovalForNullableChild<NameWithTypeParameters>( | |
| destination: destination, | |
| childAccessor: (node) => node.typeParameters, | |
| ); | |
| } | |
| void test_nativeFunctionBody() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() native 'foo'; | |
| void g() native 'bar'; | |
| '''); | |
| _assertReplacementForChildren<NativeFunctionBody>( | |
| destination: parseResult.findNode.nativeFunctionBody('foo'), | |
| source: parseResult.findNode.nativeFunctionBody('bar'), | |
| childAccessors: [(node) => node.stringLiteral!], | |
| ); | |
| } | |
| void test_parenthesizedExpression() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| (0); | |
| (1); | |
| } | |
| '''); | |
| _assertReplacementForChildren<ParenthesizedExpression>( | |
| destination: parseResult.findNode.parenthesized('0'), | |
| source: parseResult.findNode.parenthesized('1'), | |
| childAccessors: [(node) => node.expression2], | |
| ); | |
| } | |
| void test_parsedNameAccess() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| a.foo; | |
| b.bar; | |
| } | |
| '''); | |
| _assertReplacementForChildren<ParsedNameAccess>( | |
| destination: | |
| parseResult.findNode.parsedExpression('a.foo') as ParsedNameAccess, | |
| source: | |
| parseResult.findNode.parsedExpression('b.bar') as ParsedNameAccess, | |
| childAccessors: [(node) => node.operand], | |
| ); | |
| } | |
| void test_parsedTypeArguments() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| (a).foo<int>(0); | |
| (b).bar<double>(1); | |
| } | |
| '''); | |
| _assertReplacementForChildren<ParsedTypeArguments>( | |
| destination: | |
| (parseResult.findNode.expressionStatement('(a)').expression2 | |
| as ParsedValueArguments) | |
| .operand | |
| as ParsedTypeArguments, | |
| source: | |
| (parseResult.findNode.expressionStatement('(b)').expression2 | |
| as ParsedValueArguments) | |
| .operand | |
| as ParsedTypeArguments, | |
| childAccessors: [(node) => node.operand, (node) => node.typeArguments], | |
| ); | |
| } | |
| void test_parsedValueArguments() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| (a).foo<int>(0); | |
| (b).bar<double>(1); | |
| } | |
| '''); | |
| _assertReplacementForChildren<ParsedValueArguments>( | |
| destination: | |
| parseResult.findNode.expressionStatement('(a)').expression2 | |
| as ParsedValueArguments, | |
| source: | |
| parseResult.findNode.expressionStatement('(b)').expression2 | |
| as ParsedValueArguments, | |
| childAccessors: [(node) => node.operand, (node) => node.argumentList], | |
| ); | |
| } | |
| void test_parsedValueArguments_cascade() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| class A { | |
| void f() { | |
| a..foo<int>(0); | |
| c..bar<double>(1); | |
| } | |
| } | |
| '''); | |
| _assertReplacementForChildren<ParsedValueArguments>( | |
| destination: | |
| parseResult.findNode.cascade('a..').sections.single.body | |
| as ParsedValueArguments, | |
| source: | |
| parseResult.findNode.cascade('c..').sections.single.body | |
| as ParsedValueArguments, | |
| childAccessors: [(node) => node.operand, (node) => node.argumentList], | |
| ); | |
| } | |
| void test_partDirective() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| @myA1 | |
| @myA2 | |
| part 'a.dart'; | |
| part 'b.dart'; | |
| '''); | |
| var part_a = parseResult.findNode.part('a.dart'); | |
| _assertAnnotatedNode(part_a); | |
| _assertReplacementForChildren<PartDirective>( | |
| destination: parseResult.findNode.part('a.dart'), | |
| source: parseResult.findNode.part('b.dart'), | |
| childAccessors: [(node) => node.uri], | |
| ); | |
| } | |
| void test_partOfDirective() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| @myA1 | |
| @myA2 | |
| part of 'a.dart'; | |
| '''); | |
| var partOf_a = parseResult.findNode.partOf('a.dart'); | |
| _assertAnnotatedNode(partOf_a); | |
| _assertReplacementForChildren<PartOfDirective>( | |
| destination: parseResult.findNode.partOf('a.dart'), | |
| source: parseResult.findNode.partOf('a.dart'), | |
| childAccessors: [(node) => node.uri!], | |
| ); | |
| } | |
| void test_patternAssignment() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| int a; | |
| int b; | |
| (a) = 0; | |
| (b) = 1; | |
| } | |
| '''); | |
| _assertReplacementForChildren<PatternAssignment>( | |
| destination: parseResult.findNode.patternAssignment('0'), | |
| source: parseResult.findNode.patternAssignment('1'), | |
| childAccessors: [(node) => node.expression2], | |
| ); | |
| } | |
| void test_patternVariableDeclaration() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| var (a) = 0; | |
| var (b) = 1; | |
| } | |
| '''); | |
| _assertReplacementForChildren<PatternVariableDeclaration>( | |
| destination: parseResult.findNode.patternVariableDeclaration('0'), | |
| source: parseResult.findNode.patternVariableDeclaration('1'), | |
| childAccessors: [(node) => node.expression2], | |
| ); | |
| } | |
| void test_postfixIncrement() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| a++; | |
| b++; | |
| } | |
| '''); | |
| _assertReplacementForChildren<IncrementOrDecrementExpression>( | |
| destination: parseResult.findNode.incrementOrDecrement('a++'), | |
| source: parseResult.findNode.incrementOrDecrement('b++'), | |
| childAccessors: [(node) => node.target], | |
| ); | |
| } | |
| void test_prefixIncrement() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| ++a; | |
| ++b; | |
| } | |
| '''); | |
| _assertReplacementForChildren<IncrementOrDecrementExpression>( | |
| destination: parseResult.findNode.incrementOrDecrement('++a'), | |
| source: parseResult.findNode.incrementOrDecrement('++b'), | |
| childAccessors: [(node) => node.target], | |
| ); | |
| } | |
| void test_primaryConstructorDeclaration() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| class A<T>.a(int a) {} | |
| class B<U>.b(double b) {} | |
| '''); | |
| var destination = parseResult.findNode.primaryConstructorDeclaration( | |
| 'A<T>', | |
| ); | |
| _assertReplacementForChildren<PrimaryConstructorDeclaration>( | |
| destination: destination, | |
| source: parseResult.findNode.primaryConstructorDeclaration('B<U>'), | |
| childAccessors: [ | |
| (node) => node.typeParameters!, | |
| (node) => node.constructorName!, | |
| (node) => node.formalParameters, | |
| ], | |
| ); | |
| _assertRemovalForNullableChild<PrimaryConstructorDeclaration>( | |
| destination: destination, | |
| childAccessor: (node) => node.typeParameters, | |
| ); | |
| } | |
| void test_propertyExtraction() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| (a).foo; | |
| (b).bar; | |
| } | |
| '''); | |
| _assertReplacementForChildren<ReceiverPropertyExtraction>( | |
| destination: parseResult.findNode.receiverPropertyExtraction('(a)'), | |
| source: parseResult.findNode.receiverPropertyExtraction('(b)'), | |
| childAccessors: [(node) => node.receiver], | |
| ); | |
| } | |
| void test_recordLiteral() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| (1, 2); | |
| } | |
| '''); | |
| var node = parseResult.findNode.recordLiteral('(1'); | |
| _assertReplaceInList( | |
| destination: node, | |
| child: node.fields2[0], | |
| replacement: node.fields2[1], | |
| ); | |
| } | |
| void test_redirectingConstructorInvocation() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| class A { | |
| A.named(); | |
| A.foo() : this.named(0); | |
| A.bar() : this.named(1); | |
| } | |
| '''); | |
| _assertReplacementForChildren<RedirectingConstructorInvocation>( | |
| destination: parseResult.findNode.redirectingConstructorInvocation('(0)'), | |
| source: parseResult.findNode.redirectingConstructorInvocation('(1)'), | |
| childAccessors: [ | |
| (node) => node.constructorSelector!, | |
| (node) => node.argumentList, | |
| ], | |
| ); | |
| } | |
| void test_regularFormalParameter() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f([int a = 0, double b = 1]) {} | |
| '''); | |
| _assertReplacementForChildren<RegularFormalParameter>( | |
| destination: | |
| parseResult.findNode.formalParameter('a =') as RegularFormalParameter, | |
| source: | |
| parseResult.findNode.formalParameter('b =') as RegularFormalParameter, | |
| childAccessors: [(node) => node.type!, (node) => node.defaultClause!], | |
| ); | |
| } | |
| void test_regularFormalParameter_functionTyped() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f( | |
| @myA1 | |
| @myA2 | |
| int a<T>(int a1), | |
| double b<U>(double b2), | |
| ) {} | |
| '''); | |
| var a = parseResult.findNode.formalParameter('a<T>'); | |
| _assertFormalParameterMetadata(a); | |
| _assertReplacementForChildren<RegularFormalParameter>( | |
| destination: | |
| parseResult.findNode.formalParameter('a<T>') | |
| as RegularFormalParameter, | |
| source: | |
| parseResult.findNode.formalParameter('b<U>') | |
| as RegularFormalParameter, | |
| childAccessors: [ | |
| (node) => node.type!, | |
| (node) => node.functionTypedSuffix!, | |
| ], | |
| ); | |
| } | |
| void test_relationalPattern() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f(x) { | |
| if (x case > 0) {} | |
| if (x case > 1) {} | |
| } | |
| '''); | |
| _assertReplacementForChildren<RelationalPattern>( | |
| destination: parseResult.findNode.relationalPattern('> 0'), | |
| source: parseResult.findNode.relationalPattern('> 1'), | |
| childAccessors: [(node) => node.operand2], | |
| ); | |
| } | |
| void test_returnStatement() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| return 0; | |
| return 1; | |
| } | |
| '''); | |
| _assertReplacementForChildren<ReturnStatement>( | |
| destination: parseResult.findNode.returnStatement('0;'), | |
| source: parseResult.findNode.returnStatement('1;'), | |
| childAccessors: [(node) => node.expression2!], | |
| ); | |
| } | |
| void test_setOrMapLiteral() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| <int, int>{0: 1, 2: 3}; | |
| <double, double>{}; | |
| } | |
| '''); | |
| var node = parseResult.findNode.setOrMapLiteral('<int'); | |
| _assertReplaceInList( | |
| destination: node, | |
| child: node.elements2[0], | |
| replacement: node.elements2[1], | |
| ); | |
| _assertReplacementForChildren<SetOrMapLiteral>( | |
| destination: parseResult.findNode.setOrMapLiteral('<int'), | |
| source: parseResult.findNode.setOrMapLiteral('<double'), | |
| childAccessors: [(node) => node.typeArguments!], | |
| ); | |
| } | |
| void test_showCombinator() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| import '' show A, B; | |
| '''); | |
| var node = parseResult.findNode.showCombinator('show'); | |
| _assertReplaceInList( | |
| destination: node, | |
| child: node.names[0], | |
| replacement: node.names[1], | |
| ); | |
| } | |
| void test_simpleFormalParameter() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f( | |
| @myA1 | |
| @myA2 | |
| int a, | |
| int b | |
| ) {} | |
| '''); | |
| var a = parseResult.findNode.regularFormalParameter('int a'); | |
| _assertFormalParameterMetadata(a); | |
| _assertReplacementForChildren<RegularFormalParameter>( | |
| destination: a, | |
| source: parseResult.findNode.regularFormalParameter('int b'), | |
| childAccessors: [(node) => node.type!], | |
| ); | |
| } | |
| void test_stringInterpolation() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| 'my $foo other $bar'; | |
| } | |
| '''); | |
| var node = parseResult.findNode.stringInterpolation('foo'); | |
| _assertReplaceInList( | |
| destination: node, | |
| child: node.elements[0], | |
| replacement: node.elements[1], | |
| ); | |
| } | |
| void test_superConstructorInvocation() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| class A { | |
| A.foo() : super.first(0); | |
| A.bar() : super.second(0); | |
| } | |
| '''); | |
| _assertReplacementForChildren<SuperConstructorInvocation>( | |
| destination: parseResult.findNode.superConstructorInvocation('first'), | |
| source: parseResult.findNode.superConstructorInvocation('second'), | |
| childAccessors: [ | |
| (node) => node.constructorSelector!, | |
| (node) => node.argumentList, | |
| ], | |
| ); | |
| } | |
| void test_superFormalParameter() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| class A { | |
| A([num a = 0]); | |
| } | |
| class B extends A { | |
| B.sub1([int super.a1 = 1]); | |
| B.sub2([double super.a2 = 2]); | |
| } | |
| '''); | |
| _assertReplacementForChildren<SuperFormalParameter>( | |
| destination: parseResult.findNode.superFormalParameter('a1 ='), | |
| source: parseResult.findNode.superFormalParameter('a2 ='), | |
| childAccessors: [(node) => node.type!, (node) => node.defaultClause!], | |
| ); | |
| } | |
| void test_superFormalParameter_functionTyped() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| class A { | |
| A(int foo<T>(int a)); | |
| } | |
| class B extends A { | |
| B.sub1(double super.bar1<T1>(int a1),); | |
| B.sub2(double super.bar2<T2>(int a2),); | |
| } | |
| '''); | |
| _assertReplacementForChildren<SuperFormalParameter>( | |
| destination: parseResult.findNode.superFormalParameter('bar1'), | |
| source: parseResult.findNode.superFormalParameter('bar2'), | |
| childAccessors: [ | |
| (node) => node.type!, | |
| (node) => node.functionTypedSuffix!, | |
| ], | |
| ); | |
| } | |
| void test_switchCase_beforePatterns() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| // %before-language-feature: patterns | |
| void f() { | |
| switch (x) { | |
| foo: bar: | |
| case 0: 0; 1; | |
| case 1: break; | |
| } | |
| } | |
| '''); | |
| _assertSwitchMember(parseResult.findNode.switchCase('case 0')); | |
| _assertReplacementForChildren<SwitchCase>( | |
| destination: parseResult.findNode.switchCase('case 0'), | |
| source: parseResult.findNode.switchCase('case 1'), | |
| childAccessors: [(node) => node.expression2], | |
| ); | |
| } | |
| void test_switchDefault() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| switch (x) { | |
| foo: bar: | |
| default: 0; 1; | |
| } | |
| } | |
| '''); | |
| _assertSwitchMember(parseResult.findNode.switchDefault('default: 0')); | |
| } | |
| void test_switchStatement_beforePatterns() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| // %before-language-feature: patterns | |
| void f() { | |
| switch (0) { | |
| case 0: break; | |
| case 1: break; | |
| } | |
| switch (1) {} | |
| } | |
| '''); | |
| _assertReplaceInList( | |
| destination: parseResult.findNode.switchStatement('(0)'), | |
| child: parseResult.findNode.switchCase('case 0'), | |
| replacement: parseResult.findNode.switchCase('case 1'), | |
| ); | |
| _assertReplacementForChildren<SwitchStatement>( | |
| destination: parseResult.findNode.switchStatement('(0)'), | |
| source: parseResult.findNode.switchStatement('(1)'), | |
| childAccessors: [(node) => node.expression2], | |
| ); | |
| } | |
| void test_throwExpression() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| throw 0; | |
| throw 1; | |
| } | |
| '''); | |
| _assertReplacementForChildren<ThrowExpression>( | |
| destination: parseResult.findNode.throw_('throw 0'), | |
| source: parseResult.findNode.throw_('throw 1'), | |
| childAccessors: [(node) => node.expression2], | |
| ); | |
| } | |
| void test_topLevelVariableDeclaration() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| @myA1 | |
| @myA2 | |
| var a = 0; | |
| var b = 1; | |
| '''); | |
| _assertAnnotatedNode( | |
| parseResult.findNode.topLevelVariableDeclaration('a = 0'), | |
| ); | |
| _assertReplacementForChildren<TopLevelVariableDeclaration>( | |
| destination: parseResult.findNode.topLevelVariableDeclaration('a = 0'), | |
| source: parseResult.findNode.topLevelVariableDeclaration('b = 1'), | |
| childAccessors: [(node) => node.variables], | |
| ); | |
| } | |
| void test_tryStatement() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| try { // 0 | |
| 0; | |
| } on E1 { | |
| } on E2 { | |
| } finally { | |
| 1; | |
| } | |
| try { // 1 | |
| 2; | |
| } finally { | |
| 3; | |
| } | |
| } | |
| '''); | |
| _assertReplaceInList( | |
| destination: parseResult.findNode.tryStatement('// 0'), | |
| child: parseResult.findNode.catchClause('E1'), | |
| replacement: parseResult.findNode.catchClause('E2'), | |
| ); | |
| _assertReplacementForChildren<TryStatement>( | |
| destination: parseResult.findNode.tryStatement('// 0'), | |
| source: parseResult.findNode.tryStatement('// 1'), | |
| childAccessors: [(node) => node.body, (node) => node.finallyBlock!], | |
| ); | |
| } | |
| void test_typeArgumentList() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| g<int, double>(); | |
| } | |
| '''); | |
| _assertReplaceInList( | |
| destination: parseResult.findNode.typeArgumentList('<int'), | |
| child: parseResult.findNode.namedType('int'), | |
| replacement: parseResult.findNode.namedType('double'), | |
| ); | |
| } | |
| void test_typeParameter() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| class A<T extends int, U extends double> {} | |
| '''); | |
| _assertReplacementForChildren<TypeParameter>( | |
| destination: parseResult.findNode.typeParameter('T extends'), | |
| source: parseResult.findNode.typeParameter('U extends'), | |
| childAccessors: [(node) => node.bound!], | |
| ); | |
| } | |
| void test_typeParameterList() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| class A<T, U> {} | |
| '''); | |
| // Find from the offset after the `<` because NodeLocator usually picks | |
| // the name for the offset between the name and `<`. | |
| var node = parseResult.findNode.typeParameterList('T, U>'); | |
| _assertReplaceInList( | |
| destination: node, | |
| child: node.typeParameters[0], | |
| replacement: node.typeParameters[1], | |
| ); | |
| } | |
| void test_variableDeclaration() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| var a = 0; | |
| var b = 1; | |
| } | |
| '''); | |
| _assertReplacementForChildren<VariableDeclaration>( | |
| destination: parseResult.findNode.variableDeclaration('a = 0'), | |
| source: parseResult.findNode.variableDeclaration('b = 1'), | |
| childAccessors: [(node) => node.initializer2!], | |
| ); | |
| } | |
| void test_variableDeclarationList() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| int a = 0, b = 1; | |
| double c = 2; | |
| } | |
| '''); | |
| _assertReplaceInList( | |
| destination: parseResult.findNode.variableDeclarationList('int a'), | |
| child: parseResult.findNode.variableDeclaration('a = 0'), | |
| replacement: parseResult.findNode.variableDeclaration('b = 1'), | |
| ); | |
| _assertReplacementForChildren<VariableDeclarationList>( | |
| destination: parseResult.findNode.variableDeclarationList('int a'), | |
| source: parseResult.findNode.variableDeclarationList('double c'), | |
| childAccessors: [(node) => node.type!], | |
| ); | |
| } | |
| void test_variableDeclarationStatement() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| int a = 0; | |
| double b = 1; | |
| } | |
| '''); | |
| _assertReplacementForChildren<VariableDeclarationStatement>( | |
| destination: parseResult.findNode.variableDeclarationStatement('int a'), | |
| source: parseResult.findNode.variableDeclarationStatement('double b'), | |
| childAccessors: [(node) => node.variables], | |
| ); | |
| } | |
| void test_whenClause() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| if (x case 0 when 1) {} | |
| if (x case 0 when 2) {} | |
| } | |
| '''); | |
| _assertReplacementForChildren<WhenClause>( | |
| destination: parseResult.findNode.whenClause('when 1'), | |
| source: parseResult.findNode.whenClause('when 2'), | |
| childAccessors: [(node) => node.expression2], | |
| ); | |
| } | |
| void test_whileStatement() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() { | |
| while (true) { | |
| 0; | |
| } | |
| while (false) { | |
| 1; | |
| } | |
| } | |
| '''); | |
| _assertReplacementForChildren<WhileStatement>( | |
| destination: parseResult.findNode.whileStatement('(true)'), | |
| source: parseResult.findNode.whileStatement('(false)'), | |
| childAccessors: [(node) => node.condition2, (node) => node.body], | |
| ); | |
| } | |
| void test_withClause() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| class A with M, N {} | |
| '''); | |
| var node = parseResult.findNode.withClause('with'); | |
| _assertReplaceInList( | |
| destination: node, | |
| child: node.mixinTypes[0], | |
| replacement: node.mixinTypes[1], | |
| ); | |
| } | |
| void test_yieldStatement() { | |
| var parseResult = parseTestCodeWithDiagnostics(r''' | |
| void f() sync* { | |
| yield 0; | |
| yield 1; | |
| } | |
| '''); | |
| _assertReplacementForChildren<YieldStatement>( | |
| destination: parseResult.findNode.yieldStatement('yield 0;'), | |
| source: parseResult.findNode.yieldStatement('yield 1'), | |
| childAccessors: [(node) => node.expression2], | |
| ); | |
| } | |
| /// Asserts that the first annotation can be replaced with the second. | |
| /// Expects that [node] has at least 2 annotations. | |
| void _assertAnnotatedNode(AnnotatedNode node) { | |
| _assertReplaceInList( | |
| destination: node, | |
| child: node.metadata[0], | |
| replacement: node.metadata[1], | |
| ); | |
| } | |
| /// Asserts that the first annotation can be replaced with the second. | |
| /// Expects that [node] has at least 2 annotations. | |
| void _assertFormalParameterMetadata(FormalParameter node) { | |
| _assertReplaceInList( | |
| destination: node, | |
| child: node.metadata[0], | |
| replacement: node.metadata[1], | |
| ); | |
| } | |
| /// Asserts that a nullable [childAccessor] child can be removed from | |
| /// [destination]. | |
| void _assertRemovalForNullableChild<T extends AstNode>({ | |
| required T destination, | |
| required AstNode? Function(T node) childAccessor, | |
| }) { | |
| var child = childAccessor(destination)!; | |
| expect(child.parent2, destination); | |
| (child as AstNodeImpl).removeFromParent(); | |
| expect(childAccessor(destination), isNull); | |
| } | |
| /// Asserts that a [child] node, with parent that is [destination], can | |
| /// by replaced with the [replacement], and then its parent is [destination]. | |
| void _assertReplaceInList({ | |
| required AstNode destination, | |
| required AstNode child, | |
| required AstNode replacement, | |
| }) { | |
| expect(child.parent2, destination); | |
| (child as AstNodeImpl).replaceWith(replacement as AstNodeImpl); | |
| expect(replacement.parent2, destination); | |
| } | |
| /// Asserts for each child returned by a function from [childAccessors] | |
| /// for [destination] that its parent is actually [destination], and then | |
| /// replaces it with a node returned this function for [source]. At the end, | |
| /// checks that the function, invoked for [destination] now returns the | |
| /// replacement node, and its parent is now [destination]. | |
| void _assertReplacementForChildren<T extends AstNode>({ | |
| required T destination, | |
| required T source, | |
| required List<AstNode Function(T node)> childAccessors, | |
| }) { | |
| for (var childAccessor in childAccessors) { | |
| var child = childAccessor(destination); | |
| expect(child.parent2, destination); | |
| var replacement = childAccessor(source); | |
| (child as AstNodeImpl).replaceWith(replacement as AstNodeImpl); | |
| expect(childAccessor(destination), replacement); | |
| expect(replacement.parent2, destination); | |
| } | |
| } | |
| void _assertSwitchMember(SwitchMember node) { | |
| _assertReplaceInList( | |
| destination: node, | |
| child: node.labels[0], | |
| replacement: node.labels[1], | |
| ); | |
| _assertReplaceInList( | |
| destination: node, | |
| child: node.statements[0], | |
| replacement: node.statements[1], | |
| ); | |
| } | |
| } | |
| @reflectiveTest | |
| class SourceRangeTest { | |
| void test_access() { | |
| SourceRange r = SourceRange(10, 1); | |
| expect(r.offset, 10); | |
| expect(r.length, 1); | |
| expect(r.end, 10 + 1); | |
| // to check | |
| r.hashCode; | |
| } | |
| void test_contains() { | |
| SourceRange r = SourceRange(5, 10); | |
| expect(r.contains(5), isTrue); | |
| expect(r.contains(10), isTrue); | |
| expect(r.contains(15), isTrue); | |
| expect(r.contains(0), isFalse); | |
| expect(r.contains(16), isFalse); | |
| } | |
| void test_containsExclusive() { | |
| SourceRange r = SourceRange(5, 10); | |
| expect(r.containsExclusive(5), isFalse); | |
| expect(r.containsExclusive(10), isTrue); | |
| expect(r.containsExclusive(14), isTrue); | |
| expect(r.containsExclusive(0), isFalse); | |
| expect(r.containsExclusive(15), isFalse); | |
| } | |
| void test_coveredBy() { | |
| SourceRange r = SourceRange(5, 10); | |
| // ends before | |
| expect(r.coveredBy(SourceRange(20, 10)), isFalse); | |
| // starts after | |
| expect(r.coveredBy(SourceRange(0, 3)), isFalse); | |
| // only intersects | |
| expect(r.coveredBy(SourceRange(0, 10)), isFalse); | |
| expect(r.coveredBy(SourceRange(10, 10)), isFalse); | |
| // covered | |
| expect(r.coveredBy(SourceRange(0, 20)), isTrue); | |
| expect(r.coveredBy(SourceRange(5, 10)), isTrue); | |
| } | |
| void test_covers() { | |
| SourceRange r = SourceRange(5, 10); | |
| // ends before | |
| expect(r.covers(SourceRange(0, 3)), isFalse); | |
| // starts after | |
| expect(r.covers(SourceRange(20, 3)), isFalse); | |
| // only intersects | |
| expect(r.covers(SourceRange(0, 10)), isFalse); | |
| expect(r.covers(SourceRange(10, 10)), isFalse); | |
| // covers | |
| expect(r.covers(SourceRange(5, 10)), isTrue); | |
| expect(r.covers(SourceRange(6, 9)), isTrue); | |
| expect(r.covers(SourceRange(6, 8)), isTrue); | |
| } | |
| void test_endsIn() { | |
| SourceRange r = SourceRange(5, 10); | |
| // ends before | |
| expect(r.endsIn(SourceRange(20, 10)), isFalse); | |
| // starts after | |
| expect(r.endsIn(SourceRange(0, 3)), isFalse); | |
| // ends | |
| expect(r.endsIn(SourceRange(10, 20)), isTrue); | |
| expect(r.endsIn(SourceRange(0, 20)), isTrue); | |
| } | |
| void test_equals() { | |
| SourceRange r = SourceRange(10, 1); | |
| // ignore: unrelated_type_equality_checks | |
| expect(r == this, isFalse); | |
| expect(r == SourceRange(20, 2), isFalse); | |
| expect(r == SourceRange(10, 1), isTrue); | |
| expect(r == r, isTrue); | |
| } | |
| void test_getExpanded() { | |
| SourceRange r = SourceRange(5, 3); | |
| expect(r.getExpanded(0), r); | |
| expect(r.getExpanded(2), SourceRange(3, 7)); | |
| expect(r.getExpanded(-1), SourceRange(6, 1)); | |
| } | |
| void test_getMoveEnd() { | |
| SourceRange r = SourceRange(5, 3); | |
| expect(r.getMoveEnd(0), r); | |
| expect(r.getMoveEnd(3), SourceRange(5, 6)); | |
| expect(r.getMoveEnd(-1), SourceRange(5, 2)); | |
| } | |
| void test_getTranslated() { | |
| SourceRange r = SourceRange(5, 3); | |
| expect(r.getTranslated(0), r); | |
| expect(r.getTranslated(2), SourceRange(7, 3)); | |
| expect(r.getTranslated(-1), SourceRange(4, 3)); | |
| } | |
| void test_getUnion() { | |
| expect( | |
| SourceRange(10, 10).getUnion(SourceRange(15, 10)), | |
| SourceRange(10, 15), | |
| ); | |
| expect( | |
| SourceRange(15, 10).getUnion(SourceRange(10, 10)), | |
| SourceRange(10, 15), | |
| ); | |
| // "other" is covered/covers | |
| expect( | |
| SourceRange(10, 10).getUnion(SourceRange(15, 2)), | |
| SourceRange(10, 10), | |
| ); | |
| expect( | |
| SourceRange(15, 2).getUnion(SourceRange(10, 10)), | |
| SourceRange(10, 10), | |
| ); | |
| } | |
| void test_intersects() { | |
| SourceRange r = SourceRange(5, 3); | |
| // null | |
| expect(r.intersects(null), isFalse); | |
| // ends before | |
| expect(r.intersects(SourceRange(0, 5)), isFalse); | |
| // begins after | |
| expect(r.intersects(SourceRange(8, 5)), isFalse); | |
| // begins on same offset | |
| expect(r.intersects(SourceRange(5, 1)), isTrue); | |
| // begins inside, ends inside | |
| expect(r.intersects(SourceRange(6, 1)), isTrue); | |
| // begins inside, ends after | |
| expect(r.intersects(SourceRange(6, 10)), isTrue); | |
| // begins before, ends after | |
| expect(r.intersects(SourceRange(0, 10)), isTrue); | |
| } | |
| void test_startsIn() { | |
| SourceRange r = SourceRange(5, 10); | |
| // ends before | |
| expect(r.startsIn(SourceRange(20, 10)), isFalse); | |
| // starts after | |
| expect(r.startsIn(SourceRange(0, 3)), isFalse); | |
| // starts | |
| expect(r.startsIn(SourceRange(5, 1)), isTrue); | |
| expect(r.startsIn(SourceRange(0, 20)), isTrue); | |
| } | |
| void test_toString() { | |
| SourceRange r = SourceRange(10, 1); | |
| expect(r.toString(), "[offset=10, length=1]"); | |
| } | |
| } | |
| enum _MyEnum { foo, bar } |