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

Side by Side Diff: pkg/analysis_server/lib/src/services/correction/util.dart

Issue 706263003: Issue 20827. Add imports as needed the 'Add type annotation' Quick Assist. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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 library services.src.correction.util; 5 library services.src.correction.util;
6 6
7 import 'dart:math'; 7 import 'dart:math';
8 8
9 import 'package:analysis_server/src/protocol.dart' show SourceChange, 9 import 'package:analysis_server/src/protocol.dart' show SourceChange,
10 SourceEdit; 10 SourceEdit;
11 import 'package:analysis_server/src/services/correction/source_range.dart'; 11 import 'package:analysis_server/src/services/correction/source_range.dart';
12 import 'package:analysis_server/src/services/correction/strings.dart'; 12 import 'package:analysis_server/src/services/correction/strings.dart';
13 import 'package:analyzer/src/generated/ast.dart'; 13 import 'package:analyzer/src/generated/ast.dart';
14 import 'package:analyzer/src/generated/element.dart'; 14 import 'package:analyzer/src/generated/element.dart';
15 import 'package:analyzer/src/generated/engine.dart'; 15 import 'package:analyzer/src/generated/engine.dart';
16 import 'package:analyzer/src/generated/resolver.dart'; 16 import 'package:analyzer/src/generated/resolver.dart';
17 import 'package:analyzer/src/generated/scanner.dart'; 17 import 'package:analyzer/src/generated/scanner.dart';
18 import 'package:analyzer/src/generated/source.dart'; 18 import 'package:analyzer/src/generated/source.dart';
19 import 'package:path/path.dart';
19 20
20 21
21 /** 22 /**
22 * @return <code>true</code> if given [List]s are identical at given position. 23 * @return <code>true</code> if given [List]s are identical at given position.
23 */ 24 */
24 bool allListsIdentical(List<List> lists, int position) { 25 bool allListsIdentical(List<List> lists, int position) {
25 Object element = lists[0][position]; 26 Object element = lists[0][position];
26 for (List list in lists) { 27 for (List list in lists) {
27 if (list[position] != element) { 28 if (list[position] != element) {
28 return false; 29 return false;
(...skipping 16 matching lines...) Expand all
45 if (parent is PropertyAccess && parent.propertyName == node) { 46 if (parent is PropertyAccess && parent.propertyName == node) {
46 node = parent; 47 node = parent;
47 continue; 48 continue;
48 } 49 }
49 return node; 50 return node;
50 } 51 }
51 } 52 }
52 53
53 54
54 /** 55 /**
56 * Attempts to convert the given absolute path into an absolute URI, such as
57 * "dart" or "package" URI.
58 *
59 * [context] - the [AnalysisContext] to work in.
60 * [path] - the absolute path, not `null`.
61 *
62 * Returns the absolute (non-file) URI or `null`.
63 */
64 String findAbsoluteUri(AnalysisContext context, String path) {
65 Source fileSource = new NonExistingSource(path, UriKind.FILE_URI);
66 Uri uri = context.sourceFactory.restoreUri(fileSource);
67 if (uri == null) {
68 return null;
69 }
70 return uri.toString();
71 }
72
73
74 /**
55 * TODO(scheglov) replace with nodes once there will be [CompilationUnit#getComm ents]. 75 * TODO(scheglov) replace with nodes once there will be [CompilationUnit#getComm ents].
56 * 76 *
57 * Returns [SourceRange]s of all comments in [unit]. 77 * Returns [SourceRange]s of all comments in [unit].
58 */ 78 */
59 List<SourceRange> getCommentRanges(CompilationUnit unit) { 79 List<SourceRange> getCommentRanges(CompilationUnit unit) {
60 List<SourceRange> ranges = <SourceRange>[]; 80 List<SourceRange> ranges = <SourceRange>[];
61 Token token = unit.beginToken; 81 Token token = unit.beginToken;
62 while (token != null && token.type != TokenType.EOF) { 82 while (token != null && token.type != TokenType.EOF) {
63 Token commentToken = token.precedingComments; 83 Token commentToken = token.precedingComments;
64 while (commentToken != null) { 84 while (commentToken != null) {
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 /** 235 /**
216 * Returns the namespace of the given [ImportElement]. 236 * Returns the namespace of the given [ImportElement].
217 */ 237 */
218 Map<String, Element> getImportNamespace(ImportElement imp) { 238 Map<String, Element> getImportNamespace(ImportElement imp) {
219 NamespaceBuilder builder = new NamespaceBuilder(); 239 NamespaceBuilder builder = new NamespaceBuilder();
220 Namespace namespace = builder.createImportNamespaceForDirective(imp); 240 Namespace namespace = builder.createImportNamespaceForDirective(imp);
221 return namespace.definedNames; 241 return namespace.definedNames;
222 } 242 }
223 243
224 /** 244 /**
245 * Computes the best URI to import [what] into [from].
246 */
247 String getLibrarySourceUri(LibraryElement from, Source what) {
248 String whatFile = what.fullName;
249 // check if an absolute URI (such as 'dart:' or 'package:')
250 Uri whatUri = what.uri;
251 String whatUriScheme = whatUri.scheme;
252 if (whatUriScheme != '' && whatUriScheme != 'file') {
253 return whatUri.toString();
254 }
255 // compute a relative URI
256 String fromFolder = dirname(from.source.fullName);
257 String relativeFile = relative(whatFile, from: fromFolder);
258 return split(relativeFile).join('/');
259 }
260
261 /**
225 * Returns the line prefix from the given source, i.e. basically just a 262 * Returns the line prefix from the given source, i.e. basically just a
226 * whitespace prefix of the given [String]. 263 * whitespace prefix of the given [String].
227 */ 264 */
228 String getLinePrefix(String line) { 265 String getLinePrefix(String line) {
229 int index = 0; 266 int index = 0;
230 while (index < line.length) { 267 while (index < line.length) {
231 int c = line.codeUnitAt(index); 268 int c = line.codeUnitAt(index);
232 if (!isWhitespace(c)) { 269 if (!isWhitespace(c)) {
233 break; 270 break;
234 } 271 }
235 index++; 272 index++;
236 } 273 }
237 return line.substring(0, index); 274 return line.substring(0, index);
238 } 275 }
239 276
277
240 /** 278 /**
241 * @return the [LocalVariableElement] or [ParameterElement] if given 279 * @return the [LocalVariableElement] or [ParameterElement] if given
242 * [SimpleIdentifier] is the reference to local variable or parameter, o r 280 * [SimpleIdentifier] is the reference to local variable or parameter, o r
243 * <code>null</code> in the other case. 281 * <code>null</code> in the other case.
244 */ 282 */
245 VariableElement getLocalOrParameterVariableElement(SimpleIdentifier node) { 283 VariableElement getLocalOrParameterVariableElement(SimpleIdentifier node) {
246 Element element = node.staticElement; 284 Element element = node.staticElement;
247 if (element is LocalVariableElement) { 285 if (element is LocalVariableElement) {
248 return element; 286 return element;
249 } 287 }
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 } 421 }
384 if (parent is PropertyAccess) { 422 if (parent is PropertyAccess) {
385 PropertyAccess access = parent; 423 PropertyAccess access = parent;
386 if (access.propertyName == node) { 424 if (access.propertyName == node) {
387 return access.realTarget; 425 return access.realTarget;
388 } 426 }
389 } 427 }
390 return null; 428 return null;
391 } 429 }
392 430
393
394 /** 431 /**
395 * Returns the given [Statement] if not a [Block], or the first child 432 * Returns the given [Statement] if not a [Block], or the first child
396 * [Statement] if a [Block], or `null` if more than one child. 433 * [Statement] if a [Block], or `null` if more than one child.
397 */ 434 */
398 Statement getSingleStatement(Statement statement) { 435 Statement getSingleStatement(Statement statement) {
399 if (statement is Block) { 436 if (statement is Block) {
400 List<Statement> blockStatements = statement.statements; 437 List<Statement> blockStatements = statement.statements;
401 if (blockStatements.length != 1) { 438 if (blockStatements.length != 1) {
402 return null; 439 return null;
403 } 440 }
404 return blockStatements[0]; 441 return blockStatements[0];
405 } 442 }
406 return statement; 443 return statement;
407 } 444 }
408 445
446
409 /** 447 /**
410 * Returns the [String] content of the given [Source]. 448 * Returns the [String] content of the given [Source].
411 */ 449 */
412 String getSourceContent(AnalysisContext context, Source source) { 450 String getSourceContent(AnalysisContext context, Source source) {
413 return context.getContents(source).data; 451 return context.getContents(source).data;
414 } 452 }
415 453
416 454
417 /** 455 /**
418 * Returns the given [Statement] if not a [Block], or all the children 456 * Returns the given [Statement] if not a [Block], or all the children
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 /** 572 /**
535 * Returns the [AstNode] that encloses the given offset. 573 * Returns the [AstNode] that encloses the given offset.
536 */ 574 */
537 AstNode findNode(int offset) => 575 AstNode findNode(int offset) =>
538 new NodeLocator.con1(offset).searchWithin(unit); 576 new NodeLocator.con1(offset).searchWithin(unit);
539 577
540 /** 578 /**
541 * Returns the actual type source of the given [Expression], may be `null` 579 * Returns the actual type source of the given [Expression], may be `null`
542 * if can not be resolved, should be treated as the `dynamic` type. 580 * if can not be resolved, should be treated as the `dynamic` type.
543 */ 581 */
544 String getExpressionTypeSource(Expression expression) { 582 String getExpressionTypeSource(Expression expression,
583 Set<LibraryElement> librariesToImport) {
545 if (expression == null) { 584 if (expression == null) {
546 return null; 585 return null;
547 } 586 }
548 DartType type = expression.bestType; 587 DartType type = expression.bestType;
549 if (type.isDynamic) { 588 if (type.isDynamic) {
550 return null; 589 return null;
551 } 590 }
552 return getTypeSource(type); 591 return getTypeSource(type, librariesToImport);
553 } 592 }
554 593
555 /** 594 /**
556 * Returns the indentation with the given level. 595 * Returns the indentation with the given level.
557 */ 596 */
558 String getIndent(int level) => repeat(' ', level); 597 String getIndent(int level) => repeat(' ', level);
559 598
560 /** 599 /**
561 * Returns a [InsertDesc] describing where to insert a new library-related 600 * Returns a [InsertDesc] describing where to insert a new library-related
562 * directive. 601 * directive.
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
818 /** 857 /**
819 * Returns the text of the given [AstNode] in the unit. 858 * Returns the text of the given [AstNode] in the unit.
820 */ 859 */
821 String getNodeText(AstNode node) { 860 String getNodeText(AstNode node) {
822 return getText(node.offset, node.length); 861 return getText(node.offset, node.length);
823 } 862 }
824 863
825 /** 864 /**
826 * @return the source for the parameter with the given type and name. 865 * @return the source for the parameter with the given type and name.
827 */ 866 */
828 String getParameterSource(DartType type, String name) { 867 String getParameterSource(DartType type, String name,
868 Set<LibraryElement> librariesToImport) {
829 // no type 869 // no type
830 if (type == null || type.isDynamic) { 870 if (type == null || type.isDynamic) {
831 return name; 871 return name;
832 } 872 }
833 // function type 873 // function type
834 if (type is FunctionType) { 874 if (type is FunctionType) {
835 FunctionType functionType = type; 875 FunctionType functionType = type;
836 StringBuffer sb = new StringBuffer(); 876 StringBuffer sb = new StringBuffer();
837 // return type 877 // return type
838 DartType returnType = functionType.returnType; 878 DartType returnType = functionType.returnType;
839 if (returnType != null && !returnType.isDynamic) { 879 if (returnType != null && !returnType.isDynamic) {
840 sb.write(getTypeSource(returnType)); 880 sb.write(getTypeSource(returnType, librariesToImport));
841 sb.write(' '); 881 sb.write(' ');
842 } 882 }
843 // parameter name 883 // parameter name
844 sb.write(name); 884 sb.write(name);
845 // parameters 885 // parameters
846 sb.write('('); 886 sb.write('(');
847 List<ParameterElement> fParameters = functionType.parameters; 887 List<ParameterElement> fParameters = functionType.parameters;
848 for (int i = 0; i < fParameters.length; i++) { 888 for (int i = 0; i < fParameters.length; i++) {
849 ParameterElement fParameter = fParameters[i]; 889 ParameterElement fParameter = fParameters[i];
850 if (i != 0) { 890 if (i != 0) {
851 sb.write(", "); 891 sb.write(", ");
852 } 892 }
853 sb.write(getParameterSource(fParameter.type, fParameter.name)); 893 sb.write(
894 getParameterSource(fParameter.type, fParameter.name, librariesToImpo rt));
854 } 895 }
855 sb.write(')'); 896 sb.write(')');
856 // done 897 // done
857 return sb.toString(); 898 return sb.toString();
858 } 899 }
859 // simple type 900 // simple type
860 return "${getTypeSource(type)} ${name}"; 901 String typeSource = getTypeSource(type, librariesToImport);
902 return '$typeSource $name';
861 } 903 }
862 904
863 /** 905 /**
864 * Returns the line prefix consisting of spaces and tabs on the left from the 906 * Returns the line prefix consisting of spaces and tabs on the left from the
865 * given offset. 907 * given offset.
866 */ 908 */
867 String getPrefix(int endIndex) { 909 String getPrefix(int endIndex) {
868 int startIndex = getLineContentStart(endIndex); 910 int startIndex = getLineContentStart(endIndex);
869 return _buffer.substring(startIndex, endIndex); 911 return _buffer.substring(startIndex, endIndex);
870 } 912 }
871 913
872 /** 914 /**
873 * Returns the text of the given range in the unit. 915 * Returns the text of the given range in the unit.
874 */ 916 */
875 String getRangeText(SourceRange range) { 917 String getRangeText(SourceRange range) {
876 return getText(range.offset, range.length); 918 return getText(range.offset, range.length);
877 } 919 }
878 920
879 /** 921 /**
880 * Returns the text of the given range in the unit. 922 * Returns the text of the given range in the unit.
881 */ 923 */
882 String getText(int offset, int length) { 924 String getText(int offset, int length) {
883 return _buffer.substring(offset, offset + length); 925 return _buffer.substring(offset, offset + length);
884 } 926 }
885 927
886 /** 928 /**
887 * Returns the source to reference [type] in this [CompilationUnit]. 929 * Returns the source to reference [type] in this [CompilationUnit].
930 *
931 * Fills [librariesToImport] with [LibraryElement]s whose elements are
932 * used by the generated source, but not imported.
888 */ 933 */
889 String getTypeSource(DartType type) { 934 String getTypeSource(DartType type, Set<LibraryElement> librariesToImport) {
890 StringBuffer sb = new StringBuffer(); 935 StringBuffer sb = new StringBuffer();
891 // just a Function, not FunctionTypeAliasElement 936 // just a Function, not FunctionTypeAliasElement
892 if (type is FunctionType && type.element is! FunctionTypeAliasElement) { 937 if (type is FunctionType && type.element is! FunctionTypeAliasElement) {
893 return "Function"; 938 return "Function";
894 } 939 }
895 // prepare element 940 // prepare element
896 Element element = type.element; 941 Element element = type.element;
897 if (element == null) { 942 if (element == null) {
898 String source = type.toString(); 943 String source = type.toString();
899 source = source.replaceAll('<dynamic>', ''); 944 source = source.replaceAll('<dynamic>', '');
900 source = source.replaceAll('<dynamic, dynamic>', ''); 945 source = source.replaceAll('<dynamic, dynamic>', '');
901 return source; 946 return source;
902 } 947 }
903 // append prefix 948 // check if imported
904 { 949 {
905 ImportElement imp = _getImportElement(element); 950 ImportElement importElement = _getImportElement(element);
906 if (imp != null && imp.prefix != null) { 951 if (importElement != null) {
907 sb.write(imp.prefix.displayName); 952 if (importElement.prefix != null) {
908 sb.write("."); 953 sb.write(importElement.prefix.displayName);
954 sb.write(".");
955 }
956 } else {
957 librariesToImport.add(element.library);
909 } 958 }
910 } 959 }
911 // append simple name 960 // append simple name
912 String name = element.displayName; 961 String name = element.displayName;
913 sb.write(name); 962 sb.write(name);
914 // may be type arguments 963 // may be type arguments
915 if (type is ParameterizedType) { 964 if (type is ParameterizedType) {
916 List<DartType> arguments = type.typeArguments; 965 List<DartType> arguments = type.typeArguments;
917 // check if has arguments 966 // check if has arguments
918 bool hasArguments = false; 967 bool hasArguments = false;
919 for (DartType argument in arguments) { 968 for (DartType argument in arguments) {
920 if (!argument.isDynamic) { 969 if (!argument.isDynamic) {
921 hasArguments = true; 970 hasArguments = true;
922 break; 971 break;
923 } 972 }
924 } 973 }
925 // append type arguments 974 // append type arguments
926 if (hasArguments) { 975 if (hasArguments) {
927 sb.write("<"); 976 sb.write("<");
928 for (int i = 0; i < arguments.length; i++) { 977 for (int i = 0; i < arguments.length; i++) {
929 DartType argument = arguments[i]; 978 DartType argument = arguments[i];
930 if (i != 0) { 979 if (i != 0) {
931 sb.write(", "); 980 sb.write(", ");
932 } 981 }
933 sb.write(getTypeSource(argument)); 982 String argumentSrc = getTypeSource(argument, librariesToImport);
983 sb.write(argumentSrc);
934 } 984 }
935 sb.write(">"); 985 sb.write(">");
936 } 986 }
937 } 987 }
938 // done 988 // done
939 return sb.toString(); 989 return sb.toString();
940 } 990 }
941 991
942 /** 992 /**
943 * Indents given source left or right. 993 * Indents given source left or right.
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after
1400 1450
1401 @override 1451 @override
1402 Object visitExpression(Expression node) { 1452 Object visitExpression(Expression node) {
1403 if (node is BinaryExpression && node.operator.type == groupOperatorType) { 1453 if (node is BinaryExpression && node.operator.type == groupOperatorType) {
1404 return super.visitNode(node); 1454 return super.visitNode(node);
1405 } 1455 }
1406 operands.add(node); 1456 operands.add(node);
1407 return null; 1457 return null;
1408 } 1458 }
1409 } 1459 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698