OLD | NEW |
---|---|
1 // Copyright (c) 2016, the Dart Team. All rights reserved. Use of this | 1 // Copyright (c) 2016, the Dart Team. All rights reserved. Use of this |
2 // source code is governed by a BSD-style license that can be found in | 2 // source code is governed by a BSD-style license that can be found in |
3 // the LICENSE file. | 3 // the LICENSE file. |
4 | 4 |
5 library reflectable.src.transformer_implementation; | 5 library reflectable.src.transformer_implementation; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:developer' as developer; | 8 import 'dart:developer' as developer; |
9 import 'package:analyzer/src/generated/ast.dart'; | 9 import 'package:analyzer/src/generated/ast.dart'; |
10 import 'package:analyzer/src/generated/constant.dart'; | 10 import 'package:analyzer/src/generated/constant.dart'; |
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
651 String optionalsWithDefaults = | 651 String optionalsWithDefaults = |
652 new Iterable.generate(optionalPositionalCount, (int i) { | 652 new Iterable.generate(optionalPositionalCount, (int i) { |
653 ParameterElement parameterElement = | 653 ParameterElement parameterElement = |
654 constructor.parameters[requiredPositionalCount + i]; | 654 constructor.parameters[requiredPositionalCount + i]; |
655 FormalParameter parameterNode = parameterElement.computeNode(); | 655 FormalParameter parameterNode = parameterElement.computeNode(); |
656 String defaultValueCode = ""; | 656 String defaultValueCode = ""; |
657 if (parameterNode is DefaultFormalParameter && | 657 if (parameterNode is DefaultFormalParameter && |
658 parameterNode.defaultValue != null) { | 658 parameterNode.defaultValue != null) { |
659 defaultValueCode = " = ${_extractConstantCode( | 659 defaultValueCode = " = ${_extractConstantCode( |
660 parameterNode.defaultValue, | 660 parameterNode.defaultValue, |
661 parameterElement.library, | |
662 importCollector, logger, _generatedLibraryId, _resolver)}"; | 661 importCollector, logger, _generatedLibraryId, _resolver)}"; |
663 } | 662 } |
664 return "${parameterNames[requiredPositionalCount + i]}" | 663 return "${parameterNames[requiredPositionalCount + i]}" |
665 "$defaultValueCode"; | 664 "$defaultValueCode"; |
666 }).join(", "); | 665 }).join(", "); |
667 | 666 |
668 String namedWithDefaults = | 667 String namedWithDefaults = |
669 new Iterable.generate(namedParameterNames.length, (int i) { | 668 new Iterable.generate(namedParameterNames.length, (int i) { |
670 // Note that the use of `requiredPositionalCount + i` below relies | 669 // Note that the use of `requiredPositionalCount + i` below relies |
671 // on a language design where no parameter list can include | 670 // on a language design where no parameter list can include |
672 // both optional positional and named parameters, so if there are | 671 // both optional positional and named parameters, so if there are |
673 // any named parameters then all optional parameters are named. | 672 // any named parameters then all optional parameters are named. |
674 ParameterElement parameterElement = | 673 ParameterElement parameterElement = |
675 constructor.parameters[requiredPositionalCount + i]; | 674 constructor.parameters[requiredPositionalCount + i]; |
676 FormalParameter parameterNode = parameterElement.computeNode(); | 675 FormalParameter parameterNode = parameterElement.computeNode(); |
677 String defaultValueCode = ""; | 676 String defaultValueCode = ""; |
678 if (parameterNode is DefaultFormalParameter && | 677 if (parameterNode is DefaultFormalParameter && |
679 parameterNode.defaultValue != null) { | 678 parameterNode.defaultValue != null) { |
680 defaultValueCode = ": ${_extractConstantCode( | 679 defaultValueCode = ": ${_extractConstantCode( |
681 parameterNode.defaultValue, | 680 parameterNode.defaultValue, |
682 parameterElement.library, | |
683 importCollector, logger, _generatedLibraryId, _resolver)}"; | 681 importCollector, logger, _generatedLibraryId, _resolver)}"; |
684 } | 682 } |
685 return "${namedParameterNames[i]}$defaultValueCode"; | 683 return "${namedParameterNames[i]}$defaultValueCode"; |
686 }).join(", "); | 684 }).join(", "); |
687 | 685 |
688 String optionalArguments = new Iterable.generate(optionalPositionalCount, | 686 String optionalArguments = new Iterable.generate(optionalPositionalCount, |
689 (int i) => parameterNames[i + requiredPositionalCount]).join(", "); | 687 (int i) => parameterNames[i + requiredPositionalCount]).join(", "); |
690 String namedArguments = | 688 String namedArguments = |
691 namedParameterNames.map((String name) => "$name: $name").join(", "); | 689 namedParameterNames.map((String name) => "$name: $name").join(", "); |
692 | 690 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
780 if (!_isImportableLibrary(library, _generatedLibraryId, _resolver)) | 778 if (!_isImportableLibrary(library, _generatedLibraryId, _resolver)) |
781 return; | 779 return; |
782 importCollector._addLibrary(library); | 780 importCollector._addLibrary(library); |
783 uncheckedAddLibrary(library); | 781 uncheckedAddLibrary(library); |
784 } | 782 } |
785 | 783 |
786 // Fill in [libraries], [typeParameters], [members], [fields], | 784 // Fill in [libraries], [typeParameters], [members], [fields], |
787 // [parameters], [instanceGetterNames], and [instanceSetterNames]. | 785 // [parameters], [instanceGetterNames], and [instanceSetterNames]. |
788 _libraries.items.forEach(uncheckedAddLibrary); | 786 _libraries.items.forEach(uncheckedAddLibrary); |
789 classes.forEach((ClassElement classElement) { | 787 classes.forEach((ClassElement classElement) { |
788 LibraryElement classLibrary = classElement.library; | |
790 if (!libraries.items.any((_LibraryDomain libraryDomain) => | 789 if (!libraries.items.any((_LibraryDomain libraryDomain) => |
791 libraryDomain._libraryElement == classElement.library)) { | 790 libraryDomain._libraryElement == classLibrary)) { |
792 addLibrary(classElement.library); | 791 addLibrary(classLibrary); |
793 } | 792 } |
794 classElement.typeParameters.forEach(typeParameters.add); | 793 classElement.typeParameters.forEach(typeParameters.add); |
795 }); | 794 }); |
796 for (_ClassDomain classDomain in classes.domains) { | 795 for (_ClassDomain classDomain in classes.domains) { |
797 // Gather the behavioral interface into [members]. Note that | 796 // Gather the behavioral interface into [members]. Note that |
798 // this includes implicitly generated getters and setters, but | 797 // this includes implicitly generated getters and setters, but |
799 // omits fields. Also note that this does not match the | 798 // omits fields. Also note that this does not match the |
800 // semantics of the `declarations` method in a [ClassMirror]. | 799 // semantics of the `declarations` method in a [ClassMirror]. |
801 classDomain._declarations.forEach(members.add); | 800 classDomain._declarations.forEach(members.add); |
802 | 801 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
856 // `isStatic`, we do not wish to include them among | 855 // `isStatic`, we do not wish to include them among |
857 // instanceGetterNames, so we do nothing here. | 856 // instanceGetterNames, so we do nothing here. |
858 } | 857 } |
859 }); | 858 }); |
860 } | 859 } |
861 | 860 |
862 // Add classes used as bounds for type variables, if needed. | 861 // Add classes used as bounds for type variables, if needed. |
863 if (_capabilities._impliesTypes && _capabilities._impliesTypeAnnotations) { | 862 if (_capabilities._impliesTypes && _capabilities._impliesTypeAnnotations) { |
864 void addClass(ClassElement classElement) { | 863 void addClass(ClassElement classElement) { |
865 classes.add(classElement); | 864 classes.add(classElement); |
866 if (!libraries.items.contains(classElement.library)) { | 865 LibraryElement classLibrary = classElement.library; |
867 uncheckedAddLibrary(classElement.library); | 866 if (!libraries.items.contains(classLibrary)) { |
867 uncheckedAddLibrary(classLibrary); | |
868 } | 868 } |
869 } | 869 } |
870 | 870 |
871 bool hasObject = false; | 871 bool hasObject = false; |
872 bool mustHaveObject = false; | 872 bool mustHaveObject = false; |
873 Set<ClassElement> classesToAdd = new Set<ClassElement>(); | 873 Set<ClassElement> classesToAdd = new Set<ClassElement>(); |
874 ClassElement anyClassElement; | 874 ClassElement anyClassElement; |
875 for (ClassElement classElement in classes) { | 875 for (ClassElement classElement in classes) { |
876 if (classElement.type.isObject) { | 876 if (classElement.type.isObject) { |
877 hasObject = true; | 877 hasObject = true; |
(...skipping 1049 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1927 metadataCode = "const []"; | 1927 metadataCode = "const []"; |
1928 } else { | 1928 } else { |
1929 metadataCode = _extractMetadataCode( | 1929 metadataCode = _extractMetadataCode( |
1930 element, _resolver, importCollector, logger, _generatedLibraryId); | 1930 element, _resolver, importCollector, logger, _generatedLibraryId); |
1931 } | 1931 } |
1932 } | 1932 } |
1933 FormalParameter parameterNode = element.computeNode(); | 1933 FormalParameter parameterNode = element.computeNode(); |
1934 String defaultValueCode = "null"; | 1934 String defaultValueCode = "null"; |
1935 if (parameterNode is DefaultFormalParameter && | 1935 if (parameterNode is DefaultFormalParameter && |
1936 parameterNode.defaultValue != null) { | 1936 parameterNode.defaultValue != null) { |
1937 defaultValueCode = _extractConstantCode( | 1937 defaultValueCode = _extractConstantCode(parameterNode.defaultValue, |
1938 parameterNode.defaultValue, | 1938 importCollector, logger, _generatedLibraryId, _resolver); |
1939 element.library, | |
1940 importCollector, | |
1941 logger, | |
1942 _generatedLibraryId, | |
1943 _resolver); | |
1944 } | 1939 } |
1945 String parameterSymbolCode = descriptor & constants.namedAttribute != 0 | 1940 String parameterSymbolCode = descriptor & constants.namedAttribute != 0 |
1946 ? "#${element.name}" | 1941 ? "#${element.name}" |
1947 : "null"; | 1942 : "null"; |
1948 | 1943 |
1949 return 'new r.ParameterMirrorImpl(r"${element.name}", $descriptor, ' | 1944 return 'new r.ParameterMirrorImpl(r"${element.name}", $descriptor, ' |
1950 '$ownerIndex, ${_constConstructionCode(importCollector, logger)}, ' | 1945 '$ownerIndex, ${_constConstructionCode(importCollector, logger)}, ' |
1951 '$classMirrorIndex, $reflectedTypeIndex, $dynamicReflectedTypeIndex, ' | 1946 '$classMirrorIndex, $reflectedTypeIndex, $dynamicReflectedTypeIndex, ' |
1952 '$metadataCode, $defaultValueCode, $parameterSymbolCode)'; | 1947 '$metadataCode, $defaultValueCode, $parameterSymbolCode)'; |
1953 } | 1948 } |
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2549 // fully when the set of supported classes was computed. | 2544 // fully when the set of supported classes was computed. |
2550 } | 2545 } |
2551 | 2546 |
2552 // All options exhausted, give up. | 2547 // All options exhausted, give up. |
2553 return false; | 2548 return false; |
2554 } | 2549 } |
2555 | 2550 |
2556 Iterable<DartObjectImpl> _getEvaluatedMetadata( | 2551 Iterable<DartObjectImpl> _getEvaluatedMetadata( |
2557 Iterable<ElementAnnotation> metadata) { | 2552 Iterable<ElementAnnotation> metadata) { |
2558 return metadata.map((ElementAnnotationImpl elementAnnotation) { | 2553 return metadata.map((ElementAnnotationImpl elementAnnotation) { |
2559 EvaluationResultImpl evaluation = elementAnnotation.evaluationResult; | 2554 EvaluationResultImpl evaluation = |
2555 _annotationEvaluationResult(elementAnnotation); | |
2560 if (evaluation != null) return evaluation.value; | 2556 if (evaluation != null) return evaluation.value; |
2561 // The `evaluationResult` from a getter is `null`, so we have to deal | 2557 // The `evaluationResult` from a getter is `null`, so we have to deal |
2562 // with that case separately. | 2558 // with that case separately. |
2563 Element element = elementAnnotation.element; | 2559 Element element = elementAnnotation.element; |
2564 if (element is PropertyAccessorElement && | 2560 if (element is PropertyAccessorElement && |
2565 element.isGetter && | 2561 element.isGetter && |
2566 element.isSynthetic) { | 2562 element.isSynthetic) { |
2567 return element.variable.constantValue; | 2563 return element.variable.constantValue; |
2568 } else if (element is ConstructorElementImpl) { | 2564 } else if (element is ConstructorElementImpl) { |
2569 DartType dartType = element.returnType; | 2565 DartType dartType = element.returnType; |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2906 /// across all usage locations for reflectable.dart, so we cannot easily | 2902 /// across all usage locations for reflectable.dart, so we cannot easily |
2907 /// predict all the possible URIs that could be used to import | 2903 /// predict all the possible URIs that could be used to import |
2908 /// reflectable.dart; and it would be awkward to require that all user | 2904 /// reflectable.dart; and it would be awkward to require that all user |
2909 /// programs must use exactly one specific URI to import | 2905 /// programs must use exactly one specific URI to import |
2910 /// reflectable.dart. So we use [Reflectable.thisClassId] which is very | 2906 /// reflectable.dart. So we use [Reflectable.thisClassId] which is very |
2911 /// unlikely to occur with the same value elsewhere by accident. | 2907 /// unlikely to occur with the same value elsewhere by accident. |
2912 bool _equalsClassReflectable(ClassElement type) { | 2908 bool _equalsClassReflectable(ClassElement type) { |
2913 FieldElement idField = type.getField("thisClassId"); | 2909 FieldElement idField = type.getField("thisClassId"); |
2914 if (idField == null || !idField.isStatic) return false; | 2910 if (idField == null || !idField.isStatic) return false; |
2915 if (idField is ConstFieldElementImpl) { | 2911 if (idField is ConstFieldElementImpl) { |
2916 EvaluationResultImpl idResult = idField.evaluationResult; | 2912 EvaluationResultImpl idResult = _constFieldEvaluationResult(idField); |
2917 if (idResult != null) { | 2913 if (idResult != null) { |
2918 return idField.constantValue.toStringValue() == | 2914 return idField.constantValue.toStringValue() == |
2919 reflectable_class_constants.id; | 2915 reflectable_class_constants.id; |
2920 } | 2916 } |
2921 // idResult == null: analyzer/.../element.dart specifies that this can | 2917 // idResult == null: analyzer/.../element.dart specifies that this can |
2922 // occur "if this variable is not a 'const' variable, if it does not | 2918 // occur "if this variable is not a 'const' variable, if it does not |
2923 // have an initializer, or if the compilation unit containing the | 2919 // have an initializer, or if the compilation unit containing the |
2924 // variable has not been resolved". The third case should not occur with | 2920 // variable has not been resolved". The third case should not occur with |
2925 // the approach we use to obtain a `LibraryElement`, so it is not the | 2921 // the approach we use to obtain the `LibraryElement` for the library |
2922 // 'package:reflectable/reflectable.dart', so it is not the | |
2926 // right declaration we are looking at. | 2923 // right declaration we are looking at. |
2927 } | 2924 } |
2928 // Not a const field, or failed the test, cannot be the right class. | 2925 // Not a const field, or failed the `id` test: cannot be the right class. |
2929 return false; | 2926 return false; |
2930 } | 2927 } |
2931 | 2928 |
2932 /// Returns the ClassElement in the target program which corresponds to class | 2929 /// Returns the ClassElement in the target program which corresponds to class |
2933 /// [Reflectable]. | 2930 /// [Reflectable]. |
2934 ClassElement _findReflectableClassElement(LibraryElement reflectableLibrary) { | 2931 ClassElement _findReflectableClassElement(LibraryElement reflectableLibrary) { |
2935 for (CompilationUnitElement unit in reflectableLibrary.units) { | 2932 for (CompilationUnitElement unit in reflectableLibrary.units) { |
2936 for (ClassElement type in unit.types) { | 2933 for (ClassElement type in unit.types) { |
2937 if (type.name == reflectable_class_constants.name && | 2934 if (type.name == reflectable_class_constants.name && |
2938 _equalsClassReflectable(type)) { | 2935 _equalsClassReflectable(type)) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3003 return isOk ? element.enclosingElement.type.element : null; | 3000 return isOk ? element.enclosingElement.type.element : null; |
3004 } else if (element is PropertyAccessorElement) { | 3001 } else if (element is PropertyAccessorElement) { |
3005 PropertyInducingElement variable = element.variable; | 3002 PropertyInducingElement variable = element.variable; |
3006 // Surprisingly, we have to use [ConstTopLevelVariableElementImpl] | 3003 // Surprisingly, we have to use [ConstTopLevelVariableElementImpl] |
3007 // here (or a similar type). This is because none of the "public name" | 3004 // here (or a similar type). This is because none of the "public name" |
3008 // types (types whose name does not end in `..Impl`) declare the getter | 3005 // types (types whose name does not end in `..Impl`) declare the getter |
3009 // `evaluationResult`. Another possible choice of type would be | 3006 // `evaluationResult`. Another possible choice of type would be |
3010 // [VariableElementImpl], but with that one we would have to test | 3007 // [VariableElementImpl], but with that one we would have to test |
3011 // `isConst` as well. | 3008 // `isConst` as well. |
3012 if (variable is ConstTopLevelVariableElementImpl) { | 3009 if (variable is ConstTopLevelVariableElementImpl) { |
3013 EvaluationResultImpl result = variable.evaluationResult; | 3010 EvaluationResultImpl result = |
3011 _constTopLevelVariableEvaluationResult(variable); | |
3014 // Handle errors during evaluation. In general `evaluationResult` is | 3012 // Handle errors during evaluation. In general `evaluationResult` is |
3015 // null for (1) non-const variables, (2) variables without an | 3013 // null for (1) non-const variables, (2) variables without an |
3016 // initializer, and (3) unresolved libraries; (3) should not occur | 3014 // initializer, and (3) unresolved libraries; (3) should not occur |
3017 // because of the approach we use to get the resolver; we will not | 3015 // because of the approach we use to get the resolver; we will not |
3018 // see (1) because we have checked the type of `variable`; and (2) | 3016 // see (1) because we have checked the type of `variable`; and (2) |
3019 // would mean that the value is actually null, which we will also | 3017 // would mean that the value is actually null, which we will also |
3020 // reject as irrelevant. | 3018 // reject as irrelevant. |
3021 if (result?.value == null) return null; | 3019 if (result?.value == null) return null; |
3022 bool isOk = checkInheritance(result.value.type, focusClass.type); | 3020 bool isOk = checkInheritance(result.value.type, focusClass.type); |
3023 return isOk ? result.value.type.element : null; | 3021 return isOk ? result.value.type.element : null; |
3024 } else if (variable is ConstFieldElementImpl) { | 3022 } else if (variable is ConstFieldElementImpl) { |
3025 // A [ConstFieldElementImpl] is also used for non-const (final) | 3023 // A [ConstFieldElementImpl] is also used for non-const (final) |
3026 // fields, so we could also check `variable.isConst`; however, if | 3024 // fields, so we could also check `variable.isConst`; however, if |
3027 // we have non-const metadata then the program (pre- and post- | 3025 // we have non-const metadata then the program (pre- and post- |
3028 // transformed) will be rejected by the analyzer and the compilers, | 3026 // transformed) will be rejected by the analyzer and the compilers, |
3029 // which means that it is unimportant for us to reject that case. | 3027 // which means that it is unimportant for us to reject that case. |
3030 EvaluationResultImpl result = variable.evaluationResult; | 3028 EvaluationResultImpl result = _constFieldEvaluationResult(variable); |
3031 if (result?.value == null) return null; | 3029 if (result?.value == null) return null; |
3032 bool isOk = checkInheritance(result.value.type, focusClass.type); | 3030 bool isOk = checkInheritance(result.value.type, focusClass.type); |
3033 return isOk ? result.value.type.element : null; | 3031 return isOk ? result.value.type.element : null; |
3034 } else { | 3032 } else { |
3035 _logger.fine("Ignoring unsupported metadata form ${element}", | 3033 _logger.fine("Ignoring unsupported metadata form ${element}", |
3036 asset: _resolver.getSourceAssetId(element), | 3034 asset: _resolver.getSourceAssetId(element), |
3037 span: _resolver.getSourceSpan(element)); | 3035 span: _resolver.getSourceSpan(element)); |
3038 return null; | 3036 return null; |
3039 } | 3037 } |
3040 } | 3038 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3076 ConstructorElement globalQuantifyCapabilityConstructor = capabilityLibrary | 3074 ConstructorElement globalQuantifyCapabilityConstructor = capabilityLibrary |
3077 .getType("GlobalQuantifyCapability") | 3075 .getType("GlobalQuantifyCapability") |
3078 .getNamedConstructor(""); | 3076 .getNamedConstructor(""); |
3079 ConstructorElement globalQuantifyMetaCapabilityConstructor = | 3077 ConstructorElement globalQuantifyMetaCapabilityConstructor = |
3080 capabilityLibrary | 3078 capabilityLibrary |
3081 .getType("GlobalQuantifyMetaCapability") | 3079 .getType("GlobalQuantifyMetaCapability") |
3082 .getNamedConstructor(""); | 3080 .getNamedConstructor(""); |
3083 | 3081 |
3084 for (LibraryElement library in _resolver.libraries) { | 3082 for (LibraryElement library in _resolver.libraries) { |
3085 for (ImportElement import in library.imports) { | 3083 for (ImportElement import in library.imports) { |
3084 if (import.importedLibrary != reflectableLibrary) continue; | |
3086 for (ElementAnnotationImpl metadatum in import.metadata) { | 3085 for (ElementAnnotationImpl metadatum in import.metadata) { |
3087 if (metadatum.element == globalQuantifyCapabilityConstructor) { | 3086 if (metadatum.element == globalQuantifyCapabilityConstructor) { |
3088 EvaluationResultImpl evaluation = metadatum.evaluationResult; | 3087 EvaluationResultImpl evaluation = |
3088 _annotationEvaluationResult(metadatum); | |
3089 if (evaluation != null && evaluation.value != null) { | 3089 if (evaluation != null && evaluation.value != null) { |
3090 DartObjectImpl value = evaluation.value; | 3090 DartObjectImpl value = evaluation.value; |
3091 String pattern = value.fields["classNamePattern"].toStringValue(); | 3091 String pattern = value.fields["classNamePattern"].toStringValue(); |
3092 if (pattern == null) { | 3092 if (pattern == null) { |
3093 // TODO(sigurdm) implement: Create a span for the annotation | 3093 // TODO(sigurdm) implement: Create a span for the annotation |
3094 // rather than the import. | 3094 // rather than the import. |
3095 _warn(WarningKind.badNamePattern, | 3095 _warn(WarningKind.badNamePattern, |
3096 "The classNamePattern must be a string", import); | 3096 "The classNamePattern must be a string", import); |
3097 continue; | 3097 continue; |
3098 } | 3098 } |
(...skipping 10 matching lines...) Expand all Loading... | |
3109 found, | 3109 found, |
3110 import); | 3110 import); |
3111 continue; | 3111 continue; |
3112 } | 3112 } |
3113 globalPatterns | 3113 globalPatterns |
3114 .putIfAbsent(new RegExp(pattern), () => <ClassElement>[]) | 3114 .putIfAbsent(new RegExp(pattern), () => <ClassElement>[]) |
3115 .add(reflector); | 3115 .add(reflector); |
3116 } | 3116 } |
3117 } else if (metadatum.element == | 3117 } else if (metadatum.element == |
3118 globalQuantifyMetaCapabilityConstructor) { | 3118 globalQuantifyMetaCapabilityConstructor) { |
3119 EvaluationResultImpl evaluation = metadatum.evaluationResult; | 3119 EvaluationResultImpl evaluation = |
3120 _annotationEvaluationResult(metadatum); | |
3120 if (evaluation?.value != null) { | 3121 if (evaluation?.value != null) { |
3121 DartObjectImpl value = evaluation.value; | 3122 DartObjectImpl value = evaluation.value; |
3122 Object metadataFieldValue = | 3123 Object metadataFieldValue = |
3123 value.fields["metadataType"].toTypeValue().element; | 3124 value.fields["metadataType"].toTypeValue().element; |
3124 if (metadataFieldValue == null || | 3125 if (metadataFieldValue == null || |
3125 value.fields["metadataType"].type.element != typeClass) { | 3126 value.fields["metadataType"].type.element != typeClass) { |
3126 // TODO(sigurdm) implement: Create a span for the annotation. | 3127 // TODO(sigurdm) implement: Create a span for the annotation. |
3127 _warn( | 3128 _warn( |
3128 WarningKind.badMetadata, | 3129 WarningKind.badMetadata, |
3129 "The metadata must be a Type. " | 3130 "The metadata must be a Type. " |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3258 Map<ClassElement, List<ClassElement>> globalMetadata = | 3259 Map<ClassElement, List<ClassElement>> globalMetadata = |
3259 new Map<ClassElement, List<ClassElement>>(); | 3260 new Map<ClassElement, List<ClassElement>>(); |
3260 | 3261 |
3261 final LibraryElement capabilityLibrary = | 3262 final LibraryElement capabilityLibrary = |
3262 _resolver.getLibraryByName("reflectable.capability"); | 3263 _resolver.getLibraryByName("reflectable.capability"); |
3263 | 3264 |
3264 /// Gets the [ReflectorDomain] associated with [reflector], or creates | 3265 /// Gets the [ReflectorDomain] associated with [reflector], or creates |
3265 /// it if none exists. | 3266 /// it if none exists. |
3266 _ReflectorDomain getReflectorDomain(ClassElement reflector) { | 3267 _ReflectorDomain getReflectorDomain(ClassElement reflector) { |
3267 return domains.putIfAbsent(reflector, () { | 3268 return domains.putIfAbsent(reflector, () { |
3269 LibraryElement reflectorLibrary = reflector.library; | |
3268 _Capabilities capabilities = | 3270 _Capabilities capabilities = |
3269 _capabilitiesOf(capabilityLibrary, reflector); | 3271 _capabilitiesOf(capabilityLibrary, reflector); |
3270 assert(_isImportableLibrary(reflector.library, dataId, _resolver)); | 3272 assert(_isImportableLibrary(reflectorLibrary, dataId, _resolver)); |
3271 importCollector._addLibrary(reflector.library); | 3273 importCollector._addLibrary(reflectorLibrary); |
3272 return new _ReflectorDomain(_resolver, dataId, reflector, capabilities); | 3274 return new _ReflectorDomain(_resolver, dataId, reflector, capabilities); |
3273 }); | 3275 }); |
3274 } | 3276 } |
3275 | 3277 |
3276 /// Adds [library] to the supported libraries of [reflector]. | 3278 /// Adds [library] to the supported libraries of [reflector]. |
3277 void addLibrary(LibraryElement library, ClassElement reflector) { | 3279 void addLibrary(LibraryElement library, ClassElement reflector) { |
3278 _ReflectorDomain domain = getReflectorDomain(reflector); | 3280 _ReflectorDomain domain = getReflectorDomain(reflector); |
3279 if (domain._capabilities._supportsLibraries) { | 3281 if (domain._capabilities._supportsLibraries) { |
3280 assert(_isImportableLibrary(library, dataId, _resolver)); | 3282 assert(_isImportableLibrary(library, dataId, _resolver)); |
3281 importCollector._addLibrary(library); | 3283 importCollector._addLibrary(library); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3319 // generated library, even in cases where the transformed program | 3321 // generated library, even in cases where the transformed program |
3320 // will not get library support. | 3322 // will not get library support. |
3321 // TODO(eernst) clarify: Maybe the following statement could be moved | 3323 // TODO(eernst) clarify: Maybe the following statement could be moved |
3322 // out of the `if` in `addLibrary` such that we don't have to have | 3324 // out of the `if` in `addLibrary` such that we don't have to have |
3323 // an extra copy of it here. | 3325 // an extra copy of it here. |
3324 importCollector._addLibrary(type.library); | 3326 importCollector._addLibrary(type.library); |
3325 } | 3327 } |
3326 } | 3328 } |
3327 } | 3329 } |
3328 | 3330 |
3329 /// Runs through a list of metadata, and finds any Reflectors, and | 3331 /// Runs through [metadata] and finds all reflectors as well as |
3330 /// objects that are associated with reflectors via | 3332 /// objects that are associated with reflectors via |
3331 /// GlobalQuantifyMetaCapability and GlobalQuantifyCapability. | 3333 /// [GlobalQuantifyMetaCapability] or [GlobalQuantifyCapability]. |
3332 /// [qualifiedName] is the name of the library or class annotated by | 3334 /// [qualifiedName] is the name of the library or class annotated by |
3333 /// metadata. | 3335 /// [metadata]. |
3334 Iterable<ClassElement> getReflectors( | 3336 Iterable<ClassElement> getReflectors( |
3335 String qualifiedName, List<ElementAnnotation> metadata) { | 3337 String qualifiedName, List<ElementAnnotation> metadata) { |
3336 List<ClassElement> result = <ClassElement>[]; | 3338 List<ClassElement> result = <ClassElement>[]; |
3337 | 3339 |
3338 for (ElementAnnotationImpl metadatum in metadata) { | 3340 for (ElementAnnotationImpl metadatum in metadata) { |
3339 EvaluationResultImpl evaluation = metadatum.evaluationResult; | 3341 EvaluationResultImpl evaluation = metadatum.evaluationResult; |
3340 DartObject value = evaluation?.value; | 3342 DartObject value = evaluation?.value; |
3341 | 3343 |
3342 // Test if the type of this metadata is associated with any reflectors | 3344 // Test if the type of this metadata is associated with any reflectors |
3343 // via GlobalQuantifyMetaCapability. | 3345 // via GlobalQuantifyMetaCapability. |
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3763 if (reflectableLibrary == null) { | 3765 if (reflectableLibrary == null) { |
3764 // Stop and do not consumePrimary, i.e., let the original source | 3766 // Stop and do not consumePrimary, i.e., let the original source |
3765 // pass through without changes. | 3767 // pass through without changes. |
3766 _logger.info("Ignoring entry point $currentEntryPoint that does not " | 3768 _logger.info("Ignoring entry point $currentEntryPoint that does not " |
3767 "include the library 'package:reflectable/reflectable.dart'"); | 3769 "include the library 'package:reflectable/reflectable.dart'"); |
3768 if (const bool.fromEnvironment("reflectable.pause.at.exit")) { | 3770 if (const bool.fromEnvironment("reflectable.pause.at.exit")) { |
3769 _processedEntryPointCount++; | 3771 _processedEntryPointCount++; |
3770 } | 3772 } |
3771 return; | 3773 return; |
3772 } | 3774 } |
3775 reflectableLibrary = _resolvedLibraryOf(reflectableLibrary); | |
3773 | 3776 |
3774 LibraryElement entryPointLibrary = _resolver.getLibrary(asset.id); | 3777 LibraryElement entryPointLibrary = _resolver.getLibrary(asset.id); |
3775 if (const bool.fromEnvironment("reflectable.print.entry.point")) { | 3778 if (const bool.fromEnvironment("reflectable.print.entry.point")) { |
3776 print("Starting transformation of '$currentEntryPoint'."); | 3779 print("Starting transformation of '$currentEntryPoint'."); |
3777 } | 3780 } |
3778 | 3781 |
3779 ReflectionWorld world = | 3782 ReflectionWorld world = |
3780 _computeWorld(reflectableLibrary, entryPointLibrary, asset.id); | 3783 _computeWorld(reflectableLibrary, entryPointLibrary, asset.id); |
3781 if (world == null) { | 3784 if (world == null) { |
3782 // Errors have already been reported during `_computeWorld`. | 3785 // Errors have already been reported during `_computeWorld`. |
(...skipping 21 matching lines...) Expand all Loading... | |
3804 | 3807 |
3805 // Generate a new file with the name of the entry-point, whose main | 3808 // Generate a new file with the name of the entry-point, whose main |
3806 // initializes the reflection data, and calls the main from | 3809 // initializes the reflection data, and calls the main from |
3807 // [originalEntryPointId]. | 3810 // [originalEntryPointId]. |
3808 String newEntryPoint = | 3811 String newEntryPoint = |
3809 _generateNewEntryPoint(world, asset.id, originalEntryPointFilename); | 3812 _generateNewEntryPoint(world, asset.id, originalEntryPointFilename); |
3810 transform.addOutput(new Asset.fromString(asset.id, newEntryPoint)); | 3813 transform.addOutput(new Asset.fromString(asset.id, newEntryPoint)); |
3811 if (const bool.fromEnvironment("reflectable.pause.at.exit")) { | 3814 if (const bool.fromEnvironment("reflectable.pause.at.exit")) { |
3812 _processedEntryPointCount++; | 3815 _processedEntryPointCount++; |
3813 } | 3816 } |
3817 if (const bool.fromEnvironment("reflectable.print.resolved.libraries")) { | |
3818 print("Resolved libraries for $currentEntryPoint: " | |
3819 "${_resolvedLibraries.length}/${_resolver.libraries.length}"); | |
3820 } | |
3814 _resolver.release(); | 3821 _resolver.release(); |
3815 | 3822 |
3816 if (const bool.fromEnvironment("reflectable.pause.at.exit")) { | 3823 if (const bool.fromEnvironment("reflectable.pause.at.exit")) { |
3817 if (_processedEntryPointCount == | 3824 if (_processedEntryPointCount == |
3818 const int.fromEnvironment("reflectable.pause.at.exit.count")) { | 3825 const int.fromEnvironment("reflectable.pause.at.exit.count")) { |
3819 print("Transformation complete, pausing at exit."); | 3826 print("Transformation complete, pausing at exit."); |
3820 developer.debugger(); | 3827 developer.debugger(); |
3821 } | 3828 } |
3822 } | 3829 } |
3823 } | 3830 } |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3999 | 4006 |
4000 String _formatAsDynamicList(Iterable parts) => "[${parts.join(", ")}]"; | 4007 String _formatAsDynamicList(Iterable parts) => "[${parts.join(", ")}]"; |
4001 | 4008 |
4002 String _formatAsMap(Iterable parts) => "{${parts.join(", ")}}"; | 4009 String _formatAsMap(Iterable parts) => "{${parts.join(", ")}}"; |
4003 | 4010 |
4004 /// Returns a [String] containing code that will evaluate to the same | 4011 /// Returns a [String] containing code that will evaluate to the same |
4005 /// value when evaluated in the generated file as the given [expression] | 4012 /// value when evaluated in the generated file as the given [expression] |
4006 /// would evaluate to in [originatingLibrary]. | 4013 /// would evaluate to in [originatingLibrary]. |
4007 String _extractConstantCode( | 4014 String _extractConstantCode( |
4008 Expression expression, | 4015 Expression expression, |
4009 LibraryElement originatingLibrary, | |
4010 _ImportCollector importCollector, | 4016 _ImportCollector importCollector, |
4011 TransformLogger logger, | 4017 TransformLogger logger, |
4012 AssetId generatedLibraryId, | 4018 AssetId generatedLibraryId, |
4013 Resolver resolver) { | 4019 Resolver resolver) { |
4014 String helper(Expression expression) { | 4020 String helper(Expression expression) { |
4015 if (expression is ListLiteral) { | 4021 if (expression is ListLiteral) { |
4016 Iterable<String> elements = | 4022 Iterable<String> elements = |
4017 expression.elements.map((Expression subExpression) { | 4023 expression.elements.map((Expression subExpression) { |
4018 return helper(subExpression); | 4024 return helper(subExpression); |
4019 }); | 4025 }); |
(...skipping 11 matching lines...) Expand all Loading... | |
4031 } else if (expression is InstanceCreationExpression) { | 4037 } else if (expression is InstanceCreationExpression) { |
4032 String constructor = expression.constructorName.toSource(); | 4038 String constructor = expression.constructorName.toSource(); |
4033 if (_isPrivateName(constructor)) { | 4039 if (_isPrivateName(constructor)) { |
4034 logger.error("Cannot access private name $constructor, " | 4040 logger.error("Cannot access private name $constructor, " |
4035 "needed for expression $expression"); | 4041 "needed for expression $expression"); |
4036 } | 4042 } |
4037 LibraryElement libraryOfConstructor = expression.staticElement.library; | 4043 LibraryElement libraryOfConstructor = expression.staticElement.library; |
4038 if (_isImportableLibrary( | 4044 if (_isImportableLibrary( |
4039 libraryOfConstructor, generatedLibraryId, resolver)) { | 4045 libraryOfConstructor, generatedLibraryId, resolver)) { |
4040 importCollector._addLibrary(libraryOfConstructor); | 4046 importCollector._addLibrary(libraryOfConstructor); |
4041 String prefix = | 4047 String prefix = importCollector._getPrefix(libraryOfConstructor); |
4042 importCollector._getPrefix(expression.staticElement.library); | |
4043 // TODO(sigurdm) implement: Named arguments. | 4048 // TODO(sigurdm) implement: Named arguments. |
4044 String arguments = | 4049 String arguments = |
4045 expression.argumentList.arguments.map((Expression argument) { | 4050 expression.argumentList.arguments.map((Expression argument) { |
4046 return helper(argument); | 4051 return helper(argument); |
4047 }).join(", "); | 4052 }).join(", "); |
4048 // TODO(sigurdm) feature: Type arguments. | 4053 // TODO(sigurdm) feature: Type arguments. |
4049 if (_isPrivateName(constructor)) { | 4054 if (_isPrivateName(constructor)) { |
4050 logger.error("Cannot access private name $constructor, " | 4055 logger.error("Cannot access private name $constructor, " |
4051 "needed for expression $expression"); | 4056 "needed for expression $expression"); |
4052 } | 4057 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4108 } else if (expression is MethodInvocation) { | 4113 } else if (expression is MethodInvocation) { |
4109 // We only handle "identical(a, b)". | 4114 // We only handle "identical(a, b)". |
4110 assert(expression.target == null); | 4115 assert(expression.target == null); |
4111 assert(expression.methodName.token.lexeme == "identical"); | 4116 assert(expression.methodName.token.lexeme == "identical"); |
4112 NodeList arguments = expression.argumentList.arguments; | 4117 NodeList arguments = expression.argumentList.arguments; |
4113 assert(arguments.length == 2); | 4118 assert(arguments.length == 2); |
4114 String a = helper(arguments[0]); | 4119 String a = helper(arguments[0]); |
4115 String b = helper(arguments[1]); | 4120 String b = helper(arguments[1]); |
4116 return "identical($a, $b)"; | 4121 return "identical($a, $b)"; |
4117 } else if (expression is NamedExpression) { | 4122 } else if (expression is NamedExpression) { |
4118 String value = _extractConstantCode( | 4123 String value = _extractConstantCode(expression.expression, |
4119 expression.expression, | 4124 importCollector, logger, generatedLibraryId, resolver); |
4120 originatingLibrary, | |
4121 importCollector, | |
4122 logger, | |
4123 generatedLibraryId, | |
4124 resolver); | |
4125 return "${expression.name} $value"; | 4125 return "${expression.name} $value"; |
4126 } else { | 4126 } else { |
4127 assert(expression is IntegerLiteral || | 4127 assert(expression is IntegerLiteral || |
4128 expression is BooleanLiteral || | 4128 expression is BooleanLiteral || |
4129 expression is StringLiteral || | 4129 expression is StringLiteral || |
4130 expression is NullLiteral || | 4130 expression is NullLiteral || |
4131 expression is SymbolLiteral || | 4131 expression is SymbolLiteral || |
4132 expression is DoubleLiteral || | 4132 expression is DoubleLiteral || |
4133 expression is TypedLiteral); | 4133 expression is TypedLiteral); |
4134 return expression.toSource(); | 4134 return expression.toSource(); |
4135 } | 4135 } |
4136 } | 4136 } |
4137 | |
4137 return helper(expression); | 4138 return helper(expression); |
4138 } | 4139 } |
4139 | 4140 |
4140 /// The names of the libraries that can be accessed with a 'dart:x' import uri. | 4141 /// The names of the libraries that can be accessed with a 'dart:x' import uri. |
4141 Set<String> sdkLibraryNames = new Set.from([ | 4142 Set<String> sdkLibraryNames = new Set.from([ |
4142 "async", | 4143 "async", |
4143 "collection", | 4144 "collection", |
4144 "convert", | 4145 "convert", |
4145 "core", | 4146 "core", |
4146 "developer", | 4147 "developer", |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4219 // Some internal constants (mainly in dart:html) cannot be resolved by | 4220 // Some internal constants (mainly in dart:html) cannot be resolved by |
4220 // the analyzer. Ignore them. | 4221 // the analyzer. Ignore them. |
4221 // TODO(sigurdm) clarify: Investigate this, and see if these constants can | 4222 // TODO(sigurdm) clarify: Investigate this, and see if these constants can |
4222 // somehow be included. | 4223 // somehow be included. |
4223 logger.fine("Ignoring unresolved metadata $annotationNode", | 4224 logger.fine("Ignoring unresolved metadata $annotationNode", |
4224 asset: resolver.getSourceAssetId(element), | 4225 asset: resolver.getSourceAssetId(element), |
4225 span: resolver.getSourceSpan(element)); | 4226 span: resolver.getSourceSpan(element)); |
4226 continue; | 4227 continue; |
4227 } | 4228 } |
4228 | 4229 |
4229 LibraryElement library = annotationNode.element.library; | |
4230 if (!_isImportable(annotationNode.element, dataId, resolver)) { | 4230 if (!_isImportable(annotationNode.element, dataId, resolver)) { |
4231 // Private constants, and constants made of classes in internal libraries | 4231 // Private constants, and constants made of classes in internal libraries |
4232 // cannot be represented. | 4232 // cannot be represented. |
4233 // Skip them. | 4233 // Skip them. |
4234 // TODO(sigurdm) clarify: Investigate this, and see if these constants can | 4234 // TODO(sigurdm) clarify: Investigate this, and see if these constants can |
4235 // somehow be included. | 4235 // somehow be included. |
4236 logger.fine("Ignoring unrepresentable metadata $annotationNode", | 4236 logger.fine("Ignoring unrepresentable metadata $annotationNode", |
4237 asset: resolver.getSourceAssetId(element), | 4237 asset: resolver.getSourceAssetId(element), |
4238 span: resolver.getSourceSpan(element)); | 4238 span: resolver.getSourceSpan(element)); |
4239 continue; | 4239 continue; |
4240 } | 4240 } |
4241 importCollector._addLibrary(library); | 4241 LibraryElement annotationLibrary = annotationNode.element.library; |
4242 String prefix = importCollector._getPrefix(library); | 4242 importCollector._addLibrary(annotationLibrary); |
4243 String prefix = importCollector._getPrefix(annotationLibrary); | |
4243 if (annotationNode.arguments != null) { | 4244 if (annotationNode.arguments != null) { |
4244 // A const constructor. | 4245 // A const constructor. |
4245 Identifier annotationName = annotationNode.name; | 4246 Identifier annotationName = annotationNode.name; |
4246 String name; | 4247 String name; |
4247 if (annotationName is SimpleIdentifier) { | 4248 if (annotationName is SimpleIdentifier) { |
4248 name = "$annotationName"; | 4249 name = "$annotationName"; |
4249 } else if (annotationName is PrefixedIdentifier) { | 4250 } else if (annotationName is PrefixedIdentifier) { |
4250 // The annotation is on the form `@p.C(..)` where `p` is a library | 4251 // The annotation is on the form `@p.C(..)` where `p` is a library |
4251 // prefix, or it is on the form `@C.n(..)` where `C` is a class and | 4252 // prefix, or it is on the form `@C.n(..)` where `C` is a class and |
4252 // `n` a named constructor. | 4253 // `n` a named constructor. |
4253 if (annotationName.prefix.staticElement is PrefixElement) { | 4254 if (annotationName.prefix.staticElement is PrefixElement) { |
4254 // We must replace the library prefix by the appropriate prefix for | 4255 // We must replace the library prefix by the appropriate prefix for |
4255 // code in the generated library, so we omit `prefix`. | 4256 // code in the generated library, so we omit `prefix`. |
4256 name = "${annotationName.identifier}"; | 4257 name = "${annotationName.identifier}"; |
4257 } else { | 4258 } else { |
4258 // We must preserve the prefix which is a class name. | 4259 // We must preserve the prefix which is a class name. |
4259 name = "$annotationName"; | 4260 name = "$annotationName"; |
4260 } | 4261 } |
4261 // In both cases we must include the library prefix. | 4262 // In both cases we must include the library prefix. |
4262 prefix = importCollector._getPrefix(annotationNode.element.library); | 4263 prefix = importCollector._getPrefix(annotationNode.element.library); |
4263 } else { | 4264 } else { |
4264 throw unimplementedError( | 4265 throw unimplementedError( |
4265 "This kind of metadata not yet supported: $annotationNode"); | 4266 "This kind of metadata not yet supported: $annotationNode"); |
4266 } | 4267 } |
4267 String arguments = | 4268 String arguments = |
4268 annotationNode.arguments.arguments.map((Expression argument) { | 4269 annotationNode.arguments.arguments.map((Expression argument) { |
4269 return _extractConstantCode(argument, element.library, importCollector, | 4270 return _extractConstantCode( |
4270 logger, dataId, resolver); | 4271 argument, importCollector, logger, dataId, resolver); |
4271 }).join(", "); | 4272 }).join(", "); |
4272 if (_isPrivateName(name)) { | 4273 if (_isPrivateName(name)) { |
4273 logger.error("Cannot access private name $name"); | 4274 logger.error("Cannot access private name $name"); |
4274 } | 4275 } |
4275 metadataParts.add("const $prefix$name($arguments)"); | 4276 metadataParts.add("const $prefix$name($arguments)"); |
4276 } else { | 4277 } else { |
4277 // A field reference. | 4278 // A field reference. |
4278 if (_isPrivateName(annotationNode.name.name)) { | 4279 if (_isPrivateName(annotationNode.name.name)) { |
4279 logger.error("Cannot access private name ${annotationNode.name}"); | 4280 logger.error("Cannot access private name ${annotationNode.name}"); |
4280 } | 4281 } |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4597 } | 4598 } |
4598 } | 4599 } |
4599 | 4600 |
4600 @override | 4601 @override |
4601 int get nameLength => name.length; | 4602 int get nameLength => name.length; |
4602 | 4603 |
4603 @override | 4604 @override |
4604 String get displayName => name; | 4605 String get displayName => name; |
4605 | 4606 |
4606 @override | 4607 @override |
4608 String get documentationComment { | |
sigurdm
2016/03/07 08:53:08
Are we using this?
Otherwise it might make sense t
eernst
2016/03/07 14:50:34
It guess it feels like a very brittle approach to
| |
4609 if (subclass != null) { | |
4610 // This is a named mixin application (`class D = A with M`), so the | |
4611 // documentation comment is the one associated with `subclass` | |
4612 // (corresponding to `D` in the example). | |
4613 return subclass.documentationComment; | |
4614 } | |
4615 // This is an anonymous mixin application, so there is no way a programmer | |
4616 // could attach a documentation comment to it. However, adding a mixin `M` | |
4617 // to a given superclass is conceptually similar to using `M` directly, so | |
4618 // we return that documentation comment as the result. Note that `this` | |
4619 // mixin application and the returned comment are in unrelated locations | |
4620 // syntactically (e.g., they could be in different libraries), but it still | |
4621 // seems like the most meaningful return value. | |
4622 return mixin.documentationComment; | |
4623 } | |
4624 | |
4625 @override | |
4607 List<InterfaceType> get interfaces => <InterfaceType>[]; | 4626 List<InterfaceType> get interfaces => <InterfaceType>[]; |
4608 | 4627 |
4609 @override | 4628 @override |
4610 List<ElementAnnotation> get metadata => <ElementAnnotation>[]; | 4629 List<ElementAnnotation> get metadata => <ElementAnnotation>[]; |
4611 | 4630 |
4612 @override | 4631 @override |
4613 bool get isSynthetic => declaredName == null; | 4632 bool get isSynthetic => declaredName == null; |
4614 | 4633 |
4615 // The `InterfaceTypeImpl` may well call methods on this `MixinApplication` | 4634 // The `InterfaceTypeImpl` may well call methods on this `MixinApplication` |
4616 // whose body is unimplemented, but it still provides a slightly better | 4635 // whose body is unimplemented, but it still provides a slightly better |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4652 bool get isEnum => false; | 4671 bool get isEnum => false; |
4653 | 4672 |
4654 @override | 4673 @override |
4655 List<TypeParameterElement> get typeParameters => <TypeParameterElement>[]; | 4674 List<TypeParameterElement> get typeParameters => <TypeParameterElement>[]; |
4656 | 4675 |
4657 @override | 4676 @override |
4658 NamedCompilationUnitMember computeNode() => | 4677 NamedCompilationUnitMember computeNode() => |
4659 declaredName != null ? subclass.computeNode() : null; | 4678 declaredName != null ? subclass.computeNode() : null; |
4660 | 4679 |
4661 @override | 4680 @override |
4681 ElementKind get kind => ElementKind.CLASS; | |
4682 | |
4683 @override | |
4684 ElementLocation get location => null; | |
4685 | |
4686 @override | |
4662 bool operator ==(Object object) { | 4687 bool operator ==(Object object) { |
4663 return object is MixinApplication && | 4688 return object is MixinApplication && |
4664 superclass == object.superclass && | 4689 superclass == object.superclass && |
4665 mixin == object.mixin && | 4690 mixin == object.mixin && |
4666 library == object.library && | 4691 library == object.library && |
4667 subclass == object.subclass; | 4692 subclass == object.subclass; |
4668 } | 4693 } |
4669 | 4694 |
4670 @override | 4695 @override |
4671 int get hashCode => superclass.hashCode ^ mixin.hashCode ^ library.hashCode; | 4696 int get hashCode => superclass.hashCode ^ mixin.hashCode ^ library.hashCode; |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4794 @override | 4819 @override |
4795 bool get isDeprecated => throw unreachableError("isDeprecated"); | 4820 bool get isDeprecated => throw unreachableError("isDeprecated"); |
4796 | 4821 |
4797 @override | 4822 @override |
4798 bool get isOverride => throw unreachableError("isOverride"); | 4823 bool get isOverride => throw unreachableError("isOverride"); |
4799 | 4824 |
4800 @override | 4825 @override |
4801 bool get isPublic => throw unreachableError("isPublic"); | 4826 bool get isPublic => throw unreachableError("isPublic"); |
4802 | 4827 |
4803 @override | 4828 @override |
4804 ElementKind get kind => throw unreachableError("kind"); | |
4805 | |
4806 @override | |
4807 ElementLocation get location => throw unreachableError("location"); | |
4808 | |
4809 @override | |
4810 int get nameOffset => throw unreachableError("nameOffset"); | 4829 int get nameOffset => throw unreachableError("nameOffset"); |
4811 | 4830 |
4812 @override | 4831 @override |
4813 get source => throw unreachableError("source"); | 4832 get source => throw unreachableError("source"); |
4814 | 4833 |
4815 @override | 4834 @override |
4835 @deprecated | |
4816 get docRange => throw unreachableError("docRange"); | 4836 get docRange => throw unreachableError("docRange"); |
4817 | 4837 |
4818 @override | 4838 @override |
4819 CompilationUnit get unit => throw unreachableError("unit"); | 4839 CompilationUnit get unit => throw unreachableError("unit"); |
4820 | 4840 |
4821 @override | 4841 @override |
4822 accept(ElementVisitor visitor) => throw unreachableError("accept"); | 4842 accept(ElementVisitor visitor) => throw unreachableError("accept"); |
4823 | 4843 |
4824 @override | 4844 @override |
4845 @deprecated | |
4825 String computeDocumentationComment() => | 4846 String computeDocumentationComment() => |
4826 throw unreachableError("computeDocumentationComment"); | 4847 throw unreachableError("computeDocumentationComment"); |
4827 | 4848 |
4828 @override | 4849 @override |
4829 Element getAncestor(predicate) => throw unreachableError("getAncestor"); | 4850 Element getAncestor(predicate) => throw unreachableError("getAncestor"); |
4830 | 4851 |
4831 @override | 4852 @override |
4832 String getExtendedDisplayName(String shortName) => | 4853 String getExtendedDisplayName(String shortName) => |
4833 throw unreachableError("getExtendedDisplayName"); | 4854 throw unreachableError("getExtendedDisplayName"); |
4834 | 4855 |
(...skipping 27 matching lines...) Expand all Loading... | |
4862 | 4883 |
4863 String _qualifiedTypeParameterName(TypeParameterElement typeParameterElement) { | 4884 String _qualifiedTypeParameterName(TypeParameterElement typeParameterElement) { |
4864 if (typeParameterElement == null) return "null"; | 4885 if (typeParameterElement == null) return "null"; |
4865 return "${_qualifiedName(typeParameterElement.enclosingElement)}." | 4886 return "${_qualifiedName(typeParameterElement.enclosingElement)}." |
4866 "${typeParameterElement.name}"; | 4887 "${typeParameterElement.name}"; |
4867 } | 4888 } |
4868 | 4889 |
4869 bool _isPrivateName(String name) { | 4890 bool _isPrivateName(String name) { |
4870 return name.startsWith("_") || name.contains("._"); | 4891 return name.startsWith("_") || name.contains("._"); |
4871 } | 4892 } |
4893 | |
4894 /// Returns the `evaluationResult` for [annotation], after having forced | |
4895 /// constant resolution to take place in `annotation.compilationUnit.library`. | |
4896 /// Note that future invocations of `annotation.compilationUnit.library` will | |
4897 /// return a resolved library, but previously obtained results from that method | |
4898 /// will remain unresolved if they were unresolved when they were obtained. | |
4899 EvaluationResultImpl _annotationEvaluationResult( | |
4900 ElementAnnotationImpl annotation) { | |
4901 _resolvedLibraryOf(annotation.compilationUnit.library); | |
4902 return annotation.evaluationResult; | |
4903 } | |
4904 | |
4905 /// Returns the `evaluationResult` for [constFieldElement], after having forced | |
4906 /// constant resolution to take place in `constFieldElement.library`. | |
4907 /// Note that future invocations of `constFieldElement.library` will | |
4908 /// return a resolved library, but previously obtained results from that method | |
4909 /// will remain unresolved if they were unresolved when they were obtained. | |
4910 EvaluationResultImpl _constFieldEvaluationResult( | |
4911 ConstFieldElementImpl constFieldElement) { | |
4912 // This is safe: The result returned from `library` will not be used again. | |
4913 _resolvedLibraryOf(constFieldElement.library); | |
4914 return constFieldElement.evaluationResult; | |
4915 } | |
4916 | |
4917 /// Returns the `evaluationResult` for [constTopLevelVariable], after having | |
4918 /// forced constant resolution to take place in `constTopLevelvariable.library`. | |
4919 /// Note that future invocations of `constTopLevelVariable.library` will | |
4920 /// return a resolved library, but previously obtained results from that method | |
4921 /// will remain unresolved if they were unresolved when they were obtained. | |
4922 EvaluationResultImpl _constTopLevelVariableEvaluationResult( | |
4923 ConstTopLevelVariableElementImpl constTopLevelVariable) { | |
4924 // This is safe: The result returned from `library` will not be used again. | |
4925 _resolvedLibraryOf(constTopLevelVariable.library); | |
4926 return constTopLevelVariable.evaluationResult; | |
4927 } | |
4928 | |
4929 /// Requests resolution of constants in [libraryElement] and returns a | |
4930 /// [LibraryElement] wherein they have been resolved. If the library has | |
4931 /// been obtained by evaluating `library` on an `Element` and all further | |
4932 /// usage of that library will happen by invoking `library` again then it is | |
4933 /// safe to ignore the returned value (because the future invocations of | |
4934 /// `library` will return the resolved library). | |
4935 LibraryElement _resolvedLibraryOf(LibraryElement libraryElement) { | |
sigurdm
2016/03/07 08:53:08
would it be simpler to split this in two
void _en
eernst
2016/03/07 14:50:34
The reason why I did not do that (I tried) is that
| |
4936 LibraryElement resolvedLibrary = _resolvedLibraries[libraryElement]; | |
4937 if (resolvedLibrary == null) { | |
4938 resolvedLibrary = libraryElement.context | |
4939 .computeLibraryElement(libraryElement.definingCompilationUnit.source); | |
4940 _resolvedLibraries[libraryElement] = resolvedLibrary; | |
4941 } | |
4942 return resolvedLibrary; | |
4943 } | |
4944 | |
4945 Map<LibraryElement, LibraryElement> _resolvedLibraries = | |
4946 <LibraryElement, LibraryElement>{}; | |
OLD | NEW |