| 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 |