/pkg/analysis_server/lib/src/services/correction/dart/surround_with.dart

https://github.com/dart-lang/sdk · Dart · 364 lines · 292 code · 36 blank · 36 comment · 9 complexity · f095605e11e13e126fc65a313f0d4aca MD5 · raw file

  1. // Copyright (c) 2020, 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. import 'package:analysis_server/src/services/correction/assist.dart';
  5. import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
  6. import 'package:analysis_server/src/services/correction/statement_analyzer.dart';
  7. import 'package:analyzer/dart/ast/ast.dart';
  8. import 'package:analyzer/source/source_range.dart';
  9. import 'package:analyzer_plugin/utilities/assist/assist.dart';
  10. import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
  11. class SurroundWith extends MultiCorrectionProducer {
  12. @override
  13. Iterable<CorrectionProducer> get producers sync* {
  14. // prepare selected statements
  15. var selectionAnalyzer = StatementAnalyzer(
  16. resolvedResult, SourceRange(selectionOffset, selectionLength));
  17. selectionAnalyzer.analyze();
  18. var selectedNodes = selectionAnalyzer.selectedNodes;
  19. // convert nodes to statements
  20. var selectedStatements = <Statement>[];
  21. for (var selectedNode in selectedNodes) {
  22. if (selectedNode is Statement) {
  23. selectedStatements.add(selectedNode);
  24. }
  25. }
  26. // we want only statements in blocks
  27. for (var statement in selectedStatements) {
  28. if (statement.parent is! Block) {
  29. return;
  30. }
  31. }
  32. // we want only statements
  33. if (selectedStatements.isEmpty ||
  34. selectedStatements.length != selectedNodes.length) {
  35. return;
  36. }
  37. // prepare statement information
  38. var firstStatement = selectedStatements[0];
  39. var statementsRange = utils.getLinesRangeStatements(selectedStatements);
  40. // prepare environment
  41. var indentOld = utils.getNodePrefix(firstStatement);
  42. var indentNew = '$indentOld${utils.getIndent(1)}';
  43. var indentedCode =
  44. utils.replaceSourceRangeIndent(statementsRange, indentOld, indentNew);
  45. yield _SurroundWithBlock(
  46. statementsRange, indentOld, indentNew, indentedCode);
  47. yield _SurroundWithDoWhile(
  48. statementsRange, indentOld, indentNew, indentedCode);
  49. yield _SurroundWithFor(statementsRange, indentOld, indentNew, indentedCode);
  50. yield _SurroundWithForIn(
  51. statementsRange, indentOld, indentNew, indentedCode);
  52. yield _SurroundWithIf(statementsRange, indentOld, indentNew, indentedCode);
  53. yield _SurroundWithSetState(
  54. statementsRange, indentOld, indentNew, indentedCode);
  55. yield _SurroundWithTryCatch(
  56. statementsRange, indentOld, indentNew, indentedCode);
  57. yield _SurroundWithTryFinally(
  58. statementsRange, indentOld, indentNew, indentedCode);
  59. yield _SurroundWithWhile(
  60. statementsRange, indentOld, indentNew, indentedCode);
  61. }
  62. /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
  63. static SurroundWith newInstance() => SurroundWith();
  64. }
  65. /// A correction processor that can make one of the possible change computed by
  66. /// the [SurroundWith] producer.
  67. abstract class _SurroundWith extends CorrectionProducer {
  68. final SourceRange statementsRange;
  69. final String indentOld;
  70. final String indentNew;
  71. final String indentedCode;
  72. _SurroundWith(
  73. this.statementsRange, this.indentOld, this.indentNew, this.indentedCode);
  74. }
  75. /// A correction processor that can make one of the possible change computed by
  76. /// the [SurroundWith] producer.
  77. class _SurroundWithBlock extends _SurroundWith {
  78. _SurroundWithBlock(SourceRange statementsRange, String indentOld,
  79. String indentNew, String indentedCode)
  80. : super(statementsRange, indentOld, indentNew, indentedCode);
  81. @override
  82. AssistKind get assistKind => DartAssistKind.SURROUND_WITH_BLOCK;
  83. @override
  84. Future<void> compute(ChangeBuilder builder) async {
  85. await builder.addDartFileEdit(file, (builder) {
  86. builder.addSimpleInsertion(statementsRange.offset, '$indentOld{$eol');
  87. builder.addSimpleReplacement(
  88. statementsRange,
  89. utils.replaceSourceRangeIndent(
  90. statementsRange, indentOld, indentNew));
  91. builder.addSimpleInsertion(statementsRange.end, '$indentOld}$eol');
  92. });
  93. }
  94. }
  95. /// A correction processor that can make one of the possible change computed by
  96. /// the [SurroundWith] producer.
  97. class _SurroundWithDoWhile extends _SurroundWith {
  98. _SurroundWithDoWhile(SourceRange statementsRange, String indentOld,
  99. String indentNew, String indentedCode)
  100. : super(statementsRange, indentOld, indentNew, indentedCode);
  101. @override
  102. AssistKind get assistKind => DartAssistKind.SURROUND_WITH_DO_WHILE;
  103. @override
  104. Future<void> compute(ChangeBuilder builder) async {
  105. await builder.addDartFileEdit(file, (builder) {
  106. builder.addReplacement(statementsRange, (builder) {
  107. builder.write(indentOld);
  108. builder.write('do {');
  109. builder.write(eol);
  110. builder.write(indentedCode);
  111. builder.write(indentOld);
  112. builder.write('} while (');
  113. builder.addSimpleLinkedEdit('CONDITION', 'condition');
  114. builder.write(');');
  115. builder.selectHere();
  116. builder.write(eol);
  117. });
  118. });
  119. }
  120. }
  121. /// A correction processor that can make one of the possible change computed by
  122. /// the [SurroundWith] producer.
  123. class _SurroundWithFor extends _SurroundWith {
  124. _SurroundWithFor(SourceRange statementsRange, String indentOld,
  125. String indentNew, String indentedCode)
  126. : super(statementsRange, indentOld, indentNew, indentedCode);
  127. @override
  128. AssistKind get assistKind => DartAssistKind.SURROUND_WITH_FOR;
  129. @override
  130. Future<void> compute(ChangeBuilder builder) async {
  131. await builder.addDartFileEdit(file, (builder) {
  132. builder.addReplacement(statementsRange, (builder) {
  133. builder.write(indentOld);
  134. builder.write('for (var ');
  135. builder.addSimpleLinkedEdit('VAR', 'v');
  136. builder.write(' = ');
  137. builder.addSimpleLinkedEdit('INIT', 'init');
  138. builder.write('; ');
  139. builder.addSimpleLinkedEdit('CONDITION', 'condition');
  140. builder.write('; ');
  141. builder.addSimpleLinkedEdit('INCREMENT', 'increment');
  142. builder.write(') {');
  143. builder.write(eol);
  144. builder.write(indentedCode);
  145. builder.write(indentOld);
  146. builder.write('}');
  147. builder.selectHere();
  148. builder.write(eol);
  149. });
  150. });
  151. }
  152. }
  153. /// A correction processor that can make one of the possible change computed by
  154. /// the [SurroundWith] producer.
  155. class _SurroundWithForIn extends _SurroundWith {
  156. _SurroundWithForIn(SourceRange statementsRange, String indentOld,
  157. String indentNew, String indentedCode)
  158. : super(statementsRange, indentOld, indentNew, indentedCode);
  159. @override
  160. AssistKind get assistKind => DartAssistKind.SURROUND_WITH_FOR_IN;
  161. @override
  162. Future<void> compute(ChangeBuilder builder) async {
  163. await builder.addDartFileEdit(file, (builder) {
  164. builder.addReplacement(statementsRange, (builder) {
  165. builder.write(indentOld);
  166. builder.write('for (var ');
  167. builder.addSimpleLinkedEdit('NAME', 'item');
  168. builder.write(' in ');
  169. builder.addSimpleLinkedEdit('ITERABLE', 'iterable');
  170. builder.write(') {');
  171. builder.write(eol);
  172. builder.write(indentedCode);
  173. builder.write(indentOld);
  174. builder.write('}');
  175. builder.selectHere();
  176. builder.write(eol);
  177. });
  178. });
  179. }
  180. }
  181. /// A correction processor that can make one of the possible change computed by
  182. /// the [SurroundWith] producer.
  183. class _SurroundWithIf extends _SurroundWith {
  184. _SurroundWithIf(SourceRange statementsRange, String indentOld,
  185. String indentNew, String indentedCode)
  186. : super(statementsRange, indentOld, indentNew, indentedCode);
  187. @override
  188. AssistKind get assistKind => DartAssistKind.SURROUND_WITH_IF;
  189. @override
  190. Future<void> compute(ChangeBuilder builder) async {
  191. await builder.addDartFileEdit(file, (builder) {
  192. builder.addReplacement(statementsRange, (builder) {
  193. builder.write(indentOld);
  194. builder.write('if (');
  195. builder.addSimpleLinkedEdit('CONDITION', 'condition');
  196. builder.write(') {');
  197. builder.write(eol);
  198. builder.write(indentedCode);
  199. builder.write(indentOld);
  200. builder.write('}');
  201. builder.selectHere();
  202. builder.write(eol);
  203. });
  204. });
  205. }
  206. }
  207. /// A correction processor that can make one of the possible change computed by
  208. /// the [SurroundWith] producer.
  209. class _SurroundWithSetState extends _SurroundWith {
  210. _SurroundWithSetState(SourceRange statementsRange, String indentOld,
  211. String indentNew, String indentedCode)
  212. : super(statementsRange, indentOld, indentNew, indentedCode);
  213. @override
  214. AssistKind get assistKind => DartAssistKind.SURROUND_WITH_SET_STATE;
  215. @override
  216. Future<void> compute(ChangeBuilder builder) async {
  217. var classDeclaration = node.parent.thisOrAncestorOfType<ClassDeclaration>();
  218. if (classDeclaration != null &&
  219. flutter.isState(classDeclaration.declaredElement)) {
  220. await builder.addDartFileEdit(file, (builder) {
  221. builder.addReplacement(statementsRange, (builder) {
  222. builder.write(indentOld);
  223. builder.writeln('setState(() {');
  224. builder.write(indentedCode);
  225. builder.write(indentOld);
  226. builder.selectHere();
  227. builder.writeln('});');
  228. });
  229. });
  230. }
  231. }
  232. }
  233. /// A correction processor that can make one of the possible change computed by
  234. /// the [SurroundWith] producer.
  235. class _SurroundWithTryCatch extends _SurroundWith {
  236. _SurroundWithTryCatch(SourceRange statementsRange, String indentOld,
  237. String indentNew, String indentedCode)
  238. : super(statementsRange, indentOld, indentNew, indentedCode);
  239. @override
  240. AssistKind get assistKind => DartAssistKind.SURROUND_WITH_TRY_CATCH;
  241. @override
  242. Future<void> compute(ChangeBuilder builder) async {
  243. await builder.addDartFileEdit(file, (builder) {
  244. builder.addReplacement(statementsRange, (builder) {
  245. builder.write(indentOld);
  246. builder.write('try {');
  247. builder.write(eol);
  248. builder.write(indentedCode);
  249. builder.write(indentOld);
  250. builder.write('} on ');
  251. builder.addSimpleLinkedEdit('EXCEPTION_TYPE', 'Exception');
  252. builder.write(' catch (');
  253. builder.addSimpleLinkedEdit('EXCEPTION_VAR', 'e');
  254. builder.write(') {');
  255. builder.write(eol);
  256. //
  257. builder.write(indentNew);
  258. builder.addSimpleLinkedEdit('CATCH', '// TODO');
  259. builder.selectHere();
  260. builder.write(eol);
  261. //
  262. builder.write(indentOld);
  263. builder.write('}');
  264. builder.write(eol);
  265. });
  266. });
  267. }
  268. }
  269. /// A correction processor that can make one of the possible change computed by
  270. /// the [SurroundWith] producer.
  271. class _SurroundWithTryFinally extends _SurroundWith {
  272. _SurroundWithTryFinally(SourceRange statementsRange, String indentOld,
  273. String indentNew, String indentedCode)
  274. : super(statementsRange, indentOld, indentNew, indentedCode);
  275. @override
  276. AssistKind get assistKind => DartAssistKind.SURROUND_WITH_TRY_FINALLY;
  277. @override
  278. Future<void> compute(ChangeBuilder builder) async {
  279. await builder.addDartFileEdit(file, (builder) {
  280. builder.addReplacement(statementsRange, (builder) {
  281. builder.write(indentOld);
  282. builder.write('try {');
  283. builder.write(eol);
  284. //
  285. builder.write(indentedCode);
  286. //
  287. builder.write(indentOld);
  288. builder.write('} finally {');
  289. builder.write(eol);
  290. //
  291. builder.write(indentNew);
  292. builder.addSimpleLinkedEdit('FINALLY', '// TODO');
  293. builder.selectHere();
  294. builder.write(eol);
  295. //
  296. builder.write(indentOld);
  297. builder.write('}');
  298. builder.write(eol);
  299. });
  300. });
  301. }
  302. }
  303. /// A correction processor that can make one of the possible change computed by
  304. /// the [SurroundWith] producer.
  305. class _SurroundWithWhile extends _SurroundWith {
  306. _SurroundWithWhile(SourceRange statementsRange, String indentOld,
  307. String indentNew, String indentedCode)
  308. : super(statementsRange, indentOld, indentNew, indentedCode);
  309. @override
  310. AssistKind get assistKind => DartAssistKind.SURROUND_WITH_WHILE;
  311. @override
  312. Future<void> compute(ChangeBuilder builder) async {
  313. await builder.addDartFileEdit(file, (builder) {
  314. builder.addReplacement(statementsRange, (builder) {
  315. builder.write(indentOld);
  316. builder.write('while (');
  317. builder.addSimpleLinkedEdit('CONDITION', 'condition');
  318. builder.write(') {');
  319. builder.write(eol);
  320. builder.write(indentedCode);
  321. builder.write(indentOld);
  322. builder.write('}');
  323. builder.selectHere();
  324. builder.write(eol);
  325. });
  326. });
  327. }
  328. }