Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(903)

Side by Side Diff: pkg/analysis_services/lib/src/correction/fix.dart

Issue 418203002: Implement more fixes. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 // This code was auto-generated, is not intended to be edited, and is subject to 5 // This code was auto-generated, is not intended to be edited, and is subject to
6 // significant change. Please see the README file for more information. 6 // significant change. Please see the README file for more information.
7 7
8 library services.src.correction.fix; 8 library services.src.correction.fix;
9 9
10 import 'package:analysis_services/correction/change.dart'; 10 import 'package:analysis_services/correction/change.dart';
11 import 'package:analysis_services/correction/fix.dart'; 11 import 'package:analysis_services/correction/fix.dart';
12 import 'package:analysis_services/search/search_engine.dart'; 12 import 'package:analysis_services/search/search_engine.dart';
13 import 'package:analysis_services/src/correction/name_suggestion.dart'; 13 import 'package:analysis_services/src/correction/name_suggestion.dart';
14 import 'package:analysis_services/src/correction/source_buffer.dart'; 14 import 'package:analysis_services/src/correction/source_buffer.dart';
15 import 'package:analysis_services/src/correction/source_range.dart' as rf; 15 import 'package:analysis_services/src/correction/source_range.dart' as rf;
16 import 'package:analysis_services/src/correction/strings.dart';
16 import 'package:analysis_services/src/correction/util.dart'; 17 import 'package:analysis_services/src/correction/util.dart';
17 import 'package:analyzer/src/generated/ast.dart'; 18 import 'package:analyzer/src/generated/ast.dart';
18 import 'package:analyzer/src/generated/element.dart'; 19 import 'package:analyzer/src/generated/element.dart';
19 import 'package:analyzer/src/generated/error.dart'; 20 import 'package:analyzer/src/generated/error.dart';
20 import 'package:analyzer/src/generated/java_core.dart'; 21 import 'package:analyzer/src/generated/java_core.dart';
21 import 'package:analyzer/src/generated/parser.dart'; 22 import 'package:analyzer/src/generated/parser.dart';
23 import 'package:analyzer/src/generated/scanner.dart';
22 import 'package:analyzer/src/generated/source.dart'; 24 import 'package:analyzer/src/generated/source.dart';
23 import 'package:analyzer/src/generated/utilities_dart.dart'; 25 import 'package:analyzer/src/generated/utilities_dart.dart';
24 26
25 27
26 /** 28 /**
27 * The computer for Dart fixes. 29 * The computer for Dart fixes.
28 */ 30 */
29 class FixProcessor { 31 class FixProcessor {
30 final SearchEngine searchEngine; 32 final SearchEngine searchEngine;
33 final Source source;
31 final String file; 34 final String file;
32 final CompilationUnit unit; 35 final CompilationUnit unit;
33 final AnalysisError error; 36 final AnalysisError error;
37 CompilationUnitElement unitElement;
38 LibraryElement unitLibraryElement;
34 39
35 final List<Edit> edits = <Edit>[]; 40 final List<Edit> edits = <Edit>[];
36 final Map<String, LinkedPositionGroup> linkedPositionGroups = <String, 41 final Map<String, LinkedPositionGroup> linkedPositionGroups = <String,
37 LinkedPositionGroup>{}; 42 LinkedPositionGroup>{};
43 Position endPosition = null;
38 final List<Fix> fixes = <Fix>[]; 44 final List<Fix> fixes = <Fix>[];
39 45
40 CorrectionUtils utils; 46 CorrectionUtils utils;
41 int errorOffset; 47 int errorOffset;
42 int errorLength; 48 int errorLength;
43 int errorEnd; 49 int errorEnd;
44 AstNode node; 50 AstNode node;
45 AstNode coveredNode; 51 AstNode coveredNode;
46 52
47 53
48 FixProcessor(this.searchEngine, this.file, this.unit, this.error); 54 FixProcessor(this.searchEngine, this.source, this.file, this.unit, this.error)
55 {
56 unitElement = unit.element;
57 unitLibraryElement = unitElement.library;
58 }
59
60 DartType get coreTypeBool => _getCoreType("bool");
49 61
50 List<Fix> compute() { 62 List<Fix> compute() {
51 utils = new CorrectionUtils(unit); 63 utils = new CorrectionUtils(unit);
52 errorOffset = error.offset; 64 errorOffset = error.offset;
53 errorLength = error.length; 65 errorLength = error.length;
54 errorEnd = errorOffset + errorLength; 66 errorEnd = errorOffset + errorLength;
55 node = new NodeLocator.con1(errorOffset).searchWithin(unit); 67 node = new NodeLocator.con1(errorOffset).searchWithin(unit);
56 coveredNode = new NodeLocator.con2( 68 coveredNode = new NodeLocator.con2(
57 errorOffset, 69 errorOffset,
58 errorOffset + errorLength).searchWithin(unit); 70 errorOffset + errorLength).searchWithin(unit);
59 // analyze ErrorCode 71 // analyze ErrorCode
60 ErrorCode errorCode = error.errorCode; 72 ErrorCode errorCode = error.errorCode;
61 if (errorCode == StaticWarningCode.UNDEFINED_CLASS_BOOLEAN) { 73 if (errorCode == StaticWarningCode.UNDEFINED_CLASS_BOOLEAN) {
62 _addFix_boolInsteadOfBoolean(); 74 _addFix_boolInsteadOfBoolean();
63 } 75 }
64 if (errorCode == 76 if (errorCode ==
65 CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE) { 77 CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE) {
66 _addFix_replaceWithConstInstanceCreation(); 78 _addFix_replaceWithConstInstanceCreation();
67 } 79 }
68 if (errorCode == 80 if (errorCode ==
69 CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT) { 81 CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT) {
70 _addFix_createConstructorSuperExplicit(); 82 _addFix_createConstructorSuperExplicit();
71 } 83 }
72 // if (identical( 84 if (errorCode ==
73 // errorCode, 85 CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT) {
74 // CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT)) { 86 _addFix_createConstructorSuperImplicit();
75 // _addFix_createConstructorSuperImplicit(); 87 }
76 // }
77 if (errorCode == 88 if (errorCode ==
78 CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT) { 89 CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT) {
79 _addFix_createConstructorSuperExplicit(); 90 _addFix_createConstructorSuperExplicit();
80 } 91 }
81 // if (identical(errorCode, CompileTimeErrorCode.URI_DOES_NOT_EXIST)) { 92 // if (identical(errorCode, CompileTimeErrorCode.URI_DOES_NOT_EXIST)) {
82 // _addFix_createPart(); 93 // _addFix_createPart();
83 // _addFix_addPackageDependency(); 94 // _addFix_addPackageDependency();
84 // } 95 // }
85 if (errorCode == HintCode.DIVISION_OPTIMIZATION) { 96 if (errorCode == HintCode.DIVISION_OPTIMIZATION) {
86 _addFix_useEffectiveIntegerDivision(); 97 _addFix_useEffectiveIntegerDivision();
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 List<ExecutableElement> missingOverrides = 143 List<ExecutableElement> missingOverrides =
133 property as List<ExecutableElement>; 144 property as List<ExecutableElement>;
134 _addFix_createMissingOverrides(missingOverrides); 145 _addFix_createMissingOverrides(missingOverrides);
135 _addFix_createNoSuchMethod(); 146 _addFix_createNoSuchMethod();
136 } 147 }
137 if (errorCode == StaticWarningCode.UNDEFINED_CLASS) { 148 if (errorCode == StaticWarningCode.UNDEFINED_CLASS) {
138 _addFix_importLibrary_withType(); 149 _addFix_importLibrary_withType();
139 _addFix_createClass(); 150 _addFix_createClass();
140 _addFix_undefinedClass_useSimilar(); 151 _addFix_undefinedClass_useSimilar();
141 } 152 }
142 // if (identical(errorCode, StaticWarningCode.UNDEFINED_IDENTIFIER)) { 153 if (errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER) {
143 // _addFix_createFunction_forFunctionType(); 154 _addFix_createFunction_forFunctionType();
144 // _addFix_importLibrary_withType(); 155 _addFix_importLibrary_withType();
145 // _addFix_importLibrary_withTopLevelVariable(); 156 _addFix_importLibrary_withTopLevelVariable();
146 // } 157 }
147 if (errorCode == StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER) { 158 if (errorCode == StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER) {
148 _addFix_useStaticAccess_method(); 159 _addFix_useStaticAccess_method();
149 _addFix_useStaticAccess_property(); 160 _addFix_useStaticAccess_property();
150 } 161 }
151 if (errorCode == StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION) { 162 if (errorCode == StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION) {
152 _addFix_removeParentheses_inGetterInvocation(); 163 _addFix_removeParentheses_inGetterInvocation();
153 } 164 }
154 // if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_FUNCTION)) { 165 // if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_FUNCTION)) {
155 // _addFix_importLibrary_withFunction(); 166 // _addFix_importLibrary_withFunction();
156 // _addFix_undefinedFunction_useSimilar(); 167 // _addFix_undefinedFunction_useSimilar();
157 // _addFix_undefinedFunction_create(); 168 // _addFix_undefinedFunction_create();
158 // } 169 // }
159 // if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_GETTER)) { 170 if (errorCode == StaticTypeWarningCode.UNDEFINED_GETTER) {
160 // _addFix_createFunction_forFunctionType(); 171 _addFix_createFunction_forFunctionType();
161 // } 172 }
162 // if (identical(errorCode, HintCode.UNDEFINED_METHOD) || 173 if (errorCode == HintCode.UNDEFINED_METHOD ||
163 // identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) { 174 errorCode == StaticTypeWarningCode.UNDEFINED_METHOD) {
164 // _addFix_undefinedMethod_useSimilar(); 175 _addFix_undefinedMethod_useSimilar();
165 // _addFix_undefinedMethod_create(); 176 _addFix_undefinedMethod_create();
166 // _addFix_undefinedFunction_create(); 177 _addFix_undefinedFunction_create();
167 // } 178 }
168 // done 179 // done
169 return fixes; 180 return fixes;
170 } 181 }
171 182
172 void _addFix(FixKind kind, List args, {String fixFile}) { 183 void _addFix(FixKind kind, List args, {String fixFile}) {
173 if (fixFile == null) { 184 if (fixFile == null) {
174 fixFile = file; 185 fixFile = file;
175 } 186 }
176 FileEdit fileEdit = new FileEdit(file); 187 FileEdit fileEdit = new FileEdit(file);
177 edits.forEach((edit) => fileEdit.add(edit)); 188 edits.forEach((edit) => fileEdit.add(edit));
178 // prepare Change 189 // prepare Change
179 String message = JavaString.format(kind.message, args); 190 String message = JavaString.format(kind.message, args);
180 Change change = new Change(message); 191 Change change = new Change(message);
181 change.add(fileEdit); 192 change.add(fileEdit);
182 linkedPositionGroups.values.forEach( 193 linkedPositionGroups.values.forEach(
183 (group) => change.addLinkedPositionGroup(group)); 194 (group) => change.addLinkedPositionGroup(group));
195 change.endPosition = endPosition;
184 // add Fix 196 // add Fix
185 Fix fix = new Fix(kind, change); 197 Fix fix = new Fix(kind, change);
186 fixes.add(fix); 198 fixes.add(fix);
199 // clear
200 edits.clear();
201 linkedPositionGroups.clear();
202 endPosition = null;
187 } 203 }
188 204
189 void _addFix_addPackageDependency() { 205 void _addFix_addPackageDependency() {
190 // TODO(scheglov) implement 206 // TODO(scheglov) implement
191 // if (node is SimpleStringLiteral && node.parent is NamespaceDirective) { 207 // if (node is SimpleStringLiteral && node.parent is NamespaceDirective) {
192 // SimpleStringLiteral uriLiteral = node as SimpleStringLiteral; 208 // SimpleStringLiteral uriLiteral = node as SimpleStringLiteral;
193 // String uriString = uriLiteral.value; 209 // String uriString = uriLiteral.value;
194 // // we need package: import 210 // // we need package: import
195 // if (!uriString.startsWith("package:")) { 211 // if (!uriString.startsWith("package:")) {
196 // return; 212 // return;
197 // } 213 // }
198 // // prepare package name 214 // // prepare package name
199 // String packageName = StringUtils.removeStart(uriString, "package:"); 215 // String packageName = StringUtils.removeStart(uriString, "package:");
200 // packageName = StringUtils.substringBefore(packageName, "/"); 216 // packageName = StringUtils.substringBefore(packageName, "/");
201 // // add proposal 217 // // add proposal
202 // _proposals.add( 218 // _proposals.add(
203 // new AddDependencyCorrectionProposal( 219 // new AddDependencyCorrectionProposal(
204 // _unitFile, 220 // _unitFile,
205 // packageName, 221 // packageName,
206 // FixKind.ADD_PACKAGE_DEPENDENCY, 222 // FixKind.ADD_PACKAGE_DEPENDENCY,
207 // [packageName])); 223 // [packageName]));
208 // } 224 // }
209 } 225 }
210 226
227
211 void _addFix_boolInsteadOfBoolean() { 228 void _addFix_boolInsteadOfBoolean() {
212 SourceRange range = rf.rangeError(error); 229 SourceRange range = rf.rangeError(error);
213 _addReplaceEdit(range, "bool"); 230 _addReplaceEdit(range, "bool");
214 _addFix(FixKind.REPLACE_BOOLEAN_WITH_BOOL, []); 231 _addFix(FixKind.REPLACE_BOOLEAN_WITH_BOOL, []);
215 } 232 }
216 233
217 234
218 void _addFix_createClass() { 235 void _addFix_createClass() {
219 if (_mayBeTypeIdentifier(node)) { 236 if (_mayBeTypeIdentifier(node)) {
220 String name = (node as SimpleIdentifier).name; 237 String name = (node as SimpleIdentifier).name;
(...skipping 22 matching lines...) Expand all
243 sb.append("}"); 260 sb.append("}");
244 } 261 }
245 // insert source 262 // insert source
246 _insertBuilder(sb); 263 _insertBuilder(sb);
247 _addLinkedPosition("NAME", rf.rangeNode(node)); 264 _addLinkedPosition("NAME", rf.rangeNode(node));
248 // add proposal 265 // add proposal
249 _addFix(FixKind.CREATE_CLASS, [name]); 266 _addFix(FixKind.CREATE_CLASS, [name]);
250 } 267 }
251 } 268 }
252 269
253
254 void _addFix_createConstructorSuperExplicit() { 270 void _addFix_createConstructorSuperExplicit() {
255 ConstructorDeclaration targetConstructor = 271 ConstructorDeclaration targetConstructor =
256 node.parent as ConstructorDeclaration; 272 node.parent as ConstructorDeclaration;
257 ClassDeclaration targetClassNode = 273 ClassDeclaration targetClassNode =
258 targetConstructor.parent as ClassDeclaration; 274 targetConstructor.parent as ClassDeclaration;
259 ClassElement targetClassElement = targetClassNode.element; 275 ClassElement targetClassElement = targetClassNode.element;
260 ClassElement superClassElement = targetClassElement.supertype.element; 276 ClassElement superClassElement = targetClassElement.supertype.element;
261 // add proposals for all super constructors 277 // add proposals for all super constructors
262 List<ConstructorElement> superConstructors = superClassElement.constructors; 278 List<ConstructorElement> superConstructors = superClassElement.constructors;
263 for (ConstructorElement superConstructor in superConstructors) { 279 for (ConstructorElement superConstructor in superConstructors) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 sb.append(")"); 328 sb.append(")");
313 // insert proposal 329 // insert proposal
314 _insertBuilder(sb); 330 _insertBuilder(sb);
315 // add proposal 331 // add proposal
316 String proposalName = _getConstructorProposalName(superConstructor); 332 String proposalName = _getConstructorProposalName(superConstructor);
317 _addFix(FixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, [proposalName]); 333 _addFix(FixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, [proposalName]);
318 } 334 }
319 } 335 }
320 336
321 void _addFix_createConstructorSuperImplicit() { 337 void _addFix_createConstructorSuperImplicit() {
322 // TODO(scheglov) implement 338 ClassDeclaration targetClassNode = node.parent as ClassDeclaration;
323 // ClassDeclaration targetClassNode = node.parent as ClassDeclaration; 339 ClassElement targetClassElement = targetClassNode.element;
324 // ClassElement targetClassElement = targetClassNode.element; 340 ClassElement superClassElement = targetClassElement.supertype.element;
325 // ClassElement superClassElement = targetClassElement.supertype.element; 341 String targetClassName = targetClassElement.name;
326 // String targetClassName = targetClassElement.name; 342 // add proposals for all super constructors
327 // // add proposals for all super constructors 343 List<ConstructorElement> superConstructors = superClassElement.constructors;
328 // List<ConstructorElement> superConstructors = superClassElement.constructor s; 344 for (ConstructorElement superConstructor in superConstructors) {
329 // for (ConstructorElement superConstructor in superConstructors) { 345 String constructorName = superConstructor.name;
330 // String constructorName = superConstructor.name; 346 // skip private
331 // // skip private 347 if (Identifier.isPrivateName(constructorName)) {
332 // if (Identifier.isPrivateName(constructorName)) { 348 continue;
333 // continue; 349 }
334 // } 350 // prepare parameters and arguments
335 // // prepare parameters and arguments 351 StringBuffer parametersBuffer = new StringBuffer();
336 // JavaStringBuilder parametersBuffer = new JavaStringBuilder(); 352 StringBuffer argumentsBuffer = new StringBuffer();
337 // JavaStringBuilder argumentsBuffer = new JavaStringBuilder(); 353 bool firstParameter = true;
338 // bool firstParameter = true; 354 for (ParameterElement parameter in superConstructor.parameters) {
339 // for (ParameterElement parameter in superConstructor.parameters) { 355 // skip non-required parameters
340 // // skip non-required parameters 356 if (parameter.parameterKind != ParameterKind.REQUIRED) {
341 // if (parameter.parameterKind != ParameterKind.REQUIRED) { 357 break;
342 // break; 358 }
343 // } 359 // comma
344 // // comma 360 if (firstParameter) {
345 // if (firstParameter) { 361 firstParameter = false;
346 // firstParameter = false; 362 } else {
347 // } else { 363 parametersBuffer.write(', ');
348 // parametersBuffer.append(", "); 364 argumentsBuffer.write(', ');
349 // argumentsBuffer.append(", "); 365 }
350 // } 366 // name
351 // // name 367 String parameterName = parameter.displayName;
352 // String parameterName = parameter.displayName; 368 if (parameterName.length > 1 && parameterName.startsWith('_')) {
353 // if (parameterName.length > 1 && parameterName.startsWith("_")) { 369 parameterName = parameterName.substring(1);
354 // parameterName = parameterName.substring(1); 370 }
355 // } 371 // parameter & argument
356 // // parameter & argument 372 _appendParameterSource(parametersBuffer, parameter.type, parameterName);
357 // _appendParameterSource(parametersBuffer, parameter.type, parameterName ); 373 argumentsBuffer.write(parameterName);
358 // argumentsBuffer.append(parameterName); 374 }
359 // } 375 // add proposal
360 // // add proposal 376 String eol = utils.endOfLine;
Paul Berry 2014/07/25 00:28:46 With my suggestion about eol below, this line coul
scheglov 2014/07/25 03:20:50 Done.
361 // String eol = utils.endOfLine; 377 QuickFixProcessorImpl_NewConstructorLocation targetLocation =
362 // QuickFixProcessorImpl_NewConstructorLocation targetLocation = 378 _prepareNewConstructorLocation(targetClassNode, eol);
363 // _prepareNewConstructorLocation(targetClassNode, eol); 379 SourceBuilder sb = new SourceBuilder(file, targetLocation._offset);
364 // SourceBuilder sb = new SourceBuilder.con1(targetLocation._offset); 380 {
365 // { 381 String indent = utils.getIndent(1);
366 // String indent = utils.getIndent(1); 382 sb.append(targetLocation._prefix);
367 // sb.append(targetLocation._prefix); 383 sb.append(indent);
368 // sb.append(indent); 384 sb.append(targetClassName);
369 // sb.append(targetClassName); 385 if (!constructorName.isEmpty) {
370 // if (!constructorName.isEmpty) { 386 sb.startPosition('NAME');
Paul Berry 2014/07/25 00:28:45 Are the strings passed to startPosition things tha
scheglov 2014/07/25 03:20:51 These strings are IDs of linked position groups. T
371 // sb.startPosition("NAME"); 387 sb.append('.');
372 // sb.append("."); 388 sb.append(constructorName);
373 // sb.append(constructorName); 389 sb.endPosition();
374 // sb.endPosition(); 390 }
375 // } 391 sb.append("(");
376 // sb.append("("); 392 sb.append(parametersBuffer.toString());
377 // sb.append(parametersBuffer.toString()); 393 sb.append(') : super');
378 // sb.append(") : super"); 394 if (!constructorName.isEmpty) {
379 // if (!constructorName.isEmpty) { 395 sb.append('.');
380 // sb.append("."); 396 sb.append(constructorName);
381 // sb.append(constructorName); 397 }
382 // } 398 sb.append('(');
383 // sb.append("("); 399 sb.append(argumentsBuffer.toString());
384 // sb.append(argumentsBuffer.toString()); 400 sb.append(');');
385 // sb.append(");"); 401 sb.append(targetLocation._suffix);
386 // sb.append(targetLocation._suffix); 402 }
387 // } 403 _insertBuilder(sb);
388 // _addInsertEdit3(sb); 404 // add proposal
389 // // add proposal 405 String proposalName = _getConstructorProposalName(superConstructor);
390 // String proposalName = _getConstructorProposalName(superConstructor); 406 _addFix(FixKind.CREATE_CONSTRUCTOR_SUPER, [proposalName]);
391 // _addFix( 407 }
392 // FixKind.CREATE_CONSTRUCTOR_SUPER,
393 // [proposalName]);
394 // }
395 } 408 }
396 409
397 void _addFix_createConstructor_insteadOfSyntheticDefault() { 410 void _addFix_createConstructor_insteadOfSyntheticDefault() {
398 TypeName typeName = null; 411 TypeName typeName = null;
399 ConstructorName constructorName = null; 412 ConstructorName constructorName = null;
400 InstanceCreationExpression instanceCreation = null; 413 InstanceCreationExpression instanceCreation = null;
401 if (node is SimpleIdentifier) { 414 if (node is SimpleIdentifier) {
402 if (node.parent is TypeName) { 415 if (node.parent is TypeName) {
403 typeName = node.parent as TypeName; 416 typeName = node.parent as TypeName;
404 if (typeName.name == node && typeName.parent is ConstructorName) { 417 if (typeName.name == node && typeName.parent is ConstructorName) {
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 // insert source 533 // insert source
521 _insertBuilder(sb); 534 _insertBuilder(sb);
522 if (targetFile == file) { 535 if (targetFile == file) {
523 _addLinkedPosition("NAME", rf.rangeNode(name)); 536 _addLinkedPosition("NAME", rf.rangeNode(name));
524 } 537 }
525 // add proposal 538 // add proposal
526 _addFix(FixKind.CREATE_CONSTRUCTOR, [constructorName], fixFile: targetFile); 539 _addFix(FixKind.CREATE_CONSTRUCTOR, [constructorName], fixFile: targetFile);
527 } 540 }
528 541
529 void _addFix_createFunction_forFunctionType() { 542 void _addFix_createFunction_forFunctionType() {
530 // TODO(scheglov) implement 543 if (node is SimpleIdentifier) {
531 // if (node is SimpleIdentifier) { 544 SimpleIdentifier nameNode = node as SimpleIdentifier;
532 // SimpleIdentifier nameNode = node as SimpleIdentifier; 545 // prepare argument expression (to get parameter)
533 // // prepare argument expression (to get parameter) 546 ClassElement targetElement;
534 // ClassElement targetElement; 547 Expression argument;
535 // Expression argument; 548 {
536 // { 549 Expression target = getQualifiedPropertyTarget(node);
537 // Expression target = CorrectionUtils.getQualifiedPropertyTarget(node); 550 if (target != null) {
538 // if (target != null) { 551 DartType targetType = target.bestType;
539 // DartType targetType = target.bestType; 552 if (targetType != null && targetType.element is ClassElement) {
540 // if (targetType != null && targetType.element is ClassElement) { 553 targetElement = targetType.element as ClassElement;
541 // targetElement = targetType.element as ClassElement; 554 argument = target.parent as Expression;
542 // argument = target.parent as Expression; 555 } else {
543 // } else { 556 return;
544 // return; 557 }
545 // } 558 } else {
546 // } else { 559 ClassDeclaration enclosingClass =
547 // ClassDeclaration enclosingClass = 560 node.getAncestor((node) => node is ClassDeclaration);
548 // node.getAncestor((node) => node is ClassDeclaration); 561 targetElement = enclosingClass != null ?
549 // targetElement = enclosingClass != null ? 562 enclosingClass.element :
550 // enclosingClass.element : 563 null;
551 // null; 564 argument = nameNode;
552 // argument = nameNode; 565 }
553 // } 566 }
554 // } 567 // should be argument of some invocation
555 // // should be argument of some invocation 568 ParameterElement parameterElement = argument.bestParameterElement;
556 // ParameterElement parameterElement = argument.bestParameterElement; 569 if (parameterElement == null) {
557 // if (parameterElement == null) { 570 return;
558 // return; 571 }
559 // } 572 // should be parameter of function type
560 // // should be parameter of function type 573 DartType parameterType = parameterElement.type;
561 // DartType parameterType = parameterElement.type; 574 if (parameterType is! FunctionType) {
562 // if (parameterType is! FunctionType) { 575 return;
563 // return; 576 }
564 // } 577 FunctionType functionType = parameterType as FunctionType;
565 // FunctionType functionType = parameterType as FunctionType; 578 // add proposal
566 // // add proposal 579 if (targetElement != null) {
567 // if (targetElement != null) { 580 _addProposal_createFunction_method(targetElement, functionType);
568 // _addProposal_createFunction_method(targetElement, functionType); 581 } else {
569 // } else { 582 _addProposal_createFunction_function(functionType);
570 // _addProposal_createFunction_function(functionType); 583 }
571 // } 584 }
572 // }
573 } 585 }
574 586
575 void 587 void
576 _addFix_createMissingOverrides(List<ExecutableElement> missingOverrides) { 588 _addFix_createMissingOverrides(List<ExecutableElement> missingOverrides) {
577 // TODO(scheglov) implement 589 // sort by name
578 // // sort by name 590 missingOverrides.sort((Element firstElement, Element secondElement) {
579 // missingOverrides.sort( 591 return compareStrings(
580 // (Element firstElement, Element secondElement) => 592 firstElement.displayName,
581 // ObjectUtils.compare(firstElement.displayName, secondElement.displa yName)); 593 secondElement.displayName);
582 // // add elements 594 });
583 // ClassDeclaration targetClass = node.parent as ClassDeclaration; 595 // add elements
584 // bool isFirst = true; 596 ClassDeclaration targetClass = node.parent as ClassDeclaration;
585 // for (ExecutableElement missingOverride in missingOverrides) { 597 bool isFirst = true;
586 // _addFix_createMissingOverrides_single( 598 for (ExecutableElement missingOverride in missingOverrides) {
587 // targetClass, 599 _addFix_createMissingOverrides_single(
588 // missingOverride, 600 targetClass,
589 // isFirst); 601 missingOverride,
590 // isFirst = false; 602 isFirst);
591 // } 603 isFirst = false;
592 // // add proposal 604 }
593 // _addFix( 605 // add proposal
594 // FixKind.CREATE_MISSING_OVERRIDES, 606 _addFix(FixKind.CREATE_MISSING_OVERRIDES, [missingOverrides.length]);
595 // [missingOverrides.length]);
596 } 607 }
597 608
598 void _addFix_createMissingOverrides_single(ClassDeclaration targetClass, 609 void _addFix_createMissingOverrides_single(ClassDeclaration targetClass,
599 ExecutableElement missingOverride, bool isFirst) { 610 ExecutableElement missingOverride, bool isFirst) {
600 // TODO(scheglov) implement 611 // prepare environment
601 // // prepare environment 612 String eol = utils.endOfLine;
602 // String eol = utils.endOfLine; 613 String prefix = utils.getIndent(1);
603 // String prefix = utils.getIndent(1); 614 String prefix2 = utils.getIndent(2);
604 // String prefix2 = utils.getIndent(2); 615 int insertOffset = targetClass.end - 1;
605 // int insertOffset = targetClass.end - 1; 616 // prepare source
606 // // prepare source 617 StringBuffer sb = new StringBuffer();
607 // JavaStringBuilder sb = new JavaStringBuilder(); 618 // may be empty line
608 // // may be empty line 619 if (!isFirst || !targetClass.members.isEmpty) {
609 // if (!isFirst || !targetClass.members.isEmpty) { 620 sb.write(eol);
610 // sb.append(eol); 621 }
611 // } 622 // may be property
612 // // may be property 623 ElementKind elementKind = missingOverride.kind;
613 // ElementKind elementKind = missingOverride.kind; 624 bool isGetter = elementKind == ElementKind.GETTER;
614 // bool isGetter = elementKind == ElementKind.GETTER; 625 bool isSetter = elementKind == ElementKind.SETTER;
615 // bool isSetter = elementKind == ElementKind.SETTER; 626 bool isMethod = elementKind == ElementKind.METHOD;
616 // bool isMethod = elementKind == ElementKind.METHOD; 627 bool isOperator = isMethod && (missingOverride as MethodElement).isOperator;
617 // bool isOperator = isMethod && (missingOverride as MethodElement).isOperato r; 628 sb.write(prefix);
618 // sb.append(prefix); 629 if (isGetter) {
619 // if (isGetter) { 630 sb.write('// TODO: implement ${missingOverride.displayName}');
620 // sb.append("// TODO: implement ${missingOverride.displayName}"); 631 sb.write(eol);
621 // sb.append(eol); 632 sb.write(prefix);
622 // sb.append(prefix); 633 }
623 // } 634 // @override
624 // // @override 635 {
625 // { 636 sb.write('@override');
626 // sb.append("@override"); 637 sb.write(eol);
627 // sb.append(eol); 638 sb.write(prefix);
628 // sb.append(prefix); 639 }
629 // } 640 // return type
630 // // return type 641 _appendType(sb, missingOverride.type.returnType);
631 // _appendType(sb, missingOverride.type.returnType); 642 if (isGetter) {
632 // if (isGetter) { 643 sb.write('get ');
633 // sb.append("get "); 644 } else if (isSetter) {
634 // } else if (isSetter) { 645 sb.write('set ');
635 // sb.append("set "); 646 } else if (isOperator) {
636 // } else if (isOperator) { 647 sb.write('operator ');
637 // sb.append("operator "); 648 }
638 // } 649 // name
639 // // name 650 sb.write(missingOverride.displayName);
640 // sb.append(missingOverride.displayName); 651 // parameters + body
641 // // parameters + body 652 if (isGetter) {
642 // if (isGetter) { 653 sb.write(' => null;');
643 // sb.append(" => null;"); 654 } else if (isMethod || isSetter) {
Paul Berry 2014/07/25 00:28:45 Any reason this couldn't just be "} else {"?
scheglov 2014/07/25 03:20:51 Done.
644 // } else if (isMethod || isSetter) { 655 List<ParameterElement> parameters = missingOverride.parameters;
645 // List<ParameterElement> parameters = missingOverride.parameters; 656 _appendParameters(sb, parameters, _getDefaultValueMap(parameters));
646 // _appendParameters(sb, parameters); 657 sb.write(' {');
647 // sb.append(" {"); 658 // TO-DO
648 // // TO-DO 659 sb.write(eol);
649 // sb.append(eol); 660 sb.write(prefix2);
650 // sb.append(prefix2); 661 if (isMethod) {
Paul Berry 2014/07/25 00:28:45 This if test is unnecessary, since we do the same
scheglov 2014/07/25 03:20:51 Done.
651 // if (isMethod) { 662 sb.write('// TODO: implement ${missingOverride.displayName}');
652 // sb.append("// TODO: implement ${missingOverride.displayName}"); 663 } else {
653 // } else { 664 sb.write('// TODO: implement ${missingOverride.displayName}');
654 // sb.append("// TODO: implement ${missingOverride.displayName}"); 665 }
655 // } 666 sb.write(eol);
656 // sb.append(eol); 667 // close method
657 // // close method 668 sb.write(prefix);
658 // sb.append(prefix); 669 sb.write('}');
659 // sb.append("}"); 670 }
660 // } 671 sb.write(eol);
661 // sb.append(eol); 672 // done
662 // // done 673 _addInsertEdit(insertOffset, sb.toString());
663 // _addInsertEdit(insertOffset, sb.toString()); 674 // maybe set end range
664 // // maybe set end range 675 if (endPosition == null) {
665 // if (_endRange == null) { 676 endPosition = new Position(file, insertOffset, 0);
666 // _endRange = SourceRangeFactory.rangeStartLength(insertOffset, 0); 677 }
667 // }
668 } 678 }
669 679
670 void _addFix_createNoSuchMethod() { 680 void _addFix_createNoSuchMethod() {
671 // TODO(scheglov) implement 681 ClassDeclaration targetClass = node.parent as ClassDeclaration;
672 // ClassDeclaration targetClass = node.parent as ClassDeclaration; 682 // prepare environment
673 // // prepare environment 683 String eol = utils.endOfLine;
674 // String eol = utils.endOfLine; 684 String prefix = utils.getIndent(1);
675 // String prefix = utils.getIndent(1); 685 int insertOffset = targetClass.end - 1;
676 // int insertOffset = targetClass.end - 1; 686 // prepare source
677 // // prepare source 687 SourceBuilder sb = new SourceBuilder(file, insertOffset);
678 // SourceBuilder sb = new SourceBuilder.con1(insertOffset); 688 {
679 // { 689 // insert empty line before existing member
680 // // insert empty line before existing member 690 if (!targetClass.members.isEmpty) {
681 // if (!targetClass.members.isEmpty) { 691 sb.append(eol);
682 // sb.append(eol); 692 }
683 // } 693 // append method
684 // // append method 694 sb.append(prefix);
685 // sb.append(prefix); 695 sb.append(
686 // sb.append( 696 "noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation) ;");
687 // "noSuchMethod(Invocation invocation) => super.noSuchMethod(invocatio n);"); 697 sb.append(eol);
688 // sb.append(eol); 698 }
689 // } 699 // done
690 // // done 700 _insertBuilder(sb);
691 // _addInsertEdit3(sb); 701 endPosition = new Position(file, insertOffset, 0);
692 // _endRange = SourceRangeFactory.rangeStartLength(insertOffset, 0); 702 // add proposal
693 // // add proposal 703 _addFix(FixKind.CREATE_NO_SUCH_METHOD, []);
694 // _addFix(FixKind.CREATE_NO_SUCH_METHOD, []);
695 } 704 }
696 705
697 void _addFix_createPart() { 706 void _addFix_createPart() {
698 // TODO(scheglov) implement 707 // TODO(scheglov) implement
699 // if (node is SimpleStringLiteral && node.parent is PartDirective) { 708 // if (node is SimpleStringLiteral && node.parent is PartDirective) {
700 // SimpleStringLiteral uriLiteral = node as SimpleStringLiteral; 709 // SimpleStringLiteral uriLiteral = node as SimpleStringLiteral;
701 // String uriString = uriLiteral.value; 710 // String uriString = uriLiteral.value;
702 // // prepare referenced File 711 // // prepare referenced File
703 // JavaFile newFile; 712 // JavaFile newFile;
704 // { 713 // {
(...skipping 15 matching lines...) Expand all
720 // _proposals.add( 729 // _proposals.add(
721 // new CreateFileCorrectionProposal( 730 // new CreateFileCorrectionProposal(
722 // newFile, 731 // newFile,
723 // source, 732 // source,
724 // FixKind.CREATE_PART, 733 // FixKind.CREATE_PART,
725 // [uriString])); 734 // [uriString]));
726 // } 735 // }
727 // } 736 // }
728 } 737 }
729 738
739
730 void _addFix_importLibrary(FixKind kind, String importPath) { 740 void _addFix_importLibrary(FixKind kind, String importPath) {
731 // TODO(scheglov) implement 741 // TODO(scheglov) implement
732 // CompilationUnitElement libraryUnitElement = 742 // CompilationUnitElement libraryUnitElement =
733 // _unitLibraryElement.definingCompilationUnit; 743 // _unitLibraryElement.definingCompilationUnit;
734 // CompilationUnit libraryUnit = libraryUnitElement.node; 744 // CompilationUnit libraryUnit = libraryUnitElement.node;
735 // // prepare new import location 745 // // prepare new import location
736 // int offset = 0; 746 // int offset = 0;
737 // String prefix; 747 // String prefix;
738 // String suffix; 748 // String suffix;
739 // { 749 // {
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after
1144 // String closestName = null; 1154 // String closestName = null;
1145 // if (finder != null && finder._distance < 5) { 1155 // if (finder != null && finder._distance < 5) {
1146 // closestName = finder._element.name; 1156 // closestName = finder._element.name;
1147 // _addReplaceEdit(SourceRangeFactory.rangeNode(node), closestName); 1157 // _addReplaceEdit(SourceRangeFactory.rangeNode(node), closestName);
1148 // _addFix(FixKind.CHANGE_TO, [closestName]); 1158 // _addFix(FixKind.CHANGE_TO, [closestName]);
1149 // } 1159 // }
1150 // } 1160 // }
1151 } 1161 }
1152 1162
1153 void _addFix_undefinedMethod_create() { 1163 void _addFix_undefinedMethod_create() {
1154 // TODO(scheglov) implement 1164 if (node is SimpleIdentifier && node.parent is MethodInvocation) {
1155 // if (node is SimpleIdentifier && node.parent is MethodInvocation) { 1165 String name = (node as SimpleIdentifier).name;
1156 // String name = (node as SimpleIdentifier).name; 1166 MethodInvocation invocation = node.parent as MethodInvocation;
1157 // MethodInvocation invocation = node.parent as MethodInvocation; 1167 // prepare environment
1158 // // prepare environment 1168 String eol = utils.endOfLine;
1159 // String eol = utils.endOfLine; 1169 Source targetSource;
1160 // Source targetSource; 1170 String prefix;
1161 // String prefix; 1171 int insertOffset;
1162 // int insertOffset; 1172 String sourcePrefix;
1163 // String sourcePrefix; 1173 String sourceSuffix;
1164 // String sourceSuffix; 1174 bool staticModifier = false;
1165 // bool staticModifier = false; 1175 Expression target = invocation.realTarget;
1166 // Expression target = invocation.realTarget; 1176 if (target == null) {
1167 // if (target == null) { 1177 targetSource = source;
1168 // targetSource = _source; 1178 ClassMember enclosingMember =
1169 // ClassMember enclosingMember = 1179 node.getAncestor((node) => node is ClassMember);
1170 // node.getAncestor((node) => node is ClassMember); 1180 staticModifier = _inStaticMemberContext2(enclosingMember);
1171 // staticModifier = _inStaticMemberContext2(enclosingMember); 1181 prefix = utils.getNodePrefix(enclosingMember);
1172 // prefix = utils.getNodePrefix(enclosingMember); 1182 insertOffset = enclosingMember.end;
1173 // insertOffset = enclosingMember.end; 1183 sourcePrefix = "${eol}${prefix}${eol}";
1174 // sourcePrefix = "${eol}${prefix}${eol}"; 1184 sourceSuffix = "";
1175 // sourceSuffix = ""; 1185 } else {
1176 // } else { 1186 // prepare target interface type
1177 // // prepare target interface type 1187 DartType targetType = target.bestType;
1178 // DartType targetType = target.bestType; 1188 if (targetType is! InterfaceType) {
1179 // if (targetType is! InterfaceType) { 1189 return;
1180 // return; 1190 }
1181 // } 1191 ClassElement targetElement = targetType.element as ClassElement;
1182 // ClassElement targetElement = targetType.element as ClassElement; 1192 targetSource = targetElement.source;
1183 // targetSource = targetElement.source; 1193 // may be static
1184 // // may be static 1194 if (target is Identifier) {
1185 // if (target is Identifier) { 1195 staticModifier = target.bestElement.kind == ElementKind.CLASS;
1186 // staticModifier = target.bestElement.kind == ElementKind.CLASS; 1196 }
1187 // } 1197 // prepare insert offset
1188 // // prepare insert offset 1198 ClassDeclaration targetClass = targetElement.node;
1189 // ClassDeclaration targetClass = targetElement.node; 1199 prefix = " ";
1190 // prefix = " "; 1200 insertOffset = targetClass.end - 1;
1191 // insertOffset = targetClass.end - 1; 1201 if (targetClass.members.isEmpty) {
1192 // if (targetClass.members.isEmpty) { 1202 sourcePrefix = "";
1193 // sourcePrefix = ""; 1203 } else {
1194 // } else { 1204 sourcePrefix = "${prefix}${eol}";
1195 // sourcePrefix = "${prefix}${eol}"; 1205 }
1196 // } 1206 sourceSuffix = eol;
1197 // sourceSuffix = eol; 1207 }
1198 // } 1208 String targetFile = targetSource.fullName;
1199 // // build method source 1209 // build method source
1200 // SourceBuilder sb = new SourceBuilder.con1(insertOffset); 1210 SourceBuilder sb = new SourceBuilder(targetFile, insertOffset);
1201 // { 1211 {
1202 // sb.append(sourcePrefix); 1212 sb.append(sourcePrefix);
1203 // sb.append(prefix); 1213 sb.append(prefix);
1204 // // may be "static" 1214 // may be "static"
1205 // if (staticModifier) { 1215 if (staticModifier) {
1206 // sb.append("static "); 1216 sb.append("static ");
1207 // } 1217 }
1208 // // may be return type 1218 // may be return type
1209 // { 1219 {
1210 // DartType type = 1220 DartType type =
1211 // _addFix_undefinedMethod_create_getReturnType(invocation); 1221 _addFix_undefinedMethod_create_getReturnType(invocation);
1212 // if (type != null) { 1222 if (type != null) {
1213 // String typeSource = utils.getTypeSource2(type); 1223 String typeSource = utils.getTypeSource(type);
1214 // if (typeSource != "dynamic") { 1224 if (typeSource != "dynamic") {
Paul Berry 2014/07/25 00:28:46 It seems weird that we use a string comparison her
scheglov 2014/07/25 03:20:50 Done.
1215 // sb.startPosition("RETURN_TYPE"); 1225 sb.startPosition("RETURN_TYPE");
1216 // sb.append(typeSource); 1226 sb.append(typeSource);
1217 // sb.endPosition(); 1227 sb.endPosition();
1218 // sb.append(" "); 1228 sb.append(" ");
1219 // } 1229 }
1220 // } 1230 }
1221 // } 1231 }
1222 // // append name 1232 // append name
1223 // { 1233 {
1224 // sb.startPosition("NAME"); 1234 sb.startPosition("NAME");
1225 // sb.append(name); 1235 sb.append(name);
1226 // sb.endPosition(); 1236 sb.endPosition();
1227 // } 1237 }
1228 // _addFix_undefinedMethod_create_parameters(sb, invocation.argumentList) ; 1238 _addFix_undefinedMethod_create_parameters(sb, invocation.argumentList);
1229 // sb.append(") {${eol}${prefix}}"); 1239 sb.append(") {${eol}${prefix}}");
1230 // sb.append(sourceSuffix); 1240 sb.append(sourceSuffix);
1231 // } 1241 }
1232 // // insert source 1242 // insert source
1233 // _addInsertEdit(insertOffset, sb.toString()); 1243 _insertBuilder(sb);
1234 // // add linked positions 1244 // add linked positions
1235 // if (targetSource == _source) { 1245 if (targetSource == source) {
1236 // _addLinkedPosition("NAME", sb, SourceRangeFactory.rangeNode(node)); 1246 _addLinkedPosition3('NAME', sb, rf.rangeNode(node));
1237 // } 1247 }
1238 // _addLinkedPositions(sb); 1248 // add proposal
1239 // // add proposal 1249 _addFix(FixKind.CREATE_METHOD, [name], fixFile: targetFile);
1240 // _addUnitCorrectionProposal2( 1250 }
1241 // targetSource,
1242 // FixKind.CREATE_METHOD,
1243 // [name]);
1244 // }
1245 } 1251 }
1246 1252
1247 /** 1253 /**
1248 * @return the possible return [Type], may be <code>null</code> if can not be identified. 1254 * @return the possible return [Type], may be <code>null</code> if can not be identified.
1249 */ 1255 */
1250 DartType 1256 DartType
1251 _addFix_undefinedMethod_create_getReturnType(MethodInvocation invocation) { 1257 _addFix_undefinedMethod_create_getReturnType(MethodInvocation invocation) {
1252 // TODO(scheglov) implement 1258 AstNode parent = invocation.parent;
1253 // AstNode parent = invocation.parent; 1259 // myFunction();
1254 // // myFunction(); 1260 if (parent is ExpressionStatement) {
1255 // if (parent is ExpressionStatement) { 1261 return VoidTypeImpl.instance;
1256 // return VoidTypeImpl.instance; 1262 }
1257 // } 1263 // return myFunction();
1258 // // return myFunction(); 1264 if (parent is ReturnStatement) {
1259 // if (parent is ReturnStatement) { 1265 ExecutableElement executable = getEnclosingExecutableElement(invocation);
1260 // ExecutableElement executable = 1266 return executable != null ? executable.returnType : null;
1261 // CorrectionUtils.getEnclosingExecutableElement(invocation); 1267 }
1262 // return executable != null ? executable.returnType : null; 1268 // int v = myFunction();
1263 // } 1269 if (parent is VariableDeclaration) {
1264 // // int v = myFunction(); 1270 VariableDeclaration variableDeclaration = parent;
1265 // if (parent is VariableDeclaration) { 1271 if (identical(variableDeclaration.initializer, invocation)) {
1266 // VariableDeclaration variableDeclaration = parent; 1272 VariableElement variableElement = variableDeclaration.element;
1267 // if (identical(variableDeclaration.initializer, invocation)) { 1273 if (variableElement != null) {
1268 // VariableElement variableElement = variableDeclaration.element; 1274 return variableElement.type;
1269 // if (variableElement != null) { 1275 }
1270 // return variableElement.type; 1276 }
1271 // } 1277 }
1272 // } 1278 // v = myFunction();
1273 // } 1279 if (parent is AssignmentExpression) {
1274 // // v = myFunction(); 1280 AssignmentExpression assignment = parent;
1275 // if (parent is AssignmentExpression) { 1281 if (identical(assignment.rightHandSide, invocation)) {
1276 // AssignmentExpression assignment = parent; 1282 if (assignment.operator.type == TokenType.EQ) {
1277 // if (identical(assignment.rightHandSide, invocation)) { 1283 // v = myFunction();
1278 // if (assignment.operator.type == TokenType.EQ) { 1284 Expression lhs = assignment.leftHandSide;
1279 // // v = myFunction(); 1285 if (lhs != null) {
1280 // Expression lhs = assignment.leftHandSide; 1286 return lhs.bestType;
1281 // if (lhs != null) { 1287 }
1282 // return lhs.bestType; 1288 } else {
1283 // } 1289 // v += myFunction();
1284 // } else { 1290 MethodElement method = assignment.bestElement;
1285 // // v += myFunction(); 1291 if (method != null) {
1286 // MethodElement method = assignment.bestElement; 1292 List<ParameterElement> parameters = method.parameters;
1287 // if (method != null) { 1293 if (parameters.length == 1) {
1288 // List<ParameterElement> parameters = method.parameters; 1294 return parameters[0].type;
1289 // if (parameters.length == 1) { 1295 }
1290 // return parameters[0].type; 1296 }
1291 // } 1297 }
1292 // } 1298 }
1293 // } 1299 }
1294 // } 1300 // v + myFunction();
1295 // } 1301 if (parent is BinaryExpression) {
1296 // // v + myFunction(); 1302 BinaryExpression binary = parent;
1297 // if (parent is BinaryExpression) { 1303 MethodElement method = binary.bestElement;
1298 // BinaryExpression binary = parent; 1304 if (method != null) {
1299 // MethodElement method = binary.bestElement; 1305 if (identical(binary.rightOperand, invocation)) {
1300 // if (method != null) { 1306 List<ParameterElement> parameters = method.parameters;
1301 // if (identical(binary.rightOperand, invocation)) { 1307 return parameters.length == 1 ? parameters[0].type : null;
1302 // List<ParameterElement> parameters = method.parameters; 1308 }
1303 // return parameters.length == 1 ? parameters[0].type : null; 1309 }
1304 // } 1310 }
1305 // } 1311 // foo( myFunction() );
1306 // } 1312 if (parent is ArgumentList) {
1307 // // foo( myFunction() ); 1313 ParameterElement parameter = invocation.bestParameterElement;
1308 // if (parent is ArgumentList) { 1314 return parameter != null ? parameter.type : null;
1309 // ParameterElement parameter = invocation.bestParameterElement; 1315 }
1310 // return parameter != null ? parameter.type : null; 1316 // bool
1311 // } 1317 {
1312 // // bool 1318 // assert( myFunction() );
1313 // { 1319 if (parent is AssertStatement) {
1314 // // assert( myFunction() ); 1320 AssertStatement statement = parent;
1315 // if (parent is AssertStatement) { 1321 if (identical(statement.condition, invocation)) {
1316 // AssertStatement statement = parent; 1322 return coreTypeBool;
1317 // if (identical(statement.condition, invocation)) { 1323 }
1318 // return coreTypeBool; 1324 }
1319 // } 1325 // if ( myFunction() ) {}
1320 // } 1326 if (parent is IfStatement) {
1321 // // if ( myFunction() ) {} 1327 IfStatement statement = parent;
1322 // if (parent is IfStatement) { 1328 if (identical(statement.condition, invocation)) {
1323 // IfStatement statement = parent; 1329 return coreTypeBool;
1324 // if (identical(statement.condition, invocation)) { 1330 }
1325 // return coreTypeBool; 1331 }
1326 // } 1332 // while ( myFunction() ) {}
1327 // } 1333 if (parent is WhileStatement) {
1328 // // while ( myFunction() ) {} 1334 WhileStatement statement = parent;
1329 // if (parent is WhileStatement) { 1335 if (identical(statement.condition, invocation)) {
1330 // WhileStatement statement = parent; 1336 return coreTypeBool;
1331 // if (identical(statement.condition, invocation)) { 1337 }
1332 // return coreTypeBool; 1338 }
1333 // } 1339 // do {} while ( myFunction() );
1334 // } 1340 if (parent is DoStatement) {
1335 // // do {} while ( myFunction() ); 1341 DoStatement statement = parent;
1336 // if (parent is DoStatement) { 1342 if (identical(statement.condition, invocation)) {
1337 // DoStatement statement = parent; 1343 return coreTypeBool;
1338 // if (identical(statement.condition, invocation)) { 1344 }
1339 // return coreTypeBool; 1345 }
1340 // } 1346 // !myFunction()
1341 // } 1347 if (parent is PrefixExpression) {
1342 // // !myFunction() 1348 PrefixExpression prefixExpression = parent;
1343 // if (parent is PrefixExpression) { 1349 if (prefixExpression.operator.type == TokenType.BANG) {
1344 // PrefixExpression prefixExpression = parent; 1350 return coreTypeBool;
1345 // if (prefixExpression.operator.type == TokenType.BANG) { 1351 }
1346 // return coreTypeBool; 1352 }
1347 // } 1353 // binary expression '&&' or '||'
1348 // } 1354 if (parent is BinaryExpression) {
1349 // // binary expression '&&' or '||' 1355 BinaryExpression binaryExpression = parent;
1350 // if (parent is BinaryExpression) { 1356 TokenType operatorType = binaryExpression.operator.type;
1351 // BinaryExpression binaryExpression = parent; 1357 if (operatorType == TokenType.AMPERSAND_AMPERSAND ||
1352 // TokenType operatorType = binaryExpression.operator.type; 1358 operatorType == TokenType.BAR_BAR) {
1353 // if (operatorType == TokenType.AMPERSAND_AMPERSAND || 1359 return coreTypeBool;
1354 // operatorType == TokenType.BAR_BAR) { 1360 }
1355 // return coreTypeBool; 1361 }
1356 // } 1362 }
1357 // }
1358 // }
1359 // we don't know 1363 // we don't know
1360 return null; 1364 return null;
1361 } 1365 }
1362 1366
1363 void _addFix_undefinedMethod_create_parameters(SourceBuilder sb, 1367 void _addFix_undefinedMethod_create_parameters(SourceBuilder sb,
1364 ArgumentList argumentList) { 1368 ArgumentList argumentList) {
1365 // append parameters 1369 // append parameters
1366 sb.append("("); 1370 sb.append("(");
1367 Set<String> excluded = new Set(); 1371 Set<String> excluded = new Set();
1368 List<Expression> arguments = argumentList.arguments; 1372 List<Expression> arguments = argumentList.arguments;
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
1510 void _addLinkedPosition2(String groupId, Position position) { 1514 void _addLinkedPosition2(String groupId, Position position) {
1511 LinkedPositionGroup group = linkedPositionGroups[groupId]; 1515 LinkedPositionGroup group = linkedPositionGroups[groupId];
1512 if (group == null) { 1516 if (group == null) {
1513 group = new LinkedPositionGroup(groupId); 1517 group = new LinkedPositionGroup(groupId);
1514 linkedPositionGroups[groupId] = group; 1518 linkedPositionGroups[groupId] = group;
1515 } 1519 }
1516 group.add(position); 1520 group.add(position);
1517 } 1521 }
1518 1522
1519 /** 1523 /**
1524 * Adds a single linked position to [groupId].
1525 */
1526 void _addLinkedPosition3(String groupId, SourceBuilder sb,
1527 SourceRange range) {
1528 if (sb.offset < range.offset) {
1529 int delta = sb.length;
1530 range = range.getTranslated(delta);
1531 }
1532 _addLinkedPosition(groupId, range);
1533 }
1534
1535 /**
1536 * Prepares proposal for creating function corresponding to the given [Functio nType].
1537 */
1538 void _addProposal_createFunction(FunctionType functionType, String name,
Paul Berry 2014/07/25 00:28:46 It seems like there's a lot in common between this
1539 Source targetSource, int insertOffset, bool isStatic, String eol, String p refix,
1540 String sourcePrefix, String sourceSuffix) {
1541 // build method source
1542 String targetFile = targetSource.fullName;
1543 SourceBuilder sb = new SourceBuilder(targetFile, insertOffset);
1544 {
1545 sb.append(sourcePrefix);
1546 sb.append(prefix);
1547 // may be static
1548 if (isStatic) {
1549 sb.append("static ");
1550 }
1551 // may be return type
1552 {
1553 DartType returnType = functionType.returnType;
1554 if (returnType != null) {
1555 String typeSource = utils.getTypeSource(returnType);
1556 if (typeSource != "dynamic") {
Paul Berry 2014/07/25 00:28:46 Use returnType.isDynamic here too.
scheglov 2014/07/25 03:20:50 Done.
1557 sb.startPosition("RETURN_TYPE");
1558 sb.append(typeSource);
1559 sb.endPosition();
1560 sb.append(" ");
1561 }
1562 }
1563 }
1564 // append name
1565 {
1566 sb.startPosition("NAME");
1567 sb.append(name);
1568 sb.endPosition();
1569 }
1570 // append parameters
1571 sb.append("(");
1572 List<ParameterElement> parameters = functionType.parameters;
1573 for (int i = 0; i < parameters.length; i++) {
1574 ParameterElement parameter = parameters[i];
1575 // append separator
1576 if (i != 0) {
1577 sb.append(", ");
1578 }
1579 // append type name
1580 DartType type = parameter.type;
1581 String typeSource = utils.getTypeSource(type);
1582 {
Paul Berry 2014/07/25 00:28:45 Should we guard this with "if (!type.isDynamic)",
scheglov 2014/07/25 03:20:50 Done. I've also added a test.
1583 sb.startPosition("TYPE${i}");
1584 sb.append(typeSource);
1585 _addSuperTypeProposals(sb, new Set(), type);
1586 sb.endPosition();
1587 }
1588 sb.append(" ");
1589 // append parameter name
1590 {
1591 sb.startPosition("ARG${i}");
1592 sb.append(parameter.displayName);
1593 sb.endPosition();
1594 }
1595 }
1596 sb.append(")");
1597 // close method
1598 sb.append(" {${eol}${prefix}}");
Paul Berry 2014/07/25 00:28:46 Space before $eol seems unnecessary.
scheglov 2014/07/25 03:20:50 The space is before "{", which opens the body bloc
1599 sb.append(sourceSuffix);
1600 }
1601 // insert source
1602 _insertBuilder(sb);
1603 // add linked positions
1604 if (targetSource == source) {
1605 _addLinkedPosition3("NAME", sb, rf.rangeNode(node));
1606 }
1607 }
1608
1609 /**
1610 * Adds proposal for creating method corresponding to the given [FunctionType] in the given
1611 * [ClassElement].
1612 */
1613 void _addProposal_createFunction_function(FunctionType functionType) {
1614 String name = (node as SimpleIdentifier).name;
1615 // prepare environment
1616 String eol = utils.endOfLine;
1617 int insertOffset = unit.end;
1618 // prepare prefix
1619 String prefix = "";
1620 String sourcePrefix = "${eol}";
1621 String sourceSuffix = eol;
1622 _addProposal_createFunction(
1623 functionType,
1624 name,
1625 source,
1626 insertOffset,
1627 false,
1628 eol,
1629 prefix,
1630 sourcePrefix,
1631 sourceSuffix);
1632 // add proposal
1633 _addFix(FixKind.CREATE_FUNCTION, [name], fixFile: file);
1634 }
1635
1636 /**
1637 * Adds proposal for creating method corresponding to the given [FunctionType] in the given
1638 * [ClassElement].
1639 */
1640 void _addProposal_createFunction_method(ClassElement targetClassElement,
1641 FunctionType functionType) {
1642 String name = (node as SimpleIdentifier).name;
1643 // prepare environment
1644 String eol = utils.endOfLine;
Paul Berry 2014/07/25 00:28:45 Suggestion: rather than force the caller to look u
scheglov 2014/07/25 03:20:50 Done.
1645 Source targetSource = targetClassElement.source;
1646 String targetFile = targetSource.fullName;
1647 // prepare insert offset
1648 ClassDeclaration targetClassNode = targetClassElement.node;
1649 int insertOffset = targetClassNode.end - 1;
1650 // prepare prefix
1651 String prefix = " ";
1652 String sourcePrefix;
1653 if (targetClassNode.members.isEmpty) {
1654 sourcePrefix = "";
1655 } else {
1656 sourcePrefix = "${prefix}${eol}";
Paul Berry 2014/07/25 00:28:45 This will just insert a blank line containing whit
scheglov 2014/07/25 03:20:51 Done.
1657 }
1658 String sourceSuffix = eol;
1659 _addProposal_createFunction(
1660 functionType,
1661 name,
1662 targetSource,
1663 insertOffset,
1664 _inStaticMemberContext(),
1665 eol,
1666 prefix,
1667 sourcePrefix,
1668 sourceSuffix);
1669 // add proposal
1670 _addFix(FixKind.CREATE_METHOD, [name], fixFile: targetFile);
1671 }
1672
1673 /**
1520 * Adds a new [Edit] to [edits]. 1674 * Adds a new [Edit] to [edits].
1521 */ 1675 */
1522 void _addRemoveEdit(SourceRange range) { 1676 void _addRemoveEdit(SourceRange range) {
1523 _addReplaceEdit(range, ''); 1677 _addReplaceEdit(range, '');
1524 } 1678 }
1525 1679
1526 /** 1680 /**
1527 * Adds a new [Edit] to [edits]. 1681 * Adds a new [Edit] to [edits].
1528 */ 1682 */
1529 void _addReplaceEdit(SourceRange range, String text) { 1683 void _addReplaceEdit(SourceRange range, String text) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1580 // close parameters 1734 // close parameters
1581 if (sawNamed) { 1735 if (sawNamed) {
1582 sb.write("}"); 1736 sb.write("}");
1583 } 1737 }
1584 if (sawPositional) { 1738 if (sawPositional) {
1585 sb.write("]"); 1739 sb.write("]");
1586 } 1740 }
1587 sb.write(")"); 1741 sb.write(")");
1588 } 1742 }
1589 1743
1590 // void _addLinkedPositionProposal(String group, 1744 void _appendType(StringBuffer sb, DartType type) {
1591 // LinkedPositionProposal proposal) { 1745 if (type != null && !type.isDynamic) {
1592 // List<LinkedPositionProposal> nodeProposals = linkedPositionProposals[group ]; 1746 String typeSource = utils.getTypeSource(type);
1593 // if (nodeProposals == null) { 1747 sb.write(typeSource);
1594 // nodeProposals = <LinkedPositionProposal>[]; 1748 sb.write(' ');
1595 // linkedPositionProposals[group] = nodeProposals; 1749 }
1596 // } 1750 }
1597 // nodeProposals.add(proposal);
1598 // }
1599 1751
1600 /** 1752 /**
1601 * @return the string to display as the name of the given constructor in a pro posal name. 1753 * @return the string to display as the name of the given constructor in a pro posal name.
1602 */ 1754 */
1603 String _getConstructorProposalName(ConstructorElement constructor) { 1755 String _getConstructorProposalName(ConstructorElement constructor) {
1604 StringBuffer proposalNameBuffer = new StringBuffer(); 1756 StringBuffer proposalNameBuffer = new StringBuffer();
1605 proposalNameBuffer.write("super"); 1757 proposalNameBuffer.write("super");
1606 // may be named 1758 // may be named
1607 String constructorName = constructor.displayName; 1759 String constructorName = constructor.displayName;
1608 if (!constructorName.isEmpty) { 1760 if (!constructorName.isEmpty) {
1609 proposalNameBuffer.write("."); 1761 proposalNameBuffer.write(".");
1610 proposalNameBuffer.write(constructorName); 1762 proposalNameBuffer.write(constructorName);
1611 } 1763 }
1612 // parameters 1764 // parameters
1613 _appendParameters(proposalNameBuffer, constructor.parameters, null); 1765 _appendParameters(proposalNameBuffer, constructor.parameters, null);
1614 // done 1766 // done
1615 return proposalNameBuffer.toString(); 1767 return proposalNameBuffer.toString();
1616 } 1768 }
1617 1769
1618 /** 1770 /**
1771 * Returns the [Type] with given name from the `dart:core` library.
1772 */
1773 DartType _getCoreType(String name) {
1774 List<LibraryElement> libraries = unitLibraryElement.importedLibraries;
1775 for (LibraryElement library in libraries) {
1776 if (library.isDartCore) {
1777 ClassElement classElement = library.getType(name);
1778 if (classElement != null) {
1779 return classElement.type;
1780 }
1781 return null;
1782 }
1783 }
1784 return null;
1785 }
1786
1787 Map<ParameterElement, String>
1788 _getDefaultValueMap(List<ParameterElement> parameters) {
1789 Map<ParameterElement, String> defaultSourceMap = {};
1790 Map<Source, String> sourceContentMap = {};
1791 for (ParameterElement parameter in parameters) {
1792 SourceRange valueRange = parameter.defaultValueRange;
1793 if (valueRange != null) {
1794 Source source = parameter.source;
1795 String sourceContent = sourceContentMap[source];
1796 if (sourceContent == null) {
1797 sourceContent = getSourceContent(parameter.context, source);
1798 sourceContentMap[source] = sourceContent;
1799 }
1800 String valueSource =
1801 sourceContent.substring(valueRange.offset, valueRange.end);
1802 defaultSourceMap[parameter] = valueSource;
1803 }
1804 }
1805 return defaultSourceMap;
1806 }
1807
1808 /**
1809 * Returns `true` if [node] if part of a static method or of a field
1810 * initializer.
1811 */
1812 bool _inStaticMemberContext() {
Paul Berry 2014/07/25 00:28:45 This won't do the right thing if node is in a cons
scheglov 2014/07/25 03:20:50 Added the test and fixed.
1813 ClassMember member = node.getAncestor((node) => node is ClassMember);
1814 return _inStaticMemberContext2(member);
Paul Berry 2014/07/25 00:28:45 Rather than having two functions and forcing the c
scheglov 2014/07/25 03:20:51 Done.
1815 }
1816
1817 // void _addLinkedPositionProposal(String group,
1818 // LinkedPositionProposal proposal) {
1819 // List<LinkedPositionProposal> nodeProposals = linkedPositionProposals[group ];
1820 // if (nodeProposals == null) {
1821 // nodeProposals = <LinkedPositionProposal>[];
1822 // linkedPositionProposals[group] = nodeProposals;
1823 // }
1824 // nodeProposals.add(proposal);
1825 // }
1826
1827 /**
1828 * Returns `true` if the given [ClassMember] is a part of a static method or
1829 * a field initializer.
1830 */
1831 bool _inStaticMemberContext2(ClassMember member) {
1832 if (member is MethodDeclaration) {
1833 return member.isStatic;
1834 }
1835 // field initializer cannot reference "this"
1836 if (member is FieldDeclaration) {
1837 return true;
1838 }
1839 return false;
1840 }
1841
1842 /**
1619 * Inserts the given [SourceBuilder] at its offset. 1843 * Inserts the given [SourceBuilder] at its offset.
1620 */ 1844 */
1621 void _insertBuilder(SourceBuilder builder) { 1845 void _insertBuilder(SourceBuilder builder) {
1622 String text = builder.toString(); 1846 String text = builder.toString();
1623 _addInsertEdit(builder.offset, text); 1847 _addInsertEdit(builder.offset, text);
1624 // add linked positions 1848 // add linked positions
1625 builder.linkedPositionGroups.forEach((LinkedPositionGroup group) { 1849 builder.linkedPositionGroups.forEach((LinkedPositionGroup group) {
1626 group.positions.forEach((Position position) { 1850 group.positions.forEach((Position position) {
1627 _addLinkedPosition2(group.id, position); 1851 _addLinkedPosition2(group.id, position);
1628 }); 1852 });
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
1729 * TODO(scheglov) rename 1953 * TODO(scheglov) rename
1730 */ 1954 */
1731 class QuickFixProcessorImpl_NewConstructorLocation { 1955 class QuickFixProcessorImpl_NewConstructorLocation {
1732 final String _prefix; 1956 final String _prefix;
1733 final int _offset; 1957 final int _offset;
1734 final String _suffix; 1958 final String _suffix;
1735 1959
1736 QuickFixProcessorImpl_NewConstructorLocation(this._prefix, this._offset, 1960 QuickFixProcessorImpl_NewConstructorLocation(this._prefix, this._offset,
1737 this._suffix); 1961 this._suffix);
1738 } 1962 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698