| Index: reflectable/lib/src/transformer_implementation.dart
|
| diff --git a/reflectable/lib/src/transformer_implementation.dart b/reflectable/lib/src/transformer_implementation.dart
|
| index deaeb57d306f116984ae071c54abfe97ece97c4d..f4850a28926b0cdd2aab2b2aa6ecdf6e0fcc52ee 100644
|
| --- a/reflectable/lib/src/transformer_implementation.dart
|
| +++ b/reflectable/lib/src/transformer_implementation.dart
|
| @@ -658,7 +658,6 @@ class _ReflectorDomain {
|
| parameterNode.defaultValue != null) {
|
| defaultValueCode = " = ${_extractConstantCode(
|
| parameterNode.defaultValue,
|
| - parameterElement.library,
|
| importCollector, logger, _generatedLibraryId, _resolver)}";
|
| }
|
| return "${parameterNames[requiredPositionalCount + i]}"
|
| @@ -679,7 +678,6 @@ class _ReflectorDomain {
|
| parameterNode.defaultValue != null) {
|
| defaultValueCode = ": ${_extractConstantCode(
|
| parameterNode.defaultValue,
|
| - parameterElement.library,
|
| importCollector, logger, _generatedLibraryId, _resolver)}";
|
| }
|
| return "${namedParameterNames[i]}$defaultValueCode";
|
| @@ -787,9 +785,10 @@ class _ReflectorDomain {
|
| // [parameters], [instanceGetterNames], and [instanceSetterNames].
|
| _libraries.items.forEach(uncheckedAddLibrary);
|
| classes.forEach((ClassElement classElement) {
|
| + LibraryElement classLibrary = classElement.library;
|
| if (!libraries.items.any((_LibraryDomain libraryDomain) =>
|
| - libraryDomain._libraryElement == classElement.library)) {
|
| - addLibrary(classElement.library);
|
| + libraryDomain._libraryElement == classLibrary)) {
|
| + addLibrary(classLibrary);
|
| }
|
| classElement.typeParameters.forEach(typeParameters.add);
|
| });
|
| @@ -863,8 +862,9 @@ class _ReflectorDomain {
|
| if (_capabilities._impliesTypes && _capabilities._impliesTypeAnnotations) {
|
| void addClass(ClassElement classElement) {
|
| classes.add(classElement);
|
| - if (!libraries.items.contains(classElement.library)) {
|
| - uncheckedAddLibrary(classElement.library);
|
| + LibraryElement classLibrary = classElement.library;
|
| + if (!libraries.items.contains(classLibrary)) {
|
| + uncheckedAddLibrary(classLibrary);
|
| }
|
| }
|
|
|
| @@ -1934,13 +1934,8 @@ class _ReflectorDomain {
|
| String defaultValueCode = "null";
|
| if (parameterNode is DefaultFormalParameter &&
|
| parameterNode.defaultValue != null) {
|
| - defaultValueCode = _extractConstantCode(
|
| - parameterNode.defaultValue,
|
| - element.library,
|
| - importCollector,
|
| - logger,
|
| - _generatedLibraryId,
|
| - _resolver);
|
| + defaultValueCode = _extractConstantCode(parameterNode.defaultValue,
|
| + importCollector, logger, _generatedLibraryId, _resolver);
|
| }
|
| String parameterSymbolCode = descriptor & constants.namedAttribute != 0
|
| ? "#${element.name}"
|
| @@ -2556,7 +2551,8 @@ class _Capabilities {
|
| Iterable<DartObjectImpl> _getEvaluatedMetadata(
|
| Iterable<ElementAnnotation> metadata) {
|
| return metadata.map((ElementAnnotationImpl elementAnnotation) {
|
| - EvaluationResultImpl evaluation = elementAnnotation.evaluationResult;
|
| + EvaluationResultImpl evaluation =
|
| + _annotationEvaluationResult(elementAnnotation);
|
| if (evaluation != null) return evaluation.value;
|
| // The `evaluationResult` from a getter is `null`, so we have to deal
|
| // with that case separately.
|
| @@ -2913,7 +2909,7 @@ class TransformerImplementation {
|
| FieldElement idField = type.getField("thisClassId");
|
| if (idField == null || !idField.isStatic) return false;
|
| if (idField is ConstFieldElementImpl) {
|
| - EvaluationResultImpl idResult = idField.evaluationResult;
|
| + EvaluationResultImpl idResult = _constFieldEvaluationResult(idField);
|
| if (idResult != null) {
|
| return idField.constantValue.toStringValue() ==
|
| reflectable_class_constants.id;
|
| @@ -2922,10 +2918,11 @@ class TransformerImplementation {
|
| // occur "if this variable is not a 'const' variable, if it does not
|
| // have an initializer, or if the compilation unit containing the
|
| // variable has not been resolved". The third case should not occur with
|
| - // the approach we use to obtain a `LibraryElement`, so it is not the
|
| + // the approach we use to obtain the `LibraryElement` for the library
|
| + // 'package:reflectable/reflectable.dart', so it is not the
|
| // right declaration we are looking at.
|
| }
|
| - // Not a const field, or failed the test, cannot be the right class.
|
| + // Not a const field, or failed the `id` test: cannot be the right class.
|
| return false;
|
| }
|
|
|
| @@ -3010,7 +3007,8 @@ class TransformerImplementation {
|
| // [VariableElementImpl], but with that one we would have to test
|
| // `isConst` as well.
|
| if (variable is ConstTopLevelVariableElementImpl) {
|
| - EvaluationResultImpl result = variable.evaluationResult;
|
| + EvaluationResultImpl result =
|
| + _constTopLevelVariableEvaluationResult(variable);
|
| // Handle errors during evaluation. In general `evaluationResult` is
|
| // null for (1) non-const variables, (2) variables without an
|
| // initializer, and (3) unresolved libraries; (3) should not occur
|
| @@ -3027,7 +3025,7 @@ class TransformerImplementation {
|
| // we have non-const metadata then the program (pre- and post-
|
| // transformed) will be rejected by the analyzer and the compilers,
|
| // which means that it is unimportant for us to reject that case.
|
| - EvaluationResultImpl result = variable.evaluationResult;
|
| + EvaluationResultImpl result = _constFieldEvaluationResult(variable);
|
| if (result?.value == null) return null;
|
| bool isOk = checkInheritance(result.value.type, focusClass.type);
|
| return isOk ? result.value.type.element : null;
|
| @@ -3083,9 +3081,11 @@ class TransformerImplementation {
|
|
|
| for (LibraryElement library in _resolver.libraries) {
|
| for (ImportElement import in library.imports) {
|
| + if (import.importedLibrary != reflectableLibrary) continue;
|
| for (ElementAnnotationImpl metadatum in import.metadata) {
|
| if (metadatum.element == globalQuantifyCapabilityConstructor) {
|
| - EvaluationResultImpl evaluation = metadatum.evaluationResult;
|
| + EvaluationResultImpl evaluation =
|
| + _annotationEvaluationResult(metadatum);
|
| if (evaluation != null && evaluation.value != null) {
|
| DartObjectImpl value = evaluation.value;
|
| String pattern = value.fields["classNamePattern"].toStringValue();
|
| @@ -3116,7 +3116,8 @@ class TransformerImplementation {
|
| }
|
| } else if (metadatum.element ==
|
| globalQuantifyMetaCapabilityConstructor) {
|
| - EvaluationResultImpl evaluation = metadatum.evaluationResult;
|
| + EvaluationResultImpl evaluation =
|
| + _annotationEvaluationResult(metadatum);
|
| if (evaluation?.value != null) {
|
| DartObjectImpl value = evaluation.value;
|
| Object metadataFieldValue =
|
| @@ -3265,10 +3266,11 @@ class TransformerImplementation {
|
| /// it if none exists.
|
| _ReflectorDomain getReflectorDomain(ClassElement reflector) {
|
| return domains.putIfAbsent(reflector, () {
|
| + LibraryElement reflectorLibrary = reflector.library;
|
| _Capabilities capabilities =
|
| _capabilitiesOf(capabilityLibrary, reflector);
|
| - assert(_isImportableLibrary(reflector.library, dataId, _resolver));
|
| - importCollector._addLibrary(reflector.library);
|
| + assert(_isImportableLibrary(reflectorLibrary, dataId, _resolver));
|
| + importCollector._addLibrary(reflectorLibrary);
|
| return new _ReflectorDomain(_resolver, dataId, reflector, capabilities);
|
| });
|
| }
|
| @@ -3326,11 +3328,11 @@ class TransformerImplementation {
|
| }
|
| }
|
|
|
| - /// Runs through a list of metadata, and finds any Reflectors, and
|
| + /// Runs through [metadata] and finds all reflectors as well as
|
| /// objects that are associated with reflectors via
|
| - /// GlobalQuantifyMetaCapability and GlobalQuantifyCapability.
|
| + /// [GlobalQuantifyMetaCapability] or [GlobalQuantifyCapability].
|
| /// [qualifiedName] is the name of the library or class annotated by
|
| - /// metadata.
|
| + /// [metadata].
|
| Iterable<ClassElement> getReflectors(
|
| String qualifiedName, List<ElementAnnotation> metadata) {
|
| List<ClassElement> result = <ClassElement>[];
|
| @@ -3770,6 +3772,7 @@ _initializeReflectable() {
|
| }
|
| return;
|
| }
|
| + reflectableLibrary = _resolvedLibraryOf(reflectableLibrary);
|
|
|
| LibraryElement entryPointLibrary = _resolver.getLibrary(asset.id);
|
| if (const bool.fromEnvironment("reflectable.print.entry.point")) {
|
| @@ -3811,6 +3814,10 @@ _initializeReflectable() {
|
| if (const bool.fromEnvironment("reflectable.pause.at.exit")) {
|
| _processedEntryPointCount++;
|
| }
|
| + if (const bool.fromEnvironment("reflectable.print.resolved.libraries")) {
|
| + print("Resolved libraries for $currentEntryPoint: "
|
| + "${_resolvedLibraries.length}/${_resolver.libraries.length}");
|
| + }
|
| _resolver.release();
|
|
|
| if (const bool.fromEnvironment("reflectable.pause.at.exit")) {
|
| @@ -4006,7 +4013,6 @@ String _formatAsMap(Iterable parts) => "{${parts.join(", ")}}";
|
| /// would evaluate to in [originatingLibrary].
|
| String _extractConstantCode(
|
| Expression expression,
|
| - LibraryElement originatingLibrary,
|
| _ImportCollector importCollector,
|
| TransformLogger logger,
|
| AssetId generatedLibraryId,
|
| @@ -4038,8 +4044,7 @@ String _extractConstantCode(
|
| if (_isImportableLibrary(
|
| libraryOfConstructor, generatedLibraryId, resolver)) {
|
| importCollector._addLibrary(libraryOfConstructor);
|
| - String prefix =
|
| - importCollector._getPrefix(expression.staticElement.library);
|
| + String prefix = importCollector._getPrefix(libraryOfConstructor);
|
| // TODO(sigurdm) implement: Named arguments.
|
| String arguments =
|
| expression.argumentList.arguments.map((Expression argument) {
|
| @@ -4115,13 +4120,8 @@ String _extractConstantCode(
|
| String b = helper(arguments[1]);
|
| return "identical($a, $b)";
|
| } else if (expression is NamedExpression) {
|
| - String value = _extractConstantCode(
|
| - expression.expression,
|
| - originatingLibrary,
|
| - importCollector,
|
| - logger,
|
| - generatedLibraryId,
|
| - resolver);
|
| + String value = _extractConstantCode(expression.expression,
|
| + importCollector, logger, generatedLibraryId, resolver);
|
| return "${expression.name} $value";
|
| } else {
|
| assert(expression is IntegerLiteral ||
|
| @@ -4134,6 +4134,7 @@ String _extractConstantCode(
|
| return expression.toSource();
|
| }
|
| }
|
| +
|
| return helper(expression);
|
| }
|
|
|
| @@ -4226,7 +4227,6 @@ String _extractMetadataCode(Element element, Resolver resolver,
|
| continue;
|
| }
|
|
|
| - LibraryElement library = annotationNode.element.library;
|
| if (!_isImportable(annotationNode.element, dataId, resolver)) {
|
| // Private constants, and constants made of classes in internal libraries
|
| // cannot be represented.
|
| @@ -4238,8 +4238,9 @@ String _extractMetadataCode(Element element, Resolver resolver,
|
| span: resolver.getSourceSpan(element));
|
| continue;
|
| }
|
| - importCollector._addLibrary(library);
|
| - String prefix = importCollector._getPrefix(library);
|
| + LibraryElement annotationLibrary = annotationNode.element.library;
|
| + importCollector._addLibrary(annotationLibrary);
|
| + String prefix = importCollector._getPrefix(annotationLibrary);
|
| if (annotationNode.arguments != null) {
|
| // A const constructor.
|
| Identifier annotationName = annotationNode.name;
|
| @@ -4266,8 +4267,8 @@ String _extractMetadataCode(Element element, Resolver resolver,
|
| }
|
| String arguments =
|
| annotationNode.arguments.arguments.map((Expression argument) {
|
| - return _extractConstantCode(argument, element.library, importCollector,
|
| - logger, dataId, resolver);
|
| + return _extractConstantCode(
|
| + argument, importCollector, logger, dataId, resolver);
|
| }).join(", ");
|
| if (_isPrivateName(name)) {
|
| logger.error("Cannot access private name $name");
|
| @@ -4659,6 +4660,12 @@ class MixinApplication implements ClassElement {
|
| declaredName != null ? subclass.computeNode() : null;
|
|
|
| @override
|
| + ElementKind get kind => ElementKind.CLASS;
|
| +
|
| + @override
|
| + ElementLocation get location => null;
|
| +
|
| + @override
|
| bool operator ==(Object object) {
|
| return object is MixinApplication &&
|
| superclass == object.superclass &&
|
| @@ -4801,18 +4808,17 @@ class MixinApplication implements ClassElement {
|
| bool get isPublic => throw unreachableError("isPublic");
|
|
|
| @override
|
| - ElementKind get kind => throw unreachableError("kind");
|
| -
|
| - @override
|
| - ElementLocation get location => throw unreachableError("location");
|
| -
|
| - @override
|
| int get nameOffset => throw unreachableError("nameOffset");
|
|
|
| @override
|
| get source => throw unreachableError("source");
|
|
|
| @override
|
| + String get documentationComment =>
|
| + throw unreachableError("documentationComment");
|
| +
|
| + @override
|
| + @deprecated
|
| get docRange => throw unreachableError("docRange");
|
|
|
| @override
|
| @@ -4822,6 +4828,7 @@ class MixinApplication implements ClassElement {
|
| accept(ElementVisitor visitor) => throw unreachableError("accept");
|
|
|
| @override
|
| + @deprecated
|
| String computeDocumentationComment() =>
|
| throw unreachableError("computeDocumentationComment");
|
|
|
| @@ -4869,3 +4876,57 @@ String _qualifiedTypeParameterName(TypeParameterElement typeParameterElement) {
|
| bool _isPrivateName(String name) {
|
| return name.startsWith("_") || name.contains("._");
|
| }
|
| +
|
| +/// Returns the `evaluationResult` for [annotation], after having forced
|
| +/// constant resolution to take place in `annotation.compilationUnit.library`.
|
| +/// Note that future invocations of `annotation.compilationUnit.library` will
|
| +/// return a resolved library, but previously obtained results from that method
|
| +/// will remain unresolved if they were unresolved when they were obtained.
|
| +EvaluationResultImpl _annotationEvaluationResult(
|
| + ElementAnnotationImpl annotation) {
|
| + _resolvedLibraryOf(annotation.compilationUnit.library);
|
| + return annotation.evaluationResult;
|
| +}
|
| +
|
| +/// Returns the `evaluationResult` for [constFieldElement], after having forced
|
| +/// constant resolution to take place in `constFieldElement.library`.
|
| +/// Note that future invocations of `constFieldElement.library` will
|
| +/// return a resolved library, but previously obtained results from that method
|
| +/// will remain unresolved if they were unresolved when they were obtained.
|
| +EvaluationResultImpl _constFieldEvaluationResult(
|
| + ConstFieldElementImpl constFieldElement) {
|
| + // This is safe: The result returned from `library` will not be used again.
|
| + _resolvedLibraryOf(constFieldElement.library);
|
| + return constFieldElement.evaluationResult;
|
| +}
|
| +
|
| +/// Returns the `evaluationResult` for [constTopLevelVariable], after having
|
| +/// forced constant resolution to take place in `constTopLevelvariable.library`.
|
| +/// Note that future invocations of `constTopLevelVariable.library` will
|
| +/// return a resolved library, but previously obtained results from that method
|
| +/// will remain unresolved if they were unresolved when they were obtained.
|
| +EvaluationResultImpl _constTopLevelVariableEvaluationResult(
|
| + ConstTopLevelVariableElementImpl constTopLevelVariable) {
|
| + // This is safe: The result returned from `library` will not be used again.
|
| + _resolvedLibraryOf(constTopLevelVariable.library);
|
| + return constTopLevelVariable.evaluationResult;
|
| +}
|
| +
|
| +/// Requests resolution of constants in [libraryElement] and returns a
|
| +/// [LibraryElement] wherein they have been resolved. If the library has
|
| +/// been obtained by evaluating `library` on an `Element` and all further
|
| +/// usage of that library will happen by invoking `library` again then it is
|
| +/// safe to ignore the returned value (because the future invocations of
|
| +/// `library` will return the resolved library).
|
| +LibraryElement _resolvedLibraryOf(LibraryElement libraryElement) {
|
| + LibraryElement resolvedLibrary = _resolvedLibraries[libraryElement];
|
| + if (resolvedLibrary == null) {
|
| + resolvedLibrary = libraryElement.context
|
| + .computeLibraryElement(libraryElement.definingCompilationUnit.source);
|
| + _resolvedLibraries[libraryElement] = resolvedLibrary;
|
| + }
|
| + return resolvedLibrary;
|
| +}
|
| +
|
| +Map<LibraryElement, LibraryElement> _resolvedLibraries =
|
| + <LibraryElement, LibraryElement>{};
|
|
|