blob: 37bb09ba4a6adceb1f0aca199b06d323d4a7a4f5 [file] [log] [blame]
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:nnbd_migration/src/edit_plan.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'abstract_single_unit.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(PassThroughMergingTest);
});
}
/// Tests to make sure the algorithm used by [EditPlaner.passThrough] is
/// correct.
@reflectiveTest
class PassThroughMergingTest extends AbstractSingleUnitTest {
Future<void> test_creates_pass_through_plans_stepwise() async {
await resolveTestUnit('var x = [[[1]]];');
var plan = _EditPlannerForTesting(testCode!).passThrough(
findNode.listLiteral('[[['),
innerPlans: [_MockPlan(findNode.integerLiteral('1'))]);
expect(plan.toString(),
'plan([[[1]]], [plan([[1]], [plan([1], [plan(1)])])])');
}
Future<void> test_merge_plans_at_lower_level() async {
await resolveTestUnit('var x = [[1, 2]];');
var plan = _EditPlannerForTesting(testCode!)
.passThrough(findNode.listLiteral('[['), innerPlans: [
_MockPlan(findNode.integerLiteral('1')),
_MockPlan(findNode.integerLiteral('2'))
]);
expect(
plan.toString(), 'plan([[1, 2]], [plan([1, 2], [plan(1), plan(2)])])');
}
Future<void> test_merge_plans_at_top_level() async {
await resolveTestUnit('var x = [[1], [2]];');
var plan = _EditPlannerForTesting(testCode!)
.passThrough(findNode.listLiteral('[['), innerPlans: [
_MockPlan(findNode.integerLiteral('1')),
_MockPlan(findNode.integerLiteral('2'))
]);
expect(plan.toString(),
'plan([[1], [2]], [plan([1], [plan(1)]), plan([2], [plan(2)])])');
}
Future<void> test_merge_plans_at_varying_levels() async {
await resolveTestUnit('var x = [1, [2, 3], 4];');
var plan = _EditPlannerForTesting(testCode!)
.passThrough(findNode.listLiteral('[1'), innerPlans: [
_MockPlan(findNode.integerLiteral('1')),
_MockPlan(findNode.integerLiteral('2')),
_MockPlan(findNode.integerLiteral('3')),
_MockPlan(findNode.integerLiteral('4'))
]);
expect(
plan.toString(),
'plan([1, [2, 3], 4], [plan(1), plan([2, 3], [plan(2), plan(3)]), '
'plan(4)])');
}
}
class _EditPlannerForTesting extends EditPlanner {
_EditPlannerForTesting(String content)
: super(LineInfo.fromContent(content), content);
@override
PassThroughBuilder createPassThroughBuilder(AstNode? node) =>
_MockPassThroughBuilder(node);
}
class _MockPassThroughBuilder implements PassThroughBuilder {
final List<EditPlan> _innerPlans = [];
@override
final AstNode? node;
_MockPassThroughBuilder(this.node);
@override
void add(EditPlan innerPlan) {
_innerPlans.add(innerPlan);
}
@override
NodeProducingEditPlan finish(EditPlanner planner) {
return _MockPlan(node, _innerPlans);
}
}
class _MockPlan implements NodeProducingEditPlan {
final AstNode? _node;
final List<EditPlan> _innerPlans;
_MockPlan(this._node, [List<EditPlan> innerPlans = const []])
: _innerPlans = innerPlans;
@override
AstNode? get parentNode => _node!.parent;
@override
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
@override
String toString() =>
_innerPlans.isEmpty ? 'plan($_node)' : 'plan($_node, $_innerPlans)';
}