Revert "Remove Registry from registerMetadataConstant" and "Serialize metadata"
This reverts commited1777e4b2. This reverts commitf8e3f22347. Review URL: https://codereview.chromium.org/2070493003 .
This commit is contained in:
@@ -131,6 +131,11 @@ abstract class Backend extends Target {
|
||||
/// Called during codegen when [constant] has been used.
|
||||
void registerCompileTimeConstant(ConstantValue constant, Registry registry) {}
|
||||
|
||||
/// Called during resolution when a constant value for [metadata] on
|
||||
/// [annotatedElement] has been evaluated.
|
||||
void registerMetadataConstant(MetadataAnnotation metadata,
|
||||
Element annotatedElement, Registry registry) {}
|
||||
|
||||
/// Called to notify to the backend that a class is being instantiated.
|
||||
// TODO(johnniwinther): Remove this. It's only called once for each [cls] and
|
||||
// only with [Compiler.globalDependencies] as [registry].
|
||||
@@ -273,25 +278,23 @@ abstract class Backend extends Target {
|
||||
/// been scanned.
|
||||
Future onLibraryScanned(LibraryElement library, LibraryLoader loader) {
|
||||
// TODO(johnniwinther): Move this to [JavaScriptBackend].
|
||||
if (!compiler.serialization.isDeserialized(library)) {
|
||||
if (canLibraryUseNative(library)) {
|
||||
library.forEachLocalMember((Element element) {
|
||||
if (element.isClass) {
|
||||
checkNativeAnnotation(compiler, element);
|
||||
}
|
||||
});
|
||||
}
|
||||
checkJsInteropAnnotation(compiler, library);
|
||||
if (canLibraryUseNative(library)) {
|
||||
library.forEachLocalMember((Element element) {
|
||||
checkJsInteropAnnotation(compiler, element);
|
||||
if (element.isClass && isJsInterop(element)) {
|
||||
ClassElement classElement = element;
|
||||
classElement.forEachMember((_, memberElement) {
|
||||
checkJsInteropAnnotation(compiler, memberElement);
|
||||
});
|
||||
if (element.isClass) {
|
||||
checkNativeAnnotation(compiler, element);
|
||||
}
|
||||
});
|
||||
}
|
||||
checkJsInteropAnnotation(compiler, library);
|
||||
library.forEachLocalMember((Element element) {
|
||||
checkJsInteropAnnotation(compiler, element);
|
||||
if (element.isClass && isJsInterop(element)) {
|
||||
ClassElement classElement = element;
|
||||
classElement.forEachMember((_, memberElement) {
|
||||
checkJsInteropAnnotation(compiler, memberElement);
|
||||
});
|
||||
}
|
||||
});
|
||||
return new Future.value();
|
||||
}
|
||||
|
||||
|
||||
@@ -165,9 +165,7 @@ abstract class ConstantCompilerBase implements ConstantCompiler {
|
||||
@override
|
||||
@deprecated
|
||||
ConstantValue getConstantValueForVariable(VariableElement element) {
|
||||
ConstantExpression constant = initialVariableValues[element.declaration];
|
||||
// TODO(johnniwinther): Support eager evaluation of the constant.
|
||||
return constant != null ? getConstantValue(constant) : null;
|
||||
return getConstantValue(initialVariableValues[element.declaration]);
|
||||
}
|
||||
|
||||
ConstantExpression compileConstant(VariableElement element) {
|
||||
@@ -322,27 +320,8 @@ abstract class ConstantCompilerBase implements ConstantCompiler {
|
||||
return constantValueMap.containsKey(expression);
|
||||
}
|
||||
|
||||
@override
|
||||
ConstantValue getConstantValue(ConstantExpression expression) {
|
||||
assert(invariant(CURRENT_ELEMENT_SPANNABLE, expression != null,
|
||||
message: "ConstantExpression is null in getConstantValue."));
|
||||
// TODO(johnniwinther): ensure expressions have been evaluated at this
|
||||
// point. This can't be enabled today due to dartbug.com/26406.
|
||||
if (compiler.serialization.supportsDeserialization) {
|
||||
evaluate(expression);
|
||||
}
|
||||
ConstantValue value = constantValueMap[expression];
|
||||
if (value == null &&
|
||||
expression != null &&
|
||||
expression.kind == ConstantExpressionKind.ERRONEOUS) {
|
||||
// TODO(johnniwinther): When the Dart constant system sees a constant
|
||||
// expression as erroneous but the JavaScript constant system finds it ok
|
||||
// we have store a constant value for the erroneous constant expression.
|
||||
// Ensure the computed constant expressions are always the same; that only
|
||||
// the constant values may be different.
|
||||
value = new NullConstantValue();
|
||||
}
|
||||
return value;
|
||||
return constantValueMap[expression];
|
||||
}
|
||||
|
||||
ConstantExpression compileNode(Node node, TreeElements elements,
|
||||
@@ -380,7 +359,7 @@ class DartConstantCompiler extends ConstantCompilerBase {
|
||||
Node node, TreeElements definitions,
|
||||
{bool isConst: true}) {
|
||||
ConstantExpression constant = definitions.getConstant(node);
|
||||
if (constant != null && hasConstantValue(constant)) {
|
||||
if (constant != null && getConstantValue(constant) != null) {
|
||||
return constant;
|
||||
}
|
||||
constant =
|
||||
|
||||
@@ -1658,9 +1658,8 @@ class CompilerDiagnosticReporter extends DiagnosticReporter {
|
||||
if (astElement.hasNode) {
|
||||
Token from = astElement.node.getBeginToken();
|
||||
Token to = astElement.node.getEndToken();
|
||||
if (astElement.metadata.isNotEmpty &&
|
||||
astElement.metadata.first.hasNode) {
|
||||
from = astElement.metadata.first.node.getBeginToken();
|
||||
if (astElement.metadata.isNotEmpty) {
|
||||
from = astElement.metadata.first.beginToken;
|
||||
}
|
||||
return validateToken(from, to);
|
||||
}
|
||||
@@ -1741,7 +1740,8 @@ class CompilerDiagnosticReporter extends DiagnosticReporter {
|
||||
} else if (node is Element) {
|
||||
return spanFromElement(node);
|
||||
} else if (node is MetadataAnnotation) {
|
||||
return node.sourcePosition;
|
||||
Uri uri = node.annotatedElement.compilationUnit.script.resourceUri;
|
||||
return spanFromTokens(node.beginToken, node.endToken, uri);
|
||||
} else if (node is Local) {
|
||||
Local local = node;
|
||||
return spanFromElement(local.executableContext);
|
||||
|
||||
@@ -28,7 +28,6 @@ abstract class ConstantValueVisitor<R, A> {
|
||||
R visitInterceptor(InterceptorConstantValue constant, A arg);
|
||||
R visitSynthetic(SyntheticConstantValue constant, A arg);
|
||||
R visitDeferred(DeferredConstantValue constant, A arg);
|
||||
R visitNonConstant(NonConstantValue constant, A arg);
|
||||
}
|
||||
|
||||
abstract class ConstantValue {
|
||||
@@ -763,7 +762,7 @@ class NonConstantValue extends ConstantValue {
|
||||
|
||||
@override
|
||||
accept(ConstantValueVisitor visitor, arg) {
|
||||
return visitor.visitNonConstant(this, arg);
|
||||
// TODO(johnniwinther): Should this be part of the visiting?
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -475,10 +475,6 @@ class ConstantStringifier extends ConstantValueVisitor<String, Null> {
|
||||
return '(Null)';
|
||||
}
|
||||
|
||||
String visitNonConstant(NonConstantValue constant, _) {
|
||||
return '(NonConstant)';
|
||||
}
|
||||
|
||||
String visitInt(IntConstantValue constant, _) {
|
||||
return '(Int ${constant.toDartText()})';
|
||||
}
|
||||
|
||||
@@ -1620,7 +1620,9 @@ abstract class MetadataAnnotation implements Spannable {
|
||||
/// The front-end constant of this metadata annotation.
|
||||
ConstantExpression get constant;
|
||||
Element get annotatedElement;
|
||||
SourceSpan get sourcePosition;
|
||||
int get resolutionState;
|
||||
Token get beginToken;
|
||||
Token get endToken;
|
||||
|
||||
bool get hasNode;
|
||||
Node get node;
|
||||
|
||||
@@ -3193,8 +3193,6 @@ abstract class MetadataAnnotationX implements MetadataAnnotation {
|
||||
*/
|
||||
Token get beginToken;
|
||||
|
||||
Token get endToken;
|
||||
|
||||
MetadataAnnotationX([this.resolutionState = STATE_NOT_STARTED]);
|
||||
|
||||
MetadataAnnotation ensureResolved(Resolution resolution) {
|
||||
@@ -3210,11 +3208,6 @@ abstract class MetadataAnnotationX implements MetadataAnnotation {
|
||||
|
||||
Node parseNode(ParsingContext parsing);
|
||||
|
||||
SourceSpan get sourcePosition {
|
||||
Uri uri = annotatedElement.compilationUnit.script.resourceUri;
|
||||
return new SourceSpan.fromTokens(uri, beginToken, endToken);
|
||||
}
|
||||
|
||||
String toString() => 'MetadataAnnotation($constant, $resolutionState)';
|
||||
}
|
||||
|
||||
|
||||
@@ -449,7 +449,6 @@ abstract class Enqueuer {
|
||||
bool includeLibrary =
|
||||
shouldIncludeElementDueToMirrors(lib, includedEnclosing: false);
|
||||
lib.forEachLocalMember((Element member) {
|
||||
if (member.isInjected) return;
|
||||
if (member.isClass) {
|
||||
enqueueReflectiveElementsInClass(member, recents, includeLibrary);
|
||||
} else {
|
||||
|
||||
@@ -449,9 +449,6 @@ class JavaScriptBackend extends Backend {
|
||||
/// these constants must be registered.
|
||||
final List<Dependency> metadataConstants = <Dependency>[];
|
||||
|
||||
/// Set of elements for which metadata has been registered as dependencies.
|
||||
final Set<Element> _registeredMetadata = new Set<Element>();
|
||||
|
||||
/// List of elements that the user has requested for reflection.
|
||||
final Set<Element> targetsUsed = new Set<Element>();
|
||||
|
||||
@@ -1057,6 +1054,14 @@ class JavaScriptBackend extends Backend {
|
||||
}
|
||||
}
|
||||
|
||||
void registerMetadataConstant(MetadataAnnotation metadata,
|
||||
Element annotatedElement, Registry registry) {
|
||||
assert(registry.isForResolution);
|
||||
ConstantValue constant = constants.getConstantValueForMetadata(metadata);
|
||||
registerCompileTimeConstant(constant, registry);
|
||||
metadataConstants.add(new Dependency(constant, annotatedElement));
|
||||
}
|
||||
|
||||
void registerInstantiatedClass(
|
||||
ClassElement cls, Enqueuer enqueuer, Registry registry) {
|
||||
_processClass(cls, enqueuer, registry);
|
||||
@@ -1267,7 +1272,6 @@ class JavaScriptBackend extends Backend {
|
||||
super.onResolutionComplete();
|
||||
computeMembersNeededForReflection();
|
||||
rti.computeClassesNeedingRti();
|
||||
_registeredMetadata.clear();
|
||||
}
|
||||
|
||||
onTypeInferenceComplete() {
|
||||
@@ -2300,60 +2304,17 @@ class JavaScriptBackend extends Backend {
|
||||
reporter.log('Retaining metadata.');
|
||||
|
||||
compiler.libraryLoader.libraries.forEach(retainMetadataOf);
|
||||
|
||||
if (enqueuer.isResolutionQueue) {
|
||||
/// Register the constant value of [metadata] as live in resolution.
|
||||
void registerMetadataConstant(MetadataAnnotation metadata) {
|
||||
ConstantValue constant =
|
||||
constants.getConstantValueForMetadata(metadata);
|
||||
Dependency dependency =
|
||||
new Dependency(constant, metadata.annotatedElement);
|
||||
metadataConstants.add(dependency);
|
||||
registerCompileTimeConstant(dependency.constant,
|
||||
new EagerRegistry('EagerRegistry for ${dependency}', enqueuer));
|
||||
}
|
||||
|
||||
// TODO(johnniwinther): We should have access to all recently processed
|
||||
// elements and process these instead.
|
||||
processMetadata(compiler.enqueuer.resolution.processedElements,
|
||||
registerMetadataConstant);
|
||||
} else {
|
||||
for (Dependency dependency in metadataConstants) {
|
||||
registerCompileTimeConstant(dependency.constant,
|
||||
new EagerRegistry('EagerRegistry for ${dependency}', enqueuer));
|
||||
}
|
||||
for (Dependency dependency in metadataConstants) {
|
||||
registerCompileTimeConstant(dependency.constant,
|
||||
new EagerRegistry('EagerRegistry for ${dependency}', enqueuer));
|
||||
}
|
||||
if (!enqueuer.isResolutionQueue) {
|
||||
metadataConstants.clear();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Call [registerMetadataConstant] on all metadata from [elements].
|
||||
void processMetadata(Iterable<Element> elements,
|
||||
void onMetadata(MetadataAnnotation metadata)) {
|
||||
void processLibraryMetadata(LibraryElement library) {
|
||||
if (_registeredMetadata.add(library)) {
|
||||
library.metadata.forEach(onMetadata);
|
||||
for (ImportElement import in library.imports) {
|
||||
import.metadata.forEach(onMetadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void processElementMetadata(Element element) {
|
||||
if (_registeredMetadata.add(element)) {
|
||||
element.metadata.forEach(onMetadata);
|
||||
if (element.enclosingClass != null) {
|
||||
processElementMetadata(element.enclosingClass);
|
||||
} else {
|
||||
processLibraryMetadata(element.library);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
elements.forEach(processElementMetadata);
|
||||
}
|
||||
|
||||
void onQueueClosed() {
|
||||
lookupMapAnalysis.onQueueClosed();
|
||||
jsInteropAnalysis.onQueueClosed();
|
||||
@@ -3076,8 +3037,6 @@ class Dependency {
|
||||
final Element annotatedElement;
|
||||
|
||||
const Dependency(this.constant, this.annotatedElement);
|
||||
|
||||
String toString() => '$annotatedElement:${constant.toStructuredText()}';
|
||||
}
|
||||
|
||||
class JavaScriptImpactStrategy extends ImpactStrategy {
|
||||
|
||||
@@ -64,11 +64,6 @@ class ConstantEmitter implements ConstantValueVisitor<jsAst.Expression, Null> {
|
||||
return new jsAst.LiteralNull();
|
||||
}
|
||||
|
||||
@override
|
||||
jsAst.Expression visitNonConstant(NonConstantValue constant, [_]) {
|
||||
return new jsAst.LiteralNull();
|
||||
}
|
||||
|
||||
static final _exponentialRE = new RegExp('^'
|
||||
'\([-+]?\)' // 1: sign
|
||||
'\([0-9]+\)' // 2: leading digit(s)
|
||||
|
||||
@@ -115,6 +115,10 @@ class JavaScriptConstantCompiler extends ConstantCompilerBase
|
||||
final Map<Node, ConstantExpression> nodeConstantMap =
|
||||
new Map<Node, ConstantExpression>();
|
||||
|
||||
// Constants computed for metadata.
|
||||
final Map<MetadataAnnotation, ConstantExpression> metadataConstantMap =
|
||||
new Map<MetadataAnnotation, ConstantExpression>();
|
||||
|
||||
JavaScriptConstantCompiler(Compiler compiler)
|
||||
: super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM);
|
||||
|
||||
@@ -208,7 +212,15 @@ class JavaScriptConstantCompiler extends ConstantCompilerBase
|
||||
}
|
||||
|
||||
ConstantValue getConstantValueForMetadata(MetadataAnnotation metadata) {
|
||||
return getConstantValue(metadata.constant);
|
||||
return getConstantValue(metadataConstantMap[metadata]);
|
||||
}
|
||||
|
||||
ConstantExpression compileMetadata(
|
||||
MetadataAnnotation metadata, Node node, TreeElements elements) {
|
||||
ConstantExpression constant =
|
||||
super.compileMetadata(metadata, node, elements);
|
||||
metadataConstantMap[metadata] = constant;
|
||||
return constant;
|
||||
}
|
||||
|
||||
void forgetElement(Element element) {
|
||||
@@ -218,6 +230,29 @@ class JavaScriptConstantCompiler extends ConstantCompilerBase
|
||||
element.node.accept(new ForgetConstantNodeVisitor(this));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
ConstantValue getConstantValue(ConstantExpression expression) {
|
||||
assert(invariant(CURRENT_ELEMENT_SPANNABLE, expression != null,
|
||||
message: "ConstantExpression is null in getConstantValue."));
|
||||
// TODO(johhniwinther): ensure expressions have been evaluated at this
|
||||
// point. This can't be enabled today due to dartbug.com/26406.
|
||||
if (compiler.serialization.supportsDeserialization) {
|
||||
evaluate(expression);
|
||||
}
|
||||
ConstantValue value = super.getConstantValue(expression);
|
||||
if (value == null &&
|
||||
expression != null &&
|
||||
expression.kind == ConstantExpressionKind.ERRONEOUS) {
|
||||
// TODO(johnniwinther): When the Dart constant system sees a constant
|
||||
// expression as erroneous but the JavaScript constant system finds it ok
|
||||
// we have store a constant value for the erroneous constant expression.
|
||||
// Ensure the computed constant expressions are always the same; that only
|
||||
// the constant values may be different.
|
||||
value = new NullConstantValue();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
class ForgetConstantElementVisitor
|
||||
@@ -226,6 +261,7 @@ class ForgetConstantElementVisitor
|
||||
|
||||
void visitElement(Element e, JavaScriptConstantCompiler constants) {
|
||||
for (MetadataAnnotation data in e.implementation.metadata) {
|
||||
constants.metadataConstantMap.remove(data);
|
||||
if (data.hasNode) {
|
||||
data.node.accept(new ForgetConstantNodeVisitor(constants));
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
/// Analysis to determine how to generate code for typed JavaScript interop.
|
||||
library compiler.src.js_backend.js_interop_analysis;
|
||||
|
||||
import '../common.dart';
|
||||
import '../constants/values.dart'
|
||||
show ConstantValue, ConstructedConstantValue, StringConstantValue;
|
||||
import '../diagnostics/messages.dart' show MessageKind;
|
||||
@@ -55,8 +54,6 @@ class JsInteropAnalysis {
|
||||
|
||||
void processJsInteropAnnotation(Element e) {
|
||||
for (MetadataAnnotation annotation in e.implementation.metadata) {
|
||||
// TODO(johnniwinther): Avoid processing unresolved elements.
|
||||
if (annotation.constant == null) continue;
|
||||
ConstantValue constant =
|
||||
backend.compiler.constants.getConstantValue(annotation.constant);
|
||||
if (constant == null || constant is! ConstructedConstantValue) continue;
|
||||
|
||||
@@ -1671,11 +1671,6 @@ class ConstantNamingVisitor implements ConstantValueVisitor {
|
||||
add('null');
|
||||
}
|
||||
|
||||
@override
|
||||
void visitNonConstant(NonConstantValue constant, [_]) {
|
||||
add('null');
|
||||
}
|
||||
|
||||
@override
|
||||
void visitInt(IntConstantValue constant, [_]) {
|
||||
// No `addRoot` since IntConstants are always inlined.
|
||||
@@ -1820,9 +1815,6 @@ class ConstantCanonicalHasher implements ConstantValueVisitor<int, Null> {
|
||||
@override
|
||||
int visitNull(NullConstantValue constant, [_]) => 1;
|
||||
|
||||
@override
|
||||
int visitNonConstant(NonConstantValue constant, [_]) => 1;
|
||||
|
||||
@override
|
||||
int visitBool(BoolConstantValue constant, [_]) {
|
||||
return constant.isTrue ? 2 : 3;
|
||||
|
||||
@@ -76,10 +76,6 @@ class _CompareVisitor implements ConstantValueVisitor<int, ConstantValue> {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int visitNonConstant(NonConstantValue a, NonConstantValue b) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int visitInt(IntConstantValue a, IntConstantValue b) {
|
||||
return a.primitiveValue.compareTo(b.primitiveValue);
|
||||
}
|
||||
@@ -193,14 +189,12 @@ class _KindVisitor implements ConstantValueVisitor<int, Null> {
|
||||
static const int INTERCEPTOR = 11;
|
||||
static const int SYNTHETIC = 12;
|
||||
static const int DEFERRED = 13;
|
||||
static const int NONCONSTANT = 13;
|
||||
|
||||
static int kind(ConstantValue constant) =>
|
||||
constant.accept(const _KindVisitor(), null);
|
||||
|
||||
int visitFunction(FunctionConstantValue a, _) => FUNCTION;
|
||||
int visitNull(NullConstantValue a, _) => NULL;
|
||||
int visitNonConstant(NonConstantValue a, _) => NONCONSTANT;
|
||||
int visitInt(IntConstantValue a, _) => INT;
|
||||
int visitDouble(DoubleConstantValue a, _) => DOUBLE;
|
||||
int visitBool(BoolConstantValue a, _) => BOOL;
|
||||
|
||||
@@ -318,7 +318,7 @@ abstract class NativeEnqueuerBase implements NativeEnqueuer {
|
||||
// TODO(sra): Better validation of the constant.
|
||||
if (fields.length != 1 || fields.single is! StringConstantValue) {
|
||||
reporter.internalError(
|
||||
annotation, 'Annotations needs one string: ${annotation}');
|
||||
annotation, 'Annotations needs one string: ${annotation.node}');
|
||||
}
|
||||
StringConstantValue specStringConstant = fields.single;
|
||||
String specString = specStringConstant.toDartString().slowToString();
|
||||
@@ -326,7 +326,7 @@ abstract class NativeEnqueuerBase implements NativeEnqueuer {
|
||||
name = specString;
|
||||
} else {
|
||||
reporter.internalError(
|
||||
annotation, 'Too many JSName annotations: ${annotation}');
|
||||
annotation, 'Too many JSName annotations: ${annotation.node}');
|
||||
}
|
||||
}
|
||||
return name;
|
||||
|
||||
@@ -17,7 +17,6 @@ import '../elements/modelx.dart'
|
||||
EnumClassElementX,
|
||||
FieldElementX,
|
||||
LibraryElementX,
|
||||
MetadataAnnotationX,
|
||||
NamedMixinApplicationElementX,
|
||||
VariableList;
|
||||
import '../id_generator.dart';
|
||||
@@ -234,8 +233,8 @@ class ElementListener extends Listener {
|
||||
|
||||
void endTopLevelDeclaration(Token token) {
|
||||
if (!metadata.isEmpty) {
|
||||
MetadataAnnotationX first = metadata.first;
|
||||
recoverableError(first.beginToken, 'Metadata not supported here.');
|
||||
recoverableError(
|
||||
metadata.first.beginToken, 'Metadata not supported here.');
|
||||
metadata.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +128,6 @@ import 'elements/modelx.dart'
|
||||
ClassElementX,
|
||||
GetterElementX,
|
||||
LibraryElementX,
|
||||
MetadataAnnotationX,
|
||||
SetterElementX;
|
||||
import 'id_generator.dart';
|
||||
import 'js_backend/js_backend.dart' show JavaScriptBackend;
|
||||
@@ -404,7 +403,7 @@ abstract class EagerAnnotationHandler<T> {
|
||||
class NativeAnnotationHandler implements EagerAnnotationHandler<String> {
|
||||
const NativeAnnotationHandler();
|
||||
|
||||
String getNativeAnnotation(MetadataAnnotationX annotation) {
|
||||
String getNativeAnnotation(MetadataAnnotation annotation) {
|
||||
if (annotation.beginToken != null &&
|
||||
annotation.beginToken.next.value == 'Native') {
|
||||
// Skipping '@', 'Native', and '('.
|
||||
@@ -444,7 +443,7 @@ class NativeAnnotationHandler implements EagerAnnotationHandler<String> {
|
||||
class JsInteropAnnotationHandler implements EagerAnnotationHandler<bool> {
|
||||
const JsInteropAnnotationHandler();
|
||||
|
||||
bool hasJsNameAnnotation(MetadataAnnotationX annotation) =>
|
||||
bool hasJsNameAnnotation(MetadataAnnotation annotation) =>
|
||||
annotation.beginToken != null && annotation.beginToken.next.value == 'JS';
|
||||
|
||||
bool apply(
|
||||
@@ -475,7 +474,7 @@ class JsInteropAnnotationHandler implements EagerAnnotationHandler<bool> {
|
||||
class PatchAnnotationHandler implements EagerAnnotationHandler<PatchVersion> {
|
||||
const PatchAnnotationHandler();
|
||||
|
||||
PatchVersion getPatchVersion(MetadataAnnotationX annotation) {
|
||||
PatchVersion getPatchVersion(MetadataAnnotation annotation) {
|
||||
if (annotation.beginToken != null) {
|
||||
if (annotation.beginToken.next.value == 'patch') {
|
||||
return const PatchVersion(null);
|
||||
|
||||
@@ -334,6 +334,10 @@ class ResolutionRegistry extends Registry {
|
||||
worldImpact.registerStaticUse(staticUse);
|
||||
}
|
||||
|
||||
void registerMetadataConstant(MetadataAnnotation metadata) {
|
||||
backend.registerMetadataConstant(metadata, metadata.annotatedElement, this);
|
||||
}
|
||||
|
||||
/// Register the use of a type.
|
||||
void registerTypeUse(TypeUse typeUse) {
|
||||
worldImpact.registerTypeUse(typeUse);
|
||||
|
||||
@@ -1088,6 +1088,7 @@ class ResolverTask extends CompilerTask {
|
||||
// and the annotated element instead. This will allow the backend to
|
||||
// retrieve the backend constant and only register metadata on the
|
||||
// elements for which it is needed. (Issue 17732).
|
||||
registry.registerMetadataConstant(annotation);
|
||||
annotation.resolutionState = STATE_DONE;
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -120,23 +120,6 @@ class SerializerUtil {
|
||||
}
|
||||
}
|
||||
|
||||
/// Serialize the metadata of [element] into [encoder].
|
||||
static void serializeMetadata(Element element, ObjectEncoder encoder) {
|
||||
if (element.metadata.isNotEmpty) {
|
||||
ListEncoder list = encoder.createList(Key.METADATA);
|
||||
for (MetadataAnnotation metadata in element.metadata) {
|
||||
ObjectEncoder object = list.createObject();
|
||||
object.setElement(Key.ELEMENT, metadata.annotatedElement);
|
||||
SourceSpan sourcePosition = metadata.sourcePosition;
|
||||
// TODO(johnniwinther): What is the base URI here?
|
||||
object.setUri(Key.URI, sourcePosition.uri, sourcePosition.uri);
|
||||
object.setInt(Key.OFFSET, sourcePosition.begin);
|
||||
object.setInt(Key.LENGTH, sourcePosition.end - sourcePosition.begin);
|
||||
object.setConstant(Key.CONSTANT, metadata.constant);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Serialize the parent relation for [element] into [encoder], i.e library,
|
||||
/// enclosing class, and compilation unit references.
|
||||
static void serializeParentRelation(Element element, ObjectEncoder encoder) {
|
||||
@@ -242,7 +225,6 @@ class LibrarySerializer implements ElementSerializer {
|
||||
|
||||
void serialize(LibraryElement element, ObjectEncoder encoder,
|
||||
SerializedElementKind kind) {
|
||||
SerializerUtil.serializeMetadata(element, encoder);
|
||||
encoder.setUri(
|
||||
Key.CANONICAL_URI, element.canonicalUri, element.canonicalUri);
|
||||
encoder.setString(Key.LIBRARY_NAME, element.libraryName);
|
||||
@@ -270,7 +252,6 @@ class CompilationUnitSerializer implements ElementSerializer {
|
||||
|
||||
void serialize(CompilationUnitElement element, ObjectEncoder encoder,
|
||||
SerializedElementKind kind) {
|
||||
SerializerUtil.serializeMetadata(element, encoder);
|
||||
encoder.setElement(Key.LIBRARY, element.library);
|
||||
encoder.setUri(
|
||||
Key.URI, element.library.canonicalUri, element.script.resourceUri);
|
||||
@@ -318,7 +299,6 @@ class ClassSerializer implements ElementSerializer {
|
||||
|
||||
void serialize(
|
||||
ClassElement element, ObjectEncoder encoder, SerializedElementKind kind) {
|
||||
SerializerUtil.serializeMetadata(element, encoder);
|
||||
encoder.setElement(Key.LIBRARY, element.library);
|
||||
encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
|
||||
encoder.setString(Key.NAME, element.name);
|
||||
@@ -327,7 +307,6 @@ class ClassSerializer implements ElementSerializer {
|
||||
encoder.setBool(Key.IS_ABSTRACT, element.isAbstract);
|
||||
SerializerUtil.serializeMembers(getMembers(element), encoder);
|
||||
encoder.setBool(Key.IS_PROXY, element.isProxy);
|
||||
encoder.setBool(Key.IS_INJECTED, element.isInjected);
|
||||
if (kind == SerializedElementKind.ENUM) {
|
||||
EnumClassElement enumClass = element;
|
||||
encoder.setElements(Key.FIELDS, enumClass.enumValues);
|
||||
@@ -389,14 +368,12 @@ class ConstructorSerializer implements ElementSerializer {
|
||||
if (kind == SerializedElementKind.FORWARDING_CONSTRUCTOR) {
|
||||
encoder.setElement(Key.ELEMENT, element.definingConstructor);
|
||||
} else {
|
||||
SerializerUtil.serializeMetadata(element, encoder);
|
||||
encoder.setType(Key.TYPE, element.type);
|
||||
encoder.setString(Key.NAME, element.name);
|
||||
SerializerUtil.serializePosition(element, encoder);
|
||||
SerializerUtil.serializeParameters(element, encoder);
|
||||
encoder.setBool(Key.IS_CONST, element.isConst);
|
||||
encoder.setBool(Key.IS_EXTERNAL, element.isExternal);
|
||||
encoder.setBool(Key.IS_INJECTED, element.isInjected);
|
||||
if (element.isConst && !element.isFromEnvironmentConstructor) {
|
||||
ConstantConstructor constantConstructor = element.constantConstructor;
|
||||
ObjectEncoder constantEncoder = encoder.createObject(Key.CONSTRUCTOR);
|
||||
@@ -442,12 +419,10 @@ class FieldSerializer implements ElementSerializer {
|
||||
void serialize(
|
||||
FieldElement element, ObjectEncoder encoder, SerializedElementKind kind) {
|
||||
encoder.setString(Key.NAME, element.name);
|
||||
SerializerUtil.serializeMetadata(element, encoder);
|
||||
SerializerUtil.serializePosition(element, encoder);
|
||||
encoder.setType(Key.TYPE, element.type);
|
||||
encoder.setBool(Key.IS_FINAL, element.isFinal);
|
||||
encoder.setBool(Key.IS_CONST, element.isConst);
|
||||
encoder.setBool(Key.IS_INJECTED, element.isInjected);
|
||||
ConstantExpression constant = element.constant;
|
||||
if (constant != null) {
|
||||
encoder.setConstant(Key.CONSTANT, constant);
|
||||
@@ -494,7 +469,6 @@ class FunctionSerializer implements ElementSerializer {
|
||||
void serialize(FunctionElement element, ObjectEncoder encoder,
|
||||
SerializedElementKind kind) {
|
||||
encoder.setString(Key.NAME, element.name);
|
||||
SerializerUtil.serializeMetadata(element, encoder);
|
||||
SerializerUtil.serializePosition(element, encoder);
|
||||
SerializerUtil.serializeParameters(element, encoder);
|
||||
encoder.setType(Key.TYPE, element.type);
|
||||
@@ -505,7 +479,6 @@ class FunctionSerializer implements ElementSerializer {
|
||||
SerializerUtil.serializeParentRelation(element, encoder);
|
||||
encoder.setBool(Key.IS_EXTERNAL, element.isExternal);
|
||||
encoder.setBool(Key.IS_ABSTRACT, element.isAbstract);
|
||||
encoder.setBool(Key.IS_INJECTED, element.isInjected);
|
||||
if (element.isLocal) {
|
||||
LocalFunctionElement localFunction = element;
|
||||
encoder.setElement(
|
||||
@@ -527,7 +500,6 @@ class TypedefSerializer implements ElementSerializer {
|
||||
void serialize(TypedefElement element, ObjectEncoder encoder,
|
||||
SerializedElementKind kind) {
|
||||
encoder.setString(Key.NAME, element.name);
|
||||
SerializerUtil.serializeMetadata(element, encoder);
|
||||
SerializerUtil.serializePosition(element, encoder);
|
||||
encoder.setType(Key.ALIAS, element.alias);
|
||||
encoder.setElement(Key.LIBRARY, element.library);
|
||||
@@ -550,7 +522,6 @@ class TypeVariableSerializer implements ElementSerializer {
|
||||
SerializedElementKind kind) {
|
||||
encoder.setElement(Key.TYPE_DECLARATION, element.typeDeclaration);
|
||||
encoder.setString(Key.NAME, element.name);
|
||||
SerializerUtil.serializeMetadata(element, encoder);
|
||||
SerializerUtil.serializePosition(element, encoder);
|
||||
encoder.setType(Key.TYPE, element.type);
|
||||
encoder.setInt(Key.INDEX, element.index);
|
||||
@@ -574,7 +545,6 @@ class ParameterSerializer implements ElementSerializer {
|
||||
SerializedElementKind kind) {
|
||||
encoder.setElement(Key.FUNCTION, element.functionDeclaration);
|
||||
encoder.setString(Key.NAME, element.name);
|
||||
SerializerUtil.serializeMetadata(element, encoder);
|
||||
SerializerUtil.serializePosition(element, encoder);
|
||||
encoder.setType(Key.TYPE, element.type);
|
||||
encoder.setBool(Key.IS_OPTIONAL, element.isOptional);
|
||||
@@ -603,7 +573,6 @@ class LocalVariableSerializer implements ElementSerializer {
|
||||
void serialize(LocalVariableElement element, ObjectEncoder encoder,
|
||||
SerializedElementKind kind) {
|
||||
encoder.setString(Key.NAME, element.name);
|
||||
SerializerUtil.serializeMetadata(element, encoder);
|
||||
SerializerUtil.serializePosition(element, encoder);
|
||||
encoder.setType(Key.TYPE, element.type);
|
||||
encoder.setBool(Key.IS_FINAL, element.isFinal);
|
||||
@@ -628,7 +597,6 @@ class ImportSerializer implements ElementSerializer {
|
||||
|
||||
void serialize(ImportElement element, ObjectEncoder encoder,
|
||||
SerializedElementKind kind) {
|
||||
SerializerUtil.serializeMetadata(element, encoder);
|
||||
encoder.setElement(Key.LIBRARY, element.library);
|
||||
encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
|
||||
encoder.setElement(Key.LIBRARY_DEPENDENCY, element.importedLibrary);
|
||||
@@ -653,7 +621,6 @@ class ExportSerializer implements ElementSerializer {
|
||||
|
||||
void serialize(ExportElement element, ObjectEncoder encoder,
|
||||
SerializedElementKind kind) {
|
||||
SerializerUtil.serializeMetadata(element, encoder);
|
||||
encoder.setElement(Key.LIBRARY, element.library);
|
||||
encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
|
||||
encoder.setElement(Key.LIBRARY_DEPENDENCY, element.exportedLibrary);
|
||||
|
||||
@@ -1832,12 +1832,3 @@ class NodeEquivalenceVisitor implements Visitor1<bool, Node> {
|
||||
throw new UnsupportedError('Unexpected nodes: $node1 <> $node2');
|
||||
}
|
||||
}
|
||||
|
||||
bool areMetadataAnnotationsEquivalent(
|
||||
MetadataAnnotation metadata1, MetadataAnnotation metadata2) {
|
||||
if (metadata1 == metadata2) return true;
|
||||
if (metadata1 == null || metadata2 == null) return false;
|
||||
return areElementsEquivalent(
|
||||
metadata1.annotatedElement, metadata2.annotatedElement) &&
|
||||
areConstantsEquivalent(metadata1.constant, metadata2.constant);
|
||||
}
|
||||
|
||||
@@ -59,7 +59,6 @@ class Key {
|
||||
static const Key IS_EMPTY = const Key('isEmpty');
|
||||
static const Key IS_EXTERNAL = const Key('isExternal');
|
||||
static const Key IS_FINAL = const Key('isFinal');
|
||||
static const Key IS_INJECTED = const Key('isInjected');
|
||||
static const Key IS_NAMED = const Key('isNamed');
|
||||
static const Key IS_OPERATOR = const Key('isOperator');
|
||||
static const Key IS_OPTIONAL = const Key('isOptional');
|
||||
@@ -84,7 +83,6 @@ class Key {
|
||||
static const Key LISTS = const Key('lists');
|
||||
static const Key MAPS = const Key('maps');
|
||||
static const Key MEMBERS = const Key('members');
|
||||
static const Key METADATA = const Key('metadata');
|
||||
static const Key MIXIN = const Key('mixin');
|
||||
static const Key MIXINS = const Key('mixins');
|
||||
static const Key NAME = const Key('name');
|
||||
|
||||
@@ -112,6 +112,7 @@ abstract class ElementZ extends Element with ElementCommon {
|
||||
@override
|
||||
bool get isTopLevel => false;
|
||||
|
||||
// TODO(johnniwinther): Support metadata.
|
||||
@override
|
||||
Iterable<MetadataAnnotation> get metadata => const <MetadataAnnotation>[];
|
||||
|
||||
@@ -121,7 +122,6 @@ abstract class ElementZ extends Element with ElementCommon {
|
||||
|
||||
abstract class DeserializedElementZ extends ElementZ {
|
||||
ObjectDecoder _decoder;
|
||||
List<MetadataAnnotation> _metadata;
|
||||
|
||||
DeserializedElementZ(this._decoder);
|
||||
|
||||
@@ -147,27 +147,6 @@ abstract class DeserializedElementZ extends ElementZ {
|
||||
}
|
||||
return new SourceSpan(uri, offset, offset + length);
|
||||
}
|
||||
|
||||
@override
|
||||
Iterable<MetadataAnnotation> get metadata {
|
||||
if (_metadata == null) {
|
||||
_metadata = <MetadataAnnotation>[];
|
||||
ListDecoder list = _decoder.getList(Key.METADATA, isOptional: true);
|
||||
if (list != null) {
|
||||
for (int index = 0; index < list.length; index++) {
|
||||
ObjectDecoder object = list.getObject(index);
|
||||
Element element = object.getElement(Key.ELEMENT);
|
||||
Uri uri = object.getUri(Key.URI);
|
||||
int offset = object.getInt(Key.OFFSET);
|
||||
int length = object.getInt(Key.LENGTH);
|
||||
ConstantExpression constant = object.getConstant(Key.CONSTANT);
|
||||
_metadata.add(new MetadataAnnotationZ(
|
||||
element, new SourceSpan(uri, offset, offset + length), constant));
|
||||
}
|
||||
}
|
||||
}
|
||||
return _metadata;
|
||||
}
|
||||
}
|
||||
|
||||
/// Deserializer for a collection of member elements serialized as a map from
|
||||
@@ -966,9 +945,6 @@ class ClassElementZ extends DeserializedElementZ
|
||||
@override
|
||||
bool get isProxy => _decoder.getBool(Key.IS_PROXY);
|
||||
|
||||
@override
|
||||
bool get isInjected => _decoder.getBool(Key.IS_INJECTED);
|
||||
|
||||
@override
|
||||
bool get isUnnamedMixinApplication => false;
|
||||
|
||||
@@ -1504,9 +1480,6 @@ abstract class MemberElementMixin
|
||||
|
||||
@override
|
||||
List<FunctionElement> get nestedClosures => <FunctionElement>[];
|
||||
|
||||
@override
|
||||
bool get isInjected => _decoder.getBool(Key.IS_INJECTED);
|
||||
}
|
||||
|
||||
abstract class FieldElementZ extends DeserializedElementZ
|
||||
@@ -2290,25 +2263,3 @@ class PrefixElementZ extends DeserializedElementZ
|
||||
return _unsupported('lookupLocalMember');
|
||||
}
|
||||
}
|
||||
|
||||
class MetadataAnnotationZ implements MetadataAnnotation {
|
||||
final Element annotatedElement;
|
||||
final SourceSpan sourcePosition;
|
||||
final ConstantExpression constant;
|
||||
|
||||
MetadataAnnotationZ(
|
||||
this.annotatedElement, this.sourcePosition, this.constant);
|
||||
|
||||
@override
|
||||
MetadataAnnotation ensureResolved(Resolution resolution) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
@override
|
||||
Node get node => throw new UnsupportedError('${this}.node');
|
||||
|
||||
@override
|
||||
bool get hasNode => false;
|
||||
|
||||
String toString() => 'MetadataAnnotationZ(${constant.toDartText()})';
|
||||
}
|
||||
|
||||
@@ -104,11 +104,6 @@ class ConstantValueTypeMasks extends ConstantValueVisitor<TypeMask, Compiler> {
|
||||
return compiler.typesTask.nullType;
|
||||
}
|
||||
|
||||
@override
|
||||
TypeMask visitNonConstant(NonConstantValue constant, Compiler compiler) {
|
||||
return compiler.typesTask.nullType;
|
||||
}
|
||||
|
||||
@override
|
||||
TypeMask visitString(StringConstantValue constant, Compiler compiler) {
|
||||
return compiler.typesTask.stringType;
|
||||
|
||||
@@ -127,22 +127,18 @@ void main() {
|
||||
});
|
||||
}
|
||||
|
||||
int metadataCount = 0;
|
||||
// There should at least be one metadata constant:
|
||||
// 1. The constructed constant for 'MirrorsUsed'.
|
||||
Expect.isTrue(backend.metadataConstants.length >= 1);
|
||||
|
||||
Set<ConstantValue> compiledConstants = backend.constants.compiledConstants;
|
||||
// Make sure that most of the metadata constants aren't included in the
|
||||
// generated code.
|
||||
backend.processMetadata(
|
||||
compiler.enqueuer.resolution.processedElements, (metadata) {
|
||||
ConstantValue constant =
|
||||
backend.constants.getConstantValueForMetadata(metadata);
|
||||
for (var dependency in backend.metadataConstants) {
|
||||
ConstantValue constant = dependency.constant;
|
||||
Expect.isFalse(compiledConstants.contains(constant),
|
||||
constant.toStructuredText());
|
||||
metadataCount++;
|
||||
});
|
||||
|
||||
// There should at least be one metadata constant:
|
||||
// 1. The constructed constant for 'MirrorsUsed'.
|
||||
Expect.isTrue(metadataCount >= 1);
|
||||
}
|
||||
|
||||
// The type literal 'Foo' is both used as metadata, and as a plain value in
|
||||
// the program. Make sure that it isn't duplicated.
|
||||
|
||||
@@ -248,16 +248,6 @@ checkElementLists(Object object1, Object object2, String property,
|
||||
list1, list2, checkElementProperties);
|
||||
}
|
||||
|
||||
/// Check the equivalence of the two metadata annotations, [metadata1] and
|
||||
/// [metadata2].
|
||||
///
|
||||
/// Uses [object1], [object2] and [property] to provide context for failures.
|
||||
checkMetadata(Object object1, Object object2, String property,
|
||||
MetadataAnnotation metadata1, MetadataAnnotation metadata2) {
|
||||
check(object1, object2, property,
|
||||
metadata1, metadata2, areMetadataAnnotationsEquivalent);
|
||||
}
|
||||
|
||||
/// Visitor that checks for equivalence of [Element] properties.
|
||||
class ElementPropertyEquivalence extends BaseElementVisitor<dynamic, Element> {
|
||||
const ElementPropertyEquivalence();
|
||||
@@ -287,8 +277,6 @@ class ElementPropertyEquivalence extends BaseElementVisitor<dynamic, Element> {
|
||||
element1.isClassMember, element2.isClassMember);
|
||||
check(element1, element2, 'isInstanceMember',
|
||||
element1.isInstanceMember, element2.isInstanceMember);
|
||||
checkListEquivalence(element1, element2, 'metadata',
|
||||
element1.metadata, element2.metadata, checkMetadata);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -442,10 +430,6 @@ class ElementPropertyEquivalence extends BaseElementVisitor<dynamic, Element> {
|
||||
element1.isAbstract, element2.isAbstract);
|
||||
check(element1, element2, 'isUnnamedMixinApplication',
|
||||
element1.isUnnamedMixinApplication, element2.isUnnamedMixinApplication);
|
||||
check(element1, element2, 'isProxy',
|
||||
element1.isProxy, element2.isProxy);
|
||||
check(element1, element2, 'isInjected',
|
||||
element1.isInjected, element2.isInjected);
|
||||
check(element1, element2, 'isEnumClass',
|
||||
element1.isEnumClass, element2.isEnumClass);
|
||||
if (element1.isEnumClass) {
|
||||
@@ -531,8 +515,6 @@ class ElementPropertyEquivalence extends BaseElementVisitor<dynamic, Element> {
|
||||
element1.isStatic, element2.isStatic);
|
||||
check(element1, element2, 'isInstanceMember',
|
||||
element1.isInstanceMember, element2.isInstanceMember);
|
||||
check(element1, element2, 'isInjected',
|
||||
element1.isInjected, element2.isInjected);
|
||||
|
||||
checkElementIdentities(
|
||||
element1, element2, 'library',
|
||||
@@ -566,8 +548,6 @@ class ElementPropertyEquivalence extends BaseElementVisitor<dynamic, Element> {
|
||||
element1, element2, 'asyncMarker',
|
||||
element1.asyncMarker,
|
||||
element2.asyncMarker);
|
||||
check(element1, element2, 'isInjected',
|
||||
element1.isInjected, element2.isInjected);
|
||||
|
||||
checkElementIdentities(
|
||||
element1, element2, 'library',
|
||||
@@ -672,8 +652,6 @@ class ElementPropertyEquivalence extends BaseElementVisitor<dynamic, Element> {
|
||||
element2.immediateRedirectionTarget);
|
||||
checkElementIdentities(element1, element2, 'redirectionDeferredPrefix',
|
||||
element1.redirectionDeferredPrefix, element2.redirectionDeferredPrefix);
|
||||
check(element1, element2, 'isInjected',
|
||||
element1.isInjected, element2.isInjected);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -32,7 +32,7 @@ main(List<String> args) {
|
||||
resolutionInputs: serializedData.toUris());
|
||||
} else {
|
||||
Uri entryPoint = Uri.parse('memory:main.dart');
|
||||
await arguments.forEachTest(serializedData, TESTS, checkModels);
|
||||
arguments.forEachTest(serializedData, TESTS, checkModels);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -44,6 +44,11 @@ Future checkModels(
|
||||
int index,
|
||||
Test test,
|
||||
bool verbose: false}) async {
|
||||
if (test != null && test.name == 'Disable tree shaking through reflection') {
|
||||
// TODO(johnniwinther): Support serialization of metadata.
|
||||
return;
|
||||
}
|
||||
|
||||
String testDescription = test != null ? test.name : '${entryPoint}';
|
||||
String id = index != null ? '$index: ' : '';
|
||||
print('------------------------------------------------------------------');
|
||||
|
||||
@@ -436,7 +436,6 @@ void checkSets(
|
||||
String messagePrefix,
|
||||
bool sameElement(a, b),
|
||||
{bool failOnUnfound: true,
|
||||
bool failOnExtra: true,
|
||||
bool verbose: false,
|
||||
void onSameElement(a, b)}) {
|
||||
List<List> common = <List>[];
|
||||
@@ -459,8 +458,7 @@ void checkSets(
|
||||
String message = sb.toString();
|
||||
if (unfound.isNotEmpty || remaining.isNotEmpty) {
|
||||
|
||||
if ((failOnUnfound && unfound.isNotEmpty) ||
|
||||
(failOnExtra && remaining.isNotEmpty)) {
|
||||
if (failOnUnfound || remaining.isNotEmpty) {
|
||||
Expect.fail(message);
|
||||
} else {
|
||||
print(message);
|
||||
|
||||
Reference in New Issue
Block a user