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

Side by Side Diff: pkg/analysis_server/lib/src/status/validator.dart

Issue 2918553002: Remove dead code related to the diagnostics server. (Closed)
Patch Set: grammar Created 3 years, 6 months 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
« no previous file with comments | « pkg/analysis_server/lib/src/status/memory_use.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 import 'dart:collection';
6
7 import 'package:analyzer/dart/ast/ast.dart';
8 import 'package:analyzer/dart/ast/token.dart';
9 import 'package:analyzer/dart/element/element.dart';
10 import 'package:analyzer/dart/element/type.dart';
11 import 'package:analyzer/error/error.dart';
12 import 'package:analyzer/src/context/cache.dart';
13 import 'package:analyzer/src/context/context.dart';
14 import 'package:analyzer/src/dart/ast/utilities.dart';
15 import 'package:analyzer/src/dart/element/element.dart';
16 import 'package:analyzer/src/generated/engine.dart'
17 show AnalysisEngine, AnalysisResult, CacheState, ChangeSet;
18 import 'package:analyzer/src/generated/resolver.dart';
19 import 'package:analyzer/src/generated/source.dart';
20 import 'package:analyzer/src/generated/utilities_collection.dart';
21 import 'package:analyzer/src/task/dart.dart';
22 import 'package:analyzer/src/task/html.dart';
23 import 'package:analyzer/task/dart.dart';
24 import 'package:analyzer/task/model.dart';
25 import 'package:html/dom.dart' as html;
26
27 /**
28 * A class used to compare two element models for equality.
29 */
30 class ElementComparator {
31 /**
32 * The buffer to which any discovered differences will be recorded.
33 */
34 final StringBuffer _buffer = new StringBuffer();
35
36 /**
37 * A flag indicating whether a line break should be added the next time data
38 * is written to the [_buffer].
39 */
40 bool _needsLineBreak = false;
41
42 /**
43 * Initialize a newly created comparator.
44 */
45 ElementComparator();
46
47 /**
48 * A textual description of the differences that were found.
49 */
50 String get description => _buffer.toString();
51
52 /**
53 * Return `true` if at least one difference was found between the expected and
54 * actual elements.
55 */
56 bool get hasDifference => _buffer.length > 0;
57
58 /**
59 * Compare the [expected] and [actual] elements. The results of the comparison
60 * can be accessed via the [hasDifference] and [description] getters.
61 */
62 void compareElements(Element expected, Element actual) {
63 if (expected == null) {
64 if (actual != null) {
65 _writeMismatch(expected, actual, (Object element) {
66 return element == null ? 'null' : 'non null ${element.runtimeType}';
67 });
68 }
69 } else if (actual == null) {
70 _writeMismatch(expected, actual, (Object element) {
71 return element == null ? 'null' : 'non null ${element.runtimeType}';
72 });
73 } else if (expected is ClassElement && actual is ClassElement) {
74 _compareClassElements(expected, actual);
75 } else if (expected is CompilationUnitElement &&
76 actual is CompilationUnitElement) {
77 _compareCompilationUnitElements(expected, actual);
78 } else if (expected is ConstructorElement && actual is ConstructorElement) {
79 _compareConstructorElements(expected, actual);
80 } else if (expected is ExportElement && actual is ExportElement) {
81 _compareExportElements(expected, actual);
82 } else if (expected is FieldElement && actual is FieldElement) {
83 _compareFieldElements(expected, actual);
84 } else if (expected is FieldFormalParameterElement &&
85 actual is FieldFormalParameterElement) {
86 _compareFieldFormalParameterElements(expected, actual);
87 } else if (expected is FunctionElement && actual is FunctionElement) {
88 _compareFunctionElements(expected, actual);
89 } else if (expected is FunctionTypeAliasElement &&
90 actual is FunctionTypeAliasElement) {
91 _compareFunctionTypeAliasElements(expected, actual);
92 } else if (expected is ImportElement && actual is ImportElement) {
93 _compareImportElements(expected, actual);
94 } else if (expected is LabelElement && actual is LabelElement) {
95 _compareLabelElements(expected, actual);
96 } else if (expected is LibraryElement && actual is LibraryElement) {
97 _compareLibraryElements(expected, actual);
98 } else if (expected is LocalVariableElement &&
99 actual is LocalVariableElement) {
100 _compareLocalVariableElements(expected, actual);
101 } else if (expected is MethodElement && actual is MethodElement) {
102 _compareMethodElements(expected, actual);
103 } else if (expected is MultiplyDefinedElement &&
104 actual is MultiplyDefinedElement) {
105 _compareMultiplyDefinedElements(expected, actual);
106 } else if (expected is ParameterElement && actual is ParameterElement) {
107 _compareParameterElements(expected, actual);
108 } else if (expected is PrefixElement && actual is PrefixElement) {
109 _comparePrefixElements(expected, actual);
110 } else if (expected is PropertyAccessorElement &&
111 actual is PropertyAccessorElement) {
112 _comparePropertyAccessorElements(expected, actual);
113 } else if (expected is TopLevelVariableElement &&
114 actual is TopLevelVariableElement) {
115 _compareTopLevelVariableElements(expected, actual);
116 } else if (expected is TypeParameterElement &&
117 actual is TypeParameterElement) {
118 _compareTypeParameterElements(expected, actual);
119 } else {
120 _write('Expected an instance of ');
121 _write(expected.runtimeType);
122 _write('; found an instance of ');
123 _writeln(actual.runtimeType);
124 }
125 }
126
127 void _compareClassElements(ClassElement expected, ClassElement actual) {
128 _compareGenericElements(expected, actual);
129 //
130 // Compare attributes.
131 //
132 if (expected.hasReferenceToSuper != actual.hasReferenceToSuper) {
133 _writeMismatch(
134 expected,
135 actual,
136 (Object element) => (element as ClassElement).hasReferenceToSuper
137 ? 'a class that references super'
138 : 'a class that does not reference super');
139 }
140 if (expected.isAbstract != actual.isAbstract) {
141 _writeMismatch(
142 expected,
143 actual,
144 (Object element) => (element as ClassElement).isAbstract
145 ? 'an abstract class'
146 : 'a concrete class');
147 }
148 if (expected.isEnum != actual.isEnum ||
149 expected.isMixinApplication != actual.isMixinApplication) {
150 _writeMismatch(expected, actual, (Object element) {
151 ClassElement classElement = element as ClassElement;
152 return classElement.isEnum
153 ? 'an enum'
154 : (classElement.isMixinApplication
155 ? 'a mixin application'
156 : 'a class');
157 });
158 }
159 if (expected.isOrInheritsProxy != actual.isOrInheritsProxy) {
160 _writeMismatch(
161 expected,
162 actual,
163 (Object element) => (element as ClassElement).isOrInheritsProxy
164 ? 'a class that is marked as a proxy'
165 : 'a class that is not marked as a proxy');
166 }
167 if (expected.isValidMixin != actual.isValidMixin) {
168 _writeMismatch(
169 expected,
170 actual,
171 (Object element) => (element as ClassElement).isValidMixin
172 ? 'a valid mixin'
173 : 'an invalid mixin');
174 }
175 _compareTypes('supertype', expected.supertype, actual.supertype);
176 _compareTypeLists('mixin', expected.mixins, actual.mixins);
177 _compareTypeLists('interface', expected.interfaces, actual.interfaces);
178 //
179 // Compare children.
180 //
181 _compareElementLists(expected.accessors, actual.accessors);
182 _compareElementLists(expected.constructors, actual.constructors);
183 _compareElementLists(expected.fields, actual.fields);
184 _compareElementLists(expected.methods, actual.methods);
185 _compareElementLists(expected.typeParameters, actual.typeParameters);
186 }
187
188 void _compareCompilationUnitElements(
189 CompilationUnitElement expected, CompilationUnitElement actual) {
190 _compareGenericElements(expected, actual);
191 //
192 // Compare children.
193 //
194 _compareElementLists(expected.accessors, actual.accessors);
195 _compareElementLists(expected.enums, actual.enums);
196 _compareElementLists(expected.functions, actual.functions);
197 _compareElementLists(
198 expected.functionTypeAliases, actual.functionTypeAliases);
199 _compareElementLists(expected.topLevelVariables, actual.topLevelVariables);
200 _compareElementLists(expected.types, actual.types);
201 }
202
203 void _compareConstructorElements(
204 ConstructorElement expected, ConstructorElement actual) {
205 _compareExecutableElements(expected, actual, 'constructor');
206 //
207 // Compare attributes.
208 //
209 if (expected.isConst != actual.isConst) {
210 _writeMismatch(
211 expected,
212 actual,
213 (Object element) => (element as ConstructorElement).isConst
214 ? 'a const constructor'
215 : 'a non-const constructor');
216 }
217 if (expected.isFactory != actual.isFactory) {
218 _writeMismatch(
219 expected,
220 actual,
221 (Object element) => (element as ConstructorElement).isFactory
222 ? 'a factory constructor'
223 : 'a non-factory constructor');
224 }
225 if (expected.periodOffset != actual.periodOffset) {
226 _write('Expected a period offset of ');
227 _write(expected.periodOffset);
228 _write('; found ');
229 _writeln(actual.periodOffset);
230 }
231 if ((expected.redirectedConstructor == null) !=
232 (actual.redirectedConstructor == null)) {
233 _writeMismatch(
234 expected,
235 actual,
236 (Object element) =>
237 (element as ConstructorElement).redirectedConstructor == null
238 ? 'a redirecting constructor'
239 : 'a non-redirecting constructor');
240 }
241 }
242
243 void _compareElementLists(List expected, List actual) {
244 Set<Element> extraElements = new HashSet<Element>();
245 Map<Element, Element> commonElements = new HashMap<Element, Element>();
246
247 Map<String, Element> expectedElements = new HashMap<String, Element>();
248 for (Element expectedElement in expected) {
249 expectedElements[expectedElement.name] = expectedElement;
250 }
251 for (Element actualElement in actual) {
252 String name = actualElement.name;
253 Element expectedElement = expectedElements[name];
254 if (expectedElement == null) {
255 extraElements.add(actualElement);
256 } else {
257 commonElements[expectedElement] = actualElement;
258 expectedElements.remove(name);
259 }
260 }
261
262 commonElements.forEach((Element expected, Element actual) {
263 compareElements(expected, actual);
264 });
265 void writeElement(Element element) {
266 _write('an instance of ');
267 _write(element.runtimeType);
268 if (element.name == null) {
269 _write(' with no name');
270 } else {
271 _write(' named ');
272 _write(element.name);
273 }
274 }
275
276 expectedElements.forEach((String name, Element element) {
277 _write('Expected ');
278 writeElement(element);
279 _writeln('; found no match');
280 });
281 extraElements.forEach((Element element) {
282 _write('Expected nothing; found ');
283 writeElement(element);
284 });
285 }
286
287 void _compareExecutableElements(
288 ExecutableElement expected, ExecutableElement actual, String kind) {
289 _compareGenericElements(expected, actual);
290 //
291 // Compare attributes.
292 //
293 if (expected.hasImplicitReturnType != actual.hasImplicitReturnType) {
294 _writeMismatch(
295 expected,
296 actual,
297 (Object element) =>
298 (element as ExecutableElement).hasImplicitReturnType
299 ? 'an implicit return type'
300 : 'an explicit return type');
301 }
302 if (expected.isAbstract != actual.isAbstract) {
303 _writeMismatch(
304 expected,
305 actual,
306 (Object element) => (element as ExecutableElement).isAbstract
307 ? 'an abstract $kind'
308 : 'a concrete $kind');
309 }
310 if (expected.isAsynchronous != actual.isAsynchronous) {
311 _writeMismatch(
312 expected,
313 actual,
314 (Object element) => (element as ExecutableElement).isAsynchronous
315 ? 'an asynchronous $kind'
316 : 'a synchronous $kind');
317 }
318 if (expected.isExternal != actual.isExternal) {
319 _writeMismatch(
320 expected,
321 actual,
322 (Object element) => (element as ExecutableElement).isExternal
323 ? 'an external $kind'
324 : 'a non-external $kind');
325 }
326 if (expected.isGenerator != actual.isGenerator) {
327 _writeMismatch(
328 expected,
329 actual,
330 (Object element) => (element as ExecutableElement).isGenerator
331 ? 'a generator $kind'
332 : 'a non-generator $kind');
333 }
334 if (expected.isOperator != actual.isOperator) {
335 _writeMismatch(
336 expected,
337 actual,
338 (Object element) => (element as ExecutableElement).isOperator
339 ? 'an operator'
340 : 'a non-operator $kind');
341 }
342 if (expected.isStatic != actual.isStatic) {
343 _writeMismatch(
344 expected,
345 actual,
346 (Object element) => (element as ExecutableElement).isStatic
347 ? 'a static $kind'
348 : 'an instance $kind');
349 }
350 if ((expected.returnType == null) != (actual.returnType == null)) {
351 _writeMismatch(
352 expected,
353 actual,
354 (Object element) => (element as ExecutableElement).returnType == null
355 ? 'a $kind with no return type'
356 : 'a $kind with a return type');
357 } else {
358 _compareTypes('return type', expected.returnType, actual.returnType);
359 }
360 //
361 // Compare children.
362 //
363 _compareElementLists(expected.functions, actual.functions);
364 _compareElementLists(expected.labels, actual.labels);
365 _compareElementLists(expected.localVariables, actual.localVariables);
366 _compareElementLists(expected.parameters, actual.parameters);
367 _compareElementLists(expected.typeParameters, actual.typeParameters);
368 }
369
370 void _compareExportElements(ExportElement expected, ExportElement actual) {
371 _compareUriReferencedElements(expected, actual);
372 //
373 // Compare attributes.
374 //
375 if ((expected.exportedLibrary == null) !=
376 (actual.exportedLibrary == null)) {
377 // TODO(brianwilkerson) Check for more than existence?
378 _writeMismatch(expected, actual, (Object element) {
379 ExportElement exportElement = element as ExportElement;
380 return exportElement.exportedLibrary == null
381 ? 'unresolved uri'
382 : 'uri resolved to ${exportElement.exportedLibrary.source.fullName}' ;
383 });
384 }
385 //
386 // Compare children.
387 //
388 _compareElementLists(expected.combinators, actual.combinators);
389 }
390
391 void _compareFieldElements(FieldElement expected, FieldElement actual) {
392 _comparePropertyInducingElements(expected, actual, 'field');
393 //
394 // Compare attributes.
395 //
396 if (expected.isEnumConstant != actual.isEnumConstant) {
397 _writeMismatch(
398 expected,
399 actual,
400 (Object element) => (element as FieldElement).isEnumConstant
401 ? 'an enum constant'
402 : 'a normal field');
403 }
404 }
405
406 void _compareFieldFormalParameterElements(
407 FieldFormalParameterElement expected,
408 FieldFormalParameterElement actual) {
409 // TODO(brianwilkerson) Implement this
410 _compareGenericElements(expected, actual);
411 }
412
413 void _compareFunctionElements(
414 FunctionElement expected, FunctionElement actual) {
415 // TODO(brianwilkerson) Implement this
416 _compareGenericElements(expected, actual);
417 }
418
419 void _compareFunctionTypeAliasElements(
420 FunctionTypeAliasElement expected, FunctionTypeAliasElement actual) {
421 // TODO(brianwilkerson) Implement this
422 _compareGenericElements(expected, actual);
423 }
424
425 void _compareGenericElements(Element expected, Element actual) {
426 _compareMetadata(expected.metadata, actual.metadata);
427 if (expected.nameOffset != actual.nameOffset) {
428 _write('Expected name offset of ');
429 _write(expected.nameOffset);
430 _write('; found ');
431 _writeln(actual.nameOffset);
432 }
433 String expectedComment = expected.documentationComment;
434 String actualComment = actual.documentationComment;
435 if (expectedComment != actualComment) {
436 _write('Expected documentation comment of "');
437 _write(expectedComment);
438 _write('"; found "');
439 _write(actualComment);
440 _writeln('"');
441 }
442 }
443
444 void _compareImportElements(ImportElement expected, ImportElement actual) {
445 _compareUriReferencedElements(expected, actual);
446 //
447 // Compare attributes.
448 //
449 if (expected.isDeferred != actual.isDeferred) {
450 _writeMismatch(
451 expected,
452 actual,
453 (Object element) => (element as ImportElement).isDeferred
454 ? 'a deferred import'
455 : 'a non-deferred import');
456 }
457 if ((expected.importedLibrary == null) !=
458 (actual.importedLibrary == null)) {
459 _writeMismatch(expected, actual, (Object element) {
460 ImportElement importElement = element as ImportElement;
461 return importElement.importedLibrary == null
462 ? 'unresolved uri'
463 : 'uri resolved to ${importElement.importedLibrary.source.fullName}' ;
464 });
465 }
466 if ((expected.prefix == null) != (actual.prefix == null)) {
467 _writeMismatch(expected, actual, (Object element) {
468 ImportElement importElement = element as ImportElement;
469 return importElement.prefix == null
470 ? 'no prefix'
471 : 'a prefix named ${importElement.prefix.name}';
472 });
473 }
474 if (expected.prefixOffset != actual.prefixOffset) {
475 _write('Expected a prefix offset of ');
476 _write(expected.prefixOffset);
477 _write('; found ');
478 _writeln(actual.prefixOffset);
479 }
480 //
481 // Compare children.
482 //
483 _compareElementLists(expected.combinators, actual.combinators);
484 }
485
486 void _compareLabelElements(LabelElement expected, LabelElement actual) {
487 // TODO(brianwilkerson) Implement this
488 _compareGenericElements(expected, actual);
489 }
490
491 void _compareLibraryElements(LibraryElement expected, LibraryElement actual) {
492 _compareGenericElements(expected, actual);
493 //
494 // Compare attributes.
495 //
496 // TODO(brianwilkerson) Implement this
497 expected.hasLoadLibraryFunction;
498 expected.name;
499 expected.source;
500 //
501 // Compare children.
502 //
503 _compareElementLists(expected.imports, actual.imports);
504 _compareElementLists(expected.exports, actual.exports);
505 _compareElementLists(expected.units, actual.units);
506 }
507
508 void _compareLocalVariableElements(
509 LocalVariableElement expected, LocalVariableElement actual) {
510 // TODO(brianwilkerson) Implement this
511 _compareGenericElements(expected, actual);
512 }
513
514 void _compareMetadata(
515 List<ElementAnnotation> expected, List<ElementAnnotation> actual) {
516 // TODO(brianwilkerson) Implement this
517 }
518
519 void _compareMethodElements(MethodElement expected, MethodElement actual) {
520 // TODO(brianwilkerson) Implement this
521 _compareExecutableElements(expected, actual, 'method');
522 //
523 // Compare attributes.
524 //
525 if (expected.isStatic != actual.isStatic) {
526 _writeMismatch(
527 expected,
528 actual,
529 (Object element) => (element as FieldElement).isStatic
530 ? 'a static field'
531 : 'an instance field');
532 }
533 }
534
535 void _compareMultiplyDefinedElements(
536 MultiplyDefinedElement expected, MultiplyDefinedElement actual) {
537 // TODO(brianwilkerson) Implement this
538 }
539
540 void _compareParameterElements(
541 ParameterElement expected, ParameterElement actual) {
542 // TODO(brianwilkerson) Implement this
543 _compareGenericElements(expected, actual);
544 }
545
546 void _comparePrefixElements(PrefixElement expected, PrefixElement actual) {
547 // TODO(brianwilkerson) Implement this
548 _compareGenericElements(expected, actual);
549 }
550
551 void _comparePropertyAccessorElements(
552 PropertyAccessorElement expected, PropertyAccessorElement actual) {
553 // TODO(brianwilkerson) Implement this
554 _compareGenericElements(expected, actual);
555 }
556
557 void _comparePropertyInducingElements(PropertyInducingElement expected,
558 PropertyInducingElement actual, String kind) {
559 _compareVariableElements(expected, actual, kind);
560 }
561
562 void _compareTopLevelVariableElements(
563 TopLevelVariableElement expected, TopLevelVariableElement actual) {
564 // TODO(brianwilkerson) Implement this
565 _compareGenericElements(expected, actual);
566 }
567
568 void _compareTypeLists(String descriptor, List<InterfaceType> expected,
569 List<InterfaceType> actual) {
570 int expectedLength = expected.length;
571 if (expectedLength != actual.length) {
572 _write('Expected ');
573 _write(expectedLength);
574 _write(' ');
575 _write(descriptor);
576 _write('s; found ');
577 _write(actual.length);
578 } else {
579 for (int i = 0; i < expectedLength; i++) {
580 _compareTypes(descriptor, expected[i], actual[i]);
581 }
582 }
583 }
584
585 void _compareTypeParameterElements(
586 TypeParameterElement expected, TypeParameterElement actual) {
587 // TODO(brianwilkerson) Implement this
588 _compareGenericElements(expected, actual);
589 expected.bound;
590 }
591
592 void _compareTypes(String descriptor, DartType expected, DartType actual) {
593 void compareNames() {
594 if (expected.name != actual.name) {
595 _write('Expected a ');
596 _write(descriptor);
597 _write(' named ');
598 _write(expected.name);
599 _write('; found a ');
600 _write(descriptor);
601 _write(' named ');
602 _write(actual.name);
603 }
604 }
605
606 void compareTypeArguments(
607 ParameterizedType expected, ParameterizedType actual) {
608 List<DartType> expectedArguments = expected.typeArguments;
609 List<DartType> actualArguments = actual.typeArguments;
610 int expectedLength = expectedArguments.length;
611 if (expectedLength != actualArguments.length) {
612 _write('Expected ');
613 _write(expectedLength);
614 _write(' type arguments; found ');
615 _write(actualArguments.length);
616 } else {
617 for (int i = 0; i < expectedLength; i++) {
618 _compareTypes(
619 'type argument', expectedArguments[i], actualArguments[i]);
620 }
621 }
622 }
623
624 if (expected == null) {
625 if (actual != null) {
626 _write('Expected no ');
627 _write(descriptor);
628 _write('; found a ');
629 _write(descriptor);
630 _write(' named ');
631 _write(actual.name);
632 }
633 } else if (actual == null) {
634 _write('Expected a ');
635 _write(descriptor);
636 _write(' named ');
637 _write(expected.name);
638 _write('; found none');
639 } else if ((expected.isBottom && actual.isBottom) ||
640 (expected.isDynamic && actual.isDynamic) ||
641 (expected.isVoid && actual.isVoid)) {
642 // The types are the same
643 } else if (expected is InterfaceType && actual is InterfaceType) {
644 compareNames();
645 compareTypeArguments(expected, actual);
646 } else if (expected is FunctionType && actual is FunctionType) {
647 compareNames();
648 compareTypeArguments(expected, actual);
649 } else if (expected is TypeParameterType && actual is TypeParameterType) {
650 compareNames();
651 _compareTypes('bound', expected.element.bound, actual.element.bound);
652 } else {
653 _write('Expected an instance of ');
654 _write(expected.runtimeType);
655 _write(' named ');
656 _write(expected.name);
657 _write('; found an instance of ');
658 _writeln(actual.runtimeType);
659 _write(' named ');
660 _write(actual.name);
661 }
662 }
663
664 void _compareUriReferencedElements(
665 UriReferencedElement expected, UriReferencedElement actual) {
666 _compareGenericElements(expected, actual);
667 //
668 // Compare attributes.
669 //
670 if (expected.uri != actual.uri) {
671 _write('Expected a uri of ');
672 _write(expected.uri);
673 _write('; found ');
674 _writeln(actual.uri);
675 }
676 if (expected.uriOffset != actual.uriOffset) {
677 _write('Expected a uri offset of ');
678 _write(expected.uriOffset);
679 _write('; found ');
680 _writeln(actual.uriOffset);
681 }
682 }
683
684 void _compareVariableElements(
685 VariableElement expected, VariableElement actual, String kind) {
686 _compareGenericElements(expected, actual);
687 //
688 // Compare attributes.
689 //
690 if ((expected.constantValue == null) != (actual.constantValue == null)) {
691 // TODO(brianwilkerson) Check for more than existence.
692 _writeMismatch(
693 expected,
694 actual,
695 (Object element) => (element as VariableElement).constantValue == null
696 ? 'a $kind with no constant value'
697 : 'a $kind with a constant value');
698 }
699 if (expected.hasImplicitType != actual.hasImplicitType) {
700 _writeMismatch(
701 expected,
702 actual,
703 (Object element) => (element as VariableElement).hasImplicitType
704 ? 'a $kind with an implicit type'
705 : 'a $kind with an explicit type');
706 }
707 if (expected.isConst != actual.isConst) {
708 _writeMismatch(
709 expected,
710 actual,
711 (Object element) => (element as VariableElement).isConst
712 ? 'a const $kind'
713 : 'a non-const $kind');
714 }
715 if (expected.isFinal != actual.isFinal) {
716 _writeMismatch(
717 expected,
718 actual,
719 (Object element) => (element as VariableElement).isFinal
720 ? 'a final $kind'
721 : 'a non-final $kind');
722 }
723 if (expected.isStatic != actual.isStatic) {
724 _writeMismatch(
725 expected,
726 actual,
727 (Object element) => (element as VariableElement).isStatic
728 ? 'a static $kind'
729 : 'an instance $kind');
730 }
731 //
732 // Compare children.
733 //
734 compareElements(expected.initializer, actual.initializer);
735 }
736
737 void _write(Object value) {
738 if (_needsLineBreak) {
739 _buffer.write('</p><p>');
740 _needsLineBreak = false;
741 }
742 _buffer.write(value);
743 }
744
745 void _writeln(Object value) {
746 _buffer.write(value);
747 _needsLineBreak = true;
748 }
749
750 /**
751 * Write a simple message explaining that the [expected] and [actual] values
752 * were different, using the [describe] function to describe the values.
753 */
754 void _writeMismatch/*<E>*/(Object/*=E*/ expected, Object/*=E*/ actual,
755 String describe(Object/*=E*/ value)) {
756 _write('Expected ');
757 _write(describe(expected));
758 _write('; found ');
759 _writeln(describe(actual));
760 }
761 }
762
763 /**
764 * The comparison of two analyses of the same target.
765 */
766 class EntryComparison {
767 /**
768 * The target that was analyzed.
769 */
770 final AnalysisTarget target;
771
772 /**
773 * The cache entry from the original context.
774 */
775 final CacheEntry originalEntry;
776
777 /**
778 * The cache entry from the re-analysis in a cloned context.
779 */
780 final CacheEntry cloneEntry;
781
782 /**
783 * A flag indicating whether the target is obsolete. A target is obsolete if
784 * it is an element in an element model that was replaced at a some point.
785 */
786 bool obsoleteTarget = false;
787
788 /**
789 * A table mapping the results that were computed for the target to
790 * comparisons of the values of those results. The table only contains entries
791 * for results for which the comparison produced interesting data.
792 */
793 Map<ResultDescriptor, ResultComparison> resultMap =
794 new HashMap<ResultDescriptor, ResultComparison>();
795
796 /**
797 * Initialize a newly created comparison of the given [target]'s analysis,
798 * given the [originalEntry] from the original context and the [cloneEntry]
799 * from the cloned context.
800 */
801 EntryComparison(this.target, this.originalEntry, this.cloneEntry) {
802 _performComparison();
803 }
804
805 /**
806 * Return `true` if there is something interesting about the analysis of this
807 * target that should be reported.
808 */
809 bool hasInterestingState() => obsoleteTarget || resultMap.isNotEmpty;
810
811 /**
812 * Write an HTML formatted description of the validation results to the given
813 * [buffer].
814 */
815 void writeOn(StringBuffer buffer) {
816 buffer.write('<p>');
817 buffer.write(target);
818 buffer.write('</p>');
819 buffer.write('<blockquote>');
820 if (obsoleteTarget) {
821 buffer.write('<p><b>This target is obsolete.</b></p>');
822 }
823 List<ResultDescriptor> results = resultMap.keys.toList();
824 results.sort((ResultDescriptor first, ResultDescriptor second) =>
825 first.toString().compareTo(second.toString()));
826 for (ResultDescriptor result in results) {
827 resultMap[result].writeOn(buffer);
828 }
829 buffer.write('</blockquote>');
830 }
831
832 /**
833 * Compare all of the results that were computed in the two contexts, adding
834 * the interesting comparisons to the [resultMap].
835 */
836 void _compareResults() {
837 Set<ResultDescriptor> results = new Set<ResultDescriptor>();
838 results.addAll(originalEntry.nonInvalidResults);
839 results.addAll(cloneEntry.nonInvalidResults);
840
841 for (ResultDescriptor result in results) {
842 ResultComparison difference = new ResultComparison(this, result);
843 if (difference.hasInterestingState()) {
844 resultMap[result] = difference;
845 }
846 }
847 }
848
849 /**
850 * Return `true` if the target of this entry is an obsolete element.
851 */
852 bool _isTargetObsolete() {
853 if (target is Element) {
854 LibraryElement library = (target as Element).library;
855 AnalysisContextImpl context = library.context;
856 CacheEntry entry = context.analysisCache.get(library.source);
857 LibraryElement value = entry.getValue(LIBRARY_ELEMENT);
858 return value != library;
859 }
860 return false;
861 }
862
863 /**
864 * Determine whether or not there is any interesting difference between the
865 * original and cloned contexts.
866 */
867 void _performComparison() {
868 obsoleteTarget = _isTargetObsolete();
869 _compareResults();
870 }
871 }
872
873 /**
874 * The comparison of the value of a single result computed for a single target.
875 */
876 class ResultComparison {
877 /**
878 * The entry for the target for which the result was computed.
879 */
880 final EntryComparison entry;
881
882 /**
883 * The result that was computed for the target.
884 */
885 final ResultDescriptor result;
886
887 /**
888 * A flag indicating whether the state of the result is different.
889 */
890 bool differentStates = false;
891
892 /**
893 * The result of comparing the values of the results, or `null` if the states
894 * are different or if the values are the same.
895 */
896 ValueComparison valueComparison;
897
898 /**
899 * Initialize a newly created result comparison.
900 */
901 ResultComparison(this.entry, this.result) {
902 _performComparison();
903 }
904
905 /**
906 * Return `true` if this object represents a difference between the original
907 * and cloned contexts.
908 */
909 bool hasInterestingState() => differentStates || valueComparison != null;
910
911 /**
912 * Write an HTML formatted description of the validation results to the given
913 * [buffer].
914 */
915 void writeOn(StringBuffer buffer) {
916 buffer.write('<p>');
917 buffer.write(result);
918 buffer.write('</p>');
919 buffer.write('<blockquote>');
920 if (differentStates) {
921 CacheState originalState = entry.originalEntry.getState(result);
922 CacheState cloneState = entry.cloneEntry.getState(result);
923 buffer.write('<p>Original state = ');
924 buffer.write(originalState.name);
925 buffer.write('; clone state = ');
926 buffer.write(cloneState.name);
927 buffer.write('</p>');
928 }
929 if (valueComparison != null) {
930 valueComparison.writeOn(buffer);
931 }
932 buffer.write('</blockquote>');
933 }
934
935 /**
936 * Determine whether the state of the result is different between the
937 * original and cloned contexts.
938 */
939 bool _areStatesDifferent(CacheState originalState, CacheState cloneState) {
940 if (originalState == cloneState) {
941 return false;
942 } else if (originalState == CacheState.FLUSHED &&
943 cloneState == CacheState.VALID) {
944 return false;
945 } else if (originalState == CacheState.VALID &&
946 cloneState == CacheState.FLUSHED) {
947 return false;
948 }
949 return true;
950 }
951
952 /**
953 * Determine whether the value of the result is different between the
954 * original and cloned contexts.
955 */
956 void _compareValues(CacheState originalState, CacheState cloneState) {
957 if (originalState != cloneState || originalState != CacheState.VALID) {
958 return null;
959 }
960 ValueComparison comparison = new ValueComparison(
961 entry.originalEntry.getValue(result),
962 entry.cloneEntry.getValue(result));
963 if (comparison.hasInterestingState()) {
964 valueComparison = comparison;
965 }
966 }
967
968 /**
969 * Determine whether or not there is any interesting difference between the
970 * original and cloned contexts.
971 */
972 void _performComparison() {
973 CacheState originalState = entry.originalEntry.getState(result);
974 CacheState cloneState = entry.cloneEntry.getState(result);
975 if (_areStatesDifferent(originalState, cloneState)) {
976 differentStates = true;
977 _compareValues(originalState, cloneState);
978 }
979 }
980 }
981
982 /**
983 * The results of validating an analysis context.
984 *
985 * Validation is done by re-analyzing all of the explicitly added source in a
986 * new analysis context that is configured to be the same as the original
987 * context.
988 */
989 class ValidationResults {
990 /**
991 * A set of targets that were in the original context that were not included
992 * in the re-created context.
993 */
994 Set<AnalysisTarget> extraTargets;
995
996 /**
997 * A set of targets that were in the re-created context that were not included
998 * in the original context.
999 */
1000 Set<AnalysisTarget> missingTargets;
1001
1002 /**
1003 * A table, keyed by targets, whose values are comparisons of the analysis of
1004 * those targets. The table only contains entries for targets for which the
1005 * comparison produced interesting data.
1006 */
1007 Map<AnalysisTarget, EntryComparison> targetMap =
1008 new HashMap<AnalysisTarget, EntryComparison>();
1009
1010 /**
1011 * Initialize a newly created validation result by validating the given
1012 * [context].
1013 */
1014 ValidationResults(AnalysisContextImpl context) {
1015 _validate(context);
1016 }
1017
1018 /**
1019 * Write an HTML formatted description of the validation results to the given
1020 * [buffer].
1021 */
1022 void writeOn(StringBuffer buffer) {
1023 if (extraTargets.isEmpty && missingTargets.isEmpty && targetMap.isEmpty) {
1024 buffer.write('<p>No interesting results.</p>');
1025 return;
1026 }
1027 if (extraTargets.isNotEmpty) {
1028 buffer.write('<h4>Extra Targets</h4>');
1029 buffer.write('<p style="commentary">');
1030 buffer.write('Targets that exist in the original context that were not ');
1031 buffer.write('re-created in the cloned context.');
1032 buffer.write('</p>');
1033 _writeTargetList(buffer, extraTargets.toList());
1034 }
1035 if (missingTargets.isNotEmpty) {
1036 buffer.write('<h4>Missing Targets</h4>');
1037 buffer.write('<p style="commentary">');
1038 buffer.write('Targets that do <b>not</b> exist in the original context ');
1039 buffer.write('but do exist in the cloned context.');
1040 buffer.write('</p>');
1041 _writeTargetList(buffer, missingTargets.toList());
1042 }
1043 if (targetMap.isNotEmpty) {
1044 buffer.write('<h4>Differing Targets</h4>');
1045 // TODO(brianwilkerson) Sort the list of targets.
1046 for (EntryComparison comparison in targetMap.values) {
1047 comparison.writeOn(buffer);
1048 }
1049 }
1050 }
1051
1052 /**
1053 * Analyze all of the explicit sources in the given [context].
1054 */
1055 void _analyze(AnalysisContextImpl context) {
1056 while (true) {
1057 AnalysisResult result = context.performAnalysisTask();
1058 if (!result.hasMoreWork) {
1059 return;
1060 }
1061 }
1062 }
1063
1064 /**
1065 * Create and return a new analysis context that will analyze files in the
1066 * same way as the given [context].
1067 */
1068 AnalysisContextImpl _clone(AnalysisContextImpl context) {
1069 AnalysisContextImpl clone = AnalysisEngine.instance.createAnalysisContext();
1070
1071 clone.analysisOptions = context.analysisOptions;
1072 //clone.declaredVariables = context.declaredVariables;
1073 clone.sourceFactory = context.sourceFactory.clone();
1074 // TODO(brianwilkerson) Check content cache. We either need to copy the
1075 // cache into the clone or ensure that the context's cache is empty.
1076
1077 ChangeSet changeSet = new ChangeSet();
1078 for (AnalysisTarget target in context.explicitTargets) {
1079 if (target is Source) {
1080 changeSet.addedSource(target);
1081 }
1082 }
1083 clone.applyChanges(changeSet);
1084 return clone;
1085 }
1086
1087 /**
1088 * Compare the results produced in the [original] context to those produced in
1089 * the [clone].
1090 */
1091 void _compareContexts(
1092 AnalysisContextImpl original, AnalysisContextImpl clone) {
1093 AnalysisCache originalCache = original.analysisCache;
1094 AnalysisCache cloneCache = clone.analysisCache;
1095 List<AnalysisTarget> originalTargets = _getKeys(original, originalCache);
1096 List<AnalysisTarget> cloneTargets = _getKeys(clone, cloneCache);
1097
1098 extraTargets =
1099 new HashSet<AnalysisTarget>(equals: _equal, hashCode: _hashCode);
1100 extraTargets.addAll(originalTargets);
1101 extraTargets.removeAll(cloneTargets);
1102
1103 missingTargets =
1104 new HashSet<AnalysisTarget>(equals: _equal, hashCode: _hashCode);
1105 missingTargets.addAll(cloneTargets);
1106 missingTargets.removeAll(originalTargets);
1107
1108 for (AnalysisTarget cloneTarget in cloneTargets) {
1109 if (!missingTargets.contains(cloneTarget)) {
1110 AnalysisTarget originalTarget = _find(originalTargets, cloneTarget);
1111 CacheEntry originalEntry = originalCache.get(originalTarget);
1112 CacheEntry cloneEntry = cloneCache.get(cloneTarget);
1113 EntryComparison comparison =
1114 new EntryComparison(cloneTarget, originalEntry, cloneEntry);
1115 if (comparison.hasInterestingState()) {
1116 targetMap[cloneTarget] = comparison;
1117 }
1118 }
1119 }
1120 }
1121
1122 /**
1123 * Find the target in the list of [originalTargets] that is equal to the
1124 * [cloneTarget].
1125 */
1126 AnalysisTarget _find(
1127 List<AnalysisTarget> originalTargets, AnalysisTarget cloneTarget) {
1128 for (AnalysisTarget originalTarget in originalTargets) {
1129 if (_equal(originalTarget, cloneTarget)) {
1130 return originalTarget;
1131 }
1132 }
1133 return null;
1134 }
1135
1136 /**
1137 * Return a list of the analysis targets in the given [cache] that are owned
1138 * by the given [context].
1139 */
1140 List<AnalysisTarget> _getKeys(
1141 AnalysisContextImpl context, AnalysisCache cache) {
1142 List<AnalysisTarget> targets = <AnalysisTarget>[];
1143 MapIterator<AnalysisTarget, CacheEntry> iterator =
1144 cache.iterator(context: context);
1145 while (iterator.moveNext()) {
1146 targets.add(iterator.key);
1147 }
1148 return targets;
1149 }
1150
1151 /**
1152 * Validate the given [context].
1153 */
1154 void _validate(AnalysisContextImpl context) {
1155 AnalysisContextImpl clone = _clone(context);
1156 _analyze(clone);
1157 _compareContexts(context, clone);
1158 }
1159
1160 /**
1161 * Write the list of [targets] to the [buffer].
1162 */
1163 void _writeTargetList(StringBuffer buffer, List<AnalysisTarget> targets) {
1164 // TODO(brianwilkerson) Sort the list of targets.
1165 //targets.sort();
1166 for (AnalysisTarget target in targets) {
1167 buffer.write('<p>');
1168 buffer.write(target);
1169 buffer.write(' (');
1170 buffer.write(target.runtimeType);
1171 buffer.write(')');
1172 buffer.write('</p>');
1173 }
1174 }
1175
1176 /**
1177 * Return `true` if the [first] and [second] objects are equal.
1178 */
1179 static bool _equal(Object first, Object second) {
1180 //
1181 // Compare possible null values.
1182 //
1183 if (first == null) {
1184 return second == null;
1185 } else if (second == null) {
1186 return false;
1187 }
1188 //
1189 // Handle special cases.
1190 //
1191 if (first is ElementAnnotationImpl && second is ElementAnnotationImpl) {
1192 return _equal(first.source, second.source) &&
1193 _equal(first.librarySource, second.librarySource) &&
1194 _equal(first.annotationAst, second.annotationAst);
1195 } else if (first is AstNode && second is AstNode) {
1196 return first.runtimeType == second.runtimeType &&
1197 first.offset == second.offset &&
1198 first.length == second.length;
1199 }
1200 //
1201 // Handle the general case.
1202 //
1203 return first == second;
1204 }
1205
1206 /**
1207 * Return a hash code for the given [object].
1208 */
1209 static int _hashCode(Object object) {
1210 //
1211 // Handle special cases.
1212 //
1213 if (object is ElementAnnotation) {
1214 return object.source.hashCode;
1215 } else if (object is AstNode) {
1216 return object.offset;
1217 }
1218 //
1219 // Handle the general case.
1220 //
1221 return object.hashCode;
1222 }
1223 }
1224
1225 class ValueComparison {
1226 /**
1227 * The result value from the original context.
1228 */
1229 final Object originalValue;
1230
1231 /**
1232 * The result value from the cloned context.
1233 */
1234 final Object cloneValue;
1235
1236 /**
1237 * A description of the difference between the original and clone values, or
1238 * `null` if the values are equal.
1239 */
1240 String description = null;
1241
1242 /**
1243 * Initialize a newly created value comparison to represents the difference,
1244 * if any, between the [originalValue] and the [cloneValue].
1245 */
1246 ValueComparison(this.originalValue, this.cloneValue) {
1247 _performComparison();
1248 }
1249
1250 /**
1251 * Return `true` if this object represents a difference between the original
1252 * and cloned values.
1253 */
1254 bool hasInterestingState() => description != null;
1255
1256 /**
1257 * Write an HTML formatted description of the validation results to the given
1258 * [buffer].
1259 */
1260 void writeOn(StringBuffer buffer) {
1261 buffer.write('<p>');
1262 buffer.write(description);
1263 buffer.write('</p>');
1264 }
1265
1266 bool _compareAnalysisErrors(
1267 AnalysisError expected, AnalysisError actual, StringBuffer buffer) {
1268 if (actual.errorCode == expected.errorCode &&
1269 actual.source == expected.source &&
1270 actual.offset == expected.offset) {
1271 return true;
1272 }
1273 if (buffer != null) {
1274 void write(AnalysisError originalError) {
1275 buffer.write('a ');
1276 buffer.write(originalError.errorCode.uniqueName);
1277 buffer.write(' in ');
1278 buffer.write(originalError.source.fullName);
1279 buffer.write(' at ');
1280 buffer.write(originalError.offset);
1281 }
1282
1283 buffer.write('Expected ');
1284 write(expected);
1285 buffer.write('; found ');
1286 write(actual);
1287 }
1288 return false;
1289 }
1290
1291 bool _compareAstNodes(AstNode expected, AstNode actual, StringBuffer buffer) {
1292 if (AstComparator.equalNodes(actual, expected)) {
1293 return true;
1294 }
1295 if (buffer != null) {
1296 // TODO(brianwilkerson) Compute where the difference is rather than just
1297 // whether there is a difference.
1298 buffer.write('Different AST nodes');
1299 }
1300 return false;
1301 }
1302
1303 bool _compareConstantEvaluationTargets(ConstantEvaluationTarget expected,
1304 ConstantEvaluationTarget actual, StringBuffer buffer) {
1305 if (actual is ElementAnnotation) {
1306 ElementAnnotationImpl expectedAnnotation = expected;
1307 ElementAnnotationImpl actualAnnotation = actual;
1308 if (actualAnnotation.source == expectedAnnotation.source &&
1309 actualAnnotation.librarySource == expectedAnnotation.librarySource &&
1310 actualAnnotation.annotationAst == expectedAnnotation.annotationAst) {
1311 return true;
1312 }
1313 if (buffer != null) {
1314 void write(ElementAnnotationImpl target) {
1315 Annotation annotation = target.annotationAst;
1316 buffer.write(annotation);
1317 buffer.write(' at ');
1318 buffer.write(annotation.offset);
1319 buffer.write(' in ');
1320 buffer.write(target.source);
1321 buffer.write(' in ');
1322 buffer.write(target.librarySource);
1323 }
1324
1325 buffer.write('Expected ');
1326 write(expectedAnnotation);
1327 buffer.write('; found ');
1328 write(actualAnnotation);
1329 }
1330 return false;
1331 }
1332 if (buffer != null) {
1333 buffer.write('Unknown class of ConstantEvaluationTarget: ');
1334 buffer.write(actual.runtimeType);
1335 }
1336 return false;
1337 }
1338
1339 bool _compareDartScripts(
1340 DartScript expected, DartScript actual, StringBuffer buffer) {
1341 // TODO(brianwilkerson) Implement this.
1342 return true;
1343 }
1344
1345 bool _compareDocuments(
1346 html.Document expected, html.Document actual, StringBuffer buffer) {
1347 // TODO(brianwilkerson) Implement this.
1348 return true;
1349 }
1350
1351 bool _compareElements(Element expected, Element actual, StringBuffer buffer) {
1352 ElementComparator comparator = new ElementComparator();
1353 comparator.compareElements(expected, actual);
1354 if (comparator.hasDifference) {
1355 if (buffer != null) {
1356 buffer.write(comparator.description);
1357 }
1358 return false;
1359 }
1360 return true;
1361 }
1362
1363 bool _compareLibrarySpecificUnits(LibrarySpecificUnit expected,
1364 LibrarySpecificUnit actual, StringBuffer buffer) {
1365 if (actual.library.fullName == expected.library.fullName &&
1366 actual.unit.fullName == expected.unit.fullName) {
1367 return true;
1368 }
1369 if (buffer != null) {
1370 buffer.write('Expected ');
1371 buffer.write(expected);
1372 buffer.write('; found ');
1373 buffer.write(actual);
1374 }
1375 return false;
1376 }
1377
1378 bool _compareLineInfos(
1379 LineInfo expected, LineInfo actual, StringBuffer buffer) {
1380 // TODO(brianwilkerson) Implement this.
1381 return true;
1382 }
1383
1384 bool _compareLists(List expected, List actual, StringBuffer buffer) {
1385 int expectedLength = expected.length;
1386 int actualLength = actual.length;
1387 int left = 0;
1388 while (left < expectedLength &&
1389 left < actualLength &&
1390 _compareObjects(expected[left], actual[left], null)) {
1391 left++;
1392 }
1393 if (left == actualLength) {
1394 if (left == expectedLength) {
1395 // The lists are the same length and the elements are equal.
1396 return true;
1397 }
1398 if (buffer != null) {
1399 buffer.write('Expected a list of length ');
1400 buffer.write(expectedLength);
1401 buffer.write('; found a list of length ');
1402 buffer.write(actualLength);
1403 buffer.write(' that was a prefix of the expected list');
1404 }
1405 return false;
1406 } else if (left == expectedLength) {
1407 if (buffer != null) {
1408 buffer.write('Expected a list of length ');
1409 buffer.write(expectedLength);
1410 buffer.write('; found a list of length ');
1411 buffer.write(actualLength);
1412 buffer.write(' that was an extension of the expected list');
1413 }
1414 return false;
1415 }
1416 int expectedRight = expectedLength - 1;
1417 int actualRight = actualLength - 1;
1418 while (expectedRight > left &&
1419 actualRight > left &&
1420 _compareObjects(expected[expectedRight], actual[actualRight], null)) {
1421 actualRight--;
1422 expectedRight--;
1423 }
1424 if (buffer != null) {
1425 void write(int left, int right, int length) {
1426 buffer.write('the elements (');
1427 buffer.write(left);
1428 buffer.write('..');
1429 buffer.write(right);
1430 buffer.write(') in a list of length ');
1431 buffer.write(length);
1432 }
1433
1434 buffer.write('Expected ');
1435 write(left, expectedRight, expectedLength);
1436 buffer.write(' to match ');
1437 write(left, actualRight, actualLength);
1438 buffer.write(' but they did not');
1439 }
1440 return false;
1441 }
1442
1443 /**
1444 * Return `true` if the [expected] and [actual] objects are equal. If they are
1445 * not equal, and the given [buffer] is not `null`, then a description of the
1446 * difference will be written to the [buffer].
1447 */
1448 bool _compareObjects(Object expected, Object actual, StringBuffer buffer) {
1449 //
1450 // Compare possible null values.
1451 //
1452 if (actual == null) {
1453 if (expected == null) {
1454 return true;
1455 } else {
1456 if (buffer != null) {
1457 buffer.write('Expected an instance of ');
1458 buffer.write(expected.runtimeType);
1459 buffer.write('; found null');
1460 }
1461 return false;
1462 }
1463 }
1464 Type actualType = actual.runtimeType;
1465 if (expected == null) {
1466 if (buffer != null) {
1467 buffer.write('Expected null; found an instance of ');
1468 buffer.write(actualType);
1469 }
1470 return false;
1471 }
1472 Type expectedType = expected.runtimeType;
1473 //
1474 // Compare the types.
1475 //
1476 if (expectedType != actualType) {
1477 if (buffer != null) {
1478 buffer.write('Expected an instance of ');
1479 buffer.write(expectedType);
1480 buffer.write('; found an instance of ');
1481 buffer.write(actualType);
1482 }
1483 return false;
1484 }
1485 //
1486 // Compare non-null values of the same type.
1487 //
1488 if (actual is bool) {
1489 return _comparePrimitives(expected, actual, buffer);
1490 } else if (actual is int) {
1491 return _comparePrimitives(expected, actual, buffer);
1492 } else if (actual is String) {
1493 return _compareStrings(expected, actual, buffer);
1494 } else if (actual is List) {
1495 return _compareLists(expected, actual, buffer);
1496 } else if (actual is AnalysisError) {
1497 return _compareAnalysisErrors(expected, actual, buffer);
1498 } else if (actual is AstNode) {
1499 return _compareAstNodes(expected, actual, buffer);
1500 } else if (actual is DartScript) {
1501 return _compareDartScripts(expected, actual, buffer);
1502 } else if (actual is html.Document) {
1503 return _compareDocuments(expected, actual, buffer);
1504 } else if (actual is Element) {
1505 return _compareElements(expected, actual, buffer);
1506 } else if (actual is LibrarySpecificUnit) {
1507 return _compareLibrarySpecificUnits(expected, actual, buffer);
1508 } else if (actual is LineInfo) {
1509 return _compareLineInfos(expected, actual, buffer);
1510 } else if (actual is Source) {
1511 return _compareSources(expected, actual, buffer);
1512 } else if (actual is SourceKind) {
1513 return _comparePrimitives(expected, actual, buffer);
1514 } else if (actual is Token) {
1515 return _compareTokenStreams(expected, actual, buffer);
1516 } else if (actual is TypeProvider) {
1517 return true;
1518 } else if (actual is UsedLocalElements) {
1519 return _compareUsedLocalElements(expected, actual, buffer);
1520 } else if (actual is UsedImportedElements) {
1521 return _compareUsedImportedElements(expected, actual, buffer);
1522 } else if (actual is ConstantEvaluationTarget) {
1523 return _compareConstantEvaluationTargets(expected, actual, buffer);
1524 }
1525 if (buffer != null) {
1526 buffer.write('Cannot compare values of type ');
1527 buffer.write(actualType);
1528 }
1529 return false;
1530 }
1531
1532 bool _comparePrimitives(Object expected, Object actual, StringBuffer buffer) {
1533 if (actual == expected) {
1534 return true;
1535 }
1536 if (buffer != null) {
1537 buffer.write('Expected ');
1538 buffer.write(expected);
1539 buffer.write('; found ');
1540 buffer.write(actual);
1541 }
1542 return false;
1543 }
1544
1545 bool _compareSources(Source expected, Source actual, StringBuffer buffer) {
1546 if (actual.fullName == expected.fullName) {
1547 return true;
1548 }
1549 if (buffer != null) {
1550 buffer.write('Expected a source for ');
1551 buffer.write(expected.fullName);
1552 buffer.write('; found a source for ');
1553 buffer.write(actual.fullName);
1554 }
1555 return false;
1556 }
1557
1558 bool _compareStrings(String expected, String actual, StringBuffer buffer) {
1559 if (actual == expected) {
1560 return true;
1561 }
1562 int expectedLength = expected.length;
1563 int actualLength = actual.length;
1564 int left = 0;
1565 while (left < actualLength &&
1566 left < expectedLength &&
1567 actual.codeUnitAt(left) == expected.codeUnitAt(left)) {
1568 left++;
1569 }
1570 if (left == actualLength) {
1571 if (buffer != null) {
1572 buffer.write('Expected ...[');
1573 buffer.write(expected.substring(left));
1574 buffer.write(']; found ...[]');
1575 }
1576 return false;
1577 } else if (left == expectedLength) {
1578 if (buffer != null) {
1579 buffer.write('Expected ...[]; found ...[');
1580 buffer.write(actual.substring(left));
1581 buffer.write(']');
1582 }
1583 return false;
1584 }
1585 int actualRight = actualLength - 1;
1586 int expectedRight = expectedLength - 1;
1587 while (actualRight > left &&
1588 expectedRight > left &&
1589 actual.codeUnitAt(actualRight) == expected.codeUnitAt(expectedRight)) {
1590 actualRight--;
1591 expectedRight--;
1592 }
1593 if (buffer != null) {
1594 void write(String string, int left, int right) {
1595 buffer.write('...[');
1596 buffer.write(string.substring(left, right));
1597 buffer.write(']... (');
1598 buffer.write(left);
1599 buffer.write('..');
1600 buffer.write(right);
1601 buffer.write(')');
1602 }
1603
1604 buffer.write('Expected ');
1605 write(expected, left, expectedRight);
1606 buffer.write('; found ');
1607 write(actual, left, actualRight);
1608 }
1609 return false;
1610 }
1611
1612 bool _compareTokenStreams(Token expected, Token actual, StringBuffer buffer) {
1613 bool equals(Token originalToken, Token cloneToken) {
1614 return originalToken.type == cloneToken.type &&
1615 originalToken.offset == cloneToken.offset &&
1616 originalToken.lexeme == cloneToken.lexeme;
1617 }
1618
1619 Token actualLeft = actual;
1620 Token expectedLeft = expected;
1621 while (actualLeft.type != TokenType.EOF &&
1622 expectedLeft.type != TokenType.EOF &&
1623 equals(actualLeft, expectedLeft)) {
1624 actualLeft = actualLeft.next;
1625 expectedLeft = expectedLeft.next;
1626 }
1627 if (actualLeft.type == TokenType.EOF &&
1628 expectedLeft.type == TokenType.EOF) {
1629 return true;
1630 }
1631 if (buffer != null) {
1632 void write(Token token) {
1633 buffer.write(token.type);
1634 buffer.write(' at ');
1635 buffer.write(token.offset);
1636 buffer.write(' (');
1637 buffer.write(token.lexeme);
1638 buffer.write(')');
1639 }
1640
1641 buffer.write('Expected ');
1642 write(expectedLeft);
1643 buffer.write('; found ');
1644 write(actualLeft);
1645 }
1646 return false;
1647 }
1648
1649 bool _compareUsedImportedElements(UsedImportedElements expected,
1650 UsedImportedElements actual, StringBuffer buffer) {
1651 // TODO(brianwilkerson) Implement this.
1652 return true;
1653 }
1654
1655 bool _compareUsedLocalElements(UsedLocalElements expected,
1656 UsedLocalElements actual, StringBuffer buffer) {
1657 // TODO(brianwilkerson) Implement this.
1658 return true;
1659 }
1660
1661 /**
1662 * Determine whether or not there is any interesting difference between the
1663 * original and cloned values.
1664 */
1665 void _performComparison() {
1666 StringBuffer buffer = new StringBuffer();
1667 if (!_compareObjects(cloneValue, originalValue, buffer)) {
1668 description = buffer.toString();
1669 }
1670 }
1671 }
OLDNEW
« no previous file with comments | « pkg/analysis_server/lib/src/status/memory_use.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698