OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2013, the Dart project authors. | 2 * Copyright (c) 2013, the Dart project authors. |
3 * | 3 * |
4 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not u
se this file except | 4 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not u
se this file except |
5 * in compliance with the License. You may obtain a copy of the License at | 5 * in compliance with the License. You may obtain a copy of the License at |
6 * | 6 * |
7 * http://www.eclipse.org/legal/epl-v10.html | 7 * http://www.eclipse.org/legal/epl-v10.html |
8 * | 8 * |
9 * Unless required by applicable law or agreed to in writing, software distribut
ed under the License | 9 * Unless required by applicable law or agreed to in writing, software distribut
ed under the License |
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY K
IND, either express | 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY K
IND, either express |
11 * or implied. See the License for the specific language governing permissions a
nd limitations under | 11 * or implied. See the License for the specific language governing permissions a
nd limitations under |
12 * the License. | 12 * the License. |
13 */ | 13 */ |
14 | 14 |
15 package com.google.dart.engine.services.internal.correction; | 15 package com.google.dart.engine.services.internal.correction; |
16 | 16 |
17 import com.google.common.collect.Lists; | 17 import com.google.common.collect.Lists; |
18 import com.google.common.collect.Maps; | 18 import com.google.common.collect.Maps; |
19 import com.google.common.collect.Sets; | 19 import com.google.common.collect.Sets; |
20 import com.google.dart.engine.ast.ASTNode; | 20 import com.google.dart.engine.ast.ASTNode; |
21 import com.google.dart.engine.ast.AssignmentExpression; | 21 import com.google.dart.engine.ast.AssignmentExpression; |
22 import com.google.dart.engine.ast.BinaryExpression; | 22 import com.google.dart.engine.ast.BinaryExpression; |
23 import com.google.dart.engine.ast.Block; | 23 import com.google.dart.engine.ast.Block; |
24 import com.google.dart.engine.ast.BlockFunctionBody; | 24 import com.google.dart.engine.ast.BlockFunctionBody; |
25 import com.google.dart.engine.ast.ClassDeclaration; | 25 import com.google.dart.engine.ast.ClassDeclaration; |
26 import com.google.dart.engine.ast.CompilationUnit; | 26 import com.google.dart.engine.ast.CompilationUnit; |
27 import com.google.dart.engine.ast.ConditionalExpression; | 27 import com.google.dart.engine.ast.ConditionalExpression; |
28 import com.google.dart.engine.ast.ConstructorDeclaration; | |
29 import com.google.dart.engine.ast.Expression; | 28 import com.google.dart.engine.ast.Expression; |
30 import com.google.dart.engine.ast.ExpressionFunctionBody; | 29 import com.google.dart.engine.ast.ExpressionFunctionBody; |
31 import com.google.dart.engine.ast.ExpressionStatement; | 30 import com.google.dart.engine.ast.ExpressionStatement; |
32 import com.google.dart.engine.ast.FieldDeclaration; | 31 import com.google.dart.engine.ast.FieldDeclaration; |
33 import com.google.dart.engine.ast.FunctionBody; | 32 import com.google.dart.engine.ast.FunctionBody; |
34 import com.google.dart.engine.ast.FunctionDeclaration; | 33 import com.google.dart.engine.ast.FunctionDeclaration; |
35 import com.google.dart.engine.ast.FunctionExpression; | 34 import com.google.dart.engine.ast.FunctionExpression; |
36 import com.google.dart.engine.ast.IfStatement; | 35 import com.google.dart.engine.ast.IfStatement; |
37 import com.google.dart.engine.ast.ImportDirective; | 36 import com.google.dart.engine.ast.ImportDirective; |
38 import com.google.dart.engine.ast.IsExpression; | 37 import com.google.dart.engine.ast.IsExpression; |
39 import com.google.dart.engine.ast.LibraryIdentifier; | 38 import com.google.dart.engine.ast.LibraryIdentifier; |
40 import com.google.dart.engine.ast.MethodDeclaration; | 39 import com.google.dart.engine.ast.MethodDeclaration; |
41 import com.google.dart.engine.ast.ParenthesizedExpression; | 40 import com.google.dart.engine.ast.ParenthesizedExpression; |
42 import com.google.dart.engine.ast.PartOfDirective; | 41 import com.google.dart.engine.ast.PartOfDirective; |
43 import com.google.dart.engine.ast.PrefixExpression; | 42 import com.google.dart.engine.ast.PrefixExpression; |
44 import com.google.dart.engine.ast.PrefixedIdentifier; | 43 import com.google.dart.engine.ast.PrefixedIdentifier; |
45 import com.google.dart.engine.ast.PropertyAccess; | 44 import com.google.dart.engine.ast.PropertyAccess; |
46 import com.google.dart.engine.ast.ReturnStatement; | 45 import com.google.dart.engine.ast.ReturnStatement; |
47 import com.google.dart.engine.ast.SimpleIdentifier; | 46 import com.google.dart.engine.ast.SimpleIdentifier; |
48 import com.google.dart.engine.ast.Statement; | 47 import com.google.dart.engine.ast.Statement; |
49 import com.google.dart.engine.ast.ThrowExpression; | 48 import com.google.dart.engine.ast.ThrowExpression; |
50 import com.google.dart.engine.ast.TopLevelVariableDeclaration; | 49 import com.google.dart.engine.ast.TopLevelVariableDeclaration; |
51 import com.google.dart.engine.ast.TypeName; | 50 import com.google.dart.engine.ast.TypeName; |
52 import com.google.dart.engine.ast.VariableDeclaration; | 51 import com.google.dart.engine.ast.VariableDeclaration; |
53 import com.google.dart.engine.ast.VariableDeclarationList; | 52 import com.google.dart.engine.ast.VariableDeclarationList; |
54 import com.google.dart.engine.ast.VariableDeclarationStatement; | 53 import com.google.dart.engine.ast.VariableDeclarationStatement; |
55 import com.google.dart.engine.ast.visitor.NodeLocator; | 54 import com.google.dart.engine.ast.visitor.NodeLocator; |
56 import com.google.dart.engine.context.AnalysisContext; | 55 import com.google.dart.engine.context.AnalysisContext; |
57 import com.google.dart.engine.element.ClassElement; | |
58 import com.google.dart.engine.element.CompilationUnitElement; | 56 import com.google.dart.engine.element.CompilationUnitElement; |
59 import com.google.dart.engine.element.Element; | 57 import com.google.dart.engine.element.Element; |
60 import com.google.dart.engine.element.FieldElement; | |
61 import com.google.dart.engine.element.ImportElement; | 58 import com.google.dart.engine.element.ImportElement; |
62 import com.google.dart.engine.element.LibraryElement; | 59 import com.google.dart.engine.element.LibraryElement; |
63 import com.google.dart.engine.element.PropertyAccessorElement; | |
64 import com.google.dart.engine.scanner.Keyword; | 60 import com.google.dart.engine.scanner.Keyword; |
65 import com.google.dart.engine.scanner.KeywordToken; | 61 import com.google.dart.engine.scanner.KeywordToken; |
66 import com.google.dart.engine.scanner.TokenClass; | 62 import com.google.dart.engine.scanner.TokenClass; |
67 import com.google.dart.engine.scanner.TokenType; | 63 import com.google.dart.engine.scanner.TokenType; |
68 import com.google.dart.engine.search.SearchEngine; | 64 import com.google.dart.engine.search.SearchEngine; |
69 import com.google.dart.engine.search.SearchMatch; | 65 import com.google.dart.engine.search.SearchMatch; |
70 import com.google.dart.engine.services.assist.AssistContext; | 66 import com.google.dart.engine.services.assist.AssistContext; |
71 import com.google.dart.engine.services.change.Change; | 67 import com.google.dart.engine.services.change.Change; |
72 import com.google.dart.engine.services.change.CompositeChange; | 68 import com.google.dart.engine.services.change.CompositeChange; |
73 import com.google.dart.engine.services.change.CreateFileChange; | 69 import com.google.dart.engine.services.change.CreateFileChange; |
74 import com.google.dart.engine.services.change.Edit; | 70 import com.google.dart.engine.services.change.Edit; |
75 import com.google.dart.engine.services.change.SourceChange; | 71 import com.google.dart.engine.services.change.SourceChange; |
76 import com.google.dart.engine.services.correction.ChangeCorrectionProposal; | 72 import com.google.dart.engine.services.correction.ChangeCorrectionProposal; |
77 import com.google.dart.engine.services.correction.CorrectionImage; | 73 import com.google.dart.engine.services.correction.CorrectionImage; |
78 import com.google.dart.engine.services.correction.CorrectionKind; | 74 import com.google.dart.engine.services.correction.CorrectionKind; |
79 import com.google.dart.engine.services.correction.CorrectionProposal; | 75 import com.google.dart.engine.services.correction.CorrectionProposal; |
80 import com.google.dart.engine.services.correction.LinkedPositionProposal; | 76 import com.google.dart.engine.services.correction.LinkedPositionProposal; |
81 import com.google.dart.engine.services.correction.QuickAssistProcessor; | 77 import com.google.dart.engine.services.correction.QuickAssistProcessor; |
82 import com.google.dart.engine.services.correction.SourceCorrectionProposal; | 78 import com.google.dart.engine.services.correction.SourceCorrectionProposal; |
83 import com.google.dart.engine.services.internal.correction.CorrectionUtils.Inser
tDesc; | 79 import com.google.dart.engine.services.internal.correction.CorrectionUtils.Inser
tDesc; |
84 import com.google.dart.engine.services.internal.util.ExecutionUtils; | 80 import com.google.dart.engine.services.internal.util.ExecutionUtils; |
85 import com.google.dart.engine.services.internal.util.RunnableEx; | 81 import com.google.dart.engine.services.internal.util.RunnableEx; |
86 import com.google.dart.engine.services.internal.util.TokenUtils; | 82 import com.google.dart.engine.services.internal.util.TokenUtils; |
87 import com.google.dart.engine.source.Source; | 83 import com.google.dart.engine.source.Source; |
88 import com.google.dart.engine.type.InterfaceType; | |
89 import com.google.dart.engine.type.Type; | 84 import com.google.dart.engine.type.Type; |
90 import com.google.dart.engine.utilities.ast.ScopedNameFinder; | 85 import com.google.dart.engine.utilities.ast.ScopedNameFinder; |
91 import com.google.dart.engine.utilities.instrumentation.Instrumentation; | 86 import com.google.dart.engine.utilities.instrumentation.Instrumentation; |
92 import com.google.dart.engine.utilities.instrumentation.InstrumentationBuilder; | 87 import com.google.dart.engine.utilities.instrumentation.InstrumentationBuilder; |
93 import com.google.dart.engine.utilities.source.SourceRange; | 88 import com.google.dart.engine.utilities.source.SourceRange; |
94 | 89 |
95 import static com.google.dart.engine.services.correction.CorrectionKind.QA_ADD_J
SON; | |
96 import static com.google.dart.engine.services.correction.CorrectionKind.QA_ADD_T
YPE_ANNOTATION; | 90 import static com.google.dart.engine.services.correction.CorrectionKind.QA_ADD_T
YPE_ANNOTATION; |
97 import static com.google.dart.engine.services.correction.CorrectionKind.QA_ASSIG
N_TO_LOCAL_VARIABLE; | 91 import static com.google.dart.engine.services.correction.CorrectionKind.QA_ASSIG
N_TO_LOCAL_VARIABLE; |
98 import static com.google.dart.engine.services.correction.CorrectionKind.QA_CONVE
RT_INTO_BLOCK_BODY; | 92 import static com.google.dart.engine.services.correction.CorrectionKind.QA_CONVE
RT_INTO_BLOCK_BODY; |
99 import static com.google.dart.engine.services.correction.CorrectionKind.QA_CONVE
RT_INTO_EXPRESSION_BODY; | 93 import static com.google.dart.engine.services.correction.CorrectionKind.QA_CONVE
RT_INTO_EXPRESSION_BODY; |
100 import static com.google.dart.engine.services.correction.CorrectionKind.QA_CONVE
RT_INTO_IS_NOT; | 94 import static com.google.dart.engine.services.correction.CorrectionKind.QA_CONVE
RT_INTO_IS_NOT; |
101 import static com.google.dart.engine.services.correction.CorrectionKind.QA_CONVE
RT_INTO_IS_NOT_EMPTY; | 95 import static com.google.dart.engine.services.correction.CorrectionKind.QA_CONVE
RT_INTO_IS_NOT_EMPTY; |
102 import static com.google.dart.engine.services.correction.CorrectionKind.QA_EXCHA
NGE_OPERANDS; | 96 import static com.google.dart.engine.services.correction.CorrectionKind.QA_EXCHA
NGE_OPERANDS; |
103 import static com.google.dart.engine.services.correction.CorrectionKind.QA_EXTRA
CT_CLASS; | 97 import static com.google.dart.engine.services.correction.CorrectionKind.QA_EXTRA
CT_CLASS; |
104 import static com.google.dart.engine.services.correction.CorrectionKind.QA_IMPOR
T_ADD_SHOW; | 98 import static com.google.dart.engine.services.correction.CorrectionKind.QA_IMPOR
T_ADD_SHOW; |
105 import static com.google.dart.engine.services.correction.CorrectionKind.QA_INVER
T_IF_STATEMENT; | 99 import static com.google.dart.engine.services.correction.CorrectionKind.QA_INVER
T_IF_STATEMENT; |
(...skipping 22 matching lines...) Expand all Loading... |
128 import static com.google.dart.engine.utilities.source.SourceRangeFactory.rangeSt
artStart; | 122 import static com.google.dart.engine.utilities.source.SourceRangeFactory.rangeSt
artStart; |
129 import static com.google.dart.engine.utilities.source.SourceRangeFactory.rangeTo
ken; | 123 import static com.google.dart.engine.utilities.source.SourceRangeFactory.rangeTo
ken; |
130 import static com.google.dart.engine.utilities.source.SourceRangeFactory.rangeWi
thBase; | 124 import static com.google.dart.engine.utilities.source.SourceRangeFactory.rangeWi
thBase; |
131 | 125 |
132 import org.apache.commons.lang3.StringUtils; | 126 import org.apache.commons.lang3.StringUtils; |
133 | 127 |
134 import java.io.File; | 128 import java.io.File; |
135 import java.lang.reflect.Method; | 129 import java.lang.reflect.Method; |
136 import java.net.URI; | 130 import java.net.URI; |
137 import java.text.MessageFormat; | 131 import java.text.MessageFormat; |
138 import java.util.Collections; | |
139 import java.util.List; | 132 import java.util.List; |
140 import java.util.Map; | 133 import java.util.Map; |
141 import java.util.Map.Entry; | 134 import java.util.Map.Entry; |
142 import java.util.Set; | 135 import java.util.Set; |
143 | 136 |
144 /** | 137 /** |
145 * Implementation of {@link QuickAssistProcessor}. | 138 * Implementation of {@link QuickAssistProcessor}. |
146 */ | 139 */ |
147 public class QuickAssistProcessorImpl implements QuickAssistProcessor { | 140 public class QuickAssistProcessorImpl implements QuickAssistProcessor { |
148 private static final CorrectionProposal[] NO_PROPOSALS = {}; | 141 private static final CorrectionProposal[] NO_PROPOSALS = {}; |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 instrumentation.data("QuickAssist-Source", utils.getText()); | 281 instrumentation.data("QuickAssist-Source", utils.getText()); |
289 for (int index = 0; index < proposals.size(); index++) { | 282 for (int index = 0; index < proposals.size(); index++) { |
290 instrumentation.data("QuickAssist-Proposal-" + index, proposals.get(inde
x).getName()); | 283 instrumentation.data("QuickAssist-Proposal-" + index, proposals.get(inde
x).getName()); |
291 } | 284 } |
292 return proposals.toArray(new CorrectionProposal[proposals.size()]); | 285 return proposals.toArray(new CorrectionProposal[proposals.size()]); |
293 } finally { | 286 } finally { |
294 instrumentation.log(); | 287 instrumentation.log(); |
295 } | 288 } |
296 } | 289 } |
297 | 290 |
298 void addProposal_addJson() throws Exception { | |
299 // prepare enclosing ClassDeclaration | |
300 ClassDeclaration classDeclaration = node.getAncestor(ClassDeclaration.class)
; | |
301 if (classDeclaration == null) { | |
302 return; | |
303 } | |
304 if (selectionOffset >= classDeclaration.getName().getEnd()) { | |
305 return; | |
306 } | |
307 // process ClassElement | |
308 ClassElement element = classDeclaration.getElement(); | |
309 if (element != null) { | |
310 // prepare all types | |
311 Set<InterfaceType> allTypes = Sets.newHashSet(); | |
312 allTypes.add(element.getType()); | |
313 Collections.addAll(allTypes, element.getAllSupertypes()); | |
314 // prepare all fields | |
315 Map<String, FieldElement> fields = Maps.newTreeMap(); | |
316 for (InterfaceType type : allTypes) { | |
317 for (PropertyAccessorElement accessor : type.getAccessors()) { | |
318 // check if accessible | |
319 if (!accessor.isAccessibleIn(unitLibraryElement)) { | |
320 continue; | |
321 } | |
322 // use only synthetic accessors, i.e. real fields | |
323 if (!accessor.isSynthetic()) { | |
324 continue; | |
325 } | |
326 // add field | |
327 FieldElement field = (FieldElement) accessor.getVariable(); | |
328 String name = field.getName(); | |
329 if (!fields.containsKey(name)) { | |
330 fields.put(name, field); | |
331 } | |
332 } | |
333 } | |
334 // no fields | |
335 if (fields.isEmpty()) { | |
336 return; | |
337 } | |
338 // prepare environment | |
339 String indent = utils.getIndent(1); | |
340 String indent2 = utils.getIndent(2); | |
341 String eol = utils.getEndOfLine(); | |
342 // fromJson(Map) | |
343 { | |
344 ConstructorDeclaration existing = classDeclaration.getConstructor("fromJ
son"); | |
345 int offset = existing != null ? existing.getOffset() | |
346 : classDeclaration.getRightBracket().getOffset(); | |
347 SourceBuilder builder = new SourceBuilder(offset); | |
348 if (existing == null) { | |
349 builder.append(eol); | |
350 builder.append(indent); | |
351 } | |
352 builder.append(classDeclaration.getName().getName()); | |
353 builder.append(".fromJson(Map json) {"); | |
354 builder.append(eol); | |
355 for (Entry<String, FieldElement> entry : fields.entrySet()) { | |
356 String name = entry.getKey(); | |
357 builder.append(indent2); | |
358 builder.append(name); | |
359 builder.append(" = json['"); | |
360 builder.append(name); | |
361 builder.append("'];"); | |
362 builder.append(eol); | |
363 } | |
364 builder.append(indent); | |
365 builder.append("}"); | |
366 if (existing == null) { | |
367 builder.append(eol); | |
368 } | |
369 // add/replace | |
370 if (existing == null) { | |
371 addInsertEdit(builder); | |
372 } else { | |
373 addReplaceEdit(rangeNode(existing), builder); | |
374 } | |
375 } | |
376 // toJson() | |
377 { | |
378 MethodDeclaration existing = classDeclaration.getMethod("toJson"); | |
379 int offset = existing != null ? existing.getOffset() | |
380 : classDeclaration.getRightBracket().getOffset(); | |
381 SourceBuilder builder = new SourceBuilder(offset); | |
382 if (existing == null) { | |
383 builder.append(eol); | |
384 builder.append(indent); | |
385 } | |
386 builder.append("Map toJson() {"); | |
387 builder.append(eol); | |
388 builder.append(indent2); | |
389 builder.append("return {"); | |
390 boolean isFirst = true; | |
391 for (Entry<String, FieldElement> entry : fields.entrySet()) { | |
392 String name = entry.getKey(); | |
393 if (!isFirst) { | |
394 builder.append(", "); | |
395 } | |
396 isFirst = false; | |
397 builder.append("'"); | |
398 builder.append(name); | |
399 builder.append("' : "); | |
400 builder.append(name); | |
401 } | |
402 builder.append("};"); | |
403 builder.append(eol); | |
404 builder.append(indent); | |
405 builder.append("}"); | |
406 if (existing == null) { | |
407 builder.append(eol); | |
408 } | |
409 // add/replace | |
410 if (existing == null) { | |
411 addInsertEdit(builder); | |
412 } else { | |
413 addReplaceEdit(rangeNode(existing), builder); | |
414 } | |
415 } | |
416 // add proposal | |
417 addUnitCorrectionProposal(QA_ADD_JSON); | |
418 } | |
419 } | |
420 | |
421 void addProposal_addTypeAnnotation() throws Exception { | 291 void addProposal_addTypeAnnotation() throws Exception { |
422 // prepare VariableDeclarationList | 292 // prepare VariableDeclarationList |
423 VariableDeclarationList declarationList = node.getAncestor(VariableDeclarati
onList.class); | 293 VariableDeclarationList declarationList = node.getAncestor(VariableDeclarati
onList.class); |
424 if (declarationList == null) { | 294 if (declarationList == null) { |
425 return; | 295 return; |
426 } | 296 } |
427 // may be has type annotation already | 297 // may be has type annotation already |
428 if (declarationList.getType() != null) { | 298 if (declarationList.getType() != null) { |
429 return; | 299 return; |
430 } | 300 } |
(...skipping 1294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1725 /** | 1595 /** |
1726 * Adds {@link Edit} which removes source in the given {@link SourceRange}. | 1596 * Adds {@link Edit} which removes source in the given {@link SourceRange}. |
1727 */ | 1597 */ |
1728 private void addRemoveEdit(SourceRange range) { | 1598 private void addRemoveEdit(SourceRange range) { |
1729 addReplaceEdit(range, ""); | 1599 addReplaceEdit(range, ""); |
1730 } | 1600 } |
1731 | 1601 |
1732 /** | 1602 /** |
1733 * Adds {@link Edit} to {@link #textEdits}. | 1603 * Adds {@link Edit} to {@link #textEdits}. |
1734 */ | 1604 */ |
1735 private void addReplaceEdit(SourceRange range, SourceBuilder builder) { | |
1736 String text = builder.toString(); | |
1737 textEdits.add(createReplaceEdit(range, text)); | |
1738 } | |
1739 | |
1740 /** | |
1741 * Adds {@link Edit} to {@link #textEdits}. | |
1742 */ | |
1743 private void addReplaceEdit(SourceRange range, String text) { | 1605 private void addReplaceEdit(SourceRange range, String text) { |
1744 textEdits.add(createReplaceEdit(range, text)); | 1606 textEdits.add(createReplaceEdit(range, text)); |
1745 } | 1607 } |
1746 | 1608 |
1747 /** | 1609 /** |
1748 * Adds {@link CorrectionProposal} with single {@link SourceChange} to {@link
#proposals}. | 1610 * Adds {@link CorrectionProposal} with single {@link SourceChange} to {@link
#proposals}. |
1749 */ | 1611 */ |
1750 private void addUnitCorrectionProposal(CorrectionKind kind, Object... argument
s) { | 1612 private void addUnitCorrectionProposal(CorrectionKind kind, Object... argument
s) { |
1751 if (!textEdits.isEmpty()) { | 1613 if (!textEdits.isEmpty()) { |
1752 // prepare SourceChange | 1614 // prepare SourceChange |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1874 } | 1736 } |
1875 | 1737 |
1876 private void resetProposalElements() { | 1738 private void resetProposalElements() { |
1877 textEdits.clear(); | 1739 textEdits.clear(); |
1878 linkedPositions.clear(); | 1740 linkedPositions.clear(); |
1879 positionStopEdits.clear(); | 1741 positionStopEdits.clear(); |
1880 linkedPositionProposals.clear(); | 1742 linkedPositionProposals.clear(); |
1881 proposalEndRange = null; | 1743 proposalEndRange = null; |
1882 } | 1744 } |
1883 } | 1745 } |
OLD | NEW |