|
| 1 | +// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file |
| 2 | +// for details. All rights reserved. Use of this source code is governed by a |
| 3 | +// BSD-style license that can be found in the LICENSE file. |
| 4 | + |
| 5 | +import 'package:analysis_server_plugin/edit/dart/correction_producer.dart'; |
| 6 | +import 'package:analysis_server_plugin/edit/dart/dart_fix_kind_priority.dart'; |
| 7 | +import 'package:analyzer/dart/ast/ast.dart'; |
| 8 | +import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart'; |
| 9 | +import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; |
| 10 | +import 'package:analyzer_plugin/utilities/range_factory.dart'; |
| 11 | + |
| 12 | +import 'utilities.dart'; |
| 13 | + |
| 14 | +class MoveBelowEnclosingTestCall extends ResolvedCorrectionProducer { |
| 15 | + static const _wrapInQuotesKind = FixKind( |
| 16 | + 'dart.fix.moveBelowEnclosingTestCall', |
| 17 | + DartFixKindPriority.standard, |
| 18 | + "Move below the enclosing 'test' call"); |
| 19 | + |
| 20 | + MoveBelowEnclosingTestCall({required super.context}); |
| 21 | + |
| 22 | + @override |
| 23 | + CorrectionApplicability get applicability => |
| 24 | + // This fix may break code by moving references to variables away from the |
| 25 | + // scope in which they are declared. |
| 26 | + CorrectionApplicability.singleLocation; |
| 27 | + |
| 28 | + @override |
| 29 | + FixKind get fixKind => _wrapInQuotesKind; |
| 30 | + |
| 31 | + @override |
| 32 | + Future<void> compute(ChangeBuilder builder) async { |
| 33 | + var methodCall = node; |
| 34 | + if (methodCall is! MethodInvocation) return; |
| 35 | + AstNode? enclosingTestCall = findEnclosingTestCall(methodCall); |
| 36 | + if (enclosingTestCall == null) return; |
| 37 | + |
| 38 | + if (enclosingTestCall.parent is ExpressionStatement) { |
| 39 | + // Move the 'test' call to below the outer 'test' call _statement_. |
| 40 | + enclosingTestCall = enclosingTestCall.parent!; |
| 41 | + } |
| 42 | + |
| 43 | + if (methodCall.parent is ExpressionStatement) { |
| 44 | + // Move the whole statement (don't leave the semicolon dangling). |
| 45 | + methodCall = methodCall.parent!; |
| 46 | + } |
| 47 | + |
| 48 | + await builder.addDartFileEdit(file, (builder) { |
| 49 | + var indent = utils.getLinePrefix(enclosingTestCall!.offset); |
| 50 | + var source = utils.getRangeText(range.node(methodCall)); |
| 51 | + |
| 52 | + // Move the source for `methodCall` wholsale to be just after `enclosingTestCall`. |
| 53 | + builder.addDeletion(range.deletionRange(methodCall)); |
| 54 | + builder.addSimpleInsertion( |
| 55 | + enclosingTestCall.end, '$eol$eol$indent$source'); |
| 56 | + }); |
| 57 | + } |
| 58 | +} |
0 commit comments