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

Side by Side Diff: pkg/analysis_server/lib/src/services/completion/dart/inherited_contributor.dart

Issue 1467023002: step toward new completion API (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: address comments and merge Created 5 years 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
OLDNEW
(Empty)
1 // Copyright (c) 2015, 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 library services.completion.computer.dart.invocation;
6
7 import 'dart:async';
8
9 import 'package:analysis_server/src/protocol_server.dart'
10 show CompletionSuggestion, CompletionSuggestionKind, SourceChange;
11 import 'package:analysis_server/src/protocol_server.dart' as protocol
12 hide CompletionSuggestion, CompletionSuggestionKind;
13 import 'package:analysis_server/src/provisional/completion/completion_core.dart' ;
14 import 'package:analysis_server/src/provisional/completion/completion_dart.dart' ;
15 import 'package:analysis_server/src/provisional/completion/dart/completion_targe t.dart';
16 import 'package:analysis_server/src/services/completion/dart_completion_manager. dart'
17 show DART_RELEVANCE_HIGH;
18 import 'package:analyzer/src/generated/ast.dart';
19 import 'package:analyzer/src/generated/element.dart';
20 import 'package:analyzer/src/generated/resolver.dart';
21 import 'package:analyzer/src/generated/source.dart';
22 // import 'package:analysis_server/plugin/edit/utilities/change_builder_dart.dar t';
23 // import 'package:analyzer/src/generated/engine.dart';
24
25 /**
26 * A completion contributor used to suggest replacing partial identifiers inside
27 * a class declaration with templates for inherited members.
28 */
29 class InheritedContributor implements DartCompletionContributor {
30 @override
31 Future<List<CompletionSuggestion>> computeSuggestions(
32 DartCompletionRequest request) async {
33 // Determine if the target looks like a partial identifier
34 // inside a class declaration
35 SimpleIdentifier targetId = _getTargetId(request.target);
36 if (targetId == null) {
37 return EMPTY_LIST;
38 }
39
40 // Partially resolve the compilation unit
41 CompilationUnit unit = await request.resolveDeclarationsInScope();
42 // Gracefully degrade if the compilation unit could not be resolved
43 // e.g. detached part file or source change
44 if (unit == null) {
45 return EMPTY_LIST;
46 }
47
48 // Recompute the target since resolution may have changed it
49 targetId = _getTargetId(request.target);
50 if (targetId == null) {
51 return EMPTY_LIST;
52 }
53 ClassDeclaration classDecl =
54 targetId.getAncestor((p) => p is ClassDeclaration);
55 if (classDecl == null) {
56 return EMPTY_LIST;
57 }
58
59 // Generate a collection of inherited members
60 ClassElement classElem = classDecl.element;
61 InheritanceManager manager = new InheritanceManager(classElem.library);
62 MemberMap map = manager.getMapOfMembersInheritedFromInterfaces(classElem);
63 List<String> memberNames = _computeMemberNames(map, classElem);
64
65 // Build suggestions
66 List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
67 for (String memberName in memberNames) {
68 ExecutableElement element = map.get(memberName);
69 // Gracefully degrade if the overridden element has not been resolved.
70 if (element.returnType != null) {
71 CompletionSuggestion suggestion =
72 _buildSuggestion(request, targetId, unit, element);
73 if (suggestion != null) {
74 suggestions.add(suggestion);
75 }
76 }
77 }
78 return suggestions;
79 }
80
81 /**
82 * If the target looks like a partial identifier inside a class declaration
83 * then return that identifier, otherwise return `null`.
84 */
85 SimpleIdentifier _getTargetId(CompletionTarget target) {
86 AstNode node = target.containingNode;
87 if (node is ClassDeclaration) {
88 Object entity = target.entity;
89 if (entity is FieldDeclaration) {
90 NodeList<VariableDeclaration> variables = entity.fields.variables;
91 if (variables.length == 1) {
92 SimpleIdentifier targetId = variables[0].name;
93 if (targetId.name.isEmpty) {
94 return targetId;
95 }
96 }
97 }
98 }
99 return null;
100 }
101
102 /**
103 * Return a template for an override of the given [element] in the given
104 * [source]. If selected, the template will replace [targetId].
105 */
106 String _buildRepacementText(Source source, SimpleIdentifier targetId,
107 CompilationUnit unit, ExecutableElement element) {
108 // AnalysisContext context = element.context;
109 // Inject partially resolved unit for use by change builder
110 // DartChangeBuilder builder = new DartChangeBuilder(context, unit);
111 // builder.addFileEdit(source, context.getModificationStamp(source),
112 // (DartFileEditBuilder builder) {
113 // builder.addReplacement(targetId.offset, targetId.length,
114 // (DartEditBuilder builder) {
115 // builder.writeOverrideOfInheritedMember(element);
116 // });
117 // });
118 // return builder.sourceChange.edits[0].edits[0].replacement.trim();
119 return '';
120 }
121
122 /**
123 * Build a suggestion to replace [targetId] in the given [unit]
124 * with an override of the given [element].
125 */
126 CompletionSuggestion _buildSuggestion(
127 DartCompletionRequest request,
128 SimpleIdentifier targetId,
129 CompilationUnit unit,
130 ExecutableElement element) {
131 String completion =
132 _buildRepacementText(request.source, targetId, unit, element);
133 if (completion == null || completion.length == 0) {
134 return null;
135 }
136 CompletionSuggestion suggestion = new CompletionSuggestion(
137 CompletionSuggestionKind.IDENTIFIER,
138 DART_RELEVANCE_HIGH,
139 completion,
140 targetId.offset,
141 0,
142 element.isDeprecated,
143 false);
144 suggestion.element = protocol.convertElement(element);
145 return suggestion;
146 }
147
148 /**
149 * Return a list containing the names of all of the inherited but not
150 * implemented members of the class represented by the given [element].
151 * The [map] is used to find all of the members that are inherited.
152 */
153 List<String> _computeMemberNames(MemberMap map, ClassElement element) {
154 List<String> memberNames = <String>[];
155 int count = map.size;
156 for (int i = 0; i < count; i++) {
157 String memberName = map.getKey(i);
158 if (!_hasMember(element, memberName)) {
159 memberNames.add(memberName);
160 }
161 }
162 return memberNames;
163 }
164
165 /**
166 * Return `true` if the given [classElement] directly declares a member with
167 * the given [memberName].
168 */
169 bool _hasMember(ClassElement classElement, String memberName) {
170 return classElement.getField(memberName) != null ||
171 classElement.getGetter(memberName) != null ||
172 classElement.getMethod(memberName) != null ||
173 classElement.getSetter(memberName) != null;
174 }
175 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698