OLD | NEW |
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 protocol; | 5 library protocol; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 import 'dart:convert'; | 8 import 'dart:convert'; |
9 | 9 |
10 import 'package:analysis_server/src/computer/element.dart' show | 10 import 'json.dart'; |
11 elementFromEngine; | |
12 import 'package:analysis_server/src/search/search_result.dart' show | |
13 searchResultFromMatch; | |
14 import 'package:analysis_server/src/services/correction/fix.dart' show Fix; | |
15 import 'package:analysis_server/src/services/json.dart'; | |
16 import 'package:analysis_server/src/services/search/search_engine.dart' as | |
17 engine; | |
18 import 'package:analyzer/src/generated/ast.dart' as engine; | |
19 import 'package:analyzer/src/generated/element.dart' as engine; | |
20 import 'package:analyzer/src/generated/engine.dart' as engine; | |
21 import 'package:analyzer/src/generated/error.dart' as engine; | |
22 import 'package:analyzer/src/generated/source.dart' as engine; | |
23 | 11 |
24 part 'generated_protocol.dart'; | 12 part 'generated_protocol.dart'; |
25 | 13 |
26 | 14 |
27 final Map<String, RefactoringKind> REQUEST_ID_REFACTORING_KINDS = | 15 final Map<String, RefactoringKind> REQUEST_ID_REFACTORING_KINDS = |
28 new HashMap<String, RefactoringKind>(); | 16 new HashMap<String, RefactoringKind>(); |
29 | 17 |
30 /** | 18 /** |
31 * Translate the input [map], applying [keyCallback] to all its keys, and | 19 * Translate the input [map], applying [keyCallback] to all its keys, and |
32 * [valueCallback] to all its values. | 20 * [valueCallback] to all its values. |
(...skipping 29 matching lines...) Expand all Loading... |
62 while (index < edits.length && edits[index].offset > sourceEdit.offset) { | 50 while (index < edits.length && edits[index].offset > sourceEdit.offset) { |
63 index++; | 51 index++; |
64 } | 52 } |
65 edits.insert(index, sourceEdit); | 53 edits.insert(index, sourceEdit); |
66 } | 54 } |
67 | 55 |
68 /** | 56 /** |
69 * Adds [edit] to the [FileEdit] for the given [file]. | 57 * Adds [edit] to the [FileEdit] for the given [file]. |
70 */ | 58 */ |
71 void _addEditToSourceChange(SourceChange change, String file, int fileStamp, | 59 void _addEditToSourceChange(SourceChange change, String file, int fileStamp, |
72 SourceEdit edit) { | 60 SourceEdit edit) { |
73 SourceFileEdit fileEdit = change.getFileEdit(file); | 61 SourceFileEdit fileEdit = change.getFileEdit(file); |
74 if (fileEdit == null) { | 62 if (fileEdit == null) { |
75 fileEdit = new SourceFileEdit(file, fileStamp); | 63 fileEdit = new SourceFileEdit(file, fileStamp); |
76 change.addFileEdit(fileEdit); | 64 change.addFileEdit(fileEdit); |
77 } | 65 } |
78 fileEdit.add(edit); | 66 fileEdit.add(edit); |
79 } | 67 } |
80 | 68 |
81 | |
82 void _addElementEditToSourceChange(SourceChange change, engine.Element element, | |
83 SourceEdit edit) { | |
84 engine.AnalysisContext context = element.context; | |
85 engine.Source source = element.source; | |
86 _addSourceEditToSourceChange(change, context, source, edit); | |
87 } | |
88 | |
89 | |
90 void _addSourceEditToSourceChange(SourceChange change, | |
91 engine.AnalysisContext context, engine.Source source, SourceEdit edit) { | |
92 String file = source.fullName; | |
93 int fileStamp = context.getModificationStamp(source); | |
94 change.addEdit(file, fileStamp, edit); | |
95 } | |
96 | |
97 /** | |
98 * Create an AnalysisError based on error information from the analyzer | |
99 * engine. Access via AnalysisError.fromEngine(). | |
100 */ | |
101 AnalysisError _analysisErrorFromEngine(engine.LineInfo lineInfo, | |
102 engine.AnalysisError error) { | |
103 engine.ErrorCode errorCode = error.errorCode; | |
104 // prepare location | |
105 Location location; | |
106 { | |
107 String file = error.source.fullName; | |
108 int offset = error.offset; | |
109 int length = error.length; | |
110 int startLine = -1; | |
111 int startColumn = -1; | |
112 if (lineInfo != null) { | |
113 engine.LineInfo_Location lineLocation = lineInfo.getLocation(offset); | |
114 if (lineLocation != null) { | |
115 startLine = lineLocation.lineNumber; | |
116 startColumn = lineLocation.columnNumber; | |
117 } | |
118 } | |
119 location = new Location(file, offset, length, startLine, startColumn); | |
120 } | |
121 // done | |
122 var severity = new AnalysisErrorSeverity(errorCode.errorSeverity.name); | |
123 var type = new AnalysisErrorType(errorCode.type.name); | |
124 String message = error.message; | |
125 String correction = error.correction; | |
126 return new AnalysisError( | |
127 severity, | |
128 type, | |
129 location, | |
130 message, | |
131 correction: correction); | |
132 } | |
133 | |
134 /** | |
135 * Returns a list of AnalysisErrors correponding to the given list of Engine | |
136 * errors. Access via AnalysisError.listFromEngine(). | |
137 */ | |
138 List<AnalysisError> _analysisErrorListFromEngine(engine.LineInfo lineInfo, | |
139 List<engine.AnalysisError> errors) { | |
140 return errors.map((engine.AnalysisError error) { | |
141 return new AnalysisError.fromEngine(lineInfo, error); | |
142 }).toList(); | |
143 } | |
144 | |
145 /** | 69 /** |
146 * Get the result of applying the edit to the given [code]. Access via | 70 * Get the result of applying the edit to the given [code]. Access via |
147 * SourceEdit.apply(). | 71 * SourceEdit.apply(). |
148 */ | 72 */ |
149 String _applyEdit(String code, SourceEdit edit) { | 73 String _applyEdit(String code, SourceEdit edit) { |
150 if (edit.length < 0) { | 74 if (edit.length < 0) { |
151 throw new RangeError('length is negative'); | 75 throw new RangeError('length is negative'); |
152 } | 76 } |
153 return code.substring(0, edit.offset) + | 77 return code.substring(0, edit.offset) + |
154 edit.replacement + | 78 edit.replacement + |
155 code.substring(edit.end); | 79 code.substring(edit.end); |
156 } | 80 } |
157 | 81 |
158 /** | 82 /** |
159 * Get the result of applying a set of [edits] to the given [code]. Edits | 83 * Get the result of applying a set of [edits] to the given [code]. Edits |
160 * are applied in the order they appear in [edits]. Access via | 84 * are applied in the order they appear in [edits]. Access via |
161 * SourceEdit.applySequence(). | 85 * SourceEdit.applySequence(). |
162 */ | 86 */ |
163 String _applySequence(String code, Iterable<SourceEdit> edits) { | 87 String _applySequence(String code, Iterable<SourceEdit> edits) { |
164 edits.forEach((SourceEdit edit) { | 88 edits.forEach((SourceEdit edit) { |
165 code = edit.apply(code); | 89 code = edit.apply(code); |
166 }); | 90 }); |
167 return code; | 91 return code; |
168 } | 92 } |
169 | 93 |
170 /** | 94 /** |
171 * Map an element kind from the analyzer engine to a [CompletionSuggestionKind]. | |
172 */ | |
173 CompletionSuggestionKind _completionSuggestionKindFromElementKind(engine.Element
Kind kind) { | |
174 // ElementKind.ANGULAR_FORMATTER, | |
175 // ElementKind.ANGULAR_COMPONENT, | |
176 // ElementKind.ANGULAR_CONTROLLER, | |
177 // ElementKind.ANGULAR_DIRECTIVE, | |
178 // ElementKind.ANGULAR_PROPERTY, | |
179 // ElementKind.ANGULAR_SCOPE_PROPERTY, | |
180 // ElementKind.ANGULAR_SELECTOR, | |
181 // ElementKind.ANGULAR_VIEW, | |
182 if (kind == engine.ElementKind.CLASS) return CompletionSuggestionKind.CLASS; | |
183 // ElementKind.COMPILATION_UNIT, | |
184 if (kind == engine.ElementKind.CONSTRUCTOR) return CompletionSuggestionKind.CO
NSTRUCTOR; | |
185 // ElementKind.DYNAMIC, | |
186 // ElementKind.EMBEDDED_HTML_SCRIPT, | |
187 // ElementKind.ERROR, | |
188 // ElementKind.EXPORT, | |
189 // ElementKind.EXTERNAL_HTML_SCRIPT, | |
190 if (kind == engine.ElementKind.FIELD) return CompletionSuggestionKind.FIELD; | |
191 if (kind == engine.ElementKind.FUNCTION) return CompletionSuggestionKind.FUNCT
ION; | |
192 if (kind == engine.ElementKind.FUNCTION_TYPE_ALIAS) return CompletionSuggestio
nKind.FUNCTION_TYPE_ALIAS; | |
193 if (kind == engine.ElementKind.GETTER) return CompletionSuggestionKind.GETTER; | |
194 // ElementKind.HTML, | |
195 if (kind == engine.ElementKind.IMPORT) return CompletionSuggestionKind.IMPORT; | |
196 // ElementKind.LABEL, | |
197 // ElementKind.LIBRARY, | |
198 if (kind == engine.ElementKind.LOCAL_VARIABLE) return CompletionSuggestionKind
.LOCAL_VARIABLE; | |
199 if (kind == engine.ElementKind.METHOD) return CompletionSuggestionKind.METHOD; | |
200 // ElementKind.NAME, | |
201 if (kind == engine.ElementKind.PARAMETER) return CompletionSuggestionKind.PARA
METER; | |
202 // ElementKind.POLYMER_ATTRIBUTE, | |
203 // ElementKind.POLYMER_TAG_DART, | |
204 // ElementKind.POLYMER_TAG_HTML, | |
205 // ElementKind.PREFIX, | |
206 if (kind == engine.ElementKind.SETTER) return CompletionSuggestionKind.SETTER; | |
207 if (kind == engine.ElementKind.TOP_LEVEL_VARIABLE) return CompletionSuggestion
Kind.TOP_LEVEL_VARIABLE; | |
208 // ElementKind.TYPE_PARAMETER, | |
209 // ElementKind.UNIVERSE | |
210 throw new ArgumentError('Unknown CompletionSuggestionKind for: $kind'); | |
211 } | |
212 | |
213 /** | |
214 * Create an ElementKind based on a value from the analyzer engine. Access | |
215 * this function via new ElementKind.fromEngine(). | |
216 */ | |
217 ElementKind _elementKindFromEngine(engine.ElementKind kind) { | |
218 if (kind == engine.ElementKind.CLASS) { | |
219 return ElementKind.CLASS; | |
220 } | |
221 if (kind == engine.ElementKind.COMPILATION_UNIT) { | |
222 return ElementKind.COMPILATION_UNIT; | |
223 } | |
224 if (kind == engine.ElementKind.CONSTRUCTOR) { | |
225 return ElementKind.CONSTRUCTOR; | |
226 } | |
227 if (kind == engine.ElementKind.FIELD) { | |
228 return ElementKind.FIELD; | |
229 } | |
230 if (kind == engine.ElementKind.FUNCTION) { | |
231 return ElementKind.FUNCTION; | |
232 } | |
233 if (kind == engine.ElementKind.FUNCTION_TYPE_ALIAS) { | |
234 return ElementKind.FUNCTION_TYPE_ALIAS; | |
235 } | |
236 if (kind == engine.ElementKind.GETTER) { | |
237 return ElementKind.GETTER; | |
238 } | |
239 if (kind == engine.ElementKind.LABEL) { | |
240 return ElementKind.LABEL; | |
241 } | |
242 if (kind == engine.ElementKind.LIBRARY) { | |
243 return ElementKind.LIBRARY; | |
244 } | |
245 if (kind == engine.ElementKind.LOCAL_VARIABLE) { | |
246 return ElementKind.LOCAL_VARIABLE; | |
247 } | |
248 if (kind == engine.ElementKind.METHOD) { | |
249 return ElementKind.METHOD; | |
250 } | |
251 if (kind == engine.ElementKind.PARAMETER) { | |
252 return ElementKind.PARAMETER; | |
253 } | |
254 if (kind == engine.ElementKind.PREFIX) { | |
255 return ElementKind.PREFIX; | |
256 } | |
257 if (kind == engine.ElementKind.SETTER) { | |
258 return ElementKind.SETTER; | |
259 } | |
260 if (kind == engine.ElementKind.TOP_LEVEL_VARIABLE) { | |
261 return ElementKind.TOP_LEVEL_VARIABLE; | |
262 } | |
263 if (kind == engine.ElementKind.TYPE_PARAMETER) { | |
264 return ElementKind.TYPE_PARAMETER; | |
265 } | |
266 return ElementKind.UNKNOWN; | |
267 } | |
268 | |
269 /** | |
270 * Returns the [FileEdit] for the given [file], maybe `null`. | 95 * Returns the [FileEdit] for the given [file], maybe `null`. |
271 */ | 96 */ |
272 SourceFileEdit _getChangeFileEdit(SourceChange change, String file) { | 97 SourceFileEdit _getChangeFileEdit(SourceChange change, String file) { |
273 for (SourceFileEdit fileEdit in change.edits) { | 98 for (SourceFileEdit fileEdit in change.edits) { |
274 if (fileEdit.file == file) { | 99 if (fileEdit.file == file) { |
275 return fileEdit; | 100 return fileEdit; |
276 } | 101 } |
277 } | 102 } |
278 return null; | 103 return null; |
279 } | 104 } |
280 | 105 |
281 /** | 106 /** |
282 * Compare the lists [listA] and [listB], using [itemEqual] to compare | 107 * Compare the lists [listA] and [listB], using [itemEqual] to compare |
283 * list elements. | 108 * list elements. |
284 */ | 109 */ |
285 bool _listEqual(List listA, List listB, bool itemEqual(a, b)) { | 110 bool _listEqual(List listA, List listB, bool itemEqual(a, b)) { |
286 if (listA.length != listB.length) { | 111 if (listA.length != listB.length) { |
287 return false; | 112 return false; |
288 } | 113 } |
289 for (int i = 0; i < listA.length; i++) { | 114 for (int i = 0; i < listA.length; i++) { |
290 if (!itemEqual(listA[i], listB[i])) { | 115 if (!itemEqual(listA[i], listB[i])) { |
291 return false; | 116 return false; |
292 } | 117 } |
293 } | 118 } |
294 return true; | 119 return true; |
295 } | 120 } |
296 | 121 |
297 /** | 122 /** |
298 * Creates a new [Location]. | |
299 */ | |
300 Location _locationForArgs(engine.AnalysisContext context, engine.Source source, | |
301 engine.SourceRange range) { | |
302 int startLine = 0; | |
303 int startColumn = 0; | |
304 { | |
305 engine.LineInfo lineInfo = context.getLineInfo(source); | |
306 if (lineInfo != null) { | |
307 engine.LineInfo_Location offsetLocation = | |
308 lineInfo.getLocation(range.offset); | |
309 startLine = offsetLocation.lineNumber; | |
310 startColumn = offsetLocation.columnNumber; | |
311 } | |
312 } | |
313 return new Location( | |
314 source.fullName, | |
315 range.offset, | |
316 range.length, | |
317 startLine, | |
318 startColumn); | |
319 } | |
320 | |
321 /** | |
322 * Creates a new [Location] for the given [engine.Element]. | |
323 */ | |
324 Location _locationFromElement(engine.Element element) { | |
325 engine.AnalysisContext context = element.context; | |
326 engine.Source source = element.source; | |
327 if (context == null || source == null) { | |
328 return null; | |
329 } | |
330 String name = element.displayName; | |
331 int offset = element.nameOffset; | |
332 int length = name != null ? name.length : 0; | |
333 if (element is engine.CompilationUnitElement) { | |
334 offset = 0; | |
335 length = 0; | |
336 } | |
337 engine.SourceRange range = new engine.SourceRange(offset, length); | |
338 return _locationForArgs(context, source, range); | |
339 } | |
340 | |
341 /** | |
342 * Creates a new [Location] for the given [engine.SearchMatch]. | |
343 */ | |
344 Location _locationFromMatch(engine.SearchMatch match) { | |
345 engine.Element enclosingElement = match.element; | |
346 return _locationForArgs( | |
347 enclosingElement.context, | |
348 enclosingElement.source, | |
349 match.sourceRange); | |
350 } | |
351 | |
352 /** | |
353 * Creates a new [Location] for the given [engine.AstNode]. | |
354 */ | |
355 Location _locationFromNode(engine.AstNode node) { | |
356 engine.CompilationUnit unit = | |
357 node.getAncestor((node) => node is engine.CompilationUnit); | |
358 engine.CompilationUnitElement unitElement = unit.element; | |
359 engine.AnalysisContext context = unitElement.context; | |
360 engine.Source source = unitElement.source; | |
361 engine.SourceRange range = new engine.SourceRange(node.offset, node.length); | |
362 return _locationForArgs(context, source, range); | |
363 } | |
364 | |
365 /** | |
366 * Creates a new [Location] for the given [engine.CompilationUnit]. | |
367 */ | |
368 Location _locationFromUnit(engine.CompilationUnit unit, | |
369 engine.SourceRange range) { | |
370 engine.CompilationUnitElement unitElement = unit.element; | |
371 engine.AnalysisContext context = unitElement.context; | |
372 engine.Source source = unitElement.source; | |
373 return _locationForArgs(context, source, range); | |
374 } | |
375 | |
376 /** | |
377 * Compare the maps [mapA] and [mapB], using [valueEqual] to compare map | 123 * Compare the maps [mapA] and [mapB], using [valueEqual] to compare map |
378 * values. | 124 * values. |
379 */ | 125 */ |
380 bool _mapEqual(Map mapA, Map mapB, bool valueEqual(a, b)) { | 126 bool _mapEqual(Map mapA, Map mapB, bool valueEqual(a, b)) { |
381 if (mapA.length != mapB.length) { | 127 if (mapA.length != mapB.length) { |
382 return false; | 128 return false; |
383 } | 129 } |
384 for (var key in mapA.keys) { | 130 for (var key in mapA.keys) { |
385 if (!mapB.containsKey(key)) { | 131 if (!mapB.containsKey(key)) { |
386 return false; | 132 return false; |
(...skipping 22 matching lines...) Expand all Loading... |
409 } | 155 } |
410 } else if (a == RefactoringProblemSeverity.ERROR) { | 156 } else if (a == RefactoringProblemSeverity.ERROR) { |
411 if (b == RefactoringProblemSeverity.FATAL) { | 157 if (b == RefactoringProblemSeverity.FATAL) { |
412 return b; | 158 return b; |
413 } | 159 } |
414 } | 160 } |
415 return a; | 161 return a; |
416 } | 162 } |
417 | 163 |
418 /** | 164 /** |
419 * Create an OverriddenMember based on an element from the analyzer engine. | |
420 */ | |
421 OverriddenMember _overriddenMemberFromEngine(engine.Element member) { | |
422 Element element = elementFromEngine(member); | |
423 String className = member.enclosingElement.displayName; | |
424 return new OverriddenMember(element, className); | |
425 } | |
426 | |
427 | |
428 /** | |
429 * Create a [RefactoringFeedback] corresponding the given [kind]. | 165 * Create a [RefactoringFeedback] corresponding the given [kind]. |
430 */ | 166 */ |
431 RefactoringFeedback _refactoringFeedbackFromJson(JsonDecoder jsonDecoder, | 167 RefactoringFeedback _refactoringFeedbackFromJson(JsonDecoder jsonDecoder, |
432 String jsonPath, Object json, Map feedbackJson) { | 168 String jsonPath, Object json, Map feedbackJson) { |
433 String requestId; | 169 String requestId; |
434 if (jsonDecoder is ResponseDecoder) { | 170 if (jsonDecoder is ResponseDecoder) { |
435 requestId = jsonDecoder.response.id; | 171 requestId = jsonDecoder.response.id; |
436 } | 172 } |
437 RefactoringKind kind = REQUEST_ID_REFACTORING_KINDS.remove(requestId); | 173 RefactoringKind kind = REQUEST_ID_REFACTORING_KINDS.remove(requestId); |
438 if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE) { | 174 if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE) { |
439 return new ExtractLocalVariableFeedback.fromJson(jsonDecoder, jsonPath, json
); | 175 return new ExtractLocalVariableFeedback.fromJson( |
| 176 jsonDecoder, |
| 177 jsonPath, |
| 178 json); |
440 } | 179 } |
441 if (kind == RefactoringKind.EXTRACT_METHOD) { | 180 if (kind == RefactoringKind.EXTRACT_METHOD) { |
442 return new ExtractMethodFeedback.fromJson(jsonDecoder, jsonPath, json); | 181 return new ExtractMethodFeedback.fromJson(jsonDecoder, jsonPath, json); |
443 } | 182 } |
444 if (kind == RefactoringKind.INLINE_LOCAL_VARIABLE) { | 183 if (kind == RefactoringKind.INLINE_LOCAL_VARIABLE) { |
445 return new InlineLocalVariableFeedback.fromJson(jsonDecoder, jsonPath, json)
; | 184 return new InlineLocalVariableFeedback.fromJson( |
| 185 jsonDecoder, |
| 186 jsonPath, |
| 187 json); |
446 } | 188 } |
447 if (kind == RefactoringKind.INLINE_METHOD) { | 189 if (kind == RefactoringKind.INLINE_METHOD) { |
448 return new InlineMethodFeedback.fromJson(jsonDecoder, jsonPath, json); | 190 return new InlineMethodFeedback.fromJson(jsonDecoder, jsonPath, json); |
449 } | 191 } |
450 if (kind == RefactoringKind.RENAME) { | 192 if (kind == RefactoringKind.RENAME) { |
451 return new RenameFeedback.fromJson(jsonDecoder, jsonPath, json); | 193 return new RenameFeedback.fromJson(jsonDecoder, jsonPath, json); |
452 } | 194 } |
453 return null; | 195 return null; |
454 } | 196 } |
455 | 197 |
456 | 198 |
457 /** | 199 /** |
458 * Create a [RefactoringOptions] corresponding the given [kind]. | 200 * Create a [RefactoringOptions] corresponding the given [kind]. |
459 */ | 201 */ |
460 RefactoringOptions _refactoringOptionsFromJson(JsonDecoder jsonDecoder, | 202 RefactoringOptions _refactoringOptionsFromJson(JsonDecoder jsonDecoder, |
461 String jsonPath, Object json, RefactoringKind kind) { | 203 String jsonPath, Object json, RefactoringKind kind) { |
462 if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE) { | 204 if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE) { |
463 return new ExtractLocalVariableOptions.fromJson(jsonDecoder, jsonPath, json)
; | 205 return new ExtractLocalVariableOptions.fromJson( |
| 206 jsonDecoder, |
| 207 jsonPath, |
| 208 json); |
464 } | 209 } |
465 if (kind == RefactoringKind.EXTRACT_METHOD) { | 210 if (kind == RefactoringKind.EXTRACT_METHOD) { |
466 return new ExtractMethodOptions.fromJson(jsonDecoder, jsonPath, json); | 211 return new ExtractMethodOptions.fromJson(jsonDecoder, jsonPath, json); |
467 } | 212 } |
468 if (kind == RefactoringKind.INLINE_METHOD) { | 213 if (kind == RefactoringKind.INLINE_METHOD) { |
469 return new InlineMethodOptions.fromJson(jsonDecoder, jsonPath, json); | 214 return new InlineMethodOptions.fromJson(jsonDecoder, jsonPath, json); |
470 } | 215 } |
471 if (kind == RefactoringKind.RENAME) { | 216 if (kind == RefactoringKind.RENAME) { |
472 return new RenameOptions.fromJson(jsonDecoder, jsonPath, json); | 217 return new RenameOptions.fromJson(jsonDecoder, jsonPath, json); |
473 } | 218 } |
474 return null; | 219 return null; |
475 } | 220 } |
476 | 221 |
477 | |
478 /** | |
479 * Create a SearchResultKind based on a value from the search engine. | |
480 */ | |
481 SearchResultKind _searchResultKindFromEngine(engine.MatchKind kind) { | |
482 if (kind == engine.MatchKind.DECLARATION) { | |
483 return SearchResultKind.DECLARATION; | |
484 } | |
485 if (kind == engine.MatchKind.READ) { | |
486 return SearchResultKind.READ; | |
487 } | |
488 if (kind == engine.MatchKind.READ_WRITE) { | |
489 return SearchResultKind.READ_WRITE; | |
490 } | |
491 if (kind == engine.MatchKind.WRITE) { | |
492 return SearchResultKind.WRITE; | |
493 } | |
494 if (kind == engine.MatchKind.INVOCATION) { | |
495 return SearchResultKind.INVOCATION; | |
496 } | |
497 if (kind == engine.MatchKind.REFERENCE) { | |
498 return SearchResultKind.REFERENCE; | |
499 } | |
500 return SearchResultKind.UNKNOWN; | |
501 } | |
502 | |
503 | |
504 /** | 222 /** |
505 * Type of callbacks used to decode parts of JSON objects. [jsonPath] is a | 223 * Type of callbacks used to decode parts of JSON objects. [jsonPath] is a |
506 * string describing the part of the JSON object being decoded, and [value] is | 224 * string describing the part of the JSON object being decoded, and [value] is |
507 * the part to decode. | 225 * the part to decode. |
508 */ | 226 */ |
509 typedef Object JsonDecoderCallback(String jsonPath, Object value); | 227 typedef Object JsonDecoderCallback(String jsonPath, Object value); |
510 | 228 |
511 /** | 229 /** |
512 * Base class for decoding JSON objects. The derived class must implement | 230 * Base class for decoding JSON objects. The derived class must implement |
513 * error reporting logic. | 231 * error reporting logic. |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
669 * Initialize a newly created [Notification] to have the given [event] name. | 387 * Initialize a newly created [Notification] to have the given [event] name. |
670 * If [_params] is provided, it will be used as the params; otherwise no | 388 * If [_params] is provided, it will be used as the params; otherwise no |
671 * params will be used. | 389 * params will be used. |
672 */ | 390 */ |
673 Notification(this.event, [this._params]); | 391 Notification(this.event, [this._params]); |
674 | 392 |
675 /** | 393 /** |
676 * Initialize a newly created instance based upon the given JSON data | 394 * Initialize a newly created instance based upon the given JSON data |
677 */ | 395 */ |
678 factory Notification.fromJson(Map<String, Object> json) { | 396 factory Notification.fromJson(Map<String, Object> json) { |
679 return new Notification(json[Notification.EVENT], | 397 return new Notification( |
| 398 json[Notification.EVENT], |
680 json[Notification.PARAMS]); | 399 json[Notification.PARAMS]); |
681 } | 400 } |
682 | 401 |
683 /** | 402 /** |
684 * Return a table representing the structure of the Json object that will be | 403 * Return a table representing the structure of the Json object that will be |
685 * sent to the client to represent this response. | 404 * sent to the client to represent this response. |
686 */ | 405 */ |
687 Map<String, Object> toJson() { | 406 Map<String, Object> toJson() { |
688 Map<String, Object> jsonObject = {}; | 407 Map<String, Object> jsonObject = {}; |
689 jsonObject[EVENT] = event; | 408 jsonObject[EVENT] = event; |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
908 */ | 627 */ |
909 factory Response.fromJson(Map<String, Object> json) { | 628 factory Response.fromJson(Map<String, Object> json) { |
910 try { | 629 try { |
911 Object id = json[Response.ID]; | 630 Object id = json[Response.ID]; |
912 if (id is! String) { | 631 if (id is! String) { |
913 return null; | 632 return null; |
914 } | 633 } |
915 Object error = json[Response.ERROR]; | 634 Object error = json[Response.ERROR]; |
916 RequestError decodedError; | 635 RequestError decodedError; |
917 if (error is Map) { | 636 if (error is Map) { |
918 decodedError = new RequestError.fromJson(new ResponseDecoder(null), | 637 decodedError = |
919 '.error', error); | 638 new RequestError.fromJson(new ResponseDecoder(null), '.error', error
); |
920 } | 639 } |
921 Object result = json[Response.RESULT]; | 640 Object result = json[Response.RESULT]; |
922 Map<String, Object> decodedResult; | 641 Map<String, Object> decodedResult; |
923 if (result is Map) { | 642 if (result is Map) { |
924 decodedResult = result; | 643 decodedResult = result; |
925 } | 644 } |
926 return new Response(id, error: decodedError, | 645 return new Response(id, error: decodedError, result: decodedResult); |
927 result: decodedResult); | |
928 } catch (exception) { | 646 } catch (exception) { |
929 return null; | 647 return null; |
930 } | 648 } |
931 } | 649 } |
932 | 650 |
933 /** | 651 /** |
934 * Initialize a newly created instance to represent the | 652 * Initialize a newly created instance to represent the |
935 * GET_ERRORS_INVALID_FILE error condition. | 653 * GET_ERRORS_INVALID_FILE error condition. |
936 */ | 654 */ |
937 Response.getErrorsInvalidFile(Request request) | 655 Response.getErrorsInvalidFile(Request request) |
938 : this( | 656 : this( |
939 request.id, | 657 request.id, |
940 error: new RequestError(RequestErrorCode.GET_ERRORS_INVALID_FILE, | 658 error: new RequestError( |
941 'Error during `analysis.getErrors`: invalid file.')); | 659 RequestErrorCode.GET_ERRORS_INVALID_FILE, |
| 660 'Error during `analysis.getErrors`: invalid file.')); |
942 | 661 |
943 /** | 662 /** |
944 * Initialize a newly created instance to represent an error condition caused | 663 * Initialize a newly created instance to represent an error condition caused |
945 * by a [request] that had invalid parameter. [path] is the path to the | 664 * by a [request] that had invalid parameter. [path] is the path to the |
946 * invalid parameter, in Javascript notation (e.g. "foo.bar" means that the | 665 * invalid parameter, in Javascript notation (e.g. "foo.bar" means that the |
947 * parameter "foo" contained a key "bar" whose value was the wrong type). | 666 * parameter "foo" contained a key "bar" whose value was the wrong type). |
948 * [expectation] is a description of the type of data that was expected. | 667 * [expectation] is a description of the type of data that was expected. |
949 */ | 668 */ |
950 Response.invalidParameter(Request request, String path, String expectation) | 669 Response.invalidParameter(Request request, String path, String expectation) |
951 : this(request.id, error: new RequestError(RequestErrorCode.INVALID_PARAME
TER, | 670 : this( |
952 "Expected parameter $path to $expectation")); | 671 request.id, |
| 672 error: new RequestError( |
| 673 RequestErrorCode.INVALID_PARAMETER, |
| 674 "Expected parameter $path to $expectation")); |
953 | 675 |
954 /** | 676 /** |
955 * Initialize a newly created instance to represent an error condition caused | 677 * Initialize a newly created instance to represent an error condition caused |
956 * by a malformed request. | 678 * by a malformed request. |
957 */ | 679 */ |
958 Response.invalidRequestFormat() | 680 Response.invalidRequestFormat() |
959 : this('', error: new RequestError(RequestErrorCode.INVALID_REQUEST, 'Invali
d request')); | 681 : this( |
| 682 '', |
| 683 error: new RequestError(RequestErrorCode.INVALID_REQUEST, 'Invalid req
uest')); |
960 | 684 |
961 /** | 685 /** |
962 * Initialize a newly created instance to represent an error condition caused | 686 * Initialize a newly created instance to represent an error condition caused |
963 * by a `analysis.setPriorityFiles` [request] that includes one or more files | 687 * by a `analysis.setPriorityFiles` [request] that includes one or more files |
964 * that are not being analyzed. | 688 * that are not being analyzed. |
965 */ | 689 */ |
966 Response.unanalyzedPriorityFiles(Request request, String fileNames) | 690 Response.unanalyzedPriorityFiles(Request request, String fileNames) |
967 : this(request.id, error: new RequestError(RequestErrorCode.UNANALYZED_PRIOR
ITY_FILES, "Unanalyzed files cannot be a priority: '$fileNames'")); | 691 : this( |
| 692 request.id, |
| 693 error: new RequestError( |
| 694 RequestErrorCode.UNANALYZED_PRIORITY_FILES, |
| 695 "Unanalyzed files cannot be a priority: '$fileNames'")); |
968 | 696 |
969 /** | 697 /** |
970 * Initialize a newly created instance to represent an error condition caused | 698 * Initialize a newly created instance to represent an error condition caused |
971 * by a [request] that cannot be handled by any known handlers. | 699 * by a [request] that cannot be handled by any known handlers. |
972 */ | 700 */ |
973 Response.unknownRequest(Request request) | 701 Response.unknownRequest(Request request) |
974 : this(request.id, error: new RequestError(RequestErrorCode.UNKNOWN_REQUEST,
'Unknown request')); | 702 : this( |
| 703 request.id, |
| 704 error: new RequestError(RequestErrorCode.UNKNOWN_REQUEST, 'Unknown req
uest')); |
975 | 705 |
976 Response.unsupportedFeature(String requestId, String message) | 706 Response.unsupportedFeature(String requestId, String message) |
977 : this(requestId, error: new RequestError(RequestErrorCode.UNSUPPORTED_FEATU
RE, message)); | 707 : this( |
| 708 requestId, |
| 709 error: new RequestError(RequestErrorCode.UNSUPPORTED_FEATURE, message)
); |
978 | 710 |
979 /** | 711 /** |
980 * Return a table representing the structure of the Json object that will be | 712 * Return a table representing the structure of the Json object that will be |
981 * sent to the client to represent this response. | 713 * sent to the client to represent this response. |
982 */ | 714 */ |
983 Map<String, Object> toJson() { | 715 Map<String, Object> toJson() { |
984 Map<String, Object> jsonObject = new HashMap<String, Object>(); | 716 Map<String, Object> jsonObject = new HashMap<String, Object>(); |
985 jsonObject[ID] = id; | 717 jsonObject[ID] = id; |
986 if (error != null) { | 718 if (error != null) { |
987 jsonObject[ERROR] = error.toJson(); | 719 jsonObject[ERROR] = error.toJson(); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1030 hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); | 762 hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); |
1031 hash = hash ^ (hash >> 11); | 763 hash = hash ^ (hash >> 11); |
1032 return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); | 764 return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); |
1033 } | 765 } |
1034 | 766 |
1035 static int hash2(a, b) => finish(combine(combine(0, a), b)); | 767 static int hash2(a, b) => finish(combine(combine(0, a), b)); |
1036 | 768 |
1037 static int hash4(a, b, c, d) => | 769 static int hash4(a, b, c, d) => |
1038 finish(combine(combine(combine(combine(0, a), b), c), d)); | 770 finish(combine(combine(combine(combine(0, a), b), c), d)); |
1039 } | 771 } |
OLD | NEW |