| // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| library js_backend.backend.annotations; |
| |
| import '../common.dart'; |
| import '../compiler.dart' show Compiler; |
| import '../constants/values.dart'; |
| import '../elements/elements.dart'; |
| import 'backend.dart'; |
| |
| /// Handling of special annotations for tests. |
| class Annotations { |
| static final Uri PACKAGE_EXPECT = |
| new Uri(scheme: 'package', path: 'expect/expect.dart'); |
| |
| final Compiler compiler; |
| |
| ClassElement expectNoInlineClass; |
| ClassElement expectTrustTypeAnnotationsClass; |
| ClassElement expectAssumeDynamicClass; |
| |
| JavaScriptBackend get backend => compiler.backend; |
| |
| DiagnosticReporter get reporter => compiler.reporter; |
| |
| Annotations(this.compiler); |
| |
| void onLibraryScanned(LibraryElement library) { |
| if (library.canonicalUri == PACKAGE_EXPECT) { |
| expectNoInlineClass = library.find('NoInline'); |
| expectTrustTypeAnnotationsClass = library.find('TrustTypeAnnotations'); |
| expectAssumeDynamicClass = library.find('AssumeDynamic'); |
| if (expectNoInlineClass == null || |
| expectTrustTypeAnnotationsClass == null || |
| expectAssumeDynamicClass == null) { |
| // This is not the package you're looking for. |
| expectNoInlineClass = null; |
| expectTrustTypeAnnotationsClass = null; |
| expectAssumeDynamicClass = null; |
| } |
| } |
| } |
| |
| /// Returns `true` if inlining is disabled for [element]. |
| bool noInline(Element element) { |
| if (_hasAnnotation(element, expectNoInlineClass)) { |
| // TODO(floitsch): restrict to elements from the test directory. |
| return true; |
| } |
| return _hasAnnotation(element, backend.helpers.noInlineClass); |
| } |
| |
| /// Returns `true` if parameter and returns types should be trusted for |
| /// [element]. |
| bool trustTypeAnnotations(Element element) { |
| return _hasAnnotation(element, expectTrustTypeAnnotationsClass); |
| } |
| |
| /// Returns `true` if inference of parameter types is disabled for [element]. |
| bool assumeDynamic(Element element) { |
| return _hasAnnotation(element, expectAssumeDynamicClass); |
| } |
| |
| /// Returns `true` if [element] is annotated with [annotationClass]. |
| bool _hasAnnotation(Element element, ClassElement annotationClass) { |
| if (annotationClass == null) return false; |
| return reporter.withCurrentElement(element, () { |
| for (MetadataAnnotation metadata in element.metadata) { |
| assert(invariant(metadata, metadata.constant != null, |
| message: "Unevaluated metadata constant.")); |
| ConstantValue value = |
| compiler.constants.getConstantValue(metadata.constant); |
| if (value.isConstructedObject) { |
| ConstructedConstantValue constructedConstant = value; |
| if (constructedConstant.type.element == annotationClass) { |
| return true; |
| } |
| } |
| } |
| return false; |
| }); |
| } |
| } |