blob: e1fffe7121d9a3d96cc267a21920a2c8c82aadd6 [file] [log] [blame]
// 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;
});
}
}