| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 /** |
| 6 * A collection of utility methods used by completion contributors. |
| 7 */ |
| 8 import 'package:analysis_server/plugin/protocol/protocol.dart' as protocol |
| 9 show Element, ElementKind; |
| 10 import 'package:analysis_server/src/protocol_server.dart' |
| 11 show CompletionSuggestion, CompletionSuggestionKind, Location; |
| 12 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.
dart'; |
| 13 import 'package:analyzer/dart/ast/ast.dart'; |
| 14 import 'package:analyzer/dart/ast/standard_ast_factory.dart'; |
| 15 import 'package:analyzer/dart/ast/token.dart'; |
| 16 import 'package:analyzer/src/dart/ast/token.dart'; |
| 17 import 'package:analyzer/src/generated/source.dart'; |
| 18 |
| 19 /** |
| 20 * The name of the type `dynamic`; |
| 21 */ |
| 22 const DYNAMIC = 'dynamic'; |
| 23 |
| 24 /** |
| 25 * A marker used in place of `null` when a function has no return type. |
| 26 */ |
| 27 final TypeName NO_RETURN_TYPE = astFactory.typeName( |
| 28 astFactory.simpleIdentifier(new StringToken(TokenType.IDENTIFIER, '', 0)), |
| 29 null); |
| 30 |
| 31 /** |
| 32 * Create a new protocol Element for inclusion in a completion suggestion. |
| 33 */ |
| 34 protocol.Element createLocalElement( |
| 35 Source source, protocol.ElementKind kind, SimpleIdentifier id, |
| 36 {String parameters, |
| 37 TypeName returnType, |
| 38 bool isAbstract: false, |
| 39 bool isDeprecated: false}) { |
| 40 String name; |
| 41 Location location; |
| 42 if (id != null) { |
| 43 name = id.name; |
| 44 // TODO(danrubel) use lineInfo to determine startLine and startColumn |
| 45 location = new Location(source.fullName, id.offset, id.length, 0, 0); |
| 46 } else { |
| 47 name = ''; |
| 48 location = new Location(source.fullName, -1, 0, 1, 0); |
| 49 } |
| 50 int flags = protocol.Element.makeFlags( |
| 51 isAbstract: isAbstract, |
| 52 isDeprecated: isDeprecated, |
| 53 isPrivate: Identifier.isPrivateName(name)); |
| 54 return new protocol.Element(kind, name, flags, |
| 55 location: location, |
| 56 parameters: parameters, |
| 57 returnType: nameForType(returnType)); |
| 58 } |
| 59 |
| 60 /** |
| 61 * Create a new suggestion for the given [fieldDecl]. Return the new suggestion |
| 62 * or `null` if it could not be created. |
| 63 */ |
| 64 CompletionSuggestion createLocalFieldSuggestion( |
| 65 Source source, FieldDeclaration fieldDecl, VariableDeclaration varDecl) { |
| 66 bool deprecated = isDeprecated(fieldDecl) || isDeprecated(varDecl); |
| 67 TypeName type = fieldDecl.fields.type; |
| 68 return createLocalSuggestion( |
| 69 varDecl.name, deprecated, DART_RELEVANCE_LOCAL_FIELD, type, |
| 70 classDecl: fieldDecl.parent, |
| 71 element: createLocalElement( |
| 72 source, protocol.ElementKind.FIELD, varDecl.name, |
| 73 returnType: type, isDeprecated: deprecated)); |
| 74 } |
| 75 |
| 76 /** |
| 77 * Create a new suggestion based upon the given information. Return the new |
| 78 * suggestion or `null` if it could not be created. |
| 79 */ |
| 80 CompletionSuggestion createLocalSuggestion(SimpleIdentifier id, |
| 81 bool isDeprecated, int defaultRelevance, TypeName returnType, |
| 82 {ClassDeclaration classDecl, |
| 83 CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION, |
| 84 protocol.Element element}) { |
| 85 if (id == null) { |
| 86 return null; |
| 87 } |
| 88 String completion = id.name; |
| 89 if (completion == null || completion.length <= 0 || completion == '_') { |
| 90 return null; |
| 91 } |
| 92 CompletionSuggestion suggestion = new CompletionSuggestion( |
| 93 kind, |
| 94 isDeprecated ? DART_RELEVANCE_LOW : defaultRelevance, |
| 95 completion, |
| 96 completion.length, |
| 97 0, |
| 98 isDeprecated, |
| 99 false, |
| 100 returnType: nameForType(returnType), |
| 101 element: element); |
| 102 if (classDecl != null) { |
| 103 SimpleIdentifier classId = classDecl.name; |
| 104 if (classId != null) { |
| 105 String className = classId.name; |
| 106 if (className != null && className.length > 0) { |
| 107 suggestion.declaringType = className; |
| 108 } |
| 109 } |
| 110 } |
| 111 return suggestion; |
| 112 } |
| 113 |
| 114 /** |
| 115 * Return `true` if the @deprecated annotation is present on the given [node]. |
| 116 */ |
| 117 bool isDeprecated(AnnotatedNode node) { |
| 118 if (node != null) { |
| 119 NodeList<Annotation> metadata = node.metadata; |
| 120 if (metadata != null) { |
| 121 return metadata.any((Annotation a) { |
| 122 return a.name is SimpleIdentifier && a.name.name == 'deprecated'; |
| 123 }); |
| 124 } |
| 125 } |
| 126 return false; |
| 127 } |
| 128 |
| 129 /** |
| 130 * Return the name for the given [type]. |
| 131 */ |
| 132 String nameForType(TypeName type) { |
| 133 if (type == NO_RETURN_TYPE) { |
| 134 return null; |
| 135 } |
| 136 if (type == null) { |
| 137 return DYNAMIC; |
| 138 } |
| 139 Identifier id = type.name; |
| 140 if (id == null) { |
| 141 return DYNAMIC; |
| 142 } |
| 143 String name = id.name; |
| 144 if (name == null || name.length <= 0) { |
| 145 return DYNAMIC; |
| 146 } |
| 147 TypeArgumentList typeArgs = type.typeArguments; |
| 148 if (typeArgs != null) { |
| 149 //TODO (danrubel) include type arguments |
| 150 } |
| 151 return name; |
| 152 } |
| OLD | NEW |