OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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 import 'dart:io'; | 5 import 'dart:io'; |
6 | 6 |
7 import 'package:analyzer/dart/ast/ast.dart'; | 7 import 'package:analyzer/dart/ast/ast.dart'; |
8 import 'package:analyzer/dart/ast/token.dart'; | 8 import 'package:analyzer/dart/ast/token.dart'; |
9 import 'package:analyzer/dart/element/element.dart'; | 9 import 'package:analyzer/dart/element/element.dart'; |
10 import 'package:analyzer/dart/element/type.dart'; | 10 import 'package:analyzer/dart/element/type.dart'; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 new File(_testPath).writeAsStringSync(newCode); | 46 new File(_testPath).writeAsStringSync(newCode); |
47 } | 47 } |
48 } | 48 } |
49 | 49 |
50 /** | 50 /** |
51 * Write the given [library] elements into the canonical text presentation | 51 * Write the given [library] elements into the canonical text presentation |
52 * taking into account the specified 'withX' options. Then compare the | 52 * taking into account the specified 'withX' options. Then compare the |
53 * actual text with the given [expected] one. | 53 * actual text with the given [expected] one. |
54 */ | 54 */ |
55 void checkElementText(LibraryElement library, String expected, | 55 void checkElementText(LibraryElement library, String expected, |
56 {bool withOffsets: false}) { | 56 {bool withOffsets: false, |
57 var writer = new _ElementWriter(withOffsets: withOffsets); | 57 bool withSyntheticAccessors: false, |
| 58 bool withSyntheticFields: false}) { |
| 59 var writer = new _ElementWriter( |
| 60 withOffsets: withOffsets, |
| 61 withSyntheticAccessors: withSyntheticAccessors, |
| 62 withSyntheticFields: withSyntheticFields); |
58 writer.writeLibraryElement(library); | 63 writer.writeLibraryElement(library); |
59 | 64 |
60 String actualText = writer.buffer.toString(); | 65 String actualText = writer.buffer.toString(); |
61 actualText = | 66 actualText = |
62 actualText.split('\n').map((line) => line.trimRight()).join('\n'); | 67 actualText.split('\n').map((line) => line.trimRight()).join('\n'); |
63 | 68 |
64 if (_testPath != null && actualText != expected) { | 69 if (_testPath != null && actualText != expected) { |
65 if (_testCode == null) { | 70 if (_testCode == null) { |
66 _testCode = new File(_testPath).readAsStringSync(); | 71 _testCode = new File(_testPath).readAsStringSync(); |
67 _testCodeLines = new LineInfo.fromContent(_testCode); | 72 _testCodeLines = new LineInfo.fromContent(_testCode); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 | 115 |
111 expect(actualText, expected); | 116 expect(actualText, expected); |
112 } | 117 } |
113 | 118 |
114 /** | 119 /** |
115 * Writes the canonical text presentation of elements. | 120 * Writes the canonical text presentation of elements. |
116 */ | 121 */ |
117 class _ElementWriter { | 122 class _ElementWriter { |
118 final bool withOffsets; | 123 final bool withOffsets; |
119 final bool withConstElements; | 124 final bool withConstElements; |
| 125 final bool withSyntheticAccessors; |
| 126 final bool withSyntheticFields; |
120 final StringBuffer buffer = new StringBuffer(); | 127 final StringBuffer buffer = new StringBuffer(); |
121 | 128 |
122 _ElementWriter({this.withOffsets: false, this.withConstElements: true}); | 129 _ElementWriter( |
| 130 {this.withOffsets: false, |
| 131 this.withConstElements: true, |
| 132 this.withSyntheticAccessors, |
| 133 this.withSyntheticFields: false}); |
123 | 134 |
124 bool isDynamicType(DartType type) => type is DynamicTypeImpl; | 135 bool isDynamicType(DartType type) => type is DynamicTypeImpl; |
125 | 136 |
126 bool isEnumElement(Element e) { | 137 bool isEnumField(Element e) { |
127 return e is ClassElement && e.isEnum; | 138 Element enclosing = e.enclosingElement; |
| 139 return enclosing is ClassElement && enclosing.isEnum; |
128 } | 140 } |
129 | 141 |
130 void newLineIfNotEmpty() { | 142 void newLineIfNotEmpty() { |
131 if (buffer.isNotEmpty) { | 143 if (buffer.isNotEmpty) { |
132 buffer.writeln(); | 144 buffer.writeln(); |
133 } | 145 } |
134 } | 146 } |
135 | 147 |
136 void writeBodyModifiers(ExecutableElement e) { | 148 void writeBodyModifiers(ExecutableElement e) { |
137 if (e.isAsynchronous) { | 149 if (e.isAsynchronous) { |
(...skipping 30 matching lines...) Expand all Loading... |
168 e.mixins.isNotEmpty) { | 180 e.mixins.isNotEmpty) { |
169 buffer.write(' extends '); | 181 buffer.write(' extends '); |
170 writeType(e.supertype); | 182 writeType(e.supertype); |
171 } | 183 } |
172 | 184 |
173 writeList(' with ', '', e.mixins, ', ', writeType); | 185 writeList(' with ', '', e.mixins, ', ', writeType); |
174 writeList(' implements ', '', e.interfaces, ', ', writeType); | 186 writeList(' implements ', '', e.interfaces, ', ', writeType); |
175 | 187 |
176 buffer.writeln(' {'); | 188 buffer.writeln(' {'); |
177 | 189 |
178 e.fields.forEach(writeFieldElement); | 190 e.fields.forEach(writePropertyInducingElement); |
179 e.accessors.forEach(writePropertyAccessorElement); | 191 e.accessors.forEach(writePropertyAccessorElement); |
180 | 192 |
181 if (e.isEnum) { | 193 if (e.isEnum) { |
182 expect(e.constructors, isEmpty); | 194 expect(e.constructors, isEmpty); |
183 } else { | 195 } else { |
184 expect(e.constructors, isNotEmpty); | 196 expect(e.constructors, isNotEmpty); |
185 } | 197 } |
186 | 198 |
187 if (e.constructors.length == 1 && | 199 if (e.constructors.length == 1 && |
188 e.constructors[0].isSynthetic && | 200 e.constructors[0].isSynthetic && |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 } else if (e is TypeName) { | 415 } else if (e is TypeName) { |
404 writeExpression(e.name); | 416 writeExpression(e.name); |
405 if (e.typeArguments != null) { | 417 if (e.typeArguments != null) { |
406 writeList('<', '>', e.typeArguments.arguments, ', ', writeExpression); | 418 writeList('<', '>', e.typeArguments.arguments, ', ', writeExpression); |
407 } | 419 } |
408 } else { | 420 } else { |
409 fail('Unsupported expression type: ${e.runtimeType}'); | 421 fail('Unsupported expression type: ${e.runtimeType}'); |
410 } | 422 } |
411 } | 423 } |
412 | 424 |
413 void writeFieldElement(FieldElement e) { | |
414 if (e.isSynthetic && !isEnumElement(e.enclosingElement)) { | |
415 return; | |
416 } | |
417 | |
418 writeDocumentation(e, ' '); | |
419 writeMetadata(e, ' ', '\n'); | |
420 | |
421 buffer.write(' '); | |
422 | |
423 writeIf(e.isStatic, 'static '); | |
424 writeIf(e is FieldElementImpl && e.isCovariant, 'covariant '); | |
425 | |
426 writePropertyInducingElement(e); | |
427 } | |
428 | |
429 void writeFunctionElement(FunctionElement e) { | 425 void writeFunctionElement(FunctionElement e) { |
430 writeIf(e.isExternal, 'external '); | 426 writeIf(e.isExternal, 'external '); |
431 | 427 |
432 writeType2(e.returnType); | 428 writeType2(e.returnType); |
433 | 429 |
434 writeName(e); | 430 writeName(e); |
435 | 431 |
436 writeTypeParameterElements(e.typeParameters); | 432 writeTypeParameterElements(e.typeParameters); |
437 writeParameterElements(e.parameters); | 433 writeParameterElements(e.parameters); |
438 | 434 |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 } | 612 } |
617 | 613 |
618 void writePartElement(CompilationUnitElement e) { | 614 void writePartElement(CompilationUnitElement e) { |
619 writeMetadata(e, '', '\n'); | 615 writeMetadata(e, '', '\n'); |
620 buffer.write('part '); | 616 buffer.write('part '); |
621 writeUri(e, e.source); | 617 writeUri(e, e.source); |
622 buffer.writeln(';'); | 618 buffer.writeln(';'); |
623 } | 619 } |
624 | 620 |
625 void writePropertyAccessorElement(PropertyAccessorElement e) { | 621 void writePropertyAccessorElement(PropertyAccessorElement e) { |
626 if (e.isSynthetic) { | 622 if (e.isSynthetic && !withSyntheticAccessors) { |
627 return; | 623 return; |
628 } | 624 } |
629 | 625 |
630 if (e.enclosingElement is ClassElement) { | 626 if (e.enclosingElement is ClassElement) { |
631 writeDocumentation(e, ' '); | 627 writeDocumentation(e, ' '); |
632 writeMetadata(e, ' ', '\n'); | 628 writeMetadata(e, ' ', '\n'); |
633 | 629 |
634 buffer.write(' '); | 630 buffer.write(' '); |
635 | 631 |
| 632 writeIf(e.isSynthetic, 'synthetic '); |
636 writeIf(e.isStatic, 'static '); | 633 writeIf(e.isStatic, 'static '); |
637 } else { | 634 } else { |
638 writeDocumentation(e); | 635 writeDocumentation(e); |
639 writeMetadata(e, '', '\n'); | 636 writeMetadata(e, '', '\n'); |
| 637 writeIf(e.isSynthetic, 'synthetic '); |
640 } | 638 } |
641 | 639 |
642 writeIf(e.isExternal, 'external '); | 640 writeIf(e.isExternal, 'external '); |
643 | 641 |
644 writeType2(e.returnType); | 642 writeType2(e.returnType); |
645 | 643 |
646 if (e.isGetter) { | 644 if (e.isGetter) { |
647 buffer.write('get '); | 645 buffer.write('get '); |
648 } else { | 646 } else { |
649 buffer.write('set '); | 647 buffer.write('set '); |
(...skipping 12 matching lines...) Expand all Loading... |
662 expect(e.isGenerator, isFalse); | 660 expect(e.isGenerator, isFalse); |
663 | 661 |
664 if (e.isAbstract) { | 662 if (e.isAbstract) { |
665 buffer.writeln(';'); | 663 buffer.writeln(';'); |
666 } else { | 664 } else { |
667 buffer.writeln(' {}'); | 665 buffer.writeln(' {}'); |
668 } | 666 } |
669 } | 667 } |
670 | 668 |
671 void writePropertyInducingElement(PropertyInducingElement e) { | 669 void writePropertyInducingElement(PropertyInducingElement e) { |
| 670 if (e.isSynthetic && !withSyntheticFields && !isEnumField(e)) { |
| 671 return; |
| 672 } |
| 673 |
672 DartType type = e.type; | 674 DartType type = e.type; |
673 expect(type, isNotNull); | 675 expect(type, isNotNull); |
674 | 676 |
| 677 if (e.enclosingElement is ClassElement) { |
| 678 writeDocumentation(e, ' '); |
| 679 writeMetadata(e, ' ', '\n'); |
| 680 |
| 681 buffer.write(' '); |
| 682 |
| 683 writeIf(e.isSynthetic, 'synthetic '); |
| 684 writeIf(e.isStatic, 'static '); |
| 685 writeIf(e is FieldElementImpl && e.isCovariant, 'covariant '); |
| 686 } else { |
| 687 writeDocumentation(e); |
| 688 writeMetadata(e, '', '\n'); |
| 689 } |
| 690 |
675 writeIf(e.isFinal, 'final '); | 691 writeIf(e.isFinal, 'final '); |
676 writeIf(e.isConst, 'const '); | 692 writeIf(e.isConst, 'const '); |
677 writeType2(type); | 693 writeType2(type); |
678 | 694 |
679 writeName(e); | 695 writeName(e); |
680 | 696 |
681 if (e is ConstVariableElement) { | 697 if (e is ConstVariableElement) { |
682 Expression initializer = (e as ConstVariableElement).constantInitializer; | 698 Expression initializer = (e as ConstVariableElement).constantInitializer; |
683 if (initializer != null) { | 699 if (initializer != null) { |
684 buffer.write(' = '); | 700 buffer.write(' = '); |
685 writeExpression(initializer); | 701 writeExpression(initializer); |
686 } | 702 } |
687 } | 703 } |
688 | 704 |
689 // TODO(scheglov) Paul: One of the things that was hardest to get right | 705 // TODO(scheglov) Paul: One of the things that was hardest to get right |
690 // when resynthesizing the element model was the synthetic function for the | 706 // when resynthesizing the element model was the synthetic function for the |
691 // initializer. Can we write that out (along with its return type)? | 707 // initializer. Can we write that out (along with its return type)? |
692 | 708 |
693 buffer.writeln(';'); | 709 buffer.writeln(';'); |
694 } | 710 } |
695 | 711 |
696 void writeTopLevelVariableElement(TopLevelVariableElement e) { | |
697 if (e.isSynthetic) { | |
698 return; | |
699 } | |
700 writeDocumentation(e); | |
701 writeMetadata(e, '', '\n'); | |
702 writePropertyInducingElement(e); | |
703 } | |
704 | |
705 void writeType(DartType type) { | 712 void writeType(DartType type) { |
706 if (type is InterfaceType) { | 713 if (type is InterfaceType) { |
707 buffer.write(type.element.name); | 714 buffer.write(type.element.name); |
708 if (type.element.typeParameters.isNotEmpty) { | 715 if (type.element.typeParameters.isNotEmpty) { |
709 writeList('<', '>', type.typeArguments, ', ', writeType); | 716 writeList('<', '>', type.typeArguments, ', ', writeType); |
710 } | 717 } |
711 } else { | 718 } else { |
712 buffer.write(type.displayName); | 719 buffer.write(type.displayName); |
713 } | 720 } |
714 } | 721 } |
(...skipping 17 matching lines...) Expand all Loading... |
732 | 739 |
733 void writeUnitElement(CompilationUnitElement e) { | 740 void writeUnitElement(CompilationUnitElement e) { |
734 if (e.library.definingCompilationUnit != e) { | 741 if (e.library.definingCompilationUnit != e) { |
735 buffer.writeln('-' * 20); | 742 buffer.writeln('-' * 20); |
736 buffer.writeln('unit: ${e.source.shortName}'); | 743 buffer.writeln('unit: ${e.source.shortName}'); |
737 buffer.writeln(); | 744 buffer.writeln(); |
738 } | 745 } |
739 e.functionTypeAliases.forEach(writeFunctionTypeAliasElement); | 746 e.functionTypeAliases.forEach(writeFunctionTypeAliasElement); |
740 e.enums.forEach(writeClassElement); | 747 e.enums.forEach(writeClassElement); |
741 e.types.forEach(writeClassElement); | 748 e.types.forEach(writeClassElement); |
742 e.topLevelVariables.forEach(writeTopLevelVariableElement); | 749 e.topLevelVariables.forEach(writePropertyInducingElement); |
743 e.accessors.forEach(writePropertyAccessorElement); | 750 e.accessors.forEach(writePropertyAccessorElement); |
744 e.functions.forEach(writeFunctionElement); | 751 e.functions.forEach(writeFunctionElement); |
745 } | 752 } |
746 | 753 |
747 void writeUri(UriReferencedElement e, Source source) { | 754 void writeUri(UriReferencedElement e, Source source) { |
748 String uri = e.uri ?? source.uri.toString(); | 755 String uri = e.uri ?? source.uri.toString(); |
749 buffer.write('\'$uri\''); | 756 buffer.write('\'$uri\''); |
750 if (withOffsets) { | 757 if (withOffsets) { |
751 buffer.write('('); | 758 buffer.write('('); |
752 buffer.write('${e.uriOffset}, '); | 759 buffer.write('${e.uriOffset}, '); |
(...skipping 26 matching lines...) Expand all Loading... |
779 return components.join(';'); | 786 return components.join(';'); |
780 } | 787 } |
781 } | 788 } |
782 | 789 |
783 class _Replacement { | 790 class _Replacement { |
784 final int offset; | 791 final int offset; |
785 final int end; | 792 final int end; |
786 final String text; | 793 final String text; |
787 _Replacement(this.offset, this.end, this.text); | 794 _Replacement(this.offset, this.end, this.text); |
788 } | 795 } |
OLD | NEW |