OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 import 'dart:async'; | 5 import 'dart:async'; |
6 import 'dart:collection'; | 6 import 'dart:collection'; |
7 | 7 |
8 import 'package:analysis_server/plugin/edit/assist/assist_core.dart'; | 8 import 'package:analysis_server/plugin/edit/assist/assist_core.dart'; |
9 import 'package:analysis_server/plugin/edit/assist/assist_dart.dart'; | 9 import 'package:analysis_server/plugin/edit/assist/assist_dart.dart'; |
10 import 'package:analysis_server/src/protocol_server.dart' hide Element; | |
11 import 'package:analysis_server/src/services/correction/assist.dart'; | 10 import 'package:analysis_server/src/services/correction/assist.dart'; |
12 import 'package:analysis_server/src/services/correction/flutter_util.dart'; | 11 import 'package:analysis_server/src/services/correction/flutter_util.dart'; |
13 import 'package:analysis_server/src/services/correction/name_suggestion.dart'; | 12 import 'package:analysis_server/src/services/correction/name_suggestion.dart'; |
14 import 'package:analysis_server/src/services/correction/source_buffer.dart'; | |
15 import 'package:analysis_server/src/services/correction/statement_analyzer.dart'
; | 13 import 'package:analysis_server/src/services/correction/statement_analyzer.dart'
; |
16 import 'package:analysis_server/src/services/correction/util.dart'; | 14 import 'package:analysis_server/src/services/correction/util.dart'; |
17 import 'package:analysis_server/src/services/search/hierarchy.dart'; | 15 import 'package:analysis_server/src/services/search/hierarchy.dart'; |
18 import 'package:analyzer/dart/ast/ast.dart'; | 16 import 'package:analyzer/dart/ast/ast.dart'; |
19 import 'package:analyzer/dart/ast/standard_resolution_map.dart'; | 17 import 'package:analyzer/dart/ast/standard_resolution_map.dart'; |
20 import 'package:analyzer/dart/ast/token.dart'; | 18 import 'package:analyzer/dart/ast/token.dart'; |
21 import 'package:analyzer/dart/ast/visitor.dart'; | 19 import 'package:analyzer/dart/ast/visitor.dart'; |
22 import 'package:analyzer/dart/element/element.dart'; | 20 import 'package:analyzer/dart/element/element.dart'; |
23 import 'package:analyzer/dart/element/type.dart'; | 21 import 'package:analyzer/dart/element/type.dart'; |
24 import 'package:analyzer/src/dart/analysis/driver.dart'; | 22 import 'package:analyzer/src/dart/analysis/driver.dart'; |
25 import 'package:analyzer/src/dart/ast/token.dart'; | 23 import 'package:analyzer/src/dart/ast/token.dart'; |
26 import 'package:analyzer/src/dart/ast/utilities.dart'; | 24 import 'package:analyzer/src/dart/ast/utilities.dart'; |
27 import 'package:analyzer/src/generated/java_core.dart'; | 25 import 'package:analyzer/src/generated/java_core.dart'; |
28 import 'package:analyzer/src/generated/resolver.dart'; | 26 import 'package:analyzer/src/generated/resolver.dart'; |
29 import 'package:analyzer/src/generated/source.dart'; | 27 import 'package:analyzer/src/generated/source.dart'; |
| 28 import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element; |
| 29 import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dar
t'; |
30 import 'package:analyzer_plugin/utilities/range_factory.dart'; | 30 import 'package:analyzer_plugin/utilities/range_factory.dart'; |
31 import 'package:path/path.dart'; | 31 import 'package:path/path.dart'; |
32 | 32 |
33 typedef _SimpleIdentifierVisitor(SimpleIdentifier node); | 33 typedef _SimpleIdentifierVisitor(SimpleIdentifier node); |
34 | 34 |
35 /** | 35 /** |
36 * The computer for Dart assists. | 36 * The computer for Dart assists. |
37 */ | 37 */ |
38 class AssistProcessor { | 38 class AssistProcessor { |
39 /** | 39 /** |
(...skipping 10 matching lines...) Expand all Loading... |
50 | 50 |
51 LibraryElement unitLibraryElement; | 51 LibraryElement unitLibraryElement; |
52 String unitLibraryFile; | 52 String unitLibraryFile; |
53 String unitLibraryFolder; | 53 String unitLibraryFolder; |
54 | 54 |
55 int selectionOffset; | 55 int selectionOffset; |
56 int selectionLength; | 56 int selectionLength; |
57 int selectionEnd; | 57 int selectionEnd; |
58 | 58 |
59 final List<Assist> assists = <Assist>[]; | 59 final List<Assist> assists = <Assist>[]; |
60 final Map<String, LinkedEditGroup> linkedPositionGroups = | 60 |
61 <String, LinkedEditGroup>{}; | |
62 Position exitPosition = null; | 61 Position exitPosition = null; |
63 | 62 |
64 CorrectionUtils utils; | 63 CorrectionUtils utils; |
| 64 |
65 AstNode node; | 65 AstNode node; |
66 | 66 |
67 SourceChange change = new SourceChange('<message>'); | |
68 | |
69 TypeProvider _typeProvider; | 67 TypeProvider _typeProvider; |
70 | 68 |
71 AssistProcessor(DartAssistContext dartContext) { | 69 AssistProcessor(DartAssistContext dartContext) { |
72 driver = dartContext.analysisDriver; | 70 driver = dartContext.analysisDriver; |
73 // source | 71 // source |
74 source = dartContext.source; | 72 source = dartContext.source; |
75 file = dartContext.source.fullName; | 73 file = dartContext.source.fullName; |
76 fileStamp = _modificationStamp(file); | 74 fileStamp = _modificationStamp(file); |
77 // unit | 75 // unit |
78 unit = dartContext.unit; | 76 unit = dartContext.unit; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 try { | 109 try { |
112 utils = new CorrectionUtils(unit); | 110 utils = new CorrectionUtils(unit); |
113 } catch (e) { | 111 } catch (e) { |
114 throw new CancelCorrectionException(exception: e); | 112 throw new CancelCorrectionException(exception: e); |
115 } | 113 } |
116 | 114 |
117 node = new NodeLocator(selectionOffset, selectionEnd).searchWithin(unit); | 115 node = new NodeLocator(selectionOffset, selectionEnd).searchWithin(unit); |
118 if (node == null) { | 116 if (node == null) { |
119 return assists; | 117 return assists; |
120 } | 118 } |
121 // try to add proposals | 119 |
122 _addProposal_addTypeAnnotation_DeclaredIdentifier(); | 120 await _addProposal_addTypeAnnotation_DeclaredIdentifier(); |
123 _addProposal_addTypeAnnotation_SimpleFormalParameter(); | 121 await _addProposal_addTypeAnnotation_SimpleFormalParameter(); |
124 _addProposal_addTypeAnnotation_VariableDeclaration(); | 122 await _addProposal_addTypeAnnotation_VariableDeclaration(); |
125 _addProposal_assignToLocalVariable(); | 123 await _addProposal_assignToLocalVariable(); |
126 _addProposal_convertIntoFinalField(); | 124 await _addProposal_convertIntoFinalField(); |
127 _addProposal_convertIntoGetter(); | 125 await _addProposal_convertIntoGetter(); |
128 _addProposal_convertDocumentationIntoBlock(); | 126 await _addProposal_convertDocumentationIntoBlock(); |
129 _addProposal_convertDocumentationIntoLine(); | 127 await _addProposal_convertDocumentationIntoLine(); |
130 _addProposal_convertToBlockFunctionBody(); | 128 await _addProposal_convertToBlockFunctionBody(); |
131 _addProposal_convertToExpressionFunctionBody(); | 129 await _addProposal_convertToExpressionFunctionBody(); |
132 _addProposal_convertFlutterChild(); | 130 await _addProposal_convertFlutterChild(); |
133 _addProposal_convertToForIndexLoop(); | 131 await _addProposal_convertToForIndexLoop(); |
134 _addProposal_convertToIsNot_onIs(); | 132 await _addProposal_convertToIsNot_onIs(); |
135 _addProposal_convertToIsNot_onNot(); | 133 await _addProposal_convertToIsNot_onNot(); |
136 _addProposal_convertToIsNotEmpty(); | 134 await _addProposal_convertToIsNotEmpty(); |
137 _addProposal_convertToFieldParameter(); | 135 await _addProposal_convertToFieldParameter(); |
138 _addProposal_convertToNormalParameter(); | 136 await _addProposal_convertToNormalParameter(); |
139 _addProposal_encapsulateField(); | 137 await _addProposal_encapsulateField(); |
140 _addProposal_exchangeOperands(); | 138 await _addProposal_exchangeOperands(); |
141 _addProposal_importAddShow(); | 139 await _addProposal_importAddShow(); |
142 _addProposal_introduceLocalTestedType(); | 140 await _addProposal_introduceLocalTestedType(); |
143 _addProposal_invertIf(); | 141 await _addProposal_invertIf(); |
144 _addProposal_joinIfStatementInner(); | 142 await _addProposal_joinIfStatementInner(); |
145 _addProposal_joinIfStatementOuter(); | 143 await _addProposal_joinIfStatementOuter(); |
146 _addProposal_joinVariableDeclaration_onAssignment(); | 144 await _addProposal_joinVariableDeclaration_onAssignment(); |
147 _addProposal_joinVariableDeclaration_onDeclaration(); | 145 await _addProposal_joinVariableDeclaration_onDeclaration(); |
148 _addProposal_moveFlutterWidgetDown(); | 146 await _addProposal_moveFlutterWidgetDown(); |
149 _addProposal_moveFlutterWidgetUp(); | 147 await _addProposal_moveFlutterWidgetUp(); |
150 _addProposal_removeTypeAnnotation(); | 148 await _addProposal_removeTypeAnnotation(); |
151 _addProposal_reparentFlutterList(); | 149 await _addProposal_reparentFlutterList(); |
152 _addProposal_reparentFlutterWidget(); | 150 await _addProposal_reparentFlutterWidget(); |
153 _addProposal_replaceConditionalWithIfElse(); | 151 await _addProposal_replaceConditionalWithIfElse(); |
154 _addProposal_replaceIfElseWithConditional(); | 152 await _addProposal_replaceIfElseWithConditional(); |
155 _addProposal_splitAndCondition(); | 153 await _addProposal_splitAndCondition(); |
156 _addProposal_splitVariableDeclaration(); | 154 await _addProposal_splitVariableDeclaration(); |
157 _addProposal_surroundWith(); | 155 await _addProposal_surroundWith(); |
158 // done | 156 |
159 return assists; | 157 return assists; |
160 } | 158 } |
161 | 159 |
162 FunctionBody getEnclosingFunctionBody() { | 160 FunctionBody getEnclosingFunctionBody() { |
163 { | 161 { |
164 FunctionExpression function = | 162 FunctionExpression function = |
165 node.getAncestor((node) => node is FunctionExpression); | 163 node.getAncestor((node) => node is FunctionExpression); |
166 if (function != null) { | 164 if (function != null) { |
167 return function.body; | 165 return function.body; |
168 } | 166 } |
(...skipping 15 matching lines...) Expand all Loading... |
184 { | 182 { |
185 MethodDeclaration method = | 183 MethodDeclaration method = |
186 node.getAncestor((node) => node is MethodDeclaration); | 184 node.getAncestor((node) => node is MethodDeclaration); |
187 if (method != null) { | 185 if (method != null) { |
188 return method.body; | 186 return method.body; |
189 } | 187 } |
190 } | 188 } |
191 return null; | 189 return null; |
192 } | 190 } |
193 | 191 |
194 void _addAssist(AssistKind kind, List args, {String assistFile}) { | 192 void _addAssistFromBuilder(DartChangeBuilder builder, AssistKind kind, |
195 if (assistFile == null) { | 193 {List args: null}) { |
196 assistFile = file; | 194 SourceChange change = builder.sourceChange; |
197 } | |
198 // check is there are any edits | |
199 if (change.edits.isEmpty) { | 195 if (change.edits.isEmpty) { |
200 _coverageMarker(); | 196 _coverageMarker(); |
201 return; | 197 return; |
202 } | 198 } |
203 // prepare Change | |
204 change.message = formatList(kind.message, args); | 199 change.message = formatList(kind.message, args); |
205 linkedPositionGroups.values | 200 assists.add(new Assist(kind, change)); |
206 .forEach((group) => change.addLinkedEditGroup(group)); | |
207 change.selection = exitPosition; | |
208 // add Assist | |
209 Assist assist = new Assist(kind, change); | |
210 assists.add(assist); | |
211 // clear | |
212 change = new SourceChange('<message>'); | |
213 linkedPositionGroups.clear(); | |
214 exitPosition = null; | |
215 } | 201 } |
216 | 202 |
217 void _addIndentEdit(SourceRange range, String oldIndent, String newIndent) { | 203 Future<Null> _addProposal_addTypeAnnotation_DeclaredIdentifier() async { |
218 SourceEdit edit = utils.createIndentEdit(range, oldIndent, newIndent); | |
219 doSourceChange_addElementEdit(change, unitElement, edit); | |
220 } | |
221 | |
222 /** | |
223 * Adds a new [Edit] to [edits]. | |
224 */ | |
225 void _addInsertEdit(int offset, String text) { | |
226 SourceEdit edit = new SourceEdit(offset, 0, text); | |
227 doSourceChange_addElementEdit(change, unitElement, edit); | |
228 } | |
229 | |
230 void _addProposal_addTypeAnnotation_DeclaredIdentifier() { | |
231 DeclaredIdentifier declaredIdentifier = | 204 DeclaredIdentifier declaredIdentifier = |
232 node.getAncestor((n) => n is DeclaredIdentifier); | 205 node.getAncestor((n) => n is DeclaredIdentifier); |
233 if (declaredIdentifier == null) { | 206 if (declaredIdentifier == null) { |
234 ForEachStatement forEach = node.getAncestor((n) => n is ForEachStatement); | 207 ForEachStatement forEach = node.getAncestor((n) => n is ForEachStatement); |
235 int offset = node.offset; | 208 int offset = node.offset; |
236 if (forEach != null && | 209 if (forEach != null && |
237 forEach.iterable != null && | 210 forEach.iterable != null && |
238 offset < forEach.iterable.offset) { | 211 offset < forEach.iterable.offset) { |
239 declaredIdentifier = forEach.loopVariable; | 212 declaredIdentifier = forEach.loopVariable; |
240 } | 213 } |
241 } | 214 } |
242 if (declaredIdentifier == null) { | 215 if (declaredIdentifier == null) { |
243 _coverageMarker(); | 216 _coverageMarker(); |
244 return; | 217 return; |
245 } | 218 } |
246 // may be has type annotation already | 219 // Ensure that there isn't already a type annotation. |
247 if (declaredIdentifier.type != null) { | 220 if (declaredIdentifier.type != null) { |
248 _coverageMarker(); | 221 _coverageMarker(); |
249 return; | 222 return; |
250 } | 223 } |
251 // prepare type source | |
252 String typeSource; | |
253 DartType type = declaredIdentifier.identifier.bestType; | 224 DartType type = declaredIdentifier.identifier.bestType; |
254 if (type is InterfaceType || type is FunctionType) { | 225 if (type is! InterfaceType && type is! FunctionType) { |
255 _configureTargetLocation(node); | |
256 Set<Source> librariesToImport = new Set<Source>(); | |
257 typeSource = utils.getTypeSource(type, librariesToImport); | |
258 addLibraryImports(change, unitLibraryElement, librariesToImport); | |
259 } else { | |
260 _coverageMarker(); | 226 _coverageMarker(); |
261 return; | 227 return; |
262 } | 228 } |
263 // type source might be null, if the type is private | 229 _configureTargetLocation(node); |
| 230 Set<Source> librariesToImport = new Set<Source>(); |
| 231 String typeSource = utils.getTypeSource(type, librariesToImport); |
264 if (typeSource == null) { | 232 if (typeSource == null) { |
| 233 // The type source might be null if the type is private. |
265 _coverageMarker(); | 234 _coverageMarker(); |
266 return; | 235 return; |
267 } | 236 } |
268 // add edit | 237 |
269 Token keyword = declaredIdentifier.keyword; | 238 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
270 if (keyword.keyword == Keyword.VAR) { | 239 await changeBuilder.addFileEdit(file, fileStamp, |
271 _addReplaceEdit(range.token(keyword), typeSource); | 240 (DartFileEditBuilder builder) { |
272 } else { | 241 Token keyword = declaredIdentifier.keyword; |
273 _addInsertEdit(declaredIdentifier.identifier.offset, '$typeSource '); | 242 if (keyword.keyword == Keyword.VAR) { |
274 } | 243 builder.addSimpleReplacement(range.token(keyword), typeSource); |
275 // add proposal | 244 } else { |
276 _addAssist(DartAssistKind.ADD_TYPE_ANNOTATION, []); | 245 builder.addSimpleInsertion( |
| 246 declaredIdentifier.identifier.offset, '$typeSource '); |
| 247 } |
| 248 builder.importLibraries(librariesToImport); |
| 249 }); |
| 250 _addAssistFromBuilder(changeBuilder, DartAssistKind.ADD_TYPE_ANNOTATION); |
277 } | 251 } |
278 | 252 |
279 void _addProposal_addTypeAnnotation_SimpleFormalParameter() { | 253 Future<Null> _addProposal_addTypeAnnotation_SimpleFormalParameter() async { |
280 AstNode node = this.node; | 254 AstNode node = this.node; |
281 // should be the name of a simple parameter | 255 // should be the name of a simple parameter |
282 if (node is! SimpleIdentifier || node.parent is! SimpleFormalParameter) { | 256 if (node is! SimpleIdentifier || node.parent is! SimpleFormalParameter) { |
283 _coverageMarker(); | 257 _coverageMarker(); |
284 return; | 258 return; |
285 } | 259 } |
286 SimpleIdentifier name = node; | 260 SimpleIdentifier name = node; |
287 SimpleFormalParameter parameter = node.parent; | 261 SimpleFormalParameter parameter = node.parent; |
288 // the parameter should not have a type | 262 // the parameter should not have a type |
289 if (parameter.type != null) { | 263 if (parameter.type != null) { |
290 _coverageMarker(); | 264 _coverageMarker(); |
291 return; | 265 return; |
292 } | 266 } |
293 // prepare the type | 267 // prepare the type |
294 DartType type = parameter.element.type; | 268 DartType type = parameter.element.type; |
295 // TODO(scheglov) If the parameter is in a method declaration, and if the | 269 // TODO(scheglov) If the parameter is in a method declaration, and if the |
296 // method overrides a method that has a type for the corresponding | 270 // method overrides a method that has a type for the corresponding |
297 // parameter, it would be nice to copy down the type from the overridden | 271 // parameter, it would be nice to copy down the type from the overridden |
298 // method. | 272 // method. |
299 if (type is! InterfaceType) { | 273 if (type is! InterfaceType) { |
300 _coverageMarker(); | 274 _coverageMarker(); |
301 return; | 275 return; |
302 } | 276 } |
303 // prepare type source | 277 // prepare type source |
304 String typeSource; | 278 _configureTargetLocation(node); |
305 { | 279 Set<Source> librariesToImport = new Set<Source>(); |
306 _configureTargetLocation(node); | 280 String typeSource = utils.getTypeSource(type, librariesToImport); |
307 Set<Source> librariesToImport = new Set<Source>(); | |
308 typeSource = utils.getTypeSource(type, librariesToImport); | |
309 addLibraryImports(change, unitLibraryElement, librariesToImport); | |
310 } | |
311 // type source might be null, if the type is private | 281 // type source might be null, if the type is private |
312 if (typeSource == null) { | 282 if (typeSource == null) { |
313 _coverageMarker(); | 283 _coverageMarker(); |
314 return; | 284 return; |
315 } | 285 } |
316 // add edit | 286 |
317 _addInsertEdit(name.offset, '$typeSource '); | 287 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
318 // add proposal | 288 await changeBuilder.addFileEdit(file, fileStamp, |
319 _addAssist(DartAssistKind.ADD_TYPE_ANNOTATION, []); | 289 (DartFileEditBuilder builder) { |
| 290 builder.addSimpleInsertion(name.offset, '$typeSource '); |
| 291 builder.importLibraries(librariesToImport); |
| 292 }); |
| 293 _addAssistFromBuilder(changeBuilder, DartAssistKind.ADD_TYPE_ANNOTATION); |
320 } | 294 } |
321 | 295 |
322 void _addProposal_addTypeAnnotation_VariableDeclaration() { | 296 Future<Null> _addProposal_addTypeAnnotation_VariableDeclaration() async { |
323 AstNode node = this.node; | 297 AstNode node = this.node; |
324 // prepare VariableDeclarationList | 298 // prepare VariableDeclarationList |
325 VariableDeclarationList declarationList = | 299 VariableDeclarationList declarationList = |
326 node.getAncestor((node) => node is VariableDeclarationList); | 300 node.getAncestor((node) => node is VariableDeclarationList); |
327 if (declarationList == null) { | 301 if (declarationList == null) { |
328 _coverageMarker(); | 302 _coverageMarker(); |
329 return; | 303 return; |
330 } | 304 } |
331 // may be has type annotation already | 305 // may be has type annotation already |
332 if (declarationList.type != null) { | 306 if (declarationList.type != null) { |
(...skipping 13 matching lines...) Expand all Loading... |
346 return; | 320 return; |
347 } | 321 } |
348 // we need an initializer to get the type from | 322 // we need an initializer to get the type from |
349 Expression initializer = variable.initializer; | 323 Expression initializer = variable.initializer; |
350 if (initializer == null) { | 324 if (initializer == null) { |
351 _coverageMarker(); | 325 _coverageMarker(); |
352 return; | 326 return; |
353 } | 327 } |
354 DartType type = initializer.bestType; | 328 DartType type = initializer.bestType; |
355 // prepare type source | 329 // prepare type source |
356 String typeSource; | 330 if ((type is! InterfaceType || type.isDartCoreNull) && |
357 if (type is InterfaceType && !type.isDartCoreNull || type is FunctionType) { | 331 type is! FunctionType) { |
358 _configureTargetLocation(node); | |
359 Set<Source> librariesToImport = new Set<Source>(); | |
360 typeSource = utils.getTypeSource(type, librariesToImport); | |
361 addLibraryImports(change, unitLibraryElement, librariesToImport); | |
362 } else { | |
363 _coverageMarker(); | 332 _coverageMarker(); |
364 return; | 333 return; |
365 } | 334 } |
| 335 _configureTargetLocation(node); |
| 336 Set<Source> librariesToImport = new Set<Source>(); |
| 337 String typeSource = utils.getTypeSource(type, librariesToImport); |
366 // type source might be null, if the type is private | 338 // type source might be null, if the type is private |
367 if (typeSource == null) { | 339 if (typeSource == null) { |
368 _coverageMarker(); | 340 _coverageMarker(); |
369 return; | 341 return; |
370 } | 342 } |
371 // add edit | 343 |
372 Token keyword = declarationList.keyword; | 344 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
373 if (keyword?.keyword == Keyword.VAR) { | 345 if (unitLibraryFile == file) { |
374 _addReplaceEdit(range.token(keyword), typeSource); | 346 // TODO(brianwilkerson) Make ChangeBuilder merge multiple edits to the |
| 347 // same file so that only the else block is necessary. |
| 348 await changeBuilder.addFileEdit(file, fileStamp, |
| 349 (DartFileEditBuilder builder) { |
| 350 Token keyword = declarationList.keyword; |
| 351 if (keyword?.keyword == Keyword.VAR) { |
| 352 builder.addSimpleReplacement(range.token(keyword), typeSource); |
| 353 } else { |
| 354 builder.addSimpleInsertion(variable.offset, '$typeSource '); |
| 355 } |
| 356 builder.importLibraries(librariesToImport); |
| 357 }); |
375 } else { | 358 } else { |
376 _addInsertEdit(variable.offset, '$typeSource '); | 359 await changeBuilder.addFileEdit(file, fileStamp, |
| 360 (DartFileEditBuilder builder) { |
| 361 Token keyword = declarationList.keyword; |
| 362 if (keyword?.keyword == Keyword.VAR) { |
| 363 builder.addSimpleReplacement(range.token(keyword), typeSource); |
| 364 } else { |
| 365 builder.addSimpleInsertion(variable.offset, '$typeSource '); |
| 366 } |
| 367 }); |
| 368 await changeBuilder |
| 369 .addFileEdit(unitLibraryFile, _modificationStamp(unitLibraryFile), |
| 370 (DartFileEditBuilder builder) { |
| 371 builder.importLibraries(librariesToImport); |
| 372 }); |
377 } | 373 } |
378 // add proposal | 374 _addAssistFromBuilder(changeBuilder, DartAssistKind.ADD_TYPE_ANNOTATION); |
379 _addAssist(DartAssistKind.ADD_TYPE_ANNOTATION, []); | |
380 } | 375 } |
381 | 376 |
382 void _addProposal_assignToLocalVariable() { | 377 Future<Null> _addProposal_assignToLocalVariable() async { |
383 // prepare enclosing ExpressionStatement | 378 // prepare enclosing ExpressionStatement |
384 ExpressionStatement expressionStatement; | 379 ExpressionStatement expressionStatement; |
385 for (AstNode node = this.node; node != null; node = node.parent) { | 380 for (AstNode node = this.node; node != null; node = node.parent) { |
386 if (node is ExpressionStatement) { | 381 if (node is ExpressionStatement) { |
387 expressionStatement = node; | 382 expressionStatement = node; |
388 break; | 383 break; |
389 } | 384 } |
390 if (node is ArgumentList || | 385 if (node is ArgumentList || |
391 node is AssignmentExpression || | 386 node is AssignmentExpression || |
392 node is Statement || | 387 node is Statement || |
393 node is ThrowExpression) { | 388 node is ThrowExpression) { |
394 _coverageMarker(); | 389 _coverageMarker(); |
395 return; | 390 return; |
396 } | 391 } |
397 } | 392 } |
398 if (expressionStatement == null) { | 393 if (expressionStatement == null) { |
399 _coverageMarker(); | 394 _coverageMarker(); |
400 return; | 395 return; |
401 } | 396 } |
402 // prepare expression | 397 // prepare expression |
403 Expression expression = expressionStatement.expression; | 398 Expression expression = expressionStatement.expression; |
404 int offset = expression.offset; | 399 int offset = expression.offset; |
405 // prepare expression type | 400 // prepare expression type |
406 DartType type = expression.bestType; | 401 DartType type = expression.bestType; |
407 if (type.isVoid) { | 402 if (type.isVoid) { |
408 _coverageMarker(); | 403 _coverageMarker(); |
409 return; | 404 return; |
410 } | 405 } |
411 // prepare source | |
412 SourceBuilder builder = new SourceBuilder(file, offset); | |
413 builder.append('var '); | |
414 // prepare excluded names | 406 // prepare excluded names |
415 Set<String> excluded = new Set<String>(); | 407 Set<String> excluded = new Set<String>(); |
416 { | 408 ScopedNameFinder scopedNameFinder = new ScopedNameFinder(offset); |
417 ScopedNameFinder scopedNameFinder = new ScopedNameFinder(offset); | 409 expression.accept(scopedNameFinder); |
418 expression.accept(scopedNameFinder); | 410 excluded.addAll(scopedNameFinder.locals.keys.toSet()); |
419 excluded.addAll(scopedNameFinder.locals.keys.toSet()); | 411 List<String> suggestions = |
| 412 getVariableNameSuggestionsForExpression(type, expression, excluded); |
| 413 |
| 414 if (suggestions.isNotEmpty) { |
| 415 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
| 416 await changeBuilder.addFileEdit(file, fileStamp, |
| 417 (DartFileEditBuilder builder) { |
| 418 builder.addInsertion(offset, (DartEditBuilder builder) { |
| 419 builder.write('var '); |
| 420 builder.addSimpleLinkedEdit('NAME', suggestions[0], |
| 421 kind: LinkedEditSuggestionKind.VARIABLE, |
| 422 suggestions: suggestions); |
| 423 builder.write(' = '); |
| 424 }); |
| 425 }); |
| 426 _addAssistFromBuilder( |
| 427 changeBuilder, DartAssistKind.ASSIGN_TO_LOCAL_VARIABLE); |
420 } | 428 } |
421 // name(s) | |
422 { | |
423 List<String> suggestions = | |
424 getVariableNameSuggestionsForExpression(type, expression, excluded); | |
425 builder.startPosition('NAME'); | |
426 for (int i = 0; i < suggestions.length; i++) { | |
427 String name = suggestions[i]; | |
428 if (i == 0) { | |
429 builder.append(name); | |
430 } | |
431 builder.addSuggestion(LinkedEditSuggestionKind.VARIABLE, name); | |
432 } | |
433 builder.endPosition(); | |
434 } | |
435 builder.append(' = '); | |
436 // add proposal | |
437 _insertBuilder(builder); | |
438 _addAssist(DartAssistKind.ASSIGN_TO_LOCAL_VARIABLE, []); | |
439 } | 429 } |
440 | 430 |
441 void _addProposal_convertDocumentationIntoBlock() { | 431 Future<Null> _addProposal_convertDocumentationIntoBlock() async { |
442 Comment comment = node.getAncestor((n) => n is Comment); | 432 Comment comment = node.getAncestor((n) => n is Comment); |
443 if (comment != null && comment.isDocumentation) { | 433 if (comment == null || !comment.isDocumentation) { |
444 String prefix = utils.getNodePrefix(comment); | 434 return; |
445 SourceBuilder sb = new SourceBuilder(file, comment.offset); | 435 } |
446 sb.append('/**'); | 436 var tokens = comment.tokens; |
447 sb.append(eol); | 437 if (tokens.isEmpty || |
448 for (Token token in comment.tokens) { | 438 tokens.any((Token token) => |
449 if (token is DocumentationCommentToken && | 439 token is! DocumentationCommentToken || |
450 token.type == TokenType.SINGLE_LINE_COMMENT) { | 440 token.type != TokenType.SINGLE_LINE_COMMENT)) { |
451 sb.append(prefix); | 441 return; |
452 sb.append(' *'); | 442 } |
453 sb.append(token.lexeme.substring('///'.length)); | 443 String prefix = utils.getNodePrefix(comment); |
454 sb.append(eol); | 444 |
455 } else { | 445 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
| 446 await changeBuilder.addFileEdit(file, fileStamp, |
| 447 (DartFileEditBuilder builder) { |
| 448 builder.addReplacement(range.node(comment), (DartEditBuilder builder) { |
| 449 builder.writeln('/**'); |
| 450 for (Token token in comment.tokens) { |
| 451 builder.write(prefix); |
| 452 builder.write(' *'); |
| 453 builder.writeln(token.lexeme.substring('///'.length)); |
| 454 } |
| 455 builder.write(prefix); |
| 456 builder.write(' */'); |
| 457 }); |
| 458 }); |
| 459 _addAssistFromBuilder( |
| 460 changeBuilder, DartAssistKind.CONVERT_DOCUMENTATION_INTO_BLOCK); |
| 461 } |
| 462 |
| 463 Future<Null> _addProposal_convertDocumentationIntoLine() async { |
| 464 Comment comment = node.getAncestor((n) => n is Comment); |
| 465 if (comment == null || |
| 466 !comment.isDocumentation || |
| 467 comment.tokens.length != 1) { |
| 468 _coverageMarker(); |
| 469 return; |
| 470 } |
| 471 Token token = comment.tokens.first; |
| 472 if (token.type != TokenType.MULTI_LINE_COMMENT) { |
| 473 _coverageMarker(); |
| 474 return; |
| 475 } |
| 476 String text = token.lexeme; |
| 477 List<String> lines = text.split('\n'); |
| 478 String prefix = utils.getNodePrefix(comment); |
| 479 List<String> newLines = <String>[]; |
| 480 bool firstLine = true; |
| 481 String linePrefix = ''; |
| 482 for (String line in lines) { |
| 483 if (firstLine) { |
| 484 firstLine = false; |
| 485 String expectedPrefix = '/**'; |
| 486 if (!line.startsWith(expectedPrefix)) { |
| 487 _coverageMarker(); |
456 return; | 488 return; |
457 } | 489 } |
| 490 line = line.substring(expectedPrefix.length).trim(); |
| 491 if (line.isNotEmpty) { |
| 492 newLines.add('/// $line'); |
| 493 linePrefix = eol + prefix; |
| 494 } |
| 495 } else { |
| 496 if (line.startsWith(prefix + ' */')) { |
| 497 break; |
| 498 } |
| 499 String expectedPrefix = prefix + ' * '; |
| 500 if (!line.startsWith(expectedPrefix)) { |
| 501 _coverageMarker(); |
| 502 return; |
| 503 } |
| 504 line = line.substring(expectedPrefix.length).trim(); |
| 505 newLines.add('$linePrefix/// $line'); |
| 506 linePrefix = eol + prefix; |
458 } | 507 } |
459 sb.append(prefix); | |
460 sb.append(' */'); | |
461 _insertBuilder(sb, comment.length); | |
462 } | 508 } |
463 // add proposal | 509 |
464 _addAssist(DartAssistKind.CONVERT_DOCUMENTATION_INTO_BLOCK, []); | 510 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
| 511 await changeBuilder.addFileEdit(file, fileStamp, |
| 512 (DartFileEditBuilder builder) { |
| 513 builder.addReplacement(range.node(comment), (DartEditBuilder builder) { |
| 514 for (String newLine in newLines) { |
| 515 builder.write(newLine); |
| 516 } |
| 517 }); |
| 518 }); |
| 519 _addAssistFromBuilder( |
| 520 changeBuilder, DartAssistKind.CONVERT_DOCUMENTATION_INTO_LINE); |
465 } | 521 } |
466 | 522 |
467 void _addProposal_convertDocumentationIntoLine() { | 523 Future<Null> _addProposal_convertFlutterChild() async { |
468 Comment comment = node.getAncestor((n) => n is Comment); | |
469 if (comment != null && comment.isDocumentation) { | |
470 if (comment.tokens.length == 1) { | |
471 Token token = comment.tokens.first; | |
472 if (token.type == TokenType.MULTI_LINE_COMMENT) { | |
473 String text = token.lexeme; | |
474 List<String> lines = text.split('\n'); | |
475 String prefix = utils.getNodePrefix(comment); | |
476 SourceBuilder sb = new SourceBuilder(file, comment.offset); | |
477 bool firstLine = true; | |
478 String linePrefix = ''; | |
479 for (String line in lines) { | |
480 if (firstLine) { | |
481 firstLine = false; | |
482 String expectedPrefix = '/**'; | |
483 if (!line.startsWith(expectedPrefix)) { | |
484 return; | |
485 } | |
486 line = line.substring(expectedPrefix.length).trim(); | |
487 if (line.isNotEmpty) { | |
488 sb.append('/// '); | |
489 sb.append(line); | |
490 linePrefix = eol + prefix; | |
491 } | |
492 } else { | |
493 if (line.startsWith(prefix + ' */')) { | |
494 break; | |
495 } | |
496 String expectedPrefix = prefix + ' * '; | |
497 if (!line.startsWith(expectedPrefix)) { | |
498 return; | |
499 } | |
500 line = line.substring(expectedPrefix.length).trim(); | |
501 sb.append(linePrefix); | |
502 sb.append('/// '); | |
503 sb.append(line); | |
504 linePrefix = eol + prefix; | |
505 } | |
506 } | |
507 _insertBuilder(sb, comment.length); | |
508 } | |
509 } | |
510 } | |
511 // add proposal | |
512 _addAssist(DartAssistKind.CONVERT_DOCUMENTATION_INTO_LINE, []); | |
513 } | |
514 | |
515 void _addProposal_convertFlutterChild() { | |
516 NamedExpression namedExp; | 524 NamedExpression namedExp; |
517 // Allow assist to activate from either the new-expr or the child: arg. | 525 // Allow assist to activate from either the new-expr or the child: arg. |
518 if (node is SimpleIdentifier && | 526 if (node is SimpleIdentifier && |
519 node.parent is Label && | 527 node.parent is Label && |
520 node.parent.parent is NamedExpression) { | 528 node.parent.parent is NamedExpression) { |
521 namedExp = node.parent.parent as NamedExpression; | 529 namedExp = node.parent.parent as NamedExpression; |
522 if ((node as SimpleIdentifier).name != 'child' || | 530 if ((node as SimpleIdentifier).name != 'child' || |
523 namedExp.expression == null) { | 531 namedExp.expression == null) { |
524 return; | 532 return; |
525 } | 533 } |
(...skipping 14 matching lines...) Expand all Loading... |
540 if (namedExp == null || namedExp.expression == null) { | 548 if (namedExp == null || namedExp.expression == null) { |
541 _coverageMarker(); | 549 _coverageMarker(); |
542 return; | 550 return; |
543 } | 551 } |
544 } | 552 } |
545 InstanceCreationExpression childArg = getChildWidget(namedExp, false); | 553 InstanceCreationExpression childArg = getChildWidget(namedExp, false); |
546 if (childArg == null) { | 554 if (childArg == null) { |
547 _coverageMarker(); | 555 _coverageMarker(); |
548 return; | 556 return; |
549 } | 557 } |
550 convertFlutterChildToChildren( | 558 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
551 childArg, | 559 await changeBuilder.addFileEdit(file, fileStamp, |
552 namedExp, | 560 (DartFileEditBuilder builder) { |
553 eol, | 561 _convertFlutterChildToChildren(childArg, namedExp, eol, utils.getNodeText, |
554 utils.getNodeText, | 562 utils.getLinePrefix, utils.getIndent, utils.getText, builder); |
555 utils.getLinePrefix, | 563 }); |
556 utils.getIndent, | 564 _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_FLUTTER_CHILD); |
557 utils.getText, | |
558 _addInsertEdit, | |
559 _addRemoveEdit, | |
560 _addReplaceEdit, | |
561 range.node); | |
562 _addAssist(DartAssistKind.CONVERT_FLUTTER_CHILD, []); | |
563 } | 565 } |
564 | 566 |
565 void _addProposal_convertIntoFinalField() { | 567 Future<Null> _addProposal_convertIntoFinalField() async { |
566 // Find the enclosing getter. | 568 // Find the enclosing getter. |
567 MethodDeclaration getter; | 569 MethodDeclaration getter; |
568 for (AstNode n = node; n != null; n = n.parent) { | 570 for (AstNode n = node; n != null; n = n.parent) { |
569 if (n is MethodDeclaration) { | 571 if (n is MethodDeclaration) { |
570 getter = n; | 572 getter = n; |
571 break; | 573 break; |
572 } | 574 } |
573 if (n is SimpleIdentifier || | 575 if (n is SimpleIdentifier || |
574 n is TypeAnnotation || | 576 n is TypeAnnotation || |
575 n is TypeArgumentList) { | 577 n is TypeArgumentList) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
615 String code = 'final'; | 617 String code = 'final'; |
616 if (getter.returnType != null) { | 618 if (getter.returnType != null) { |
617 beginNodeToReplace = getter.returnType; | 619 beginNodeToReplace = getter.returnType; |
618 code += ' ' + _getNodeText(getter.returnType); | 620 code += ' ' + _getNodeText(getter.returnType); |
619 } | 621 } |
620 code += ' ' + _getNodeText(getter.name); | 622 code += ' ' + _getNodeText(getter.name); |
621 if (expression is! NullLiteral) { | 623 if (expression is! NullLiteral) { |
622 code += ' = ' + _getNodeText(expression); | 624 code += ' = ' + _getNodeText(expression); |
623 } | 625 } |
624 code += ';'; | 626 code += ';'; |
625 _addReplaceEdit(range.startEnd(beginNodeToReplace, getter), code); | 627 SourceRange replacementRange = range.startEnd(beginNodeToReplace, getter); |
626 _addAssist(DartAssistKind.CONVERT_INTO_FINAL_FIELD, []); | 628 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
| 629 await changeBuilder.addFileEdit(file, fileStamp, |
| 630 (DartFileEditBuilder builder) { |
| 631 builder.addSimpleReplacement(replacementRange, code); |
| 632 }); |
| 633 _addAssistFromBuilder( |
| 634 changeBuilder, DartAssistKind.CONVERT_INTO_FINAL_FIELD); |
627 } | 635 } |
628 } | 636 } |
629 | 637 |
630 void _addProposal_convertIntoGetter() { | 638 Future<Null> _addProposal_convertIntoGetter() async { |
631 // Find the enclosing field declaration. | 639 // Find the enclosing field declaration. |
632 FieldDeclaration fieldDeclaration; | 640 FieldDeclaration fieldDeclaration; |
633 for (AstNode n = node; n != null; n = n.parent) { | 641 for (AstNode n = node; n != null; n = n.parent) { |
634 if (n is FieldDeclaration) { | 642 if (n is FieldDeclaration) { |
635 fieldDeclaration = n; | 643 fieldDeclaration = n; |
636 break; | 644 break; |
637 } | 645 } |
638 if (n is SimpleIdentifier || | 646 if (n is SimpleIdentifier || |
639 n is VariableDeclaration || | 647 n is VariableDeclaration || |
640 n is VariableDeclarationList || | 648 n is VariableDeclarationList || |
(...skipping 19 matching lines...) Expand all Loading... |
660 } | 668 } |
661 // Add proposal. | 669 // Add proposal. |
662 String code = ''; | 670 String code = ''; |
663 if (fieldList.type != null) { | 671 if (fieldList.type != null) { |
664 code += _getNodeText(fieldList.type) + ' '; | 672 code += _getNodeText(fieldList.type) + ' '; |
665 } | 673 } |
666 code += 'get'; | 674 code += 'get'; |
667 code += ' ' + _getNodeText(field.name); | 675 code += ' ' + _getNodeText(field.name); |
668 code += ' => ' + _getNodeText(initializer); | 676 code += ' => ' + _getNodeText(initializer); |
669 code += ';'; | 677 code += ';'; |
670 _addReplaceEdit(range.startEnd(fieldList.keyword, fieldDeclaration), code); | 678 SourceRange replacementRange = |
671 _addAssist(DartAssistKind.CONVERT_INTO_GETTER, []); | 679 range.startEnd(fieldList.keyword, fieldDeclaration); |
| 680 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
| 681 await changeBuilder.addFileEdit(file, fileStamp, |
| 682 (DartFileEditBuilder builder) { |
| 683 builder.addSimpleReplacement(replacementRange, code); |
| 684 }); |
| 685 _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_INTO_GETTER); |
672 } | 686 } |
673 | 687 |
674 void _addProposal_convertToBlockFunctionBody() { | 688 Future<Null> _addProposal_convertToBlockFunctionBody() async { |
675 FunctionBody body = getEnclosingFunctionBody(); | 689 FunctionBody body = getEnclosingFunctionBody(); |
676 // prepare expression body | 690 // prepare expression body |
677 if (body is! ExpressionFunctionBody || body.isGenerator) { | 691 if (body is! ExpressionFunctionBody || body.isGenerator) { |
678 _coverageMarker(); | 692 _coverageMarker(); |
679 return; | 693 return; |
680 } | 694 } |
681 Expression returnValue = (body as ExpressionFunctionBody).expression; | 695 Expression returnValue = (body as ExpressionFunctionBody).expression; |
682 DartType returnValueType = returnValue.staticType; | 696 DartType returnValueType = returnValue.staticType; |
683 String returnValueCode = _getNodeText(returnValue); | 697 String returnValueCode = _getNodeText(returnValue); |
684 // prepare prefix | 698 // prepare prefix |
685 String prefix = utils.getNodePrefix(body.parent); | 699 String prefix = utils.getNodePrefix(body.parent); |
686 String indent = utils.getIndent(1); | 700 String indent = utils.getIndent(1); |
687 // add change | 701 |
688 SourceBuilder sb = new SourceBuilder(file, body.offset); | 702 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
689 if (body.isAsynchronous) { | 703 await changeBuilder.addFileEdit(file, fileStamp, |
690 sb.append('async '); | 704 (DartFileEditBuilder builder) { |
691 } | 705 builder.addReplacement(range.node(body), (DartEditBuilder builder) { |
692 sb.append('{$eol$prefix$indent'); | 706 if (body.isAsynchronous) { |
693 if (!returnValueType.isVoid) { | 707 builder.write('async '); |
694 sb.append('return '); | 708 } |
695 } | 709 builder.write('{$eol$prefix$indent'); |
696 sb.append(returnValueCode); | 710 if (!returnValueType.isVoid) { |
697 sb.append(';'); | 711 builder.write('return '); |
698 sb.setExitOffset(); | 712 } |
699 sb.append('$eol$prefix}'); | 713 builder.write(returnValueCode); |
700 _insertBuilder(sb, body.length); | 714 builder.write(';'); |
701 // add proposal | 715 builder.selectHere(); |
702 _addAssist(DartAssistKind.CONVERT_INTO_BLOCK_BODY, []); | 716 builder.write('$eol$prefix}'); |
| 717 }); |
| 718 }); |
| 719 _addAssistFromBuilder( |
| 720 changeBuilder, DartAssistKind.CONVERT_INTO_BLOCK_BODY); |
703 } | 721 } |
704 | 722 |
705 void _addProposal_convertToExpressionFunctionBody() { | 723 Future<Null> _addProposal_convertToExpressionFunctionBody() async { |
706 // prepare current body | 724 // prepare current body |
707 FunctionBody body = getEnclosingFunctionBody(); | 725 FunctionBody body = getEnclosingFunctionBody(); |
708 if (body is! BlockFunctionBody || body.isGenerator) { | 726 if (body is! BlockFunctionBody || body.isGenerator) { |
709 _coverageMarker(); | 727 _coverageMarker(); |
710 return; | 728 return; |
711 } | 729 } |
712 // prepare return statement | 730 // prepare return statement |
713 List<Statement> statements = (body as BlockFunctionBody).block.statements; | 731 List<Statement> statements = (body as BlockFunctionBody).block.statements; |
714 if (statements.length != 1) { | 732 if (statements.length != 1) { |
715 _coverageMarker(); | 733 _coverageMarker(); |
716 return; | 734 return; |
717 } | 735 } |
718 Statement onlyStatement = statements.first; | 736 Statement onlyStatement = statements.first; |
719 // prepare returned expression | 737 // prepare returned expression |
720 Expression returnExpression; | 738 Expression returnExpression; |
721 if (onlyStatement is ReturnStatement) { | 739 if (onlyStatement is ReturnStatement) { |
722 returnExpression = onlyStatement.expression; | 740 returnExpression = onlyStatement.expression; |
723 } else if (onlyStatement is ExpressionStatement) { | 741 } else if (onlyStatement is ExpressionStatement) { |
724 returnExpression = onlyStatement.expression; | 742 returnExpression = onlyStatement.expression; |
725 } | 743 } |
726 if (returnExpression == null) { | 744 if (returnExpression == null) { |
727 _coverageMarker(); | 745 _coverageMarker(); |
728 return; | 746 return; |
729 } | 747 } |
730 // add change | 748 |
731 SourceBuilder sb = new SourceBuilder(file, body.offset); | 749 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
732 if (body.isAsynchronous) { | 750 await changeBuilder.addFileEdit(file, fileStamp, |
733 sb.append('async '); | 751 (DartFileEditBuilder builder) { |
734 } | 752 builder.addReplacement(range.node(body), (DartEditBuilder builder) { |
735 sb.append('=> '); | 753 if (body.isAsynchronous) { |
736 sb.append(_getNodeText(returnExpression)); | 754 builder.write('async '); |
737 if (body.parent is! FunctionExpression || | 755 } |
738 body.parent.parent is FunctionDeclaration) { | 756 builder.write('=> '); |
739 sb.append(';'); | 757 builder.write(_getNodeText(returnExpression)); |
740 } | 758 if (body.parent is! FunctionExpression || |
741 _insertBuilder(sb, body.length); | 759 body.parent.parent is FunctionDeclaration) { |
742 // add proposal | 760 builder.write(';'); |
743 _addAssist(DartAssistKind.CONVERT_INTO_EXPRESSION_BODY, []); | 761 } |
| 762 }); |
| 763 }); |
| 764 _addAssistFromBuilder( |
| 765 changeBuilder, DartAssistKind.CONVERT_INTO_EXPRESSION_BODY); |
744 } | 766 } |
745 | 767 |
746 void _addProposal_convertToFieldParameter() { | 768 Future<Null> _addProposal_convertToFieldParameter() async { |
747 if (node == null) { | 769 if (node == null) { |
748 return; | 770 return; |
749 } | 771 } |
750 // prepare ConstructorDeclaration | 772 // prepare ConstructorDeclaration |
751 ConstructorDeclaration constructor = | 773 ConstructorDeclaration constructor = |
752 node.getAncestor((node) => node is ConstructorDeclaration); | 774 node.getAncestor((node) => node is ConstructorDeclaration); |
753 if (constructor == null) { | 775 if (constructor == null) { |
754 return; | 776 return; |
755 } | 777 } |
756 FormalParameterList parameterList = constructor.parameters; | 778 FormalParameterList parameterList = constructor.parameters; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
803 if (expression is SimpleIdentifier && | 825 if (expression is SimpleIdentifier && |
804 expression.name == parameterName) { | 826 expression.name == parameterName) { |
805 parameterInitializer = initializer; | 827 parameterInitializer = initializer; |
806 } | 828 } |
807 } | 829 } |
808 } | 830 } |
809 if (parameterInitializer == null) { | 831 if (parameterInitializer == null) { |
810 return; | 832 return; |
811 } | 833 } |
812 String fieldName = parameterInitializer.fieldName.name; | 834 String fieldName = parameterInitializer.fieldName.name; |
813 // replace parameter | 835 |
814 _addReplaceEdit(range.node(parameter), 'this.$fieldName'); | 836 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
815 // remove initializer | 837 await changeBuilder.addFileEdit(file, fileStamp, |
816 int initializerIndex = initializers.indexOf(parameterInitializer); | 838 (DartFileEditBuilder builder) { |
817 if (initializers.length == 1) { | 839 // replace parameter |
818 _addRemoveEdit(range.endEnd(parameterList, parameterInitializer)); | 840 builder.addSimpleReplacement(range.node(parameter), 'this.$fieldName'); |
819 } else { | 841 // remove initializer |
820 if (initializerIndex == 0) { | 842 int initializerIndex = initializers.indexOf(parameterInitializer); |
821 ConstructorInitializer next = initializers[initializerIndex + 1]; | 843 if (initializers.length == 1) { |
822 _addRemoveEdit(range.startStart(parameterInitializer, next)); | 844 builder |
| 845 .addDeletion(range.endEnd(parameterList, parameterInitializer)); |
823 } else { | 846 } else { |
824 ConstructorInitializer prev = initializers[initializerIndex - 1]; | 847 if (initializerIndex == 0) { |
825 _addRemoveEdit(range.endEnd(prev, parameterInitializer)); | 848 ConstructorInitializer next = initializers[initializerIndex + 1]; |
| 849 builder.addDeletion(range.startStart(parameterInitializer, next)); |
| 850 } else { |
| 851 ConstructorInitializer prev = initializers[initializerIndex - 1]; |
| 852 builder.addDeletion(range.endEnd(prev, parameterInitializer)); |
| 853 } |
826 } | 854 } |
827 } | 855 }); |
828 // add proposal | 856 _addAssistFromBuilder( |
829 _addAssist(DartAssistKind.CONVERT_TO_FIELD_PARAMETER, []); | 857 changeBuilder, DartAssistKind.CONVERT_TO_FIELD_PARAMETER); |
830 } | 858 } |
831 } | 859 } |
832 | 860 |
833 void _addProposal_convertToForIndexLoop() { | 861 Future<Null> _addProposal_convertToForIndexLoop() async { |
834 // find enclosing ForEachStatement | 862 // find enclosing ForEachStatement |
835 ForEachStatement forEachStatement = | 863 ForEachStatement forEachStatement = |
836 node.getAncestor((n) => n is ForEachStatement); | 864 node.getAncestor((n) => n is ForEachStatement); |
837 if (forEachStatement == null) { | 865 if (forEachStatement == null) { |
838 _coverageMarker(); | 866 _coverageMarker(); |
839 return; | 867 return; |
840 } | 868 } |
841 if (selectionOffset < forEachStatement.offset || | 869 if (selectionOffset < forEachStatement.offset || |
842 forEachStatement.rightParenthesis.end < selectionOffset) { | 870 forEachStatement.rightParenthesis.end < selectionOffset) { |
843 _coverageMarker(); | 871 _coverageMarker(); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
889 } else { | 917 } else { |
890 _coverageMarker(); | 918 _coverageMarker(); |
891 return; | 919 return; |
892 } | 920 } |
893 } | 921 } |
894 // prepare environment | 922 // prepare environment |
895 String prefix = utils.getNodePrefix(forEachStatement); | 923 String prefix = utils.getNodePrefix(forEachStatement); |
896 String indent = utils.getIndent(1); | 924 String indent = utils.getIndent(1); |
897 int firstBlockLine = utils.getLineContentEnd(body.leftBracket.end); | 925 int firstBlockLine = utils.getLineContentEnd(body.leftBracket.end); |
898 // add change | 926 // add change |
899 _addReplaceEdit( | 927 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
900 range.startEnd(forEachStatement, forEachStatement.rightParenthesis), | 928 await changeBuilder.addFileEdit(file, fileStamp, |
901 'for (int $indexName = 0; $indexName < $listName.length; $indexName++)')
; | 929 (DartFileEditBuilder builder) { |
902 _addInsertEdit(firstBlockLine, | 930 // TODO(brianwilkerson) Create linked positions for the loop variable. |
903 '$prefix$indent$loopVariable = $listName[$indexName];$eol'); | 931 builder.addSimpleReplacement( |
904 // add proposal | 932 range.startEnd(forEachStatement, forEachStatement.rightParenthesis), |
905 _addAssist(DartAssistKind.CONVERT_INTO_FOR_INDEX, []); | 933 'for (int $indexName = 0; $indexName < $listName.length; $indexName++)
'); |
| 934 builder.addSimpleInsertion(firstBlockLine, |
| 935 '$prefix$indent$loopVariable = $listName[$indexName];$eol'); |
| 936 }); |
| 937 _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_INTO_FOR_INDEX); |
906 } | 938 } |
907 | 939 |
908 void _addProposal_convertToIsNot_onIs() { | 940 Future<Null> _addProposal_convertToIsNot_onIs() async { |
909 // may be child of "is" | 941 // may be child of "is" |
910 AstNode node = this.node; | 942 AstNode node = this.node; |
911 while (node != null && node is! IsExpression) { | 943 while (node != null && node is! IsExpression) { |
912 node = node.parent; | 944 node = node.parent; |
913 } | 945 } |
914 // prepare "is" | 946 // prepare "is" |
915 if (node is! IsExpression) { | 947 if (node is! IsExpression) { |
916 _coverageMarker(); | 948 _coverageMarker(); |
917 return; | 949 return; |
918 } | 950 } |
(...skipping 13 matching lines...) Expand all Loading... |
932 AstNode parent2 = parent.parent; | 964 AstNode parent2 = parent.parent; |
933 if (parent2 is! PrefixExpression) { | 965 if (parent2 is! PrefixExpression) { |
934 _coverageMarker(); | 966 _coverageMarker(); |
935 return; | 967 return; |
936 } | 968 } |
937 PrefixExpression prefExpression = parent2 as PrefixExpression; | 969 PrefixExpression prefExpression = parent2 as PrefixExpression; |
938 if (prefExpression.operator.type != TokenType.BANG) { | 970 if (prefExpression.operator.type != TokenType.BANG) { |
939 _coverageMarker(); | 971 _coverageMarker(); |
940 return; | 972 return; |
941 } | 973 } |
942 // strip !() | 974 |
943 if (getExpressionParentPrecedence(prefExpression) >= | 975 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
944 TokenClass.RELATIONAL_OPERATOR.precedence) { | 976 await changeBuilder.addFileEdit(file, fileStamp, |
945 _addRemoveEdit(range.token(prefExpression.operator)); | 977 (DartFileEditBuilder builder) { |
946 } else { | 978 if (getExpressionParentPrecedence(prefExpression) >= |
947 _addRemoveEdit( | 979 TokenClass.RELATIONAL_OPERATOR.precedence) { |
948 range.startEnd(prefExpression, parExpression.leftParenthesis)); | 980 builder.addDeletion(range.token(prefExpression.operator)); |
949 _addRemoveEdit( | 981 } else { |
950 range.startEnd(parExpression.rightParenthesis, prefExpression)); | 982 builder.addDeletion( |
951 } | 983 range.startEnd(prefExpression, parExpression.leftParenthesis)); |
952 _addInsertEdit(isExpression.isOperator.end, '!'); | 984 builder.addDeletion( |
953 // add proposal | 985 range.startEnd(parExpression.rightParenthesis, prefExpression)); |
954 _addAssist(DartAssistKind.CONVERT_INTO_IS_NOT, []); | 986 } |
| 987 builder.addSimpleInsertion(isExpression.isOperator.end, '!'); |
| 988 }); |
| 989 _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_INTO_IS_NOT); |
955 } | 990 } |
956 | 991 |
957 void _addProposal_convertToIsNot_onNot() { | 992 Future<Null> _addProposal_convertToIsNot_onNot() async { |
958 // may be () in prefix expression | 993 // may be () in prefix expression |
959 if (node is ParenthesizedExpression && node.parent is PrefixExpression) { | 994 if (node is ParenthesizedExpression && node.parent is PrefixExpression) { |
960 node = node.parent; | 995 node = node.parent; |
961 } | 996 } |
962 // prepare !() | 997 // prepare !() |
963 if (node is! PrefixExpression) { | 998 if (node is! PrefixExpression) { |
964 _coverageMarker(); | 999 _coverageMarker(); |
965 return; | 1000 return; |
966 } | 1001 } |
967 PrefixExpression prefExpression = node as PrefixExpression; | 1002 PrefixExpression prefExpression = node as PrefixExpression; |
(...skipping 13 matching lines...) Expand all Loading... |
981 // prepare "is" | 1016 // prepare "is" |
982 if (operand is! IsExpression) { | 1017 if (operand is! IsExpression) { |
983 _coverageMarker(); | 1018 _coverageMarker(); |
984 return; | 1019 return; |
985 } | 1020 } |
986 IsExpression isExpression = operand as IsExpression; | 1021 IsExpression isExpression = operand as IsExpression; |
987 if (isExpression.notOperator != null) { | 1022 if (isExpression.notOperator != null) { |
988 _coverageMarker(); | 1023 _coverageMarker(); |
989 return; | 1024 return; |
990 } | 1025 } |
991 // strip !() | 1026 |
992 if (getExpressionParentPrecedence(prefExpression) >= | 1027 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
993 TokenClass.RELATIONAL_OPERATOR.precedence) { | 1028 await changeBuilder.addFileEdit(file, fileStamp, |
994 _addRemoveEdit(range.token(prefExpression.operator)); | 1029 (DartFileEditBuilder builder) { |
995 } else { | 1030 if (getExpressionParentPrecedence(prefExpression) >= |
996 _addRemoveEdit( | 1031 TokenClass.RELATIONAL_OPERATOR.precedence) { |
997 range.startEnd(prefExpression, parExpression.leftParenthesis)); | 1032 builder.addDeletion(range.token(prefExpression.operator)); |
998 _addRemoveEdit( | 1033 } else { |
999 range.startEnd(parExpression.rightParenthesis, prefExpression)); | 1034 builder.addDeletion( |
1000 } | 1035 range.startEnd(prefExpression, parExpression.leftParenthesis)); |
1001 _addInsertEdit(isExpression.isOperator.end, '!'); | 1036 builder.addDeletion( |
1002 // add proposal | 1037 range.startEnd(parExpression.rightParenthesis, prefExpression)); |
1003 _addAssist(DartAssistKind.CONVERT_INTO_IS_NOT, []); | 1038 } |
| 1039 builder.addSimpleInsertion(isExpression.isOperator.end, '!'); |
| 1040 }); |
| 1041 _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_INTO_IS_NOT); |
1004 } | 1042 } |
1005 | 1043 |
1006 /** | 1044 /** |
1007 * Converts "!isEmpty" -> "isNotEmpty" if possible. | 1045 * Converts "!isEmpty" -> "isNotEmpty" if possible. |
1008 */ | 1046 */ |
1009 void _addProposal_convertToIsNotEmpty() { | 1047 Future<Null> _addProposal_convertToIsNotEmpty() async { |
1010 // prepare "expr.isEmpty" | 1048 // prepare "expr.isEmpty" |
1011 AstNode isEmptyAccess = null; | 1049 AstNode isEmptyAccess = null; |
1012 SimpleIdentifier isEmptyIdentifier = null; | 1050 SimpleIdentifier isEmptyIdentifier = null; |
1013 if (node is SimpleIdentifier) { | 1051 if (node is SimpleIdentifier) { |
1014 SimpleIdentifier identifier = node as SimpleIdentifier; | 1052 SimpleIdentifier identifier = node as SimpleIdentifier; |
1015 AstNode parent = identifier.parent; | 1053 AstNode parent = identifier.parent; |
1016 // normal case (but rare) | 1054 // normal case (but rare) |
1017 if (parent is PropertyAccess) { | 1055 if (parent is PropertyAccess) { |
1018 isEmptyIdentifier = parent.propertyName; | 1056 isEmptyIdentifier = parent.propertyName; |
1019 isEmptyAccess = parent; | 1057 isEmptyAccess = parent; |
(...skipping 26 matching lines...) Expand all Loading... |
1046 _coverageMarker(); | 1084 _coverageMarker(); |
1047 return; | 1085 return; |
1048 } | 1086 } |
1049 PrefixExpression prefixExpression = | 1087 PrefixExpression prefixExpression = |
1050 isEmptyAccess.parent as PrefixExpression; | 1088 isEmptyAccess.parent as PrefixExpression; |
1051 // should be ! | 1089 // should be ! |
1052 if (prefixExpression.operator.type != TokenType.BANG) { | 1090 if (prefixExpression.operator.type != TokenType.BANG) { |
1053 _coverageMarker(); | 1091 _coverageMarker(); |
1054 return; | 1092 return; |
1055 } | 1093 } |
1056 // do replace | 1094 |
1057 _addRemoveEdit( | 1095 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1058 range.startStart(prefixExpression, prefixExpression.operand)); | 1096 await changeBuilder.addFileEdit(file, fileStamp, |
1059 _addReplaceEdit(range.node(isEmptyIdentifier), 'isNotEmpty'); | 1097 (DartFileEditBuilder builder) { |
1060 // add proposal | 1098 builder.addDeletion( |
1061 _addAssist(DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY, []); | 1099 range.startStart(prefixExpression, prefixExpression.operand)); |
| 1100 builder.addSimpleReplacement(range.node(isEmptyIdentifier), 'isNotEmpty'); |
| 1101 }); |
| 1102 _addAssistFromBuilder( |
| 1103 changeBuilder, DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY); |
1062 } | 1104 } |
1063 | 1105 |
1064 void _addProposal_convertToNormalParameter() { | 1106 Future<Null> _addProposal_convertToNormalParameter() async { |
1065 if (node is SimpleIdentifier && | 1107 if (node is SimpleIdentifier && |
1066 node.parent is FieldFormalParameter && | 1108 node.parent is FieldFormalParameter && |
1067 node.parent.parent is FormalParameterList && | 1109 node.parent.parent is FormalParameterList && |
1068 node.parent.parent.parent is ConstructorDeclaration) { | 1110 node.parent.parent.parent is ConstructorDeclaration) { |
1069 ConstructorDeclaration constructor = node.parent.parent.parent; | 1111 ConstructorDeclaration constructor = node.parent.parent.parent; |
1070 FormalParameterList parameterList = node.parent.parent; | 1112 FormalParameterList parameterList = node.parent.parent; |
1071 FieldFormalParameter parameter = node.parent; | 1113 FieldFormalParameter parameter = node.parent; |
1072 ParameterElement parameterElement = parameter.element; | 1114 ParameterElement parameterElement = parameter.element; |
1073 String name = (node as SimpleIdentifier).name; | 1115 String name = (node as SimpleIdentifier).name; |
1074 // prepare type | 1116 // prepare type |
1075 DartType type = parameterElement.type; | 1117 DartType type = parameterElement.type; |
1076 Set<Source> librariesToImport = new Set<Source>(); | 1118 Set<Source> librariesToImport = new Set<Source>(); |
1077 String typeCode = utils.getTypeSource(type, librariesToImport); | 1119 String typeCode = utils.getTypeSource(type, librariesToImport); |
1078 // replace parameter | 1120 |
1079 if (type.isDynamic) { | 1121 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1080 _addReplaceEdit(range.node(parameter), name); | 1122 await changeBuilder.addFileEdit(file, fileStamp, |
1081 } else { | 1123 (DartFileEditBuilder builder) { |
1082 _addReplaceEdit(range.node(parameter), '$typeCode $name'); | 1124 // replace parameter |
1083 } | 1125 if (type.isDynamic) { |
1084 // add field initializer | 1126 builder.addSimpleReplacement(range.node(parameter), name); |
1085 List<ConstructorInitializer> initializers = constructor.initializers; | 1127 } else { |
1086 if (initializers.isEmpty) { | 1128 builder.addSimpleReplacement( |
1087 _addInsertEdit(parameterList.end, ' : $name = $name'); | 1129 range.node(parameter), '$typeCode $name'); |
1088 } else { | 1130 } |
1089 _addInsertEdit(initializers.last.end, ', $name = $name'); | 1131 // add field initializer |
1090 } | 1132 List<ConstructorInitializer> initializers = constructor.initializers; |
1091 // add proposal | 1133 if (initializers.isEmpty) { |
1092 _addAssist(DartAssistKind.CONVERT_TO_NORMAL_PARAMETER, []); | 1134 builder.addSimpleInsertion(parameterList.end, ' : $name = $name'); |
| 1135 } else { |
| 1136 builder.addSimpleInsertion(initializers.last.end, ', $name = $name'); |
| 1137 } |
| 1138 }); |
| 1139 _addAssistFromBuilder( |
| 1140 changeBuilder, DartAssistKind.CONVERT_TO_NORMAL_PARAMETER); |
1093 } | 1141 } |
1094 } | 1142 } |
1095 | 1143 |
1096 void _addProposal_encapsulateField() { | 1144 Future<Null> _addProposal_encapsulateField() async { |
1097 // find FieldDeclaration | 1145 // find FieldDeclaration |
1098 FieldDeclaration fieldDeclaration = | 1146 FieldDeclaration fieldDeclaration = |
1099 node.getAncestor((x) => x is FieldDeclaration); | 1147 node.getAncestor((x) => x is FieldDeclaration); |
1100 if (fieldDeclaration == null) { | 1148 if (fieldDeclaration == null) { |
1101 _coverageMarker(); | 1149 _coverageMarker(); |
1102 return; | 1150 return; |
1103 } | 1151 } |
1104 // not interesting for static | 1152 // not interesting for static |
1105 if (fieldDeclaration.isStatic) { | 1153 if (fieldDeclaration.isStatic) { |
1106 _coverageMarker(); | 1154 _coverageMarker(); |
(...skipping 23 matching lines...) Expand all Loading... |
1130 String name = nameNode.name; | 1178 String name = nameNode.name; |
1131 if (Identifier.isPrivateName(name)) { | 1179 if (Identifier.isPrivateName(name)) { |
1132 _coverageMarker(); | 1180 _coverageMarker(); |
1133 return; | 1181 return; |
1134 } | 1182 } |
1135 // should be on the name | 1183 // should be on the name |
1136 if (nameNode != node) { | 1184 if (nameNode != node) { |
1137 _coverageMarker(); | 1185 _coverageMarker(); |
1138 return; | 1186 return; |
1139 } | 1187 } |
1140 // rename field | 1188 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1141 _addReplaceEdit(range.node(nameNode), '_$name'); | 1189 await changeBuilder.addFileEdit(file, fileStamp, |
1142 // update references in constructors | 1190 (DartFileEditBuilder builder) { |
1143 ClassDeclaration classDeclaration = fieldDeclaration.parent; | 1191 // rename field |
1144 for (ClassMember member in classDeclaration.members) { | 1192 builder.addSimpleReplacement(range.node(nameNode), '_$name'); |
1145 if (member is ConstructorDeclaration) { | 1193 // update references in constructors |
1146 for (FormalParameter parameter in member.parameters.parameters) { | 1194 ClassDeclaration classDeclaration = fieldDeclaration.parent; |
1147 ParameterElement parameterElement = parameter.element; | 1195 for (ClassMember member in classDeclaration.members) { |
1148 if (parameterElement is FieldFormalParameterElement && | 1196 if (member is ConstructorDeclaration) { |
1149 parameterElement.field == fieldElement) { | 1197 for (FormalParameter parameter in member.parameters.parameters) { |
1150 _addReplaceEdit(range.node(parameter.identifier), '_$name'); | 1198 ParameterElement parameterElement = parameter.element; |
| 1199 if (parameterElement is FieldFormalParameterElement && |
| 1200 parameterElement.field == fieldElement) { |
| 1201 SimpleIdentifier identifier = parameter.identifier; |
| 1202 builder.addSimpleReplacement(range.node(identifier), '_$name'); |
| 1203 } |
1151 } | 1204 } |
1152 } | 1205 } |
1153 } | 1206 } |
1154 } | 1207 // add accessors |
1155 // add accessors | 1208 String eol2 = eol + eol; |
1156 String eol2 = eol + eol; | 1209 String typeNameCode = variableList.type != null |
1157 String typeNameCode = | 1210 ? _getNodeText(variableList.type) + ' ' |
1158 variableList.type != null ? _getNodeText(variableList.type) + ' ' : ''; | 1211 : ''; |
1159 String getterCode = '$eol2 ${typeNameCode}get $name => _$name;'; | 1212 String getterCode = '$eol2 ${typeNameCode}get $name => _$name;'; |
1160 String setterCode = '$eol2' | 1213 String setterCode = '$eol2' |
1161 ' void set $name($typeNameCode$name) {$eol' | 1214 ' void set $name($typeNameCode$name) {$eol' |
1162 ' _$name = $name;$eol' | 1215 ' _$name = $name;$eol' |
1163 ' }'; | 1216 ' }'; |
1164 _addInsertEdit(fieldDeclaration.end, getterCode + setterCode); | 1217 builder.addSimpleInsertion(fieldDeclaration.end, getterCode + setterCode); |
1165 // add proposal | 1218 }); |
1166 _addAssist(DartAssistKind.ENCAPSULATE_FIELD, []); | 1219 _addAssistFromBuilder(changeBuilder, DartAssistKind.ENCAPSULATE_FIELD); |
1167 } | 1220 } |
1168 | 1221 |
1169 void _addProposal_exchangeOperands() { | 1222 Future<Null> _addProposal_exchangeOperands() async { |
1170 // check that user invokes quick assist on binary expression | 1223 // check that user invokes quick assist on binary expression |
1171 if (node is! BinaryExpression) { | 1224 if (node is! BinaryExpression) { |
1172 _coverageMarker(); | 1225 _coverageMarker(); |
1173 return; | 1226 return; |
1174 } | 1227 } |
1175 BinaryExpression binaryExpression = node as BinaryExpression; | 1228 BinaryExpression binaryExpression = node as BinaryExpression; |
1176 // prepare operator position | 1229 // prepare operator position |
1177 if (!_isOperatorSelected( | 1230 if (!_isOperatorSelected( |
1178 binaryExpression, selectionOffset, selectionLength)) { | 1231 binaryExpression, selectionOffset, selectionLength)) { |
1179 _coverageMarker(); | 1232 _coverageMarker(); |
1180 return; | 1233 return; |
1181 } | 1234 } |
1182 // add edits | 1235 // add edits |
1183 { | 1236 Expression leftOperand = binaryExpression.leftOperand; |
1184 Expression leftOperand = binaryExpression.leftOperand; | 1237 Expression rightOperand = binaryExpression.rightOperand; |
1185 Expression rightOperand = binaryExpression.rightOperand; | 1238 // find "wide" enclosing binary expression with same operator |
1186 // find "wide" enclosing binary expression with same operator | 1239 while (binaryExpression.parent is BinaryExpression) { |
1187 while (binaryExpression.parent is BinaryExpression) { | 1240 BinaryExpression newBinaryExpression = |
1188 BinaryExpression newBinaryExpression = | 1241 binaryExpression.parent as BinaryExpression; |
1189 binaryExpression.parent as BinaryExpression; | 1242 if (newBinaryExpression.operator.type != binaryExpression.operator.type) { |
1190 if (newBinaryExpression.operator.type != | 1243 _coverageMarker(); |
1191 binaryExpression.operator.type) { | 1244 break; |
1192 _coverageMarker(); | |
1193 break; | |
1194 } | |
1195 binaryExpression = newBinaryExpression; | |
1196 } | 1245 } |
1197 // exchange parts of "wide" expression parts | 1246 binaryExpression = newBinaryExpression; |
1198 SourceRange leftRange = range.startEnd(binaryExpression, leftOperand); | 1247 } |
1199 SourceRange rightRange = range.startEnd(rightOperand, binaryExpression); | 1248 // exchange parts of "wide" expression parts |
1200 _addReplaceEdit(leftRange, _getRangeText(rightRange)); | 1249 SourceRange leftRange = range.startEnd(binaryExpression, leftOperand); |
1201 _addReplaceEdit(rightRange, _getRangeText(leftRange)); | 1250 SourceRange rightRange = range.startEnd(rightOperand, binaryExpression); |
1202 // maybe replace the operator | 1251 // maybe replace the operator |
1203 { | 1252 Token operator = binaryExpression.operator; |
1204 Token operator = binaryExpression.operator; | 1253 // prepare a new operator |
1205 // prepare a new operator | 1254 String newOperator = null; |
1206 String newOperator = null; | 1255 TokenType operatorType = operator.type; |
1207 TokenType operatorType = operator.type; | 1256 if (operatorType == TokenType.LT) { |
1208 if (operatorType == TokenType.LT) { | 1257 newOperator = '>'; |
1209 newOperator = '>'; | 1258 } else if (operatorType == TokenType.LT_EQ) { |
1210 } else if (operatorType == TokenType.LT_EQ) { | 1259 newOperator = '>='; |
1211 newOperator = '>='; | 1260 } else if (operatorType == TokenType.GT) { |
1212 } else if (operatorType == TokenType.GT) { | 1261 newOperator = '<'; |
1213 newOperator = '<'; | 1262 } else if (operatorType == TokenType.GT_EQ) { |
1214 } else if (operatorType == TokenType.GT_EQ) { | 1263 newOperator = '<='; |
1215 newOperator = '<='; | 1264 } |
1216 } | 1265 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1217 // replace the operator | 1266 await changeBuilder.addFileEdit(file, fileStamp, |
1218 if (newOperator != null) { | 1267 (DartFileEditBuilder builder) { |
1219 _addReplaceEdit(range.token(operator), newOperator); | 1268 builder.addSimpleReplacement(leftRange, _getRangeText(rightRange)); |
1220 } | 1269 builder.addSimpleReplacement(rightRange, _getRangeText(leftRange)); |
| 1270 // Optionally replace the operator. |
| 1271 if (newOperator != null) { |
| 1272 builder.addSimpleReplacement(range.token(operator), newOperator); |
1221 } | 1273 } |
1222 } | 1274 }); |
1223 // add proposal | 1275 _addAssistFromBuilder(changeBuilder, DartAssistKind.EXCHANGE_OPERANDS); |
1224 _addAssist(DartAssistKind.EXCHANGE_OPERANDS, []); | |
1225 } | 1276 } |
1226 | 1277 |
1227 void _addProposal_importAddShow() { | 1278 Future<Null> _addProposal_importAddShow() async { |
1228 // prepare ImportDirective | 1279 // prepare ImportDirective |
1229 ImportDirective importDirective = | 1280 ImportDirective importDirective = |
1230 node.getAncestor((node) => node is ImportDirective); | 1281 node.getAncestor((node) => node is ImportDirective); |
1231 if (importDirective == null) { | 1282 if (importDirective == null) { |
1232 _coverageMarker(); | 1283 _coverageMarker(); |
1233 return; | 1284 return; |
1234 } | 1285 } |
1235 // there should be no existing combinators | 1286 // there should be no existing combinators |
1236 if (importDirective.combinators.isNotEmpty) { | 1287 if (importDirective.combinators.isNotEmpty) { |
1237 _coverageMarker(); | 1288 _coverageMarker(); |
(...skipping 14 matching lines...) Expand all Loading... |
1252 if (element != null && namespace[node.name] == element) { | 1303 if (element != null && namespace[node.name] == element) { |
1253 referencedNames.add(element.displayName); | 1304 referencedNames.add(element.displayName); |
1254 } | 1305 } |
1255 }); | 1306 }); |
1256 unit.accept(visitor); | 1307 unit.accept(visitor); |
1257 // ignore if unused | 1308 // ignore if unused |
1258 if (referencedNames.isEmpty) { | 1309 if (referencedNames.isEmpty) { |
1259 _coverageMarker(); | 1310 _coverageMarker(); |
1260 return; | 1311 return; |
1261 } | 1312 } |
1262 // prepare change | 1313 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1263 String showCombinator = ' show ${referencedNames.join(', ')}'; | 1314 await changeBuilder.addFileEdit(file, fileStamp, |
1264 _addInsertEdit(importDirective.end - 1, showCombinator); | 1315 (DartFileEditBuilder builder) { |
1265 // add proposal | 1316 String showCombinator = ' show ${referencedNames.join(', ')}'; |
1266 _addAssist(DartAssistKind.IMPORT_ADD_SHOW, []); | 1317 builder.addSimpleInsertion(importDirective.end - 1, showCombinator); |
| 1318 }); |
| 1319 _addAssistFromBuilder(changeBuilder, DartAssistKind.IMPORT_ADD_SHOW); |
1267 } | 1320 } |
1268 | 1321 |
1269 void _addProposal_introduceLocalTestedType() { | 1322 Future<Null> _addProposal_introduceLocalTestedType() async { |
1270 AstNode node = this.node; | 1323 AstNode node = this.node; |
1271 if (node is IfStatement) { | 1324 if (node is IfStatement) { |
1272 node = (node as IfStatement).condition; | 1325 node = (node as IfStatement).condition; |
1273 } else if (node is WhileStatement) { | 1326 } else if (node is WhileStatement) { |
1274 node = (node as WhileStatement).condition; | 1327 node = (node as WhileStatement).condition; |
1275 } | 1328 } |
1276 // prepare IsExpression | 1329 // prepare IsExpression |
1277 if (node is! IsExpression) { | 1330 if (node is! IsExpression) { |
1278 _coverageMarker(); | 1331 _coverageMarker(); |
1279 return; | 1332 return; |
(...skipping 20 matching lines...) Expand all Loading... |
1300 // prepare location | 1353 // prepare location |
1301 int offset; | 1354 int offset; |
1302 String statementPrefix; | 1355 String statementPrefix; |
1303 if (isExpression.notOperator == null) { | 1356 if (isExpression.notOperator == null) { |
1304 offset = targetBlock.leftBracket.end; | 1357 offset = targetBlock.leftBracket.end; |
1305 statementPrefix = indent; | 1358 statementPrefix = indent; |
1306 } else { | 1359 } else { |
1307 offset = targetBlock.rightBracket.end; | 1360 offset = targetBlock.rightBracket.end; |
1308 statementPrefix = ''; | 1361 statementPrefix = ''; |
1309 } | 1362 } |
1310 // prepare source | |
1311 SourceBuilder builder = new SourceBuilder(file, offset); | |
1312 builder.append(eol + prefix + statementPrefix); | |
1313 builder.append(castTypeCode); | |
1314 // prepare excluded names | 1363 // prepare excluded names |
1315 Set<String> excluded = new Set<String>(); | 1364 Set<String> excluded = new Set<String>(); |
1316 { | 1365 ScopedNameFinder scopedNameFinder = new ScopedNameFinder(offset); |
1317 ScopedNameFinder scopedNameFinder = new ScopedNameFinder(offset); | 1366 isExpression.accept(scopedNameFinder); |
1318 isExpression.accept(scopedNameFinder); | 1367 excluded.addAll(scopedNameFinder.locals.keys.toSet()); |
1319 excluded.addAll(scopedNameFinder.locals.keys.toSet()); | 1368 // name(s) |
| 1369 List<String> suggestions = |
| 1370 getVariableNameSuggestionsForExpression(castType, null, excluded); |
| 1371 |
| 1372 if (suggestions.isNotEmpty) { |
| 1373 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
| 1374 await changeBuilder.addFileEdit(file, fileStamp, |
| 1375 (DartFileEditBuilder builder) { |
| 1376 builder.addInsertion(offset, (DartEditBuilder builder) { |
| 1377 builder.write(eol + prefix + statementPrefix); |
| 1378 builder.write(castTypeCode); |
| 1379 builder.write(' '); |
| 1380 builder.addSimpleLinkedEdit('NAME', suggestions[0], |
| 1381 kind: LinkedEditSuggestionKind.VARIABLE, |
| 1382 suggestions: suggestions); |
| 1383 builder.write(' = '); |
| 1384 builder.write(_getNodeText(isExpression.expression)); |
| 1385 builder.write(';'); |
| 1386 builder.selectHere(); |
| 1387 }); |
| 1388 }); |
| 1389 _addAssistFromBuilder( |
| 1390 changeBuilder, DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE); |
1320 } | 1391 } |
1321 // name(s) | |
1322 { | |
1323 List<String> suggestions = | |
1324 getVariableNameSuggestionsForExpression(castType, null, excluded); | |
1325 builder.append(' '); | |
1326 builder.startPosition('NAME'); | |
1327 for (int i = 0; i < suggestions.length; i++) { | |
1328 String name = suggestions[i]; | |
1329 if (i == 0) { | |
1330 builder.append(name); | |
1331 } | |
1332 builder.addSuggestion(LinkedEditSuggestionKind.VARIABLE, name); | |
1333 } | |
1334 builder.endPosition(); | |
1335 } | |
1336 builder.append(' = '); | |
1337 builder.append(_getNodeText(isExpression.expression)); | |
1338 builder.append(';'); | |
1339 builder.setExitOffset(); | |
1340 // add proposal | |
1341 _insertBuilder(builder); | |
1342 _addAssist(DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE, []); | |
1343 } | 1392 } |
1344 | 1393 |
1345 void _addProposal_invertIf() { | 1394 Future<Null> _addProposal_invertIf() async { |
1346 if (node is! IfStatement) { | 1395 if (node is! IfStatement) { |
1347 return; | 1396 return; |
1348 } | 1397 } |
1349 IfStatement ifStatement = node as IfStatement; | 1398 IfStatement ifStatement = node as IfStatement; |
1350 Expression condition = ifStatement.condition; | 1399 Expression condition = ifStatement.condition; |
1351 // should have both "then" and "else" | 1400 // should have both "then" and "else" |
1352 Statement thenStatement = ifStatement.thenStatement; | 1401 Statement thenStatement = ifStatement.thenStatement; |
1353 Statement elseStatement = ifStatement.elseStatement; | 1402 Statement elseStatement = ifStatement.elseStatement; |
1354 if (thenStatement == null || elseStatement == null) { | 1403 if (thenStatement == null || elseStatement == null) { |
1355 return; | 1404 return; |
1356 } | 1405 } |
1357 // prepare source | 1406 // prepare source |
1358 String invertedCondition = utils.invertCondition(condition); | 1407 String invertedCondition = utils.invertCondition(condition); |
1359 String thenSource = _getNodeText(thenStatement); | 1408 String thenSource = _getNodeText(thenStatement); |
1360 String elseSource = _getNodeText(elseStatement); | 1409 String elseSource = _getNodeText(elseStatement); |
1361 // do replacements | 1410 |
1362 _addReplaceEdit(range.node(condition), invertedCondition); | 1411 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1363 _addReplaceEdit(range.node(thenStatement), elseSource); | 1412 await changeBuilder.addFileEdit(file, fileStamp, |
1364 _addReplaceEdit(range.node(elseStatement), thenSource); | 1413 (DartFileEditBuilder builder) { |
1365 // add proposal | 1414 builder.addSimpleReplacement(range.node(condition), invertedCondition); |
1366 _addAssist(DartAssistKind.INVERT_IF_STATEMENT, []); | 1415 builder.addSimpleReplacement(range.node(thenStatement), elseSource); |
| 1416 builder.addSimpleReplacement(range.node(elseStatement), thenSource); |
| 1417 }); |
| 1418 _addAssistFromBuilder(changeBuilder, DartAssistKind.INVERT_IF_STATEMENT); |
1367 } | 1419 } |
1368 | 1420 |
1369 void _addProposal_joinIfStatementInner() { | 1421 Future<Null> _addProposal_joinIfStatementInner() async { |
1370 // climb up condition to the (supposedly) "if" statement | 1422 // climb up condition to the (supposedly) "if" statement |
1371 AstNode node = this.node; | 1423 AstNode node = this.node; |
1372 while (node is Expression) { | 1424 while (node is Expression) { |
1373 node = node.parent; | 1425 node = node.parent; |
1374 } | 1426 } |
1375 // prepare target "if" statement | 1427 // prepare target "if" statement |
1376 if (node is! IfStatement) { | 1428 if (node is! IfStatement) { |
1377 _coverageMarker(); | 1429 _coverageMarker(); |
1378 return; | 1430 return; |
1379 } | 1431 } |
(...skipping 25 matching lines...) Expand all Loading... |
1405 String innerConditionSource = _getNodeText(innerCondition); | 1457 String innerConditionSource = _getNodeText(innerCondition); |
1406 if (_shouldWrapParenthesisBeforeAnd(targetCondition)) { | 1458 if (_shouldWrapParenthesisBeforeAnd(targetCondition)) { |
1407 targetConditionSource = '($targetConditionSource)'; | 1459 targetConditionSource = '($targetConditionSource)'; |
1408 } | 1460 } |
1409 if (_shouldWrapParenthesisBeforeAnd(innerCondition)) { | 1461 if (_shouldWrapParenthesisBeforeAnd(innerCondition)) { |
1410 innerConditionSource = '($innerConditionSource)'; | 1462 innerConditionSource = '($innerConditionSource)'; |
1411 } | 1463 } |
1412 condition = '$targetConditionSource && $innerConditionSource'; | 1464 condition = '$targetConditionSource && $innerConditionSource'; |
1413 } | 1465 } |
1414 // replace target "if" statement | 1466 // replace target "if" statement |
1415 { | 1467 Statement innerThenStatement = innerIfStatement.thenStatement; |
1416 Statement innerThenStatement = innerIfStatement.thenStatement; | 1468 List<Statement> innerThenStatements = getStatements(innerThenStatement); |
1417 List<Statement> innerThenStatements = getStatements(innerThenStatement); | 1469 SourceRange lineRanges = utils.getLinesRangeStatements(innerThenStatements); |
1418 SourceRange lineRanges = | 1470 String oldSource = utils.getRangeText(lineRanges); |
1419 utils.getLinesRangeStatements(innerThenStatements); | 1471 String newSource = utils.indentSourceLeftRight(oldSource, false); |
1420 String oldSource = utils.getRangeText(lineRanges); | 1472 |
1421 String newSource = utils.indentSourceLeftRight(oldSource, false); | 1473 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1422 _addReplaceEdit(range.node(targetIfStatement), | 1474 await changeBuilder.addFileEdit(file, fileStamp, |
| 1475 (DartFileEditBuilder builder) { |
| 1476 builder.addSimpleReplacement(range.node(targetIfStatement), |
1423 'if ($condition) {$eol$newSource$prefix}'); | 1477 'if ($condition) {$eol$newSource$prefix}'); |
1424 } | 1478 }); |
1425 // done | 1479 _addAssistFromBuilder(changeBuilder, DartAssistKind.JOIN_IF_WITH_INNER); |
1426 _addAssist(DartAssistKind.JOIN_IF_WITH_INNER, []); | |
1427 } | 1480 } |
1428 | 1481 |
1429 void _addProposal_joinIfStatementOuter() { | 1482 Future<Null> _addProposal_joinIfStatementOuter() async { |
1430 // climb up condition to the (supposedly) "if" statement | 1483 // climb up condition to the (supposedly) "if" statement |
1431 AstNode node = this.node; | 1484 AstNode node = this.node; |
1432 while (node is Expression) { | 1485 while (node is Expression) { |
1433 node = node.parent; | 1486 node = node.parent; |
1434 } | 1487 } |
1435 // prepare target "if" statement | 1488 // prepare target "if" statement |
1436 if (node is! IfStatement) { | 1489 if (node is! IfStatement) { |
1437 _coverageMarker(); | 1490 _coverageMarker(); |
1438 return; | 1491 return; |
1439 } | 1492 } |
(...skipping 16 matching lines...) Expand all Loading... |
1456 return; | 1509 return; |
1457 } | 1510 } |
1458 IfStatement outerIfStatement = parent as IfStatement; | 1511 IfStatement outerIfStatement = parent as IfStatement; |
1459 if (outerIfStatement.elseStatement != null) { | 1512 if (outerIfStatement.elseStatement != null) { |
1460 _coverageMarker(); | 1513 _coverageMarker(); |
1461 return; | 1514 return; |
1462 } | 1515 } |
1463 // prepare environment | 1516 // prepare environment |
1464 String prefix = utils.getNodePrefix(outerIfStatement); | 1517 String prefix = utils.getNodePrefix(outerIfStatement); |
1465 // merge conditions | 1518 // merge conditions |
1466 String condition; | 1519 Expression targetCondition = targetIfStatement.condition; |
1467 { | 1520 Expression outerCondition = outerIfStatement.condition; |
1468 Expression targetCondition = targetIfStatement.condition; | 1521 String targetConditionSource = _getNodeText(targetCondition); |
1469 Expression outerCondition = outerIfStatement.condition; | 1522 String outerConditionSource = _getNodeText(outerCondition); |
1470 String targetConditionSource = _getNodeText(targetCondition); | 1523 if (_shouldWrapParenthesisBeforeAnd(targetCondition)) { |
1471 String outerConditionSource = _getNodeText(outerCondition); | 1524 targetConditionSource = '($targetConditionSource)'; |
1472 if (_shouldWrapParenthesisBeforeAnd(targetCondition)) { | |
1473 targetConditionSource = '($targetConditionSource)'; | |
1474 } | |
1475 if (_shouldWrapParenthesisBeforeAnd(outerCondition)) { | |
1476 outerConditionSource = '($outerConditionSource)'; | |
1477 } | |
1478 condition = '$outerConditionSource && $targetConditionSource'; | |
1479 } | 1525 } |
| 1526 if (_shouldWrapParenthesisBeforeAnd(outerCondition)) { |
| 1527 outerConditionSource = '($outerConditionSource)'; |
| 1528 } |
| 1529 String condition = '$outerConditionSource && $targetConditionSource'; |
1480 // replace outer "if" statement | 1530 // replace outer "if" statement |
1481 { | 1531 Statement targetThenStatement = targetIfStatement.thenStatement; |
1482 Statement targetThenStatement = targetIfStatement.thenStatement; | 1532 List<Statement> targetThenStatements = getStatements(targetThenStatement); |
1483 List<Statement> targetThenStatements = getStatements(targetThenStatement); | 1533 SourceRange lineRanges = |
1484 SourceRange lineRanges = | 1534 utils.getLinesRangeStatements(targetThenStatements); |
1485 utils.getLinesRangeStatements(targetThenStatements); | 1535 String oldSource = utils.getRangeText(lineRanges); |
1486 String oldSource = utils.getRangeText(lineRanges); | 1536 String newSource = utils.indentSourceLeftRight(oldSource, false); |
1487 String newSource = utils.indentSourceLeftRight(oldSource, false); | 1537 |
1488 _addReplaceEdit(range.node(outerIfStatement), | 1538 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
| 1539 await changeBuilder.addFileEdit(file, fileStamp, |
| 1540 (DartFileEditBuilder builder) { |
| 1541 builder.addSimpleReplacement(range.node(outerIfStatement), |
1489 'if ($condition) {$eol$newSource$prefix}'); | 1542 'if ($condition) {$eol$newSource$prefix}'); |
1490 } | 1543 }); |
1491 // done | 1544 _addAssistFromBuilder(changeBuilder, DartAssistKind.JOIN_IF_WITH_OUTER); |
1492 _addAssist(DartAssistKind.JOIN_IF_WITH_OUTER, []); | |
1493 } | 1545 } |
1494 | 1546 |
1495 void _addProposal_joinVariableDeclaration_onAssignment() { | 1547 Future<Null> _addProposal_joinVariableDeclaration_onAssignment() async { |
1496 // check that node is LHS in assignment | 1548 // check that node is LHS in assignment |
1497 if (node is SimpleIdentifier && | 1549 if (node is SimpleIdentifier && |
1498 node.parent is AssignmentExpression && | 1550 node.parent is AssignmentExpression && |
1499 (node.parent as AssignmentExpression).leftHandSide == node && | 1551 (node.parent as AssignmentExpression).leftHandSide == node && |
1500 node.parent.parent is ExpressionStatement) {} else { | 1552 node.parent.parent is ExpressionStatement) {} else { |
1501 _coverageMarker(); | 1553 _coverageMarker(); |
1502 return; | 1554 return; |
1503 } | 1555 } |
1504 AssignmentExpression assignExpression = node.parent as AssignmentExpression; | 1556 AssignmentExpression assignExpression = node.parent as AssignmentExpression; |
1505 // check that binary expression is assignment | 1557 // check that binary expression is assignment |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1546 return; | 1598 return; |
1547 } | 1599 } |
1548 Block block = assignStatement.parent as Block; | 1600 Block block = assignStatement.parent as Block; |
1549 // check that "declaration" and "assignment" statements are adjacent | 1601 // check that "declaration" and "assignment" statements are adjacent |
1550 List<Statement> statements = block.statements; | 1602 List<Statement> statements = block.statements; |
1551 if (statements.indexOf(assignStatement) == | 1603 if (statements.indexOf(assignStatement) == |
1552 statements.indexOf(declStatement) + 1) {} else { | 1604 statements.indexOf(declStatement) + 1) {} else { |
1553 _coverageMarker(); | 1605 _coverageMarker(); |
1554 return; | 1606 return; |
1555 } | 1607 } |
1556 // add edits | 1608 |
1557 _addReplaceEdit(range.endStart(declNode, assignExpression.operator), ' '); | 1609 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1558 // add proposal | 1610 await changeBuilder.addFileEdit(file, fileStamp, |
1559 _addAssist(DartAssistKind.JOIN_VARIABLE_DECLARATION, []); | 1611 (DartFileEditBuilder builder) { |
| 1612 builder.addSimpleReplacement( |
| 1613 range.endStart(declNode, assignExpression.operator), ' '); |
| 1614 }); |
| 1615 _addAssistFromBuilder( |
| 1616 changeBuilder, DartAssistKind.JOIN_VARIABLE_DECLARATION); |
1560 } | 1617 } |
1561 | 1618 |
1562 void _addProposal_joinVariableDeclaration_onDeclaration() { | 1619 Future<Null> _addProposal_joinVariableDeclaration_onDeclaration() async { |
1563 // prepare enclosing VariableDeclarationList | 1620 // prepare enclosing VariableDeclarationList |
1564 VariableDeclarationList declList = | 1621 VariableDeclarationList declList = |
1565 node.getAncestor((node) => node is VariableDeclarationList); | 1622 node.getAncestor((node) => node is VariableDeclarationList); |
1566 if (declList != null && declList.variables.length == 1) {} else { | 1623 if (declList != null && declList.variables.length == 1) {} else { |
1567 _coverageMarker(); | 1624 _coverageMarker(); |
1568 return; | 1625 return; |
1569 } | 1626 } |
1570 VariableDeclaration decl = declList.variables[0]; | 1627 VariableDeclaration decl = declList.variables[0]; |
1571 // already initialized | 1628 // already initialized |
1572 if (decl.initializer != null) { | 1629 if (decl.initializer != null) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1605 _coverageMarker(); | 1662 _coverageMarker(); |
1606 return; | 1663 return; |
1607 } | 1664 } |
1608 assignExpression = expressionStatement.expression as AssignmentExpression; | 1665 assignExpression = expressionStatement.expression as AssignmentExpression; |
1609 } | 1666 } |
1610 // check that pure assignment | 1667 // check that pure assignment |
1611 if (assignExpression.operator.type != TokenType.EQ) { | 1668 if (assignExpression.operator.type != TokenType.EQ) { |
1612 _coverageMarker(); | 1669 _coverageMarker(); |
1613 return; | 1670 return; |
1614 } | 1671 } |
1615 // add edits | 1672 |
1616 _addReplaceEdit(range.endStart(decl.name, assignExpression.operator), ' '); | 1673 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1617 // add proposal | 1674 await changeBuilder.addFileEdit(file, fileStamp, |
1618 _addAssist(DartAssistKind.JOIN_VARIABLE_DECLARATION, []); | 1675 (DartFileEditBuilder builder) { |
| 1676 builder.addSimpleReplacement( |
| 1677 range.endStart(decl.name, assignExpression.operator), ' '); |
| 1678 }); |
| 1679 _addAssistFromBuilder( |
| 1680 changeBuilder, DartAssistKind.JOIN_VARIABLE_DECLARATION); |
1619 } | 1681 } |
1620 | 1682 |
1621 void _addProposal_moveFlutterWidgetDown() { | 1683 Future<Null> _addProposal_moveFlutterWidgetDown() async { |
1622 InstanceCreationExpression exprGoingDown = identifyNewExpression(node); | 1684 InstanceCreationExpression exprGoingDown = identifyNewExpression(node); |
1623 if (exprGoingDown == null || | 1685 if (exprGoingDown == null || |
1624 !isFlutterInstanceCreationExpression(exprGoingDown)) { | 1686 !isFlutterInstanceCreationExpression(exprGoingDown)) { |
1625 _coverageMarker(); | 1687 _coverageMarker(); |
1626 return; | 1688 return; |
1627 } | 1689 } |
1628 InstanceCreationExpression exprGoingUp = findChildWidget(exprGoingDown); | 1690 InstanceCreationExpression exprGoingUp = findChildWidget(exprGoingDown); |
1629 if (exprGoingUp == null) { | 1691 if (exprGoingUp == null) { |
1630 _coverageMarker(); | 1692 _coverageMarker(); |
1631 return; | 1693 return; |
1632 } | 1694 } |
1633 NamedExpression stableChild = findChildArgument(exprGoingUp); | 1695 NamedExpression stableChild = findChildArgument(exprGoingUp); |
1634 if (stableChild == null || stableChild.expression == null) { | 1696 if (stableChild == null || stableChild.expression == null) { |
1635 _coverageMarker(); | 1697 _coverageMarker(); |
1636 return; | 1698 return; |
1637 } | 1699 } |
1638 String exprGoingDownSrc = utils.getNodeText(exprGoingDown); | 1700 String exprGoingDownSrc = utils.getNodeText(exprGoingDown); |
1639 int dnNewlineIdx = exprGoingDownSrc.lastIndexOf(eol); | 1701 int dnNewlineIdx = exprGoingDownSrc.lastIndexOf(eol); |
1640 if (dnNewlineIdx < 0 || dnNewlineIdx == exprGoingDownSrc.length - 1) { | 1702 if (dnNewlineIdx < 0 || dnNewlineIdx == exprGoingDownSrc.length - 1) { |
1641 _coverageMarker(); | 1703 _coverageMarker(); |
1642 return; // Outer new-expr needs to be in multi-line format already. | 1704 return; // Outer new-expr needs to be in multi-line format already. |
1643 } | 1705 } |
1644 String exprGoingUpSrc = utils.getNodeText(exprGoingUp); | 1706 String exprGoingUpSrc = utils.getNodeText(exprGoingUp); |
1645 int upNewlineIdx = exprGoingUpSrc.lastIndexOf(eol); | 1707 int upNewlineIdx = exprGoingUpSrc.lastIndexOf(eol); |
1646 if (upNewlineIdx < 0 || upNewlineIdx == exprGoingUpSrc.length - 1) { | 1708 if (upNewlineIdx < 0 || upNewlineIdx == exprGoingUpSrc.length - 1) { |
1647 _coverageMarker(); | 1709 _coverageMarker(); |
1648 return; // Inner new-expr needs to be in multi-line format already. | 1710 return; // Inner new-expr needs to be in multi-line format already. |
1649 } | 1711 } |
1650 _swapFlutterWidgets(exprGoingDown, exprGoingUp, stableChild, | 1712 await _swapFlutterWidgets(exprGoingDown, exprGoingUp, stableChild, |
1651 DartAssistKind.MOVE_FLUTTER_WIDGET_DOWN); | 1713 DartAssistKind.MOVE_FLUTTER_WIDGET_DOWN); |
1652 } | 1714 } |
1653 | 1715 |
1654 void _addProposal_moveFlutterWidgetUp() { | 1716 Future<Null> _addProposal_moveFlutterWidgetUp() async { |
1655 InstanceCreationExpression exprGoingUp = identifyNewExpression(node); | 1717 InstanceCreationExpression exprGoingUp = identifyNewExpression(node); |
1656 if (exprGoingUp == null || | 1718 if (exprGoingUp == null || |
1657 !isFlutterInstanceCreationExpression(exprGoingUp)) { | 1719 !isFlutterInstanceCreationExpression(exprGoingUp)) { |
1658 _coverageMarker(); | 1720 _coverageMarker(); |
1659 return; | 1721 return; |
1660 } | 1722 } |
1661 AstNode expr = exprGoingUp.parent?.parent?.parent; | 1723 AstNode expr = exprGoingUp.parent?.parent?.parent; |
1662 if (expr == null || expr is! InstanceCreationExpression) { | 1724 if (expr == null || expr is! InstanceCreationExpression) { |
1663 _coverageMarker(); | 1725 _coverageMarker(); |
1664 return; | 1726 return; |
1665 } | 1727 } |
1666 InstanceCreationExpression exprGoingDown = expr; | 1728 InstanceCreationExpression exprGoingDown = expr; |
1667 NamedExpression stableChild = findChildArgument(exprGoingUp); | 1729 NamedExpression stableChild = findChildArgument(exprGoingUp); |
1668 if (stableChild == null || stableChild.expression == null) { | 1730 if (stableChild == null || stableChild.expression == null) { |
1669 _coverageMarker(); | 1731 _coverageMarker(); |
1670 return; | 1732 return; |
1671 } | 1733 } |
1672 String exprGoingUpSrc = utils.getNodeText(exprGoingUp); | 1734 String exprGoingUpSrc = utils.getNodeText(exprGoingUp); |
1673 int upNewlineIdx = exprGoingUpSrc.lastIndexOf(eol); | 1735 int upNewlineIdx = exprGoingUpSrc.lastIndexOf(eol); |
1674 if (upNewlineIdx < 0 || upNewlineIdx == exprGoingUpSrc.length - 1) { | 1736 if (upNewlineIdx < 0 || upNewlineIdx == exprGoingUpSrc.length - 1) { |
1675 _coverageMarker(); | 1737 _coverageMarker(); |
1676 return; // Inner new-expr needs to be in multi-line format already. | 1738 return; // Inner new-expr needs to be in multi-line format already. |
1677 } | 1739 } |
1678 String exprGoingDownSrc = utils.getNodeText(exprGoingDown); | 1740 String exprGoingDownSrc = utils.getNodeText(exprGoingDown); |
1679 int dnNewlineIdx = exprGoingDownSrc.lastIndexOf(eol); | 1741 int dnNewlineIdx = exprGoingDownSrc.lastIndexOf(eol); |
1680 if (dnNewlineIdx < 0 || dnNewlineIdx == exprGoingDownSrc.length - 1) { | 1742 if (dnNewlineIdx < 0 || dnNewlineIdx == exprGoingDownSrc.length - 1) { |
1681 _coverageMarker(); | 1743 _coverageMarker(); |
1682 return; // Outer new-expr needs to be in multi-line format already. | 1744 return; // Outer new-expr needs to be in multi-line format already. |
1683 } | 1745 } |
1684 _swapFlutterWidgets(exprGoingDown, exprGoingUp, stableChild, | 1746 await _swapFlutterWidgets(exprGoingDown, exprGoingUp, stableChild, |
1685 DartAssistKind.MOVE_FLUTTER_WIDGET_UP); | 1747 DartAssistKind.MOVE_FLUTTER_WIDGET_UP); |
1686 } | 1748 } |
1687 | 1749 |
1688 void _addProposal_removeTypeAnnotation() { | 1750 Future<Null> _addProposal_removeTypeAnnotation() async { |
1689 VariableDeclarationList declarationList = | 1751 VariableDeclarationList declarationList = |
1690 node.getAncestor((n) => n is VariableDeclarationList); | 1752 node.getAncestor((n) => n is VariableDeclarationList); |
1691 if (declarationList == null) { | 1753 if (declarationList == null) { |
1692 _coverageMarker(); | 1754 _coverageMarker(); |
1693 return; | 1755 return; |
1694 } | 1756 } |
1695 // we need a type | 1757 // we need a type |
1696 TypeAnnotation typeNode = declarationList.type; | 1758 TypeAnnotation typeNode = declarationList.type; |
1697 if (typeNode == null) { | 1759 if (typeNode == null) { |
1698 _coverageMarker(); | 1760 _coverageMarker(); |
1699 return; | 1761 return; |
1700 } | 1762 } |
1701 // ignore if an incomplete variable declaration | 1763 // ignore if an incomplete variable declaration |
1702 if (declarationList.variables.length == 1 && | 1764 if (declarationList.variables.length == 1 && |
1703 declarationList.variables[0].name.isSynthetic) { | 1765 declarationList.variables[0].name.isSynthetic) { |
1704 _coverageMarker(); | 1766 _coverageMarker(); |
1705 return; | 1767 return; |
1706 } | 1768 } |
1707 // must be not after the name of the variable | 1769 // must be not after the name of the variable |
1708 VariableDeclaration firstVariable = declarationList.variables[0]; | 1770 VariableDeclaration firstVariable = declarationList.variables[0]; |
1709 if (selectionOffset > firstVariable.name.end) { | 1771 if (selectionOffset > firstVariable.name.end) { |
1710 _coverageMarker(); | 1772 _coverageMarker(); |
1711 return; | 1773 return; |
1712 } | 1774 } |
1713 // add edit | 1775 // add edit |
1714 Token keyword = declarationList.keyword; | 1776 Token keyword = declarationList.keyword; |
1715 SourceRange typeRange = range.startStart(typeNode, firstVariable); | 1777 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1716 if (keyword != null && keyword.lexeme != 'var') { | 1778 await changeBuilder.addFileEdit(file, fileStamp, |
1717 _addReplaceEdit(typeRange, ''); | 1779 (DartFileEditBuilder builder) { |
1718 } else { | 1780 SourceRange typeRange = range.startStart(typeNode, firstVariable); |
1719 _addReplaceEdit(typeRange, 'var '); | 1781 if (keyword != null && keyword.lexeme != 'var') { |
1720 } | 1782 builder.addSimpleReplacement(typeRange, ''); |
1721 // add proposal | 1783 } else { |
1722 _addAssist(DartAssistKind.REMOVE_TYPE_ANNOTATION, []); | 1784 builder.addSimpleReplacement(typeRange, 'var '); |
| 1785 } |
| 1786 }); |
| 1787 _addAssistFromBuilder(changeBuilder, DartAssistKind.REMOVE_TYPE_ANNOTATION); |
1723 } | 1788 } |
1724 | 1789 |
1725 void _addProposal_reparentFlutterList() { | 1790 Future<Null> _addProposal_reparentFlutterList() async { |
1726 if (node is! ListLiteral) { | 1791 if (node is! ListLiteral) { |
1727 return; | 1792 return; |
1728 } | 1793 } |
1729 if ((node as ListLiteral).elements.any((Expression exp) => | 1794 if ((node as ListLiteral).elements.any((Expression exp) => |
1730 !(exp is InstanceCreationExpression && | 1795 !(exp is InstanceCreationExpression && |
1731 isFlutterInstanceCreationExpression(exp)))) { | 1796 isFlutterInstanceCreationExpression(exp)))) { |
1732 _coverageMarker(); | 1797 _coverageMarker(); |
1733 return; | 1798 return; |
1734 } | 1799 } |
1735 String literalSrc = utils.getNodeText(node); | 1800 String literalSrc = utils.getNodeText(node); |
1736 SourceBuilder sb = new SourceBuilder(file, node.offset); | |
1737 int newlineIdx = literalSrc.lastIndexOf(eol); | 1801 int newlineIdx = literalSrc.lastIndexOf(eol); |
1738 if (newlineIdx < 0 || newlineIdx == literalSrc.length - 1) { | 1802 if (newlineIdx < 0 || newlineIdx == literalSrc.length - 1) { |
1739 _coverageMarker(); | 1803 _coverageMarker(); |
1740 return; // Lists need to be in multi-line format already. | 1804 return; // Lists need to be in multi-line format already. |
1741 } | 1805 } |
1742 String indentOld = utils.getLinePrefix(node.offset + 1 + newlineIdx); | 1806 String indentOld = utils.getLinePrefix(node.offset + 1 + newlineIdx); |
1743 String indentArg = '$indentOld${utils.getIndent(1)}'; | 1807 String indentArg = '$indentOld${utils.getIndent(1)}'; |
1744 String indentList = '$indentOld${utils.getIndent(2)}'; | 1808 String indentList = '$indentOld${utils.getIndent(2)}'; |
1745 sb.append('['); | 1809 |
1746 sb.append(eol); | 1810 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1747 sb.append(indentArg); | 1811 await changeBuilder.addFileEdit(file, fileStamp, |
1748 sb.append('new '); | 1812 (DartFileEditBuilder builder) { |
1749 sb.startPosition('WIDGET'); | 1813 builder.addReplacement(range.node(node), (DartEditBuilder builder) { |
1750 sb.append('widget'); | 1814 builder.write('['); |
1751 sb.endPosition(); | 1815 builder.write(eol); |
1752 sb.append('('); | 1816 builder.write(indentArg); |
1753 sb.append(eol); | 1817 builder.write('new '); |
1754 sb.append(indentList); | 1818 builder.addSimpleLinkedEdit('WIDGET', 'widget'); |
1755 // Linked editing not needed since arg is always a list. | 1819 builder.write('('); |
1756 sb.append('children: '); | 1820 builder.write(eol); |
1757 sb.append(literalSrc.replaceAll( | 1821 builder.write(indentList); |
1758 new RegExp("^$indentOld", multiLine: true), "$indentList")); | 1822 // Linked editing not needed since arg is always a list. |
1759 sb.append(','); | 1823 builder.write('children: '); |
1760 sb.append(eol); | 1824 builder.write(literalSrc.replaceAll( |
1761 sb.append(indentArg); | 1825 new RegExp("^$indentOld", multiLine: true), "$indentList")); |
1762 sb.append('),'); | 1826 builder.write(','); |
1763 sb.append(eol); | 1827 builder.write(eol); |
1764 sb.append(indentOld); | 1828 builder.write(indentArg); |
1765 sb.append(']'); | 1829 builder.write('),'); |
1766 exitPosition = _newPosition(sb.offset + sb.length); | 1830 builder.write(eol); |
1767 _insertBuilder(sb, literalSrc.length); | 1831 builder.write(indentOld); |
1768 _addAssist(DartAssistKind.REPARENT_FLUTTER_LIST, []); | 1832 builder.write(']'); |
| 1833 builder.selectHere(); |
| 1834 }); |
| 1835 }); |
| 1836 _addAssistFromBuilder(changeBuilder, DartAssistKind.REPARENT_FLUTTER_LIST); |
1769 } | 1837 } |
1770 | 1838 |
1771 void _addProposal_reparentFlutterWidget() { | 1839 Future<Null> _addProposal_reparentFlutterWidget() async { |
1772 InstanceCreationExpression newExpr = identifyNewExpression(node); | 1840 InstanceCreationExpression newExpr = identifyNewExpression(node); |
1773 if (newExpr == null || !isFlutterInstanceCreationExpression(newExpr)) { | 1841 if (newExpr == null || !isFlutterInstanceCreationExpression(newExpr)) { |
1774 _coverageMarker(); | 1842 _coverageMarker(); |
1775 return; | 1843 return; |
1776 } | 1844 } |
1777 String newExprSrc = utils.getNodeText(newExpr); | 1845 String newExprSrc = utils.getNodeText(newExpr); |
1778 SourceBuilder sb = new SourceBuilder(file, newExpr.offset); | 1846 |
1779 sb.append('new '); | 1847 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1780 sb.startPosition('WIDGET'); | 1848 await changeBuilder.addFileEdit(file, fileStamp, |
1781 sb.append('widget'); | 1849 (DartFileEditBuilder builder) { |
1782 sb.endPosition(); | 1850 builder.addReplacement(range.node(newExpr), (DartEditBuilder builder) { |
1783 sb.append('('); | 1851 builder.write('new '); |
1784 if (newExprSrc.contains(eol)) { | 1852 builder.addSimpleLinkedEdit('WIDGET', 'widget'); |
1785 int newlineIdx = newExprSrc.lastIndexOf(eol); | 1853 builder.write('('); |
1786 int eolLen = eol.length; | 1854 if (newExprSrc.contains(eol)) { |
1787 if (newlineIdx == newExprSrc.length - eolLen) { | 1855 int newlineIdx = newExprSrc.lastIndexOf(eol); |
1788 newlineIdx -= eolLen; | 1856 int eolLen = eol.length; |
1789 } | 1857 if (newlineIdx == newExprSrc.length - eolLen) { |
1790 String indentOld = | 1858 newlineIdx -= eolLen; |
1791 utils.getLinePrefix(newExpr.offset + eolLen + newlineIdx); | 1859 } |
1792 String indentNew = '$indentOld${utils.getIndent(1)}'; | 1860 String indentOld = |
1793 sb.append(eol); | 1861 utils.getLinePrefix(newExpr.offset + eolLen + newlineIdx); |
1794 sb.append(indentNew); | 1862 String indentNew = '$indentOld${utils.getIndent(1)}'; |
1795 newExprSrc = newExprSrc.replaceAll( | 1863 builder.write(eol); |
1796 new RegExp("^$indentOld", multiLine: true), "$indentNew"); | 1864 builder.write(indentNew); |
1797 newExprSrc += ",$eol$indentOld"; | 1865 newExprSrc = newExprSrc.replaceAll( |
1798 } | 1866 new RegExp("^$indentOld", multiLine: true), indentNew); |
1799 sb.startPosition('CHILD'); | 1867 newExprSrc += ",$eol$indentOld"; |
1800 sb.append('child'); | 1868 } |
1801 sb.endPosition(); | 1869 builder.addSimpleLinkedEdit('CHILD', 'child'); |
1802 sb.append(': '); | 1870 builder.write(': '); |
1803 sb.append(newExprSrc); | 1871 builder.write(newExprSrc); |
1804 sb.append(')'); | 1872 builder.write(')'); |
1805 exitPosition = _newPosition(sb.offset + sb.length); | 1873 builder.selectHere(); |
1806 _insertBuilder(sb, newExpr.length); | 1874 }); |
1807 _addAssist(DartAssistKind.REPARENT_FLUTTER_WIDGET, []); | 1875 }); |
| 1876 _addAssistFromBuilder( |
| 1877 changeBuilder, DartAssistKind.REPARENT_FLUTTER_WIDGET); |
1808 } | 1878 } |
1809 | 1879 |
1810 void _addProposal_replaceConditionalWithIfElse() { | 1880 Future<Null> _addProposal_replaceConditionalWithIfElse() async { |
1811 ConditionalExpression conditional = null; | 1881 ConditionalExpression conditional = null; |
1812 // may be on Statement with Conditional | 1882 // may be on Statement with Conditional |
1813 Statement statement = node.getAncestor((node) => node is Statement); | 1883 Statement statement = node.getAncestor((node) => node is Statement); |
1814 if (statement == null) { | 1884 if (statement == null) { |
1815 _coverageMarker(); | 1885 _coverageMarker(); |
1816 return; | 1886 return; |
1817 } | 1887 } |
1818 // variable declaration | 1888 // variable declaration |
1819 bool inVariable = false; | 1889 bool inVariable = false; |
1820 if (statement is VariableDeclarationStatement) { | 1890 if (statement is VariableDeclarationStatement) { |
(...skipping 26 matching lines...) Expand all Loading... |
1847 if (statement is ReturnStatement) { | 1917 if (statement is ReturnStatement) { |
1848 ReturnStatement returnStatement = statement; | 1918 ReturnStatement returnStatement = statement; |
1849 if (returnStatement.expression is ConditionalExpression) { | 1919 if (returnStatement.expression is ConditionalExpression) { |
1850 conditional = returnStatement.expression as ConditionalExpression; | 1920 conditional = returnStatement.expression as ConditionalExpression; |
1851 inReturn = true; | 1921 inReturn = true; |
1852 } | 1922 } |
1853 } | 1923 } |
1854 // prepare environment | 1924 // prepare environment |
1855 String indent = utils.getIndent(1); | 1925 String indent = utils.getIndent(1); |
1856 String prefix = utils.getNodePrefix(statement); | 1926 String prefix = utils.getNodePrefix(statement); |
1857 // Type v = Conditional; | 1927 |
1858 if (inVariable) { | 1928 if (inVariable || inAssignment || inReturn) { |
1859 VariableDeclaration variable = conditional.parent as VariableDeclaration; | 1929 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1860 _addRemoveEdit(range.endEnd(variable.name, conditional)); | 1930 await changeBuilder.addFileEdit(file, fileStamp, |
1861 String conditionSrc = _getNodeText(conditional.condition); | 1931 (DartFileEditBuilder builder) { |
1862 String thenSrc = _getNodeText(conditional.thenExpression); | 1932 // Type v = Conditional; |
1863 String elseSrc = _getNodeText(conditional.elseExpression); | 1933 if (inVariable) { |
1864 String name = variable.name.name; | 1934 VariableDeclaration variable = |
1865 String src = eol; | 1935 conditional.parent as VariableDeclaration; |
1866 src += prefix + 'if ($conditionSrc) {' + eol; | 1936 builder.addDeletion(range.endEnd(variable.name, conditional)); |
1867 src += prefix + indent + '$name = $thenSrc;' + eol; | 1937 String conditionSrc = _getNodeText(conditional.condition); |
1868 src += prefix + '} else {' + eol; | 1938 String thenSrc = _getNodeText(conditional.thenExpression); |
1869 src += prefix + indent + '$name = $elseSrc;' + eol; | 1939 String elseSrc = _getNodeText(conditional.elseExpression); |
1870 src += prefix + '}'; | 1940 String name = variable.name.name; |
1871 _addReplaceEdit(range.endLength(statement, 0), src); | 1941 String src = eol; |
| 1942 src += prefix + 'if ($conditionSrc) {' + eol; |
| 1943 src += prefix + indent + '$name = $thenSrc;' + eol; |
| 1944 src += prefix + '} else {' + eol; |
| 1945 src += prefix + indent + '$name = $elseSrc;' + eol; |
| 1946 src += prefix + '}'; |
| 1947 builder.addSimpleReplacement(range.endLength(statement, 0), src); |
| 1948 } |
| 1949 // v = Conditional; |
| 1950 if (inAssignment) { |
| 1951 AssignmentExpression assignment = |
| 1952 conditional.parent as AssignmentExpression; |
| 1953 Expression leftSide = assignment.leftHandSide; |
| 1954 String conditionSrc = _getNodeText(conditional.condition); |
| 1955 String thenSrc = _getNodeText(conditional.thenExpression); |
| 1956 String elseSrc = _getNodeText(conditional.elseExpression); |
| 1957 String name = _getNodeText(leftSide); |
| 1958 String src = ''; |
| 1959 src += 'if ($conditionSrc) {' + eol; |
| 1960 src += prefix + indent + '$name = $thenSrc;' + eol; |
| 1961 src += prefix + '} else {' + eol; |
| 1962 src += prefix + indent + '$name = $elseSrc;' + eol; |
| 1963 src += prefix + '}'; |
| 1964 builder.addSimpleReplacement(range.node(statement), src); |
| 1965 } |
| 1966 // return Conditional; |
| 1967 if (inReturn) { |
| 1968 String conditionSrc = _getNodeText(conditional.condition); |
| 1969 String thenSrc = _getNodeText(conditional.thenExpression); |
| 1970 String elseSrc = _getNodeText(conditional.elseExpression); |
| 1971 String src = ''; |
| 1972 src += 'if ($conditionSrc) {' + eol; |
| 1973 src += prefix + indent + 'return $thenSrc;' + eol; |
| 1974 src += prefix + '} else {' + eol; |
| 1975 src += prefix + indent + 'return $elseSrc;' + eol; |
| 1976 src += prefix + '}'; |
| 1977 builder.addSimpleReplacement(range.node(statement), src); |
| 1978 } |
| 1979 }); |
| 1980 _addAssistFromBuilder( |
| 1981 changeBuilder, DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE); |
1872 } | 1982 } |
1873 // v = Conditional; | |
1874 if (inAssignment) { | |
1875 AssignmentExpression assignment = | |
1876 conditional.parent as AssignmentExpression; | |
1877 Expression leftSide = assignment.leftHandSide; | |
1878 String conditionSrc = _getNodeText(conditional.condition); | |
1879 String thenSrc = _getNodeText(conditional.thenExpression); | |
1880 String elseSrc = _getNodeText(conditional.elseExpression); | |
1881 String name = _getNodeText(leftSide); | |
1882 String src = ''; | |
1883 src += 'if ($conditionSrc) {' + eol; | |
1884 src += prefix + indent + '$name = $thenSrc;' + eol; | |
1885 src += prefix + '} else {' + eol; | |
1886 src += prefix + indent + '$name = $elseSrc;' + eol; | |
1887 src += prefix + '}'; | |
1888 _addReplaceEdit(range.node(statement), src); | |
1889 } | |
1890 // return Conditional; | |
1891 if (inReturn) { | |
1892 String conditionSrc = _getNodeText(conditional.condition); | |
1893 String thenSrc = _getNodeText(conditional.thenExpression); | |
1894 String elseSrc = _getNodeText(conditional.elseExpression); | |
1895 String src = ''; | |
1896 src += 'if ($conditionSrc) {' + eol; | |
1897 src += prefix + indent + 'return $thenSrc;' + eol; | |
1898 src += prefix + '} else {' + eol; | |
1899 src += prefix + indent + 'return $elseSrc;' + eol; | |
1900 src += prefix + '}'; | |
1901 _addReplaceEdit(range.node(statement), src); | |
1902 } | |
1903 // add proposal | |
1904 _addAssist(DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE, []); | |
1905 } | 1983 } |
1906 | 1984 |
1907 void _addProposal_replaceIfElseWithConditional() { | 1985 Future<Null> _addProposal_replaceIfElseWithConditional() async { |
1908 // should be "if" | 1986 // should be "if" |
1909 if (node is! IfStatement) { | 1987 if (node is! IfStatement) { |
1910 _coverageMarker(); | 1988 _coverageMarker(); |
1911 return; | 1989 return; |
1912 } | 1990 } |
1913 IfStatement ifStatement = node as IfStatement; | 1991 IfStatement ifStatement = node as IfStatement; |
1914 // single then/else statements | 1992 // single then/else statements |
1915 Statement thenStatement = getSingleStatement(ifStatement.thenStatement); | 1993 Statement thenStatement = getSingleStatement(ifStatement.thenStatement); |
1916 Statement elseStatement = getSingleStatement(ifStatement.elseStatement); | 1994 Statement elseStatement = getSingleStatement(ifStatement.elseStatement); |
1917 if (thenStatement == null || elseStatement == null) { | 1995 if (thenStatement == null || elseStatement == null) { |
1918 _coverageMarker(); | 1996 _coverageMarker(); |
1919 return; | 1997 return; |
1920 } | 1998 } |
1921 // returns | 1999 Expression thenExpression = null; |
| 2000 Expression elseExpression = null; |
| 2001 bool hasReturnStatements = false; |
1922 if (thenStatement is ReturnStatement && elseStatement is ReturnStatement) { | 2002 if (thenStatement is ReturnStatement && elseStatement is ReturnStatement) { |
1923 String conditionSrc = _getNodeText(ifStatement.condition); | 2003 hasReturnStatements = true; |
1924 String theSrc = _getNodeText(thenStatement.expression); | 2004 thenExpression = thenStatement.expression; |
1925 String elseSrc = _getNodeText(elseStatement.expression); | 2005 elseExpression = elseStatement.expression; |
1926 _addReplaceEdit(range.node(ifStatement), | |
1927 'return $conditionSrc ? $theSrc : $elseSrc;'); | |
1928 } | 2006 } |
1929 // assignments -> v = Conditional; | 2007 bool hasExpressionStatements = false; |
1930 if (thenStatement is ExpressionStatement && | 2008 if (thenStatement is ExpressionStatement && |
1931 elseStatement is ExpressionStatement) { | 2009 elseStatement is ExpressionStatement) { |
1932 Expression thenExpression = thenStatement.expression; | 2010 if (thenStatement.expression is AssignmentExpression && |
1933 Expression elseExpression = elseStatement.expression; | 2011 elseStatement.expression is AssignmentExpression) { |
1934 if (thenExpression is AssignmentExpression && | 2012 hasExpressionStatements = true; |
1935 elseExpression is AssignmentExpression) { | 2013 thenExpression = thenStatement.expression; |
1936 AssignmentExpression thenAssignment = thenExpression; | 2014 elseExpression = elseStatement.expression; |
1937 AssignmentExpression elseAssignment = elseExpression; | |
1938 String thenTarget = _getNodeText(thenAssignment.leftHandSide); | |
1939 String elseTarget = _getNodeText(elseAssignment.leftHandSide); | |
1940 if (thenAssignment.operator.type == TokenType.EQ && | |
1941 elseAssignment.operator.type == TokenType.EQ && | |
1942 thenTarget == elseTarget) { | |
1943 String conditionSrc = _getNodeText(ifStatement.condition); | |
1944 String theSrc = _getNodeText(thenAssignment.rightHandSide); | |
1945 String elseSrc = _getNodeText(elseAssignment.rightHandSide); | |
1946 _addReplaceEdit(range.node(ifStatement), | |
1947 '$thenTarget = $conditionSrc ? $theSrc : $elseSrc;'); | |
1948 } | |
1949 } | 2015 } |
1950 } | 2016 } |
1951 // add proposal | 2017 |
1952 _addAssist(DartAssistKind.REPLACE_IF_ELSE_WITH_CONDITIONAL, []); | 2018 if (hasReturnStatements || hasExpressionStatements) { |
| 2019 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
| 2020 await changeBuilder.addFileEdit(file, fileStamp, |
| 2021 (DartFileEditBuilder builder) { |
| 2022 // returns |
| 2023 if (hasReturnStatements) { |
| 2024 String conditionSrc = _getNodeText(ifStatement.condition); |
| 2025 String theSrc = _getNodeText(thenExpression); |
| 2026 String elseSrc = _getNodeText(elseExpression); |
| 2027 builder.addSimpleReplacement(range.node(ifStatement), |
| 2028 'return $conditionSrc ? $theSrc : $elseSrc;'); |
| 2029 } |
| 2030 // assignments -> v = Conditional; |
| 2031 if (hasExpressionStatements) { |
| 2032 AssignmentExpression thenAssignment = thenExpression; |
| 2033 AssignmentExpression elseAssignment = elseExpression; |
| 2034 String thenTarget = _getNodeText(thenAssignment.leftHandSide); |
| 2035 String elseTarget = _getNodeText(elseAssignment.leftHandSide); |
| 2036 if (thenAssignment.operator.type == TokenType.EQ && |
| 2037 elseAssignment.operator.type == TokenType.EQ && |
| 2038 thenTarget == elseTarget) { |
| 2039 String conditionSrc = _getNodeText(ifStatement.condition); |
| 2040 String theSrc = _getNodeText(thenAssignment.rightHandSide); |
| 2041 String elseSrc = _getNodeText(elseAssignment.rightHandSide); |
| 2042 builder.addSimpleReplacement(range.node(ifStatement), |
| 2043 '$thenTarget = $conditionSrc ? $theSrc : $elseSrc;'); |
| 2044 } |
| 2045 } |
| 2046 }); |
| 2047 _addAssistFromBuilder( |
| 2048 changeBuilder, DartAssistKind.REPLACE_IF_ELSE_WITH_CONDITIONAL); |
| 2049 } |
1953 } | 2050 } |
1954 | 2051 |
1955 void _addProposal_splitAndCondition() { | 2052 Future<Null> _addProposal_splitAndCondition() async { |
1956 // check that user invokes quick assist on binary expression | 2053 // check that user invokes quick assist on binary expression |
1957 if (node is! BinaryExpression) { | 2054 if (node is! BinaryExpression) { |
1958 _coverageMarker(); | 2055 _coverageMarker(); |
1959 return; | 2056 return; |
1960 } | 2057 } |
1961 BinaryExpression binaryExpression = node as BinaryExpression; | 2058 BinaryExpression binaryExpression = node as BinaryExpression; |
1962 // prepare operator position | 2059 // prepare operator position |
1963 if (!_isOperatorSelected( | 2060 if (!_isOperatorSelected( |
1964 binaryExpression, selectionOffset, selectionLength)) { | 2061 binaryExpression, selectionOffset, selectionLength)) { |
1965 _coverageMarker(); | 2062 _coverageMarker(); |
(...skipping 30 matching lines...) Expand all Loading... |
1996 // prepare environment | 2093 // prepare environment |
1997 String prefix = utils.getNodePrefix(ifStatement); | 2094 String prefix = utils.getNodePrefix(ifStatement); |
1998 String indent = utils.getIndent(1); | 2095 String indent = utils.getIndent(1); |
1999 // prepare "rightCondition" | 2096 // prepare "rightCondition" |
2000 String rightConditionSource; | 2097 String rightConditionSource; |
2001 { | 2098 { |
2002 SourceRange rightConditionRange = | 2099 SourceRange rightConditionRange = |
2003 range.startEnd(binaryExpression.rightOperand, condition); | 2100 range.startEnd(binaryExpression.rightOperand, condition); |
2004 rightConditionSource = _getRangeText(rightConditionRange); | 2101 rightConditionSource = _getRangeText(rightConditionRange); |
2005 } | 2102 } |
2006 // remove "&& rightCondition" | 2103 |
2007 _addRemoveEdit(range.endEnd(binaryExpression.leftOperand, condition)); | 2104 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2008 // update "then" statement | 2105 await changeBuilder.addFileEdit(file, fileStamp, |
2009 Statement thenStatement = ifStatement.thenStatement; | 2106 (DartFileEditBuilder builder) { |
2010 if (thenStatement is Block) { | 2107 // remove "&& rightCondition" |
2011 Block thenBlock = thenStatement; | 2108 builder |
2012 SourceRange thenBlockRange = range.node(thenBlock); | 2109 .addDeletion(range.endEnd(binaryExpression.leftOperand, condition)); |
2013 // insert inner "if" with right part of "condition" | 2110 // update "then" statement |
| 2111 Statement thenStatement = ifStatement.thenStatement; |
| 2112 if (thenStatement is Block) { |
| 2113 Block thenBlock = thenStatement; |
| 2114 SourceRange thenBlockRange = range.node(thenBlock); |
| 2115 // insert inner "if" with right part of "condition" |
| 2116 int thenBlockInsideOffset = thenBlockRange.offset + 1; |
| 2117 builder.addSimpleInsertion(thenBlockInsideOffset, |
| 2118 '$eol$prefix${indent}if ($rightConditionSource) {'); |
| 2119 // insert closing "}" for inner "if" |
| 2120 int thenBlockEnd = thenBlockRange.end; |
| 2121 // insert before outer "then" block "}" |
| 2122 builder.addSimpleInsertion(thenBlockEnd - 1, '$indent}$eol$prefix'); |
| 2123 } else { |
| 2124 // insert inner "if" with right part of "condition" |
| 2125 String source = '$eol$prefix${indent}if ($rightConditionSource)'; |
| 2126 builder.addSimpleInsertion( |
| 2127 ifStatement.rightParenthesis.offset + 1, source); |
| 2128 } |
| 2129 // indent "then" statements to correspond inner "if" |
2014 { | 2130 { |
2015 String source = '$eol$prefix${indent}if ($rightConditionSource) {'; | 2131 List<Statement> thenStatements = getStatements(thenStatement); |
2016 int thenBlockInsideOffset = thenBlockRange.offset + 1; | 2132 SourceRange linesRange = utils.getLinesRangeStatements(thenStatements); |
2017 _addInsertEdit(thenBlockInsideOffset, source); | 2133 String thenIndentOld = '$prefix$indent'; |
| 2134 String thenIndentNew = '$thenIndentOld$indent'; |
| 2135 builder.addSimpleReplacement( |
| 2136 linesRange, |
| 2137 utils.replaceSourceRangeIndent( |
| 2138 linesRange, thenIndentOld, thenIndentNew)); |
2018 } | 2139 } |
2019 // insert closing "}" for inner "if" | 2140 }); |
2020 { | 2141 _addAssistFromBuilder(changeBuilder, DartAssistKind.SPLIT_AND_CONDITION); |
2021 int thenBlockEnd = thenBlockRange.end; | |
2022 String source = "$indent}"; | |
2023 // insert before outer "then" block "}" | |
2024 source += '$eol$prefix'; | |
2025 _addInsertEdit(thenBlockEnd - 1, source); | |
2026 } | |
2027 } else { | |
2028 // insert inner "if" with right part of "condition" | |
2029 String source = '$eol$prefix${indent}if ($rightConditionSource)'; | |
2030 _addInsertEdit(ifStatement.rightParenthesis.offset + 1, source); | |
2031 } | |
2032 // indent "then" statements to correspond inner "if" | |
2033 { | |
2034 List<Statement> thenStatements = getStatements(thenStatement); | |
2035 SourceRange linesRange = utils.getLinesRangeStatements(thenStatements); | |
2036 String thenIndentOld = '$prefix$indent'; | |
2037 String thenIndentNew = '$thenIndentOld$indent'; | |
2038 _addIndentEdit(linesRange, thenIndentOld, thenIndentNew); | |
2039 } | |
2040 // add proposal | |
2041 _addAssist(DartAssistKind.SPLIT_AND_CONDITION, []); | |
2042 } | 2142 } |
2043 | 2143 |
2044 void _addProposal_splitVariableDeclaration() { | 2144 Future<Null> _addProposal_splitVariableDeclaration() async { |
2045 // prepare DartVariableStatement, should be part of Block | 2145 // prepare DartVariableStatement, should be part of Block |
2046 VariableDeclarationStatement statement = | 2146 VariableDeclarationStatement statement = |
2047 node.getAncestor((node) => node is VariableDeclarationStatement); | 2147 node.getAncestor((node) => node is VariableDeclarationStatement); |
2048 if (statement != null && statement.parent is Block) {} else { | 2148 if (statement != null && statement.parent is Block) {} else { |
2049 _coverageMarker(); | 2149 _coverageMarker(); |
2050 return; | 2150 return; |
2051 } | 2151 } |
2052 // check that statement declares single variable | 2152 // check that statement declares single variable |
2053 List<VariableDeclaration> variables = statement.variables.variables; | 2153 List<VariableDeclaration> variables = statement.variables.variables; |
2054 if (variables.length != 1) { | 2154 if (variables.length != 1) { |
2055 _coverageMarker(); | 2155 _coverageMarker(); |
2056 return; | 2156 return; |
2057 } | 2157 } |
2058 VariableDeclaration variable = variables[0]; | 2158 VariableDeclaration variable = variables[0]; |
2059 // prepare initializer | 2159 // prepare initializer |
2060 Expression initializer = variable.initializer; | 2160 Expression initializer = variable.initializer; |
2061 if (initializer == null) { | 2161 if (initializer == null) { |
2062 _coverageMarker(); | 2162 _coverageMarker(); |
2063 return; | 2163 return; |
2064 } | 2164 } |
2065 // remove initializer value | 2165 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2066 _addRemoveEdit(range.endStart(variable.name, statement.semicolon)); | 2166 await changeBuilder.addFileEdit(file, fileStamp, |
2067 // add assignment statement | 2167 (DartFileEditBuilder builder) { |
2068 String indent = utils.getNodePrefix(statement); | 2168 // remove initializer value |
2069 String name = variable.name.name; | 2169 builder.addDeletion(range.endStart(variable.name, statement.semicolon)); |
2070 String initSrc = _getNodeText(initializer); | 2170 // add assignment statement |
2071 SourceRange assignRange = range.endLength(statement, 0); | 2171 String indent = utils.getNodePrefix(statement); |
2072 _addReplaceEdit(assignRange, eol + indent + name + ' = ' + initSrc + ';'); | 2172 String name = variable.name.name; |
2073 // add proposal | 2173 String initSrc = _getNodeText(initializer); |
2074 _addAssist(DartAssistKind.SPLIT_VARIABLE_DECLARATION, []); | 2174 SourceRange assignRange = range.endLength(statement, 0); |
| 2175 builder.addSimpleReplacement( |
| 2176 assignRange, eol + indent + name + ' = ' + initSrc + ';'); |
| 2177 }); |
| 2178 _addAssistFromBuilder( |
| 2179 changeBuilder, DartAssistKind.SPLIT_VARIABLE_DECLARATION); |
2075 } | 2180 } |
2076 | 2181 |
2077 void _addProposal_surroundWith() { | 2182 Future<Null> _addProposal_surroundWith() async { |
2078 // prepare selected statements | 2183 // prepare selected statements |
2079 List<Statement> selectedStatements; | 2184 List<Statement> selectedStatements; |
2080 { | 2185 { |
2081 SourceRange selection = new SourceRange(selectionOffset, selectionLength); | 2186 StatementAnalyzer selectionAnalyzer = new StatementAnalyzer( |
2082 StatementAnalyzer selectionAnalyzer = | 2187 unit, new SourceRange(selectionOffset, selectionLength)); |
2083 new StatementAnalyzer(unit, selection); | |
2084 unit.accept(selectionAnalyzer); | 2188 unit.accept(selectionAnalyzer); |
2085 List<AstNode> selectedNodes = selectionAnalyzer.selectedNodes; | 2189 List<AstNode> selectedNodes = selectionAnalyzer.selectedNodes; |
2086 // convert nodes to statements | 2190 // convert nodes to statements |
2087 selectedStatements = []; | 2191 selectedStatements = []; |
2088 for (AstNode selectedNode in selectedNodes) { | 2192 for (AstNode selectedNode in selectedNodes) { |
2089 if (selectedNode is Statement) { | 2193 if (selectedNode is Statement) { |
2090 selectedStatements.add(selectedNode); | 2194 selectedStatements.add(selectedNode); |
2091 } | 2195 } |
2092 } | 2196 } |
2093 // we want only statements | 2197 // we want only statements |
2094 if (selectedStatements.isEmpty || | 2198 if (selectedStatements.isEmpty || |
2095 selectedStatements.length != selectedNodes.length) { | 2199 selectedStatements.length != selectedNodes.length) { |
2096 return; | 2200 return; |
2097 } | 2201 } |
2098 } | 2202 } |
2099 // prepare statement information | 2203 // prepare statement information |
2100 Statement firstStatement = selectedStatements[0]; | 2204 Statement firstStatement = selectedStatements[0]; |
2101 Statement lastStatement = selectedStatements[selectedStatements.length - 1]; | 2205 Statement lastStatement = selectedStatements[selectedStatements.length - 1]; |
2102 SourceRange statementsRange = | 2206 SourceRange statementsRange = |
2103 utils.getLinesRangeStatements(selectedStatements); | 2207 utils.getLinesRangeStatements(selectedStatements); |
2104 // prepare environment | 2208 // prepare environment |
2105 String indentOld = utils.getNodePrefix(firstStatement); | 2209 String indentOld = utils.getNodePrefix(firstStatement); |
2106 String indentNew = '$indentOld${utils.getIndent(1)}'; | 2210 String indentNew = '$indentOld${utils.getIndent(1)}'; |
2107 String indentedCode = | 2211 String indentedCode = |
2108 utils.replaceSourceRangeIndent(statementsRange, indentOld, indentNew); | 2212 utils.replaceSourceRangeIndent(statementsRange, indentOld, indentNew); |
2109 // "block" | 2213 // "block" |
2110 { | 2214 { |
2111 _addInsertEdit(statementsRange.offset, '$indentOld{$eol'); | 2215 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2112 _addIndentEdit(statementsRange, indentOld, indentNew); | 2216 await changeBuilder.addFileEdit(file, fileStamp, |
2113 _addInsertEdit(statementsRange.end, '$indentOld}$eol'); | 2217 (DartFileEditBuilder builder) { |
2114 exitPosition = _newPosition(lastStatement.end); | 2218 builder.addSimpleInsertion(statementsRange.offset, '$indentOld{$eol'); |
2115 // add proposal | 2219 builder.addSimpleReplacement( |
2116 _addAssist(DartAssistKind.SURROUND_WITH_BLOCK, []); | 2220 statementsRange, |
| 2221 utils.replaceSourceRangeIndent( |
| 2222 statementsRange, indentOld, indentNew)); |
| 2223 builder.addSimpleInsertion(statementsRange.end, '$indentOld}$eol'); |
| 2224 exitPosition = _newPosition(lastStatement.end); |
| 2225 }); |
| 2226 _addAssistFromBuilder(changeBuilder, DartAssistKind.SURROUND_WITH_BLOCK); |
2117 } | 2227 } |
2118 // "if" | 2228 // "if" |
2119 { | 2229 { |
2120 int offset = statementsRange.offset; | 2230 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2121 SourceBuilder sb = new SourceBuilder(file, offset); | 2231 await changeBuilder.addFileEdit(file, fileStamp, |
2122 sb.append(indentOld); | 2232 (DartFileEditBuilder builder) { |
2123 sb.append('if ('); | 2233 builder.addReplacement(statementsRange, (DartEditBuilder builder) { |
2124 { | 2234 builder.write(indentOld); |
2125 sb.startPosition('CONDITION'); | 2235 builder.write('if ('); |
2126 sb.append('condition'); | 2236 builder.addSimpleLinkedEdit('CONDITION', 'condition'); |
2127 sb.endPosition(); | 2237 builder.write(') {'); |
2128 } | 2238 builder.write(eol); |
2129 sb.append(') {'); | 2239 builder.write(indentedCode); |
2130 sb.append(eol); | 2240 builder.write(indentOld); |
2131 sb.append(indentedCode); | 2241 builder.write('}'); |
2132 sb.append(indentOld); | 2242 builder.selectHere(); |
2133 sb.append('}'); | 2243 builder.write(eol); |
2134 exitPosition = _newPosition(sb.offset + sb.length); | 2244 }); |
2135 sb.append(eol); | 2245 }); |
2136 _insertBuilder(sb, statementsRange.length); | 2246 _addAssistFromBuilder(changeBuilder, DartAssistKind.SURROUND_WITH_IF); |
2137 // add proposal | |
2138 _addAssist(DartAssistKind.SURROUND_WITH_IF, []); | |
2139 } | 2247 } |
2140 // "while" | 2248 // "while" |
2141 { | 2249 { |
2142 int offset = statementsRange.offset; | 2250 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2143 SourceBuilder sb = new SourceBuilder(file, offset); | 2251 await changeBuilder.addFileEdit(file, fileStamp, |
2144 sb.append(indentOld); | 2252 (DartFileEditBuilder builder) { |
2145 sb.append('while ('); | 2253 builder.addReplacement(statementsRange, (DartEditBuilder builder) { |
2146 { | 2254 builder.write(indentOld); |
2147 sb.startPosition('CONDITION'); | 2255 builder.write('while ('); |
2148 sb.append('condition'); | 2256 builder.addSimpleLinkedEdit('CONDITION', 'condition'); |
2149 sb.endPosition(); | 2257 builder.write(') {'); |
2150 } | 2258 builder.write(eol); |
2151 sb.append(') {'); | 2259 builder.write(indentedCode); |
2152 sb.append(eol); | 2260 builder.write(indentOld); |
2153 sb.append(indentedCode); | 2261 builder.write('}'); |
2154 sb.append(indentOld); | 2262 builder.selectHere(); |
2155 sb.append('}'); | 2263 builder.write(eol); |
2156 exitPosition = _newPosition(sb.offset + sb.length); | 2264 }); |
2157 sb.append(eol); | 2265 }); |
2158 _insertBuilder(sb, statementsRange.length); | 2266 _addAssistFromBuilder(changeBuilder, DartAssistKind.SURROUND_WITH_WHILE); |
2159 // add proposal | |
2160 _addAssist(DartAssistKind.SURROUND_WITH_WHILE, []); | |
2161 } | 2267 } |
2162 // "for-in" | 2268 // "for-in" |
2163 { | 2269 { |
2164 int offset = statementsRange.offset; | 2270 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2165 SourceBuilder sb = new SourceBuilder(file, offset); | 2271 await changeBuilder.addFileEdit(file, fileStamp, |
2166 sb.append(indentOld); | 2272 (DartFileEditBuilder builder) { |
2167 sb.append('for (var '); | 2273 builder.addReplacement(statementsRange, (DartEditBuilder builder) { |
2168 { | 2274 builder.write(indentOld); |
2169 sb.startPosition('NAME'); | 2275 builder.write('for (var '); |
2170 sb.append('item'); | 2276 builder.addSimpleLinkedEdit('NAME', 'item'); |
2171 sb.endPosition(); | 2277 builder.write(' in '); |
2172 } | 2278 builder.addSimpleLinkedEdit('ITERABLE', 'iterable'); |
2173 sb.append(' in '); | 2279 builder.write(') {'); |
2174 { | 2280 builder.write(eol); |
2175 sb.startPosition('ITERABLE'); | 2281 builder.write(indentedCode); |
2176 sb.append('iterable'); | 2282 builder.write(indentOld); |
2177 sb.endPosition(); | 2283 builder.write('}'); |
2178 } | 2284 builder.selectHere(); |
2179 sb.append(') {'); | 2285 builder.write(eol); |
2180 sb.append(eol); | 2286 }); |
2181 sb.append(indentedCode); | 2287 }); |
2182 sb.append(indentOld); | 2288 _addAssistFromBuilder(changeBuilder, DartAssistKind.SURROUND_WITH_FOR_IN); |
2183 sb.append('}'); | |
2184 exitPosition = _newPosition(sb.offset + sb.length); | |
2185 sb.append(eol); | |
2186 _insertBuilder(sb, statementsRange.length); | |
2187 // add proposal | |
2188 _addAssist(DartAssistKind.SURROUND_WITH_FOR_IN, []); | |
2189 } | 2289 } |
2190 // "for" | 2290 // "for" |
2191 { | 2291 { |
2192 int offset = statementsRange.offset; | 2292 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2193 SourceBuilder sb = new SourceBuilder(file, offset); | 2293 await changeBuilder.addFileEdit(file, fileStamp, |
2194 sb.append(indentOld); | 2294 (DartFileEditBuilder builder) { |
2195 sb.append('for (var '); | 2295 builder.addReplacement(statementsRange, (DartEditBuilder builder) { |
2196 { | 2296 builder.write(indentOld); |
2197 sb.startPosition('VAR'); | 2297 builder.write('for (var '); |
2198 sb.append('v'); | 2298 builder.addSimpleLinkedEdit('VAR', 'v'); |
2199 sb.endPosition(); | 2299 builder.write(' = '); |
2200 } | 2300 builder.addSimpleLinkedEdit('INIT', 'init'); |
2201 sb.append(' = '); | 2301 builder.write('; '); |
2202 { | 2302 builder.addSimpleLinkedEdit('CONDITION', 'condition'); |
2203 sb.startPosition('INIT'); | 2303 builder.write('; '); |
2204 sb.append('init'); | 2304 builder.addSimpleLinkedEdit('INCREMENT', 'increment'); |
2205 sb.endPosition(); | 2305 builder.write(') {'); |
2206 } | 2306 builder.write(eol); |
2207 sb.append('; '); | 2307 builder.write(indentedCode); |
2208 { | 2308 builder.write(indentOld); |
2209 sb.startPosition('CONDITION'); | 2309 builder.write('}'); |
2210 sb.append('condition'); | 2310 builder.selectHere(); |
2211 sb.endPosition(); | 2311 builder.write(eol); |
2212 } | 2312 }); |
2213 sb.append('; '); | 2313 }); |
2214 { | 2314 _addAssistFromBuilder(changeBuilder, DartAssistKind.SURROUND_WITH_FOR); |
2215 sb.startPosition('INCREMENT'); | |
2216 sb.append('increment'); | |
2217 sb.endPosition(); | |
2218 } | |
2219 sb.append(') {'); | |
2220 sb.append(eol); | |
2221 sb.append(indentedCode); | |
2222 sb.append(indentOld); | |
2223 sb.append('}'); | |
2224 exitPosition = _newPosition(sb.offset + sb.length); | |
2225 sb.append(eol); | |
2226 _insertBuilder(sb, statementsRange.length); | |
2227 // add proposal | |
2228 _addAssist(DartAssistKind.SURROUND_WITH_FOR, []); | |
2229 } | 2315 } |
2230 // "do-while" | 2316 // "do-while" |
2231 { | 2317 { |
2232 int offset = statementsRange.offset; | 2318 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2233 SourceBuilder sb = new SourceBuilder(file, offset); | 2319 await changeBuilder.addFileEdit(file, fileStamp, |
2234 sb.append(indentOld); | 2320 (DartFileEditBuilder builder) { |
2235 sb.append('do {'); | 2321 builder.addReplacement(statementsRange, (DartEditBuilder builder) { |
2236 sb.append(eol); | 2322 builder.write(indentOld); |
2237 sb.append(indentedCode); | 2323 builder.write('do {'); |
2238 sb.append(indentOld); | 2324 builder.write(eol); |
2239 sb.append('} while ('); | 2325 builder.write(indentedCode); |
2240 { | 2326 builder.write(indentOld); |
2241 sb.startPosition('CONDITION'); | 2327 builder.write('} while ('); |
2242 sb.append('condition'); | 2328 builder.addSimpleLinkedEdit('CONDITION', 'condition'); |
2243 sb.endPosition(); | 2329 builder.write(');'); |
2244 } | 2330 builder.selectHere(); |
2245 sb.append(');'); | 2331 builder.write(eol); |
2246 exitPosition = _newPosition(sb.offset + sb.length); | 2332 }); |
2247 sb.append(eol); | 2333 }); |
2248 _insertBuilder(sb, statementsRange.length); | 2334 _addAssistFromBuilder( |
2249 // add proposal | 2335 changeBuilder, DartAssistKind.SURROUND_WITH_DO_WHILE); |
2250 _addAssist(DartAssistKind.SURROUND_WITH_DO_WHILE, []); | |
2251 } | 2336 } |
2252 // "try-catch" | 2337 // "try-catch" |
2253 { | 2338 { |
2254 int offset = statementsRange.offset; | 2339 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2255 SourceBuilder sb = new SourceBuilder(file, offset); | 2340 await changeBuilder.addFileEdit(file, fileStamp, |
2256 sb.append(indentOld); | 2341 (DartFileEditBuilder builder) { |
2257 sb.append('try {'); | 2342 builder.addReplacement(statementsRange, (DartEditBuilder builder) { |
2258 sb.append(eol); | 2343 builder.write(indentOld); |
2259 sb.append(indentedCode); | 2344 builder.write('try {'); |
2260 sb.append(indentOld); | 2345 builder.write(eol); |
2261 sb.append('} on '); | 2346 builder.write(indentedCode); |
2262 { | 2347 builder.write(indentOld); |
2263 sb.startPosition('EXCEPTION_TYPE'); | 2348 builder.write('} on '); |
2264 sb.append('Exception'); | 2349 builder.addSimpleLinkedEdit('EXCEPTION_TYPE', 'Exception'); |
2265 sb.endPosition(); | 2350 builder.write(' catch ('); |
2266 } | 2351 builder.addSimpleLinkedEdit('EXCEPTION_VAR', 'e'); |
2267 sb.append(' catch ('); | 2352 builder.write(') {'); |
2268 { | 2353 builder.write(eol); |
2269 sb.startPosition('EXCEPTION_VAR'); | 2354 // |
2270 sb.append('e'); | 2355 builder.write(indentNew); |
2271 sb.endPosition(); | 2356 builder.addSimpleLinkedEdit('CATCH', '// TODO'); |
2272 } | 2357 builder.selectHere(); |
2273 sb.append(') {'); | 2358 builder.write(eol); |
2274 sb.append(eol); | 2359 // |
2275 // | 2360 builder.write(indentOld); |
2276 sb.append(indentNew); | 2361 builder.write('}'); |
2277 { | 2362 builder.write(eol); |
2278 sb.startPosition('CATCH'); | 2363 }); |
2279 sb.append('// TODO'); | 2364 }); |
2280 sb.endPosition(); | 2365 _addAssistFromBuilder( |
2281 sb.setExitOffset(); | 2366 changeBuilder, DartAssistKind.SURROUND_WITH_TRY_CATCH); |
2282 } | |
2283 sb.append(eol); | |
2284 // | |
2285 sb.append(indentOld); | |
2286 sb.append('}'); | |
2287 sb.append(eol); | |
2288 _insertBuilder(sb, statementsRange.length); | |
2289 // add proposal | |
2290 _addAssist(DartAssistKind.SURROUND_WITH_TRY_CATCH, []); | |
2291 } | 2367 } |
2292 // "try-finally" | 2368 // "try-finally" |
2293 { | 2369 { |
2294 int offset = statementsRange.offset; | 2370 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2295 SourceBuilder sb = new SourceBuilder(file, offset); | 2371 await changeBuilder.addFileEdit(file, fileStamp, |
2296 // | 2372 (DartFileEditBuilder builder) { |
2297 sb.append(indentOld); | 2373 builder.addReplacement(statementsRange, (DartEditBuilder builder) { |
2298 sb.append('try {'); | 2374 builder.write(indentOld); |
2299 sb.append(eol); | 2375 builder.write('try {'); |
2300 // | 2376 builder.write(eol); |
2301 sb.append(indentedCode); | 2377 // |
2302 // | 2378 builder.write(indentedCode); |
2303 sb.append(indentOld); | 2379 // |
2304 sb.append('} finally {'); | 2380 builder.write(indentOld); |
2305 sb.append(eol); | 2381 builder.write('} finally {'); |
2306 // | 2382 builder.write(eol); |
2307 sb.append(indentNew); | 2383 // |
2308 { | 2384 builder.write(indentNew); |
2309 sb.startPosition('FINALLY'); | 2385 builder.addSimpleLinkedEdit('FINALLY', '// TODO'); |
2310 sb.append('// TODO'); | 2386 builder.selectHere(); |
2311 sb.endPosition(); | 2387 builder.write(eol); |
2312 sb.setExitOffset(); | 2388 // |
2313 } | 2389 builder.write(indentOld); |
2314 sb.setExitOffset(); | 2390 builder.write('}'); |
2315 sb.append(eol); | 2391 builder.write(eol); |
2316 // | 2392 }); |
2317 sb.append(indentOld); | 2393 }); |
2318 sb.append('}'); | 2394 _addAssistFromBuilder( |
2319 sb.append(eol); | 2395 changeBuilder, DartAssistKind.SURROUND_WITH_TRY_FINALLY); |
2320 // | |
2321 _insertBuilder(sb, statementsRange.length); | |
2322 // add proposal | |
2323 _addAssist(DartAssistKind.SURROUND_WITH_TRY_FINALLY, []); | |
2324 } | 2396 } |
2325 } | 2397 } |
2326 | 2398 |
2327 /** | 2399 /** |
2328 * Adds a new [Edit] to [edits]. | |
2329 */ | |
2330 void _addRemoveEdit(SourceRange range) { | |
2331 _addReplaceEdit(range, ''); | |
2332 } | |
2333 | |
2334 /** | |
2335 * Adds a new [SourceEdit] to [edits]. | |
2336 */ | |
2337 void _addReplaceEdit(SourceRange range, String text) { | |
2338 SourceEdit edit = new SourceEdit(range.offset, range.length, text); | |
2339 doSourceChange_addElementEdit(change, unitElement, edit); | |
2340 } | |
2341 | |
2342 /** | |
2343 * Configures [utils] using given [target]. | 2400 * Configures [utils] using given [target]. |
2344 */ | 2401 */ |
2345 void _configureTargetLocation(Object target) { | 2402 void _configureTargetLocation(Object target) { |
2346 utils.targetClassElement = null; | 2403 utils.targetClassElement = null; |
2347 if (target is AstNode) { | 2404 if (target is AstNode) { |
2348 ClassDeclaration targetClassDeclaration = | 2405 ClassDeclaration targetClassDeclaration = |
2349 target.getAncestor((node) => node is ClassDeclaration); | 2406 target.getAncestor((node) => node is ClassDeclaration); |
2350 if (targetClassDeclaration != null) { | 2407 if (targetClassDeclaration != null) { |
2351 utils.targetClassElement = targetClassDeclaration.element; | 2408 utils.targetClassElement = targetClassDeclaration.element; |
2352 } | 2409 } |
2353 } | 2410 } |
2354 } | 2411 } |
2355 | 2412 |
| 2413 void _convertFlutterChildToChildren( |
| 2414 InstanceCreationExpression childArg, |
| 2415 NamedExpression namedExp, |
| 2416 String eol, |
| 2417 Function getNodeText, |
| 2418 Function getLinePrefix, |
| 2419 Function getIndent, |
| 2420 Function getText, |
| 2421 DartFileEditBuilder builder) { |
| 2422 int childLoc = namedExp.offset + 'child'.length; |
| 2423 builder.addSimpleInsertion(childLoc, 'ren'); |
| 2424 int listLoc = childArg.offset; |
| 2425 String childArgSrc = getNodeText(childArg); |
| 2426 if (!childArgSrc.contains(eol)) { |
| 2427 builder.addSimpleInsertion(listLoc, '<Widget>['); |
| 2428 builder.addSimpleInsertion(listLoc + childArg.length, ']'); |
| 2429 } else { |
| 2430 int newlineLoc = childArgSrc.lastIndexOf(eol); |
| 2431 if (newlineLoc == childArgSrc.length) { |
| 2432 newlineLoc -= 1; |
| 2433 } |
| 2434 String indentOld = getLinePrefix(childArg.offset + 1 + newlineLoc); |
| 2435 String indentNew = '$indentOld${getIndent(1)}'; |
| 2436 // The separator includes 'child:' but that has no newlines. |
| 2437 String separator = |
| 2438 getText(namedExp.offset, childArg.offset - namedExp.offset); |
| 2439 String prefix = separator.contains(eol) ? "" : "$eol$indentNew"; |
| 2440 if (prefix.isEmpty) { |
| 2441 builder.addSimpleInsertion( |
| 2442 namedExp.offset + 'child:'.length, ' <Widget>['); |
| 2443 int argOffset = childArg.offset; |
| 2444 builder |
| 2445 .addDeletion(range.startOffsetEndOffset(argOffset - 2, argOffset)); |
| 2446 } else { |
| 2447 builder.addSimpleInsertion(listLoc, '<Widget>['); |
| 2448 } |
| 2449 String newChildArgSrc = childArgSrc.replaceAll( |
| 2450 new RegExp("^$indentOld", multiLine: true), "$indentNew"); |
| 2451 newChildArgSrc = "$prefix$newChildArgSrc,$eol$indentOld]"; |
| 2452 builder.addSimpleReplacement(range.node(childArg), newChildArgSrc); |
| 2453 } |
| 2454 } |
| 2455 |
2356 /** | 2456 /** |
2357 * Returns an existing or just added [LinkedEditGroup] with [groupId]. | |
2358 */ | |
2359 LinkedEditGroup _getLinkedPosition(String groupId) { | |
2360 LinkedEditGroup group = linkedPositionGroups[groupId]; | |
2361 if (group == null) { | |
2362 group = new LinkedEditGroup.empty(); | |
2363 linkedPositionGroups[groupId] = group; | |
2364 } | |
2365 return group; | |
2366 } | |
2367 | |
2368 /** | |
2369 * Returns the text of the given node in the unit. | 2457 * Returns the text of the given node in the unit. |
2370 */ | 2458 */ |
2371 String _getNodeText(AstNode node) { | 2459 String _getNodeText(AstNode node) { |
2372 return utils.getNodeText(node); | 2460 return utils.getNodeText(node); |
2373 } | 2461 } |
2374 | 2462 |
2375 /** | 2463 /** |
2376 * Returns the text of the given range in the unit. | 2464 * Returns the text of the given range in the unit. |
2377 */ | 2465 */ |
2378 String _getRangeText(SourceRange range) { | 2466 String _getRangeText(SourceRange range) { |
2379 return utils.getRangeText(range); | 2467 return utils.getRangeText(range); |
2380 } | 2468 } |
2381 | 2469 |
2382 /** | |
2383 * Inserts the given [SourceBuilder] at its offset. | |
2384 */ | |
2385 void _insertBuilder(SourceBuilder builder, [int length = 0]) { | |
2386 { | |
2387 SourceRange range = new SourceRange(builder.offset, length); | |
2388 String text = builder.toString(); | |
2389 _addReplaceEdit(range, text); | |
2390 } | |
2391 // add linked positions | |
2392 builder.linkedPositionGroups.forEach((String id, LinkedEditGroup group) { | |
2393 LinkedEditGroup fixGroup = _getLinkedPosition(id); | |
2394 group.positions.forEach((Position position) { | |
2395 fixGroup.addPosition(position, group.length); | |
2396 }); | |
2397 group.suggestions.forEach((LinkedEditSuggestion suggestion) { | |
2398 fixGroup.addSuggestion(suggestion); | |
2399 }); | |
2400 }); | |
2401 // add exit position | |
2402 { | |
2403 int exitOffset = builder.exitOffset; | |
2404 if (exitOffset != null) { | |
2405 exitPosition = _newPosition(exitOffset); | |
2406 } | |
2407 } | |
2408 } | |
2409 | |
2410 int _modificationStamp(String filePath) { | 2470 int _modificationStamp(String filePath) { |
2411 // TODO(brianwilkerson) We have lost the ability for clients to know whether | 2471 // TODO(brianwilkerson) We have lost the ability for clients to know whether |
2412 // it is safe to apply an edit. | 2472 // it is safe to apply an edit. |
2413 return driver.fsState.getFileForPath(filePath).exists ? 0 : -1; | 2473 return driver.fsState.getFileForPath(filePath).exists ? 0 : -1; |
2414 } | 2474 } |
2415 | 2475 |
2416 Position _newPosition(int offset) { | 2476 Position _newPosition(int offset) { |
2417 return new Position(file, offset); | 2477 return new Position(file, offset); |
2418 } | 2478 } |
2419 | 2479 |
2420 void _swapFlutterWidgets( | 2480 Future<Null> _swapFlutterWidgets( |
2421 InstanceCreationExpression exprGoingDown, | 2481 InstanceCreationExpression exprGoingDown, |
2422 InstanceCreationExpression exprGoingUp, | 2482 InstanceCreationExpression exprGoingUp, |
2423 NamedExpression stableChild, | 2483 NamedExpression stableChild, |
2424 AssistKind assistKind) { | 2484 AssistKind assistKind) async { |
2425 String currentSource = unitElement.context.getContents(source).data; | 2485 String currentSource = unitElement.context.getContents(source).data; |
2426 // TODO(messick) Find a better way to get LineInfo for the source. | 2486 // TODO(messick) Find a better way to get LineInfo for the source. |
2427 LineInfo lineInfo = new LineInfo.fromContent(currentSource); | 2487 LineInfo lineInfo = new LineInfo.fromContent(currentSource); |
2428 int currLn = lineInfo.getLocation(exprGoingUp.offset).lineNumber; | 2488 int currLn = lineInfo.getLocation(exprGoingUp.offset).lineNumber; |
2429 int lnOffset = lineInfo.getOffsetOfLine(currLn); | 2489 int lnOffset = lineInfo.getOffsetOfLine(currLn); |
2430 SourceBuilder sb = new SourceBuilder(file, exprGoingDown.offset); | |
2431 String argSrc = | |
2432 utils.getText(exprGoingUp.offset, lnOffset - exprGoingUp.offset); | |
2433 sb.append(argSrc); // Append child new-expr plus rest of line. | |
2434 | 2490 |
2435 String getSrc(Expression expr) { | 2491 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2436 int startLn = lineInfo.getLocation(expr.offset).lineNumber; | 2492 await changeBuilder.addFileEdit(file, fileStamp, |
2437 int startOffset = lineInfo.getOffsetOfLine(startLn - 1); | 2493 (DartFileEditBuilder builder) { |
2438 int endLn = | 2494 builder.addReplacement(range.node(exprGoingDown), |
2439 lineInfo.getLocation(expr.offset + expr.length).lineNumber + 1; | 2495 (DartEditBuilder builder) { |
2440 int curOffset = lineInfo.getOffsetOfLine(endLn - 1); | 2496 String argSrc = |
2441 return utils.getText(startOffset, curOffset - startOffset); | 2497 utils.getText(exprGoingUp.offset, lnOffset - exprGoingUp.offset); |
2442 } | 2498 builder.write(argSrc); // Append child new-expr plus rest of line. |
2443 | 2499 |
2444 String outerIndent = utils.getNodePrefix(exprGoingDown.parent); | 2500 String getSrc(Expression expr) { |
2445 String innerIndent = utils.getNodePrefix(exprGoingUp.parent); | 2501 int startLn = lineInfo.getLocation(expr.offset).lineNumber; |
2446 exprGoingUp.argumentList.arguments.forEach((arg) { | 2502 int startOffset = lineInfo.getOffsetOfLine(startLn - 1); |
2447 if (arg is NamedExpression && arg.name.label.name == 'child') { | 2503 int endLn = |
2448 if (stableChild != arg) { | 2504 lineInfo.getLocation(expr.offset + expr.length).lineNumber + 1; |
2449 _coverageMarker(); | 2505 int curOffset = lineInfo.getOffsetOfLine(endLn - 1); |
2450 return; | 2506 return utils.getText(startOffset, curOffset - startOffset); |
2451 } | 2507 } |
2452 // Insert exprGoingDown here. | |
2453 // Copy from start of line to offset of exprGoingDown. | |
2454 currLn = lineInfo.getLocation(stableChild.offset).lineNumber; | |
2455 lnOffset = lineInfo.getOffsetOfLine(currLn - 1); | |
2456 argSrc = | |
2457 utils.getText(lnOffset, stableChild.expression.offset - lnOffset); | |
2458 argSrc = argSrc.replaceAll( | |
2459 new RegExp("^$innerIndent", multiLine: true), "$outerIndent"); | |
2460 sb.append(argSrc); | |
2461 int nextLn = lineInfo.getLocation(exprGoingDown.offset).lineNumber; | |
2462 lnOffset = lineInfo.getOffsetOfLine(nextLn); | |
2463 argSrc = utils.getText( | |
2464 exprGoingDown.offset, lnOffset - exprGoingDown.offset); | |
2465 sb.append(argSrc); | |
2466 | 2508 |
2467 exprGoingDown.argumentList.arguments.forEach((val) { | 2509 String outerIndent = utils.getNodePrefix(exprGoingDown.parent); |
2468 if (val is NamedExpression && val.name.label.name == 'child') { | 2510 String innerIndent = utils.getNodePrefix(exprGoingUp.parent); |
2469 // Insert stableChild here at same indent level. | 2511 exprGoingUp.argumentList.arguments.forEach((arg) { |
2470 sb.append(utils.getNodePrefix(arg.name)); | 2512 if (arg is NamedExpression && arg.name.label.name == 'child') { |
2471 argSrc = utils.getNodeText(stableChild); | 2513 if (stableChild != arg) { |
2472 sb.append(argSrc); | 2514 _coverageMarker(); |
2473 if (assistKind == DartAssistKind.MOVE_FLUTTER_WIDGET_UP) { | 2515 return; |
2474 sb.append(',$eol'); | |
2475 } | 2516 } |
| 2517 // Insert exprGoingDown here. |
| 2518 // Copy from start of line to offset of exprGoingDown. |
| 2519 currLn = lineInfo.getLocation(stableChild.offset).lineNumber; |
| 2520 lnOffset = lineInfo.getOffsetOfLine(currLn - 1); |
| 2521 argSrc = utils.getText( |
| 2522 lnOffset, stableChild.expression.offset - lnOffset); |
| 2523 argSrc = argSrc.replaceAll( |
| 2524 new RegExp("^$innerIndent", multiLine: true), "$outerIndent"); |
| 2525 builder.write(argSrc); |
| 2526 int nextLn = lineInfo.getLocation(exprGoingDown.offset).lineNumber; |
| 2527 lnOffset = lineInfo.getOffsetOfLine(nextLn); |
| 2528 argSrc = utils.getText( |
| 2529 exprGoingDown.offset, lnOffset - exprGoingDown.offset); |
| 2530 builder.write(argSrc); |
| 2531 |
| 2532 exprGoingDown.argumentList.arguments.forEach((val) { |
| 2533 if (val is NamedExpression && val.name.label.name == 'child') { |
| 2534 // Insert stableChild here at same indent level. |
| 2535 builder.write(utils.getNodePrefix(arg.name)); |
| 2536 argSrc = utils.getNodeText(stableChild); |
| 2537 builder.write(argSrc); |
| 2538 if (assistKind == DartAssistKind.MOVE_FLUTTER_WIDGET_UP) { |
| 2539 builder.write(',$eol'); |
| 2540 } |
| 2541 } else { |
| 2542 argSrc = getSrc(val); |
| 2543 argSrc = argSrc.replaceAll( |
| 2544 new RegExp("^$outerIndent", multiLine: true), |
| 2545 "$innerIndent"); |
| 2546 builder.write(argSrc); |
| 2547 } |
| 2548 }); |
| 2549 if (assistKind == DartAssistKind.MOVE_FLUTTER_WIDGET_DOWN) { |
| 2550 builder.write(',$eol'); |
| 2551 } |
| 2552 builder.write(innerIndent); |
| 2553 builder.write('),$eol'); |
2476 } else { | 2554 } else { |
2477 argSrc = getSrc(val); | 2555 argSrc = getSrc(arg); |
2478 argSrc = argSrc.replaceAll( | 2556 argSrc = argSrc.replaceAll( |
2479 new RegExp("^$outerIndent", multiLine: true), "$innerIndent"); | 2557 new RegExp("^$innerIndent", multiLine: true), "$outerIndent"); |
2480 sb.append(argSrc); | 2558 builder.write(argSrc); |
2481 } | 2559 } |
2482 }); | 2560 }); |
2483 if (assistKind == DartAssistKind.MOVE_FLUTTER_WIDGET_DOWN) { | 2561 builder.write(outerIndent); |
2484 sb.append(',$eol'); | 2562 builder.write(')'); |
2485 } | 2563 builder.selectHere(); |
2486 sb.append(innerIndent); | 2564 }); |
2487 sb.append('),$eol'); | |
2488 } else { | |
2489 argSrc = getSrc(arg); | |
2490 argSrc = argSrc.replaceAll( | |
2491 new RegExp("^$innerIndent", multiLine: true), "$outerIndent"); | |
2492 sb.append(argSrc); | |
2493 } | |
2494 }); | 2565 }); |
2495 sb.append(outerIndent); | 2566 _addAssistFromBuilder(changeBuilder, assistKind); |
2496 sb.append(')'); | |
2497 | |
2498 exitPosition = _newPosition(sb.offset + sb.length); | |
2499 _insertBuilder(sb, exprGoingDown.length); | |
2500 _addAssist(assistKind, []); | |
2501 } | 2567 } |
2502 | 2568 |
2503 /** | 2569 /** |
2504 * This method does nothing, but we invoke it in places where Dart VM | 2570 * This method does nothing, but we invoke it in places where Dart VM |
2505 * coverage agent fails to provide coverage information - such as almost | 2571 * coverage agent fails to provide coverage information - such as almost |
2506 * all "return" statements. | 2572 * all "return" statements. |
2507 * | 2573 * |
2508 * https://code.google.com/p/dart/issues/detail?id=19912 | 2574 * https://code.google.com/p/dart/issues/detail?id=19912 |
2509 */ | 2575 */ |
2510 static void _coverageMarker() {} | 2576 static void _coverageMarker() {} |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2568 class _SimpleIdentifierRecursiveAstVisitor extends RecursiveAstVisitor { | 2634 class _SimpleIdentifierRecursiveAstVisitor extends RecursiveAstVisitor { |
2569 final _SimpleIdentifierVisitor visitor; | 2635 final _SimpleIdentifierVisitor visitor; |
2570 | 2636 |
2571 _SimpleIdentifierRecursiveAstVisitor(this.visitor); | 2637 _SimpleIdentifierRecursiveAstVisitor(this.visitor); |
2572 | 2638 |
2573 @override | 2639 @override |
2574 visitSimpleIdentifier(SimpleIdentifier node) { | 2640 visitSimpleIdentifier(SimpleIdentifier node) { |
2575 visitor(node); | 2641 visitor(node); |
2576 } | 2642 } |
2577 } | 2643 } |
OLD | NEW |