Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(253)

Unified Diff: pkg/compiler/lib/src/scanner/token_map.dart

Issue 1284593003: Remove dart2jslib.dart (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/compiler/lib/src/scanner/token_map.dart
diff --git a/pkg/compiler/lib/src/scanner/token_map.dart b/pkg/compiler/lib/src/scanner/token_map.dart
index f6353790b591b93f3bebbb4a9327f03e6910937b..8e4c53ed84ea66c8ad7c946834abb4c25de521ed 100644
--- a/pkg/compiler/lib/src/scanner/token_map.dart
+++ b/pkg/compiler/lib/src/scanner/token_map.dart
@@ -2,627 +2,10 @@
// 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.
-part of dart2js;
+library dart2js.tokens.token_map;
-/**
- * If true, print a warning for each method that was resolved, but not
- * compiled.
- */
-const bool REPORT_EXCESS_RESOLUTION = false;
-
-/**
- * Contains backend-specific data that is used throughout the compilation of
- * one work item.
- */
-class ItemCompilationContext {
-}
-
-abstract class WorkItem {
- final ItemCompilationContext compilationContext;
- /**
- * Documentation wanted -- johnniwinther
- *
- * Invariant: [element] must be a declaration element.
- */
- final AstElement element;
-
- WorkItem(this.element, this.compilationContext) {
- assert(invariant(element, element.isDeclaration));
- }
-
- WorldImpact run(Compiler compiler, Enqueuer world);
-}
-
-/// [WorkItem] used exclusively by the [ResolutionEnqueuer].
-class ResolutionWorkItem extends WorkItem {
- bool _isAnalyzed = false;
-
- ResolutionWorkItem(AstElement element,
- ItemCompilationContext compilationContext)
- : super(element, compilationContext);
-
- WorldImpact run(Compiler compiler, ResolutionEnqueuer world) {
- WorldImpact impact = compiler.analyze(this, world);
- _isAnalyzed = true;
- return impact;
- }
-
- bool get isAnalyzed => _isAnalyzed;
-}
-
-// TODO(johnniwinther): Split this class into interface and implementation.
-// TODO(johnniwinther): Move this implementation to the JS backend.
-class CodegenRegistry extends Registry {
- final Compiler compiler;
- final TreeElements treeElements;
-
- CodegenRegistry(this.compiler, this.treeElements);
-
- bool get isForResolution => false;
-
- Element get currentElement => treeElements.analyzedElement;
-
- // TODO(johnniwinther): Remove this getter when [Registry] creates a
- // dependency node.
- Setlet<Element> get otherDependencies => treeElements.otherDependencies;
-
- CodegenEnqueuer get world => compiler.enqueuer.codegen;
- js_backend.JavaScriptBackend get backend => compiler.backend;
-
- void registerDependency(Element element) {
- treeElements.registerDependency(element);
- }
-
- void registerInlining(Element inlinedElement, Element context) {
- if (compiler.dumpInfo) {
- compiler.dumpInfoTask.registerInlined(inlinedElement, context);
- }
- }
-
- void registerInstantiatedClass(ClassElement element) {
- world.registerInstantiatedType(element.rawType, this);
- }
-
- void registerInstantiatedType(InterfaceType type) {
- world.registerInstantiatedType(type, this);
- }
-
- void registerStaticUse(Element element) {
- world.registerStaticUse(element);
- }
-
- void registerDynamicInvocation(UniverseSelector selector) {
- world.registerDynamicInvocation(selector);
- compiler.dumpInfoTask.elementUsesSelector(currentElement, selector);
- }
-
- void registerDynamicSetter(UniverseSelector selector) {
- world.registerDynamicSetter(selector);
- compiler.dumpInfoTask.elementUsesSelector(currentElement, selector);
- }
-
- void registerDynamicGetter(UniverseSelector selector) {
- world.registerDynamicGetter(selector);
- compiler.dumpInfoTask.elementUsesSelector(currentElement, selector);
- }
-
- void registerGetterForSuperMethod(Element element) {
- world.registerGetterForSuperMethod(element);
- }
-
- void registerFieldGetter(Element element) {
- world.registerFieldGetter(element);
- }
-
- void registerFieldSetter(Element element) {
- world.registerFieldSetter(element);
- }
-
- void registerIsCheck(DartType type) {
- world.registerIsCheck(type);
- backend.registerIsCheckForCodegen(type, world, this);
- }
-
- void registerCompileTimeConstant(ConstantValue constant) {
- backend.registerCompileTimeConstant(constant, this);
- backend.constants.addCompileTimeConstantForEmission(constant);
- }
-
- void registerTypeVariableBoundsSubtypeCheck(DartType subtype,
- DartType supertype) {
- backend.registerTypeVariableBoundsSubtypeCheck(subtype, supertype);
- }
-
- void registerInstantiatedClosure(LocalFunctionElement element) {
- backend.registerInstantiatedClosure(element, this);
- }
-
- void registerGetOfStaticFunction(FunctionElement element) {
- world.registerGetOfStaticFunction(element);
- }
-
- void registerSelectorUse(Selector selector) {
- world.registerSelectorUse(new UniverseSelector(selector, null));
- }
-
- void registerConstSymbol(String name) {
- backend.registerConstSymbol(name, this);
- }
-
- void registerSpecializedGetInterceptor(Set<ClassElement> classes) {
- backend.registerSpecializedGetInterceptor(classes);
- }
-
- void registerUseInterceptor() {
- backend.registerUseInterceptor(world);
- }
-
- void registerTypeConstant(ClassElement element) {
- backend.customElementsAnalysis.registerTypeConstant(element, world);
- }
-
- void registerStaticInvocation(Element element) {
- world.registerStaticUse(element);
- }
-
- void registerSuperInvocation(Element element) {
- world.registerStaticUse(element);
- }
-
- void registerDirectInvocation(Element element) {
- world.registerStaticUse(element);
- }
-
- void registerInstantiation(InterfaceType type) {
- world.registerInstantiatedType(type, this);
- }
-
- void registerAsyncMarker(FunctionElement element) {
- backend.registerAsyncMarker(element, world, this);
- }
-
-}
-
-/// [WorkItem] used exclusively by the [CodegenEnqueuer].
-class CodegenWorkItem extends WorkItem {
- CodegenRegistry registry;
-
- factory CodegenWorkItem(
- Compiler compiler,
- AstElement element,
- ItemCompilationContext compilationContext) {
- // If this assertion fails, the resolution callbacks of the backend may be
- // missing call of form registry.registerXXX. Alternatively, the code
- // generation could spuriously be adding dependencies on things we know we
- // don't need.
- assert(invariant(element,
- compiler.enqueuer.resolution.hasBeenResolved(element),
- message: "$element has not been resolved."));
- assert(invariant(element, element.resolvedAst.elements != null,
- message: 'Resolution tree is null for $element in codegen work item'));
- return new CodegenWorkItem.internal(element, compilationContext);
- }
-
- CodegenWorkItem.internal(
- AstElement element,
- ItemCompilationContext compilationContext)
- : super(element, compilationContext);
-
- TreeElements get resolutionTree => element.resolvedAst.elements;
-
- WorldImpact run(Compiler compiler, CodegenEnqueuer world) {
- if (world.isProcessed(element)) return const WorldImpact();
-
- registry = new CodegenRegistry(compiler, resolutionTree);
- return compiler.codegen(this, world);
- }
-}
-
-typedef void DeferredAction();
-
-class DeferredTask {
- final Element element;
- final DeferredAction action;
-
- DeferredTask(this.element, this.action);
-}
-
-/// Interface for registration of element dependencies.
-abstract class Registry {
- // TODO(johnniwinther): Remove this getter when [Registry] creates a
- // dependency node.
- Iterable<Element> get otherDependencies;
-
- void registerDependency(Element element);
-
- bool get isForResolution;
-
- void registerDynamicInvocation(UniverseSelector selector);
-
- void registerDynamicGetter(UniverseSelector selector);
-
- void registerDynamicSetter(UniverseSelector selector);
-
- void registerStaticInvocation(Element element);
-
- void registerInstantiation(InterfaceType type);
-
- void registerGetOfStaticFunction(FunctionElement element);
-}
-
-abstract class Backend {
- final Compiler compiler;
-
- Backend(this.compiler);
-
- /// Returns true if the backend supports reflection.
- bool get supportsReflection;
-
- /// The [ConstantSystem] used to interpret compile-time constants for this
- /// backend.
- ConstantSystem get constantSystem;
-
- /// The constant environment for the backend interpretation of compile-time
- /// constants.
- BackendConstantEnvironment get constants;
-
- /// The compiler task responsible for the compilation of constants for both
- /// the frontend and the backend.
- ConstantCompilerTask get constantCompilerTask;
-
- /// Backend callback methods for the resolution phase.
- ResolutionCallbacks get resolutionCallbacks;
-
- /// The strategy used for collecting and emitting source information.
- SourceInformationStrategy get sourceInformationStrategy {
- return const SourceInformationStrategy();
- }
-
- // TODO(johnniwinther): Move this to the JavaScriptBackend.
- String get patchVersion => null;
-
- /// Set of classes that need to be considered for reflection although not
- /// otherwise visible during resolution.
- Iterable<ClassElement> classesRequiredForReflection = const [];
-
- // Given a [FunctionElement], return a buffer with the code generated for it
- // or null if no code was generated.
- CodeBuffer codeOf(Element element) => null;
-
- void initializeHelperClasses() {}
-
- void enqueueHelpers(ResolutionEnqueuer world, Registry registry);
- WorldImpact codegen(CodegenWorkItem work);
-
- // The backend determines the native resolution enqueuer, with a no-op
- // default, so tools like dart2dart can ignore the native classes.
- native.NativeEnqueuer nativeResolutionEnqueuer(world) {
- return new native.NativeEnqueuer();
- }
- native.NativeEnqueuer nativeCodegenEnqueuer(world) {
- return new native.NativeEnqueuer();
- }
-
- /// Generates the output and returns the total size of the generated code.
- int assembleProgram();
-
- List<CompilerTask> get tasks;
-
- void onResolutionComplete() {}
- void onTypeInferenceComplete() {}
-
- ItemCompilationContext createItemCompilationContext() {
- return new ItemCompilationContext();
- }
-
- bool classNeedsRti(ClassElement cls);
- bool methodNeedsRti(FunctionElement function);
-
- /// Enable compilation of code with compile time errors. Returns `true` if
- /// supported by the backend.
- bool enableCodegenWithErrorsIfSupported(Spannable node);
-
- /// Enable deferred loading. Returns `true` if the backend supports deferred
- /// loading.
- bool enableDeferredLoadingIfSupported(Spannable node, Registry registry);
-
- /// 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].
- void registerInstantiatedClass(ClassElement cls,
- Enqueuer enqueuer,
- Registry registry) {}
-
- /// Called to notify to the backend that an interface type has been
- /// instantiated.
- void registerInstantiatedType(InterfaceType type, Registry registry) {}
-
- /// Register an is check to the backend.
- void registerIsCheckForCodegen(DartType type,
- Enqueuer enqueuer,
- Registry registry) {}
-
- /// Register a runtime type variable bound tests between [typeArgument] and
- /// [bound].
- void registerTypeVariableBoundsSubtypeCheck(DartType typeArgument,
- DartType bound) {}
-
- /// Returns `true` if [element] represent the assert function.
- bool isAssertMethod(Element element) => false;
-
- /**
- * Call this to register that an instantiated generic class has a call
- * method.
- */
- void registerCallMethodWithFreeTypeVariables(
- Element callMethod,
- Enqueuer enqueuer,
- Registry registry) {}
-
- /**
- * Call this to register that a getter exists for a function on an
- * instantiated generic class.
- */
- void registerClosureWithFreeTypeVariables(
- Element closure,
- Enqueuer enqueuer,
- Registry registry) {}
-
- /// Call this to register that a member has been closurized.
- void registerBoundClosure(Enqueuer enqueuer) {}
-
- /// Call this to register that a static function has been closurized.
- void registerGetOfStaticFunction(Enqueuer enqueuer) {}
-
- /**
- * Call this to register that the [:runtimeType:] property has been accessed.
- */
- void registerRuntimeType(Enqueuer enqueuer, Registry registry) {}
-
- /// Call this to register a `noSuchMethod` implementation.
- void registerNoSuchMethod(FunctionElement noSuchMethodElement) {}
-
- /// Call this method to enable support for `noSuchMethod`.
- void enableNoSuchMethod(Enqueuer enqueuer) {}
-
- /// Returns whether or not `noSuchMethod` support has been enabled.
- bool get enabledNoSuchMethod => false;
-
- /// Call this method to enable support for isolates.
- void enableIsolateSupport(Enqueuer enqueuer) {}
-
- void registerRequiredType(DartType type, Element enclosingElement) {}
- void registerClassUsingVariableExpression(ClassElement cls) {}
-
- void registerConstSymbol(String name, Registry registry) {}
- void registerNewSymbol(Registry registry) {}
-
- bool isNullImplementation(ClassElement cls) {
- return cls == compiler.nullClass;
- }
-
- ClassElement get intImplementation => compiler.intClass;
- ClassElement get doubleImplementation => compiler.doubleClass;
- ClassElement get numImplementation => compiler.numClass;
- ClassElement get stringImplementation => compiler.stringClass;
- ClassElement get listImplementation => compiler.listClass;
- ClassElement get growableListImplementation => compiler.listClass;
- ClassElement get fixedListImplementation => compiler.listClass;
- ClassElement get constListImplementation => compiler.listClass;
- ClassElement get mapImplementation => compiler.mapClass;
- ClassElement get constMapImplementation => compiler.mapClass;
- ClassElement get functionImplementation => compiler.functionClass;
- ClassElement get typeImplementation => compiler.typeClass;
- ClassElement get boolImplementation => compiler.boolClass;
- ClassElement get nullImplementation => compiler.nullClass;
- ClassElement get uint32Implementation => compiler.intClass;
- ClassElement get uint31Implementation => compiler.intClass;
- ClassElement get positiveIntImplementation => compiler.intClass;
-
- ClassElement defaultSuperclass(ClassElement element) => compiler.objectClass;
-
- bool isInterceptorClass(ClassElement element) => false;
-
- /// Returns `true` if [element] is a foreign element, that is, that the
- /// backend has specialized handling for the element.
- bool isForeign(Element element) => false;
-
- /// Processes [element] for resolution and returns the [FunctionElement] that
- /// defines the implementation of [element].
- FunctionElement resolveExternalFunction(FunctionElement element) => element;
-
- /// Returns `true` if [library] is a backend specific library whose members
- /// have special treatment, such as being allowed to extends blacklisted
- /// classes or member being eagerly resolved.
- bool isBackendLibrary(LibraryElement library) {
- // TODO(johnniwinther): Remove this when patching is only done by the
- // JavaScript backend.
- Uri canonicalUri = library.canonicalUri;
- if (canonicalUri == js_backend.JavaScriptBackend.DART_JS_HELPER ||
- canonicalUri == js_backend.JavaScriptBackend.DART_INTERCEPTORS) {
- return true;
- }
- return false;
- }
-
- void registerStaticUse(Element element, Enqueuer enqueuer) {}
-
- /// This method is called immediately after the [LibraryElement] [library] has
- /// been created.
- void onLibraryCreated(LibraryElement library) {}
-
- /// This method is called immediately after the [library] and its parts have
- /// been scanned.
- Future onLibraryScanned(LibraryElement library, LibraryLoader loader) {
- if (library.canUseNative) {
- library.forEachLocalMember((Element element) {
- if (element.isClass) {
- checkNativeAnnotation(compiler, element);
- }
- });
- }
- return new Future.value();
- }
-
- /// This method is called when all new libraries loaded through
- /// [LibraryLoader.loadLibrary] has been loaded and their imports/exports
- /// have been computed.
- Future onLibrariesLoaded(LoadedLibraries loadedLibraries) {
- return new Future.value();
- }
-
- /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed
- /// annotations. The arguments corresponds to the unions of the corresponding
- /// fields of the annotations.
- void registerMirrorUsage(Set<String> symbols,
- Set<Element> targets,
- Set<Element> metaTargets) {}
-
- /// Returns true if this element needs reflection information at runtime.
- bool isAccessibleByReflection(Element element) => true;
-
- /// Returns true if this element is covered by a mirrorsUsed annotation.
- ///
- /// Note that it might still be ok to tree shake the element away if no
- /// reflection is used in the program (and thus [isTreeShakingDisabled] is
- /// still false). Therefore _do not_ use this predicate to decide inclusion
- /// in the tree, use [requiredByMirrorSystem] instead.
- bool referencedFromMirrorSystem(Element element, [recursive]) => false;
-
- /// Returns true if this element has to be enqueued due to
- /// mirror usage. Might be a subset of [referencedFromMirrorSystem] if
- /// normal tree shaking is still active ([isTreeShakingDisabled] is false).
- bool requiredByMirrorSystem(Element element) => false;
-
- /// Returns true if global optimizations such as type inferencing
- /// can apply to this element. One category of elements that do not
- /// apply is runtime helpers that the backend calls, but the
- /// optimizations don't see those calls.
- bool canBeUsedForGlobalOptimizations(Element element) => true;
-
- /// Called when [enqueuer]'s queue is empty, but before it is closed.
- /// This is used, for example, by the JS backend to enqueue additional
- /// elements needed for reflection. [recentClasses] is a collection of
- /// all classes seen for the first time by the [enqueuer] since the last call
- /// to [onQueueEmpty].
- ///
- /// A return value of [:true:] indicates that [recentClasses] has been
- /// processed and its elements do not need to be seen in the next round. When
- /// [:false:] is returned, [onQueueEmpty] will be called again once the
- /// resolution queue has drained and [recentClasses] will be a superset of the
- /// current value.
- ///
- /// There is no guarantee that a class is only present once in
- /// [recentClasses], but every class seen by the [enqueuer] will be present in
- /// [recentClasses] at least once.
- bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassElement> recentClasses) {
- return true;
- }
-
- /// Called after [element] has been resolved.
- // TODO(johnniwinther): Change [TreeElements] to [Registry] or a dependency
- // node. [elements] is currently unused by the implementation.
- void onElementResolved(Element element, TreeElements elements) {}
-
- // Does this element belong in the output
- bool shouldOutput(Element element) => true;
-
- FunctionElement helperForBadMain() => null;
-
- FunctionElement helperForMissingMain() => null;
-
- FunctionElement helperForMainArity() => null;
-
- void forgetElement(Element element) {}
-
- void registerMainHasArguments(Enqueuer enqueuer) {}
-
- void registerAsyncMarker(FunctionElement element,
- Enqueuer enqueuer,
- Registry registry) {}
-}
-
-/// Backend callbacks function specific to the resolution phase.
-class ResolutionCallbacks {
- /// Register that [node] is a call to `assert`.
- void onAssert(Send node, Registry registry) {}
-
- /// Register that an 'await for' has been seen.
- void onAsyncForIn(AsyncForIn node, Registry registry) {}
-
- /// Called during resolution to notify to the backend that the
- /// program uses string interpolation.
- void onStringInterpolation(Registry registry) {}
-
- /// Called during resolution to notify to the backend that the
- /// program has a catch statement.
- void onCatchStatement(Registry registry) {}
-
- /// Called during resolution to notify to the backend that the
- /// program explicitly throws an exception.
- void onThrowExpression(Registry registry) {}
-
- /// Called during resolution to notify to the backend that the
- /// program has a global variable with a lazy initializer.
- void onLazyField(Registry registry) {}
-
- /// Called during resolution to notify to the backend that the
- /// program uses a type variable as an expression.
- void onTypeVariableExpression(Registry registry) {}
-
- /// Called during resolution to notify to the backend that the
- /// program uses a type literal.
- void onTypeLiteral(DartType type, Registry registry) {}
-
- /// Called during resolution to notify to the backend that the
- /// program has a catch statement with a stack trace.
- void onStackTraceInCatch(Registry registry) {}
-
- /// Register an is check to the backend.
- void onIsCheck(DartType type, Registry registry) {}
-
- /// Called during resolution to notify to the backend that the
- /// program has a for-in loop.
- void onSyncForIn(Registry registry) {}
-
- /// Register an as check to the backend.
- void onAsCheck(DartType type, Registry registry) {}
-
- /// Registers that a type variable bounds check might occur at runtime.
- void onTypeVariableBoundCheck(Registry registry) {}
-
- /// Register that the application may throw a [NoSuchMethodError].
- void onThrowNoSuchMethod(Registry registry) {}
-
- /// Register that the application may throw a [RuntimeError].
- void onThrowRuntimeError(Registry registry) {}
-
- /// Register that the application may throw an
- /// [AbstractClassInstantiationError].
- void onAbstractClassInstantiation(Registry registry) {}
-
- /// Register that the application may throw a [FallThroughError].
- void onFallThroughError(Registry registry) {}
-
- /// Register that a super call will end up calling
- /// [: super.noSuchMethod :].
- void onSuperNoSuchMethod(Registry registry) {}
-
- /// Register that the application creates a constant map.
- void onMapLiteral(Registry registry, DartType type, bool isConstant) {}
-
- /// Called when resolving the `Symbol` constructor.
- void onSymbolConstructor(Registry registry) {}
-}
+import 'scannerlib.dart' show
+ Token;
/**
* Key class used in [TokenMap] in which the hash code for a token is based
@@ -662,1860 +45,3 @@ class TokenMap {
comments[new TokenKey(key)] = value;
}
}
-
-abstract class Compiler implements DiagnosticListener {
- static final Uri DART_CORE = new Uri(scheme: 'dart', path: 'core');
- static final Uri DART_MIRRORS = new Uri(scheme: 'dart', path: 'mirrors');
- static final Uri DART_NATIVE_TYPED_DATA =
- new Uri(scheme: 'dart', path: '_native_typed_data');
- static final Uri DART_INTERNAL = new Uri(scheme: 'dart', path: '_internal');
- static final Uri DART_ASYNC = new Uri(scheme: 'dart', path: 'async');
-
- final Stopwatch totalCompileTime = new Stopwatch();
- int nextFreeClassId = 0;
- World world;
- Types types;
- _CompilerCoreTypes _coreTypes;
-
- final CacheStrategy cacheStrategy;
-
- /**
- * Map from token to the first preceding comment token.
- */
- final TokenMap commentMap = new TokenMap();
-
- /**
- * Records global dependencies, that is, dependencies that don't
- * correspond to a particular element.
- *
- * We should get rid of this and ensure that all dependencies are
- * associated with a particular element.
- */
- Registry globalDependencies;
-
- /**
- * Dependencies that are only included due to mirrors.
- *
- * We should get rid of this and ensure that all dependencies are
- * associated with a particular element.
- */
- // TODO(johnniwinther): This should not be a [ResolutionRegistry].
- final Registry mirrorDependencies =
- new ResolutionRegistry.internal(null, new TreeElementMapping(null));
-
- final bool enableMinification;
-
- final bool useFrequencyNamer;
-
- /// When `true` emits URIs in the reflection metadata.
- final bool preserveUris;
-
- final bool enableTypeAssertions;
- final bool enableUserAssertions;
- final bool trustTypeAnnotations;
- final bool trustPrimitives;
- final bool enableConcreteTypeInference;
- final bool disableTypeInferenceFlag;
- final Uri deferredMapUri;
- final bool dumpInfo;
- final bool useContentSecurityPolicy;
- final bool enableExperimentalMirrors;
-
- /**
- * The maximum size of a concrete type before it widens to dynamic during
- * concrete type inference.
- */
- final int maxConcreteTypeSize;
- final bool analyzeAllFlag;
- final bool analyzeOnly;
-
- /// If true, disable tree-shaking for the main script.
- final bool analyzeMain;
-
- /**
- * If true, skip analysis of method bodies and field initializers. Implies
- * [analyzeOnly].
- */
- final bool analyzeSignaturesOnly;
- final bool enableNativeLiveTypeAnalysis;
-
- /**
- * If true, stop compilation after type inference is complete. Used for
- * debugging and testing purposes only.
- */
- bool stopAfterTypeInference = false;
-
- /**
- * If [:true:], comment tokens are collected in [commentMap] during scanning.
- */
- final bool preserveComments;
-
- /// Use the new CPS based backend end. This flag works for both the Dart and
- /// JavaScript backend.
- final bool useCpsIr;
-
- /**
- * Is the compiler in verbose mode.
- */
- final bool verbose;
-
- /**
- * URI of the main source map if the compiler is generating source
- * maps.
- */
- final Uri sourceMapUri;
-
- /**
- * URI of the main output if the compiler is generating source maps.
- */
- final Uri outputUri;
-
- /// Emit terse diagnostics without howToFix.
- final bool terseDiagnostics;
-
- /// If `true`, warnings and hints not from user code are reported.
- final bool showPackageWarnings;
-
- /// `true` if the last diagnostic was filtered, in which case the
- /// accompanying info message should be filtered as well.
- bool lastDiagnosticWasFiltered = false;
-
- /// Map containing information about the warnings and hints that have been
- /// suppressed for each library.
- Map<Uri, SuppressionInfo> suppressedWarnings = <Uri, SuppressionInfo>{};
-
- final bool suppressWarnings;
- final bool fatalWarnings;
-
- /// If `true`, some values are cached for reuse in incremental compilation.
- /// Incremental compilation is basically calling [run] more than once.
- final bool hasIncrementalSupport;
-
- /// If `true` native extension syntax is supported by the frontend.
- final bool allowNativeExtensions;
-
- /// Output provider from user of Compiler API.
- api.CompilerOutput userOutputProvider;
-
- /// Generate output even when there are compile-time errors.
- final bool generateCodeWithCompileTimeErrors;
-
- /// The compiler is run from the build bot.
- final bool testMode;
-
- bool disableInlining = false;
-
- List<Uri> librariesToAnalyzeWhenRun;
-
- Tracer tracer;
-
- CompilerTask measuredTask;
- Element _currentElement;
- LibraryElement coreLibrary;
- LibraryElement asyncLibrary;
-
- LibraryElement mainApp;
- FunctionElement mainFunction;
-
- /// Initialized when dart:mirrors is loaded.
- LibraryElement mirrorsLibrary;
-
- /// Initialized when dart:typed_data is loaded.
- LibraryElement typedDataLibrary;
-
- ClassElement get objectClass => _coreTypes.objectClass;
- ClassElement get boolClass => _coreTypes.boolClass;
- ClassElement get numClass => _coreTypes.numClass;
- ClassElement get intClass => _coreTypes.intClass;
- ClassElement get doubleClass => _coreTypes.doubleClass;
- ClassElement get stringClass => _coreTypes.stringClass;
- ClassElement get functionClass => _coreTypes.functionClass;
- ClassElement get nullClass => _coreTypes.nullClass;
- ClassElement get listClass => _coreTypes.listClass;
- ClassElement get typeClass => _coreTypes.typeClass;
- ClassElement get mapClass => _coreTypes.mapClass;
- ClassElement get symbolClass => _coreTypes.symbolClass;
- ClassElement get stackTraceClass => _coreTypes.stackTraceClass;
- ClassElement get futureClass => _coreTypes.futureClass;
- ClassElement get iterableClass => _coreTypes.iterableClass;
- ClassElement get streamClass => _coreTypes.streamClass;
-
- CoreTypes get coreTypes => _coreTypes;
-
- ClassElement typedDataClass;
-
- /// The constant for the [proxy] variable defined in dart:core.
- ConstantValue proxyConstant;
-
- // TODO(johnniwinther): Move this to the JavaScriptBackend.
- /// The class for patch annotation defined in dart:_js_helper.
- ClassElement patchAnnotationClass;
-
- // TODO(johnniwinther): Move this to the JavaScriptBackend.
- ClassElement nativeAnnotationClass;
-
- // Initialized after symbolClass has been resolved.
- FunctionElement symbolConstructor;
-
- // Initialized when dart:mirrors is loaded.
- ClassElement mirrorSystemClass;
-
- // Initialized when dart:mirrors is loaded.
- ClassElement mirrorsUsedClass;
-
- // Initialized after mirrorSystemClass has been resolved.
- FunctionElement mirrorSystemGetNameFunction;
-
- // Initialized when dart:_internal is loaded.
- ClassElement symbolImplementationClass;
-
- // Initialized when symbolImplementationClass has been resolved.
- FunctionElement symbolValidatedConstructor;
-
- // Initialized when mirrorsUsedClass has been resolved.
- FunctionElement mirrorsUsedConstructor;
-
- // Initialized when dart:mirrors is loaded.
- ClassElement deferredLibraryClass;
-
- /// Document class from dart:mirrors.
- ClassElement documentClass;
- Element identicalFunction;
- Element loadLibraryFunction;
- Element functionApplyMethod;
-
- /// The [int.fromEnvironment] constructor.
- ConstructorElement intEnvironment;
-
- /// The [bool.fromEnvironment] constructor.
- ConstructorElement boolEnvironment;
-
- /// The [String.fromEnvironment] constructor.
- ConstructorElement stringEnvironment;
-
- /// Tracks elements with compile-time errors.
- final Set<Element> elementsWithCompileTimeErrors = new Set<Element>();
-
- fromEnvironment(String name) => null;
-
- Element get currentElement => _currentElement;
-
- String tryToString(object) {
- try {
- return object.toString();
- } catch (_) {
- return '<exception in toString()>';
- }
- }
-
- /**
- * Perform an operation, [f], returning the return value from [f]. If an
- * error occurs then report it as having occurred during compilation of
- * [element]. Can be nested.
- */
- withCurrentElement(Element element, f()) {
- Element old = currentElement;
- _currentElement = element;
- try {
- return f();
- } on SpannableAssertionFailure catch (ex) {
- if (!hasCrashed) {
- reportAssertionFailure(ex);
- pleaseReportCrash();
- }
- hasCrashed = true;
- rethrow;
- } on StackOverflowError {
- // We cannot report anything useful in this case, because we
- // do not have enough stack space.
- rethrow;
- } catch (ex) {
- if (hasCrashed) rethrow;
- try {
- unhandledExceptionOnElement(element);
- } catch (doubleFault) {
- // Ignoring exceptions in exception handling.
- }
- rethrow;
- } finally {
- _currentElement = old;
- }
- }
-
- List<CompilerTask> tasks;
- ScannerTask scanner;
- DietParserTask dietParser;
- ParserTask parser;
- PatchParserTask patchParser;
- LibraryLoaderTask libraryLoader;
- SerializationTask serialization;
- ResolverTask resolver;
- closureMapping.ClosureTask closureToClassMapper;
- TypeCheckerTask checker;
- IrBuilderTask irBuilder;
- ti.TypesTask typesTask;
- Backend backend;
-
- GenericTask reuseLibraryTask;
-
- /// The constant environment for the frontend interpretation of compile-time
- /// constants.
- ConstantEnvironment constants;
-
- EnqueueTask enqueuer;
- DeferredLoadTask deferredLoadTask;
- MirrorUsageAnalyzerTask mirrorUsageAnalyzerTask;
- DumpInfoTask dumpInfoTask;
- String buildId;
-
- /// A customizable filter that is applied to enqueued work items.
- QueueFilter enqueuerFilter = new QueueFilter();
-
- static const String MAIN = 'main';
- static const String CALL_OPERATOR_NAME = 'call';
- static const String NO_SUCH_METHOD = 'noSuchMethod';
- static const int NO_SUCH_METHOD_ARG_COUNT = 1;
- static const String CREATE_INVOCATION_MIRROR =
- 'createInvocationMirror';
- static const String FROM_ENVIRONMENT = 'fromEnvironment';
-
- static const String RUNTIME_TYPE = 'runtimeType';
-
- static const String UNDETERMINED_BUILD_ID =
- "build number could not be determined";
-
- final Selector iteratorSelector =
- new Selector.getter('iterator', null);
- final Selector currentSelector =
- new Selector.getter('current', null);
- final Selector moveNextSelector =
- new Selector.call('moveNext', null, 0);
- final Selector noSuchMethodSelector = new Selector.call(
- Compiler.NO_SUCH_METHOD, null, Compiler.NO_SUCH_METHOD_ARG_COUNT);
- final Selector symbolValidatedConstructorSelector = new Selector.call(
- 'validated', null, 1);
-
- bool enabledRuntimeType = false;
- bool enabledFunctionApply = false;
- bool enabledInvokeOn = false;
- bool hasIsolateSupport = false;
-
- Stopwatch progress;
-
- bool get shouldPrintProgress {
- return verbose && progress.elapsedMilliseconds > 500;
- }
-
- static const int PHASE_SCANNING = 0;
- static const int PHASE_RESOLVING = 1;
- static const int PHASE_DONE_RESOLVING = 2;
- static const int PHASE_COMPILING = 3;
- int phase;
-
- bool compilationFailedInternal = false;
-
- bool get compilationFailed => compilationFailedInternal;
-
- void set compilationFailed(bool value) {
- if (value) {
- elementsWithCompileTimeErrors.add(currentElement);
- }
- compilationFailedInternal = value;
- }
-
- bool hasCrashed = false;
-
- /// Set by the backend if real reflection is detected in use of dart:mirrors.
- bool disableTypeInferenceForMirrors = false;
-
- Compiler({this.enableTypeAssertions: false,
- this.enableUserAssertions: false,
- this.trustTypeAnnotations: false,
- this.trustPrimitives: false,
- this.enableConcreteTypeInference: false,
- bool disableTypeInferenceFlag: false,
- this.maxConcreteTypeSize: 5,
- this.enableMinification: false,
- this.preserveUris: false,
- this.enableNativeLiveTypeAnalysis: false,
- bool emitJavaScript: true,
- bool dart2dartMultiFile: false,
- bool generateSourceMap: true,
- bool analyzeAllFlag: false,
- bool analyzeOnly: false,
- this.analyzeMain: false,
- bool analyzeSignaturesOnly: false,
- this.preserveComments: false,
- this.useCpsIr: false,
- this.useFrequencyNamer: false,
- this.verbose: false,
- this.sourceMapUri: null,
- this.outputUri: null,
- this.buildId: UNDETERMINED_BUILD_ID,
- this.terseDiagnostics: false,
- this.deferredMapUri: null,
- this.dumpInfo: false,
- this.showPackageWarnings: false,
- bool useStartupEmitter: false,
- this.useContentSecurityPolicy: false,
- this.suppressWarnings: false,
- this.fatalWarnings: false,
- bool hasIncrementalSupport: false,
- this.enableExperimentalMirrors: false,
- this.allowNativeExtensions: false,
- this.generateCodeWithCompileTimeErrors: false,
- this.testMode: false,
- api.CompilerOutput outputProvider,
- List<String> strips: const []})
- : this.disableTypeInferenceFlag =
- disableTypeInferenceFlag || !emitJavaScript,
- this.analyzeOnly =
- analyzeOnly || analyzeSignaturesOnly || analyzeAllFlag,
- this.analyzeSignaturesOnly = analyzeSignaturesOnly,
- this.analyzeAllFlag = analyzeAllFlag,
- this.hasIncrementalSupport = hasIncrementalSupport,
- cacheStrategy = new CacheStrategy(hasIncrementalSupport),
- this.userOutputProvider = outputProvider == null
- ? const NullCompilerOutput() : outputProvider {
- if (hasIncrementalSupport) {
- // TODO(ahe): This is too much. Any method from platform and package
- // libraries can be inlined.
- disableInlining = true;
- }
- world = new World(this);
- // TODO(johnniwinther): Initialize core types in [initializeCoreClasses] and
- // make its field final.
- _coreTypes = new _CompilerCoreTypes(this);
- types = new Types(this);
- tracer = new Tracer(this, this.outputProvider);
-
- if (verbose) {
- progress = new Stopwatch()..start();
- }
-
- // TODO(johnniwinther): Separate the dependency tracking from the enqueuing
- // for global dependencies.
- globalDependencies =
- new CodegenRegistry(this, new TreeElementMapping(null));
-
- if (emitJavaScript) {
- js_backend.JavaScriptBackend jsBackend =
- new js_backend.JavaScriptBackend(
- this, generateSourceMap: generateSourceMap,
- useStartupEmitter: useStartupEmitter);
- backend = jsBackend;
- } else {
- backend = new dart_backend.DartBackend(this, strips,
- multiFile: dart2dartMultiFile);
- if (dumpInfo) {
- throw new ArgumentError('--dump-info is not supported for dart2dart.');
- }
- }
-
- tasks = [
- libraryLoader = new LibraryLoaderTask(this),
- serialization = new SerializationTask(this),
- scanner = new ScannerTask(this),
- dietParser = new DietParserTask(this),
- parser = new ParserTask(this),
- patchParser = new PatchParserTask(this),
- resolver = new ResolverTask(this, backend.constantCompilerTask),
- closureToClassMapper = new closureMapping.ClosureTask(this),
- checker = new TypeCheckerTask(this),
- irBuilder = new IrBuilderTask(this, backend.sourceInformationStrategy),
- typesTask = new ti.TypesTask(this),
- constants = backend.constantCompilerTask,
- deferredLoadTask = new DeferredLoadTask(this),
- mirrorUsageAnalyzerTask = new MirrorUsageAnalyzerTask(this),
- enqueuer = new EnqueueTask(this),
- dumpInfoTask = new DumpInfoTask(this),
- reuseLibraryTask = new GenericTask('Reuse library', this),
- ];
-
- tasks.addAll(backend.tasks);
- }
-
- Universe get resolverWorld => enqueuer.resolution.universe;
- Universe get codegenWorld => enqueuer.codegen.universe;
-
- bool get hasBuildId => buildId != UNDETERMINED_BUILD_ID;
-
- bool get analyzeAll => analyzeAllFlag || compileAll;
-
- bool get compileAll => false;
-
- bool get disableTypeInference {
- return disableTypeInferenceFlag || compilationFailed;
- }
-
- int getNextFreeClassId() => nextFreeClassId++;
-
- void unimplemented(Spannable spannable, String methodName) {
- internalError(spannable, "$methodName not implemented.");
- }
-
- void internalError(Spannable node, reason) {
- String message = tryToString(reason);
- reportDiagnosticInternal(
- node, MessageKind.GENERIC, {'text': message}, api.Diagnostic.CRASH);
- throw 'Internal Error: $message';
- }
-
- void unhandledExceptionOnElement(Element element) {
- if (hasCrashed) return;
- hasCrashed = true;
- reportDiagnostic(
- element,
- MessageTemplate.TEMPLATES[MessageKind.COMPILER_CRASHED].message(),
- api.Diagnostic.CRASH);
- pleaseReportCrash();
- }
-
- void pleaseReportCrash() {
- print(
- MessageTemplate.TEMPLATES[MessageKind.PLEASE_REPORT_THE_CRASH]
- .message({'buildId': buildId}));
- }
-
- SourceSpan spanFromSpannable(Spannable node) {
- // TODO(johnniwinther): Disallow `node == null` ?
- if (node == null) return null;
- if (node == CURRENT_ELEMENT_SPANNABLE) {
- node = currentElement;
- } else if (node == NO_LOCATION_SPANNABLE) {
- if (currentElement == null) return null;
- node = currentElement;
- }
- if (node is SourceSpan) {
- return node;
- } else if (node is Node) {
- return spanFromNode(node);
- } else if (node is TokenPair) {
- return spanFromTokens(node.begin, node.end);
- } else if (node is Token) {
- return spanFromTokens(node, node);
- } else if (node is HInstruction) {
- return spanFromHInstruction(node);
- } else if (node is Element) {
- return spanFromElement(node);
- } else if (node is MetadataAnnotation) {
- 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);
- } else {
- throw 'No error location.';
- }
- }
-
- Element _elementFromHInstruction(HInstruction instruction) {
- return instruction.sourceElement is Element
- ? instruction.sourceElement : null;
- }
-
- /// Finds the approximate [Element] for [node]. [currentElement] is used as
- /// the default value.
- Element elementFromSpannable(Spannable node) {
- Element element;
- if (node is Element) {
- element = node;
- } else if (node is HInstruction) {
- element = _elementFromHInstruction(node);
- } else if (node is MetadataAnnotation) {
- element = node.annotatedElement;
- }
- return element != null ? element : currentElement;
- }
-
- void log(message) {
- reportDiagnostic(null,
- MessageTemplate.TEMPLATES[MessageKind.GENERIC]
- .message({'text': '$message'}),
- api.Diagnostic.VERBOSE_INFO);
- }
-
- Future<bool> run(Uri uri) {
- totalCompileTime.start();
-
- return new Future.sync(() => runCompiler(uri)).catchError((error) {
- try {
- if (!hasCrashed) {
- hasCrashed = true;
- if (error is SpannableAssertionFailure) {
- reportAssertionFailure(error);
- } else {
- reportDiagnostic(
- new SourceSpan(uri, 0, 0),
- MessageTemplate.TEMPLATES[MessageKind.COMPILER_CRASHED]
- .message(),
- api.Diagnostic.CRASH);
- }
- pleaseReportCrash();
- }
- } catch (doubleFault) {
- // Ignoring exceptions in exception handling.
- }
- throw error;
- }).whenComplete(() {
- tracer.close();
- totalCompileTime.stop();
- }).then((_) {
- return !compilationFailed;
- });
- }
-
- /// This method is called immediately after the [LibraryElement] [library] has
- /// been created.
- ///
- /// Use this callback method to store references to specific libraries.
- /// Note that [library] has not been scanned yet, nor has its imports/exports
- /// been resolved.
- void onLibraryCreated(LibraryElement library) {
- Uri uri = library.canonicalUri;
- if (uri == DART_CORE) {
- coreLibrary = library;
- } else if (uri == DART_NATIVE_TYPED_DATA) {
- typedDataLibrary = library;
- } else if (uri == DART_MIRRORS) {
- mirrorsLibrary = library;
- }
- backend.onLibraryCreated(library);
- }
-
- /// This method is called immediately after the [library] and its parts have
- /// been scanned.
- ///
- /// Use this callback method to store references to specific member declared
- /// in certain libraries. Note that [library] has not been patched yet, nor
- /// has its imports/exports been resolved.
- ///
- /// Use [loader] to register the creation and scanning of a patch library
- /// for [library].
- Future onLibraryScanned(LibraryElement library, LibraryLoader loader) {
- Uri uri = library.canonicalUri;
- if (uri == DART_CORE) {
- initializeCoreClasses();
- identicalFunction = coreLibrary.find('identical');
- } else if (uri == DART_INTERNAL) {
- symbolImplementationClass = findRequiredElement(library, 'Symbol');
- } else if (uri == DART_MIRRORS) {
- mirrorSystemClass = findRequiredElement(library, 'MirrorSystem');
- mirrorsUsedClass = findRequiredElement(library, 'MirrorsUsed');
- } else if (uri == DART_ASYNC) {
- asyncLibrary = library;
- deferredLibraryClass = findRequiredElement(library, 'DeferredLibrary');
- _coreTypes.futureClass = findRequiredElement(library, 'Future');
- _coreTypes.streamClass = findRequiredElement(library, 'Stream');
- } else if (uri == DART_NATIVE_TYPED_DATA) {
- typedDataClass = findRequiredElement(library, 'NativeTypedData');
- } else if (uri == js_backend.JavaScriptBackend.DART_JS_HELPER) {
- patchAnnotationClass = findRequiredElement(library, '_Patch');
- nativeAnnotationClass = findRequiredElement(library, 'Native');
- }
- return backend.onLibraryScanned(library, loader);
- }
-
- /// This method is called when all new libraries loaded through
- /// [LibraryLoader.loadLibrary] has been loaded and their imports/exports
- /// have been computed.
- ///
- /// [loadedLibraries] contains the newly loaded libraries.
- ///
- /// The method returns a [Future] allowing for the loading of additional
- /// libraries.
- Future onLibrariesLoaded(LoadedLibraries loadedLibraries) {
- return new Future.sync(() {
- if (!loadedLibraries.containsLibrary(DART_CORE)) {
- return null;
- }
- if (!enableExperimentalMirrors &&
- loadedLibraries.containsLibrary(DART_MIRRORS)) {
- // TODO(johnniwinther): Move computation of dependencies to the library
- // loader.
- Uri rootUri = loadedLibraries.rootUri;
- Set<String> importChains = new Set<String>();
- // The maximum number of full imports chains to process.
- final int chainLimit = 10000;
- // The maximum number of imports chains to show.
- final int compactChainLimit = verbose ? 20 : 10;
- int chainCount = 0;
- loadedLibraries.forEachImportChain(DART_MIRRORS,
- callback: (Link<Uri> importChainReversed) {
- Link<CodeLocation> compactImportChain = const Link<CodeLocation>();
- CodeLocation currentCodeLocation =
- new UriLocation(importChainReversed.head);
- compactImportChain = compactImportChain.prepend(currentCodeLocation);
- for (Link<Uri> link = importChainReversed.tail;
- !link.isEmpty;
- link = link.tail) {
- Uri uri = link.head;
- if (!currentCodeLocation.inSameLocation(uri)) {
- currentCodeLocation =
- verbose ? new UriLocation(uri) : new CodeLocation(uri);
- compactImportChain =
- compactImportChain.prepend(currentCodeLocation);
- }
- }
- String importChain =
- compactImportChain.map((CodeLocation codeLocation) {
- return codeLocation.relativize(rootUri);
- }).join(' => ');
-
- if (!importChains.contains(importChain)) {
- if (importChains.length > compactChainLimit) {
- importChains.add('...');
- return false;
- } else {
- importChains.add(importChain);
- }
- }
-
- chainCount++;
- if (chainCount > chainLimit) {
- // Assume there are more import chains.
- importChains.add('...');
- return false;
- }
- return true;
- });
-
- if (!backend.supportsReflection) {
- reportError(NO_LOCATION_SPANNABLE,
- MessageKind.MIRRORS_LIBRARY_NOT_SUPPORT_BY_BACKEND);
- } else {
- reportWarning(NO_LOCATION_SPANNABLE,
- MessageKind.IMPORT_EXPERIMENTAL_MIRRORS,
- {'importChain': importChains.join(
- MessageTemplate.IMPORT_EXPERIMENTAL_MIRRORS_PADDING)});
- }
- }
-
- functionClass.ensureResolved(this);
- functionApplyMethod = functionClass.lookupLocalMember('apply');
-
- proxyConstant =
- constants.getConstantValue(
- resolver.constantCompiler.compileConstant(
- coreLibrary.find('proxy')));
-
- if (preserveComments) {
- return libraryLoader.loadLibrary(DART_MIRRORS)
- .then((LibraryElement libraryElement) {
- documentClass = libraryElement.find('Comment');
- });
- }
- }).then((_) => backend.onLibrariesLoaded(loadedLibraries));
- }
-
- Element findRequiredElement(LibraryElement library, String name) {
- var element = library.find(name);
- if (element == null) {
- internalError(library,
- "The library '${library.canonicalUri}' does not contain required "
- "element: '$name'.");
- }
- return element;
- }
-
- // TODO(johnniwinther): Move this to [PatchParser] when it is moved to the
- // [JavaScriptBackend]. Currently needed for testing.
- String get patchVersion => backend.patchVersion;
-
- void onClassResolved(ClassElement cls) {
- if (mirrorSystemClass == cls) {
- mirrorSystemGetNameFunction =
- cls.lookupLocalMember('getName');
- } else if (symbolClass == cls) {
- symbolConstructor = cls.constructors.head;
- } else if (symbolImplementationClass == cls) {
- symbolValidatedConstructor = symbolImplementationClass.lookupConstructor(
- symbolValidatedConstructorSelector.name);
- } else if (mirrorsUsedClass == cls) {
- mirrorsUsedConstructor = cls.constructors.head;
- } else if (intClass == cls) {
- intEnvironment = intClass.lookupConstructor(FROM_ENVIRONMENT);
- } else if (stringClass == cls) {
- stringEnvironment =
- stringClass.lookupConstructor(FROM_ENVIRONMENT);
- } else if (boolClass == cls) {
- boolEnvironment =
- boolClass.lookupConstructor(FROM_ENVIRONMENT);
- }
- }
-
- void initializeCoreClasses() {
- final List missingCoreClasses = [];
- ClassElement lookupCoreClass(String name) {
- ClassElement result = coreLibrary.find(name);
- if (result == null) {
- missingCoreClasses.add(name);
- }
- return result;
- }
- _coreTypes.objectClass = lookupCoreClass('Object');
- _coreTypes.boolClass = lookupCoreClass('bool');
- _coreTypes.numClass = lookupCoreClass('num');
- _coreTypes.intClass = lookupCoreClass('int');
- _coreTypes.doubleClass = lookupCoreClass('double');
- _coreTypes.stringClass = lookupCoreClass('String');
- _coreTypes.functionClass = lookupCoreClass('Function');
- _coreTypes.listClass = lookupCoreClass('List');
- _coreTypes.typeClass = lookupCoreClass('Type');
- _coreTypes.mapClass = lookupCoreClass('Map');
- _coreTypes.nullClass = lookupCoreClass('Null');
- _coreTypes.stackTraceClass = lookupCoreClass('StackTrace');
- _coreTypes.iterableClass = lookupCoreClass('Iterable');
- _coreTypes.symbolClass = lookupCoreClass('Symbol');
- if (!missingCoreClasses.isEmpty) {
- internalError(
- coreLibrary,
- 'dart:core library does not contain required classes: '
- '$missingCoreClasses');
- }
- }
-
- Element _unnamedListConstructor;
- Element get unnamedListConstructor {
- if (_unnamedListConstructor != null) return _unnamedListConstructor;
- return _unnamedListConstructor = listClass.lookupDefaultConstructor();
- }
-
- Element _filledListConstructor;
- Element get filledListConstructor {
- if (_filledListConstructor != null) return _filledListConstructor;
- return _filledListConstructor = listClass.lookupConstructor("filled");
- }
-
- /**
- * Get an [Uri] pointing to a patch for the dart: library with
- * the given path. Returns null if there is no patch.
- */
- Uri resolvePatchUri(String dartLibraryPath);
-
- Future runCompiler(Uri uri) {
- // TODO(ahe): This prevents memory leaks when invoking the compiler
- // multiple times. Implement a better mechanism where we can store
- // such caches in the compiler and get access to them through a
- // suitably maintained static reference to the current compiler.
- StringToken.canonicalizedSubstrings.clear();
- Selector.canonicalizedValues.clear();
-
- assert(uri != null || analyzeOnly || hasIncrementalSupport);
- return new Future.sync(() {
- if (librariesToAnalyzeWhenRun != null) {
- return Future.forEach(librariesToAnalyzeWhenRun, (libraryUri) {
- log('Analyzing $libraryUri ($buildId)');
- return libraryLoader.loadLibrary(libraryUri);
- });
- }
- }).then((_) {
- if (uri != null) {
- if (analyzeOnly) {
- log('Analyzing $uri ($buildId)');
- } else {
- log('Compiling $uri ($buildId)');
- }
- return libraryLoader.loadLibrary(uri).then((LibraryElement library) {
- mainApp = library;
- });
- }
- }).then((_) {
- compileLoadedLibraries();
- });
- }
-
- void computeMain() {
- if (mainApp == null) return;
-
- Element main = mainApp.findExported(MAIN);
- ErroneousElement errorElement = null;
- if (main == null) {
- if (analyzeOnly) {
- if (!analyzeAll) {
- errorElement = new ErroneousElementX(
- MessageKind.CONSIDER_ANALYZE_ALL, {'main': MAIN}, MAIN, mainApp);
- }
- } else {
- // Compilation requires a main method.
- errorElement = new ErroneousElementX(
- MessageKind.MISSING_MAIN, {'main': MAIN}, MAIN, mainApp);
- }
- mainFunction = backend.helperForMissingMain();
- } else if (main.isErroneous && main.isSynthesized) {
- if (main is ErroneousElement) {
- errorElement = main;
- } else {
- internalError(main, 'Problem with $MAIN.');
- }
- mainFunction = backend.helperForBadMain();
- } else if (!main.isFunction) {
- errorElement = new ErroneousElementX(
- MessageKind.MAIN_NOT_A_FUNCTION, {'main': MAIN}, MAIN, main);
- mainFunction = backend.helperForBadMain();
- } else {
- mainFunction = main;
- mainFunction.computeType(this);
- FunctionSignature parameters = mainFunction.functionSignature;
- if (parameters.requiredParameterCount > 2) {
- int index = 0;
- parameters.orderedForEachParameter((Element parameter) {
- if (index++ < 2) return;
- errorElement = new ErroneousElementX(
- MessageKind.MAIN_WITH_EXTRA_PARAMETER, {'main': MAIN}, MAIN,
- parameter);
- mainFunction = backend.helperForMainArity();
- // Don't warn about main not being used:
- enqueuer.resolution.registerStaticUse(main);
- });
- }
- }
- if (mainFunction == null) {
- if (errorElement == null && !analyzeOnly && !analyzeAll) {
- internalError(mainApp, "Problem with '$MAIN'.");
- } else {
- mainFunction = errorElement;
- }
- }
- if (errorElement != null &&
- errorElement.isSynthesized &&
- !mainApp.isSynthesized) {
- reportWarning(
- errorElement, errorElement.messageKind,
- errorElement.messageArguments);
- }
- }
-
- /// Performs the compilation when all libraries have been loaded.
- void compileLoadedLibraries() {
- computeMain();
-
- mirrorUsageAnalyzerTask.analyzeUsage(mainApp);
-
- // In order to see if a library is deferred, we must compute the
- // compile-time constants that are metadata. This means adding
- // something to the resolution queue. So we cannot wait with
- // this until after the resolution queue is processed.
- deferredLoadTask.beforeResolution(this);
-
- phase = PHASE_RESOLVING;
- if (analyzeAll) {
- libraryLoader.libraries.forEach((LibraryElement library) {
- log('Enqueuing ${library.canonicalUri}');
- fullyEnqueueLibrary(library, enqueuer.resolution);
- });
- } else if (analyzeMain && mainApp != null) {
- fullyEnqueueLibrary(mainApp, enqueuer.resolution);
- }
- // Elements required by enqueueHelpers are global dependencies
- // that are not pulled in by a particular element.
- backend.enqueueHelpers(enqueuer.resolution, globalDependencies);
- resolveLibraryMetadata();
- log('Resolving...');
- processQueue(enqueuer.resolution, mainFunction);
- enqueuer.resolution.logSummary(log);
-
- if (!showPackageWarnings && !suppressWarnings) {
- suppressedWarnings.forEach((Uri uri, SuppressionInfo info) {
- MessageKind kind = MessageKind.HIDDEN_WARNINGS_HINTS;
- if (info.warnings == 0) {
- kind = MessageKind.HIDDEN_HINTS;
- } else if (info.hints == 0) {
- kind = MessageKind.HIDDEN_WARNINGS;
- }
- MessageTemplate template = MessageTemplate.TEMPLATES[kind];
- reportDiagnostic(null,
- template.message(
- {'warnings': info.warnings,
- 'hints': info.hints,
- 'uri': uri},
- terseDiagnostics),
- api.Diagnostic.HINT);
- });
- }
-
- if (compilationFailed){
- if (!generateCodeWithCompileTimeErrors) return;
- if (!backend.enableCodegenWithErrorsIfSupported(NO_LOCATION_SPANNABLE)) {
- return;
- }
- }
-
- if (analyzeOnly) {
- if (!analyzeAll && !compilationFailed) {
- // No point in reporting unused code when [analyzeAll] is true: all
- // code is artificially used.
- // If compilation failed, it is possible that the error prevents the
- // compiler from analyzing all the code.
- reportUnusedCode();
- }
- return;
- }
- assert(mainFunction != null);
- phase = PHASE_DONE_RESOLVING;
-
- world.populate();
- // Compute whole-program-knowledge that the backend needs. (This might
- // require the information computed in [world.populate].)
- backend.onResolutionComplete();
-
- deferredLoadTask.onResolutionComplete(mainFunction);
-
- log('Inferring types...');
- typesTask.onResolutionComplete(mainFunction);
-
- if (stopAfterTypeInference) return;
-
- backend.onTypeInferenceComplete();
-
- log('Compiling...');
- phase = PHASE_COMPILING;
- // TODO(johnniwinther): Move these to [CodegenEnqueuer].
- if (hasIsolateSupport) {
- backend.enableIsolateSupport(enqueuer.codegen);
- }
- if (compileAll) {
- libraryLoader.libraries.forEach((LibraryElement library) {
- fullyEnqueueLibrary(library, enqueuer.codegen);
- });
- }
- processQueue(enqueuer.codegen, mainFunction);
- enqueuer.codegen.logSummary(log);
-
- int programSize = backend.assembleProgram();
-
- if (dumpInfo) {
- dumpInfoTask.reportSize(programSize);
- dumpInfoTask.dumpInfo();
- }
-
- checkQueues();
- }
-
- void fullyEnqueueLibrary(LibraryElement library, Enqueuer world) {
- void enqueueAll(Element element) {
- fullyEnqueueTopLevelElement(element, world);
- }
- library.implementation.forEachLocalMember(enqueueAll);
- }
-
- void fullyEnqueueTopLevelElement(Element element, Enqueuer world) {
- if (element.isClass) {
- ClassElement cls = element;
- cls.ensureResolved(this);
- cls.forEachLocalMember(enqueuer.resolution.addToWorkList);
- world.registerInstantiatedType(cls.rawType, globalDependencies);
- } else {
- world.addToWorkList(element);
- }
- }
-
- // Resolves metadata on library elements. This is necessary in order to
- // resolve metadata classes referenced only from metadata on library tags.
- // TODO(ahe): Figure out how to do this lazily.
- void resolveLibraryMetadata() {
- for (LibraryElement library in libraryLoader.libraries) {
- if (library.metadata != null) {
- for (MetadataAnnotation metadata in library.metadata) {
- metadata.ensureResolved(this);
- }
- }
- }
- }
-
- void processQueue(Enqueuer world, Element main) {
- world.nativeEnqueuer.processNativeClasses(libraryLoader.libraries);
- if (main != null && !main.isErroneous) {
- FunctionElement mainMethod = main;
- mainMethod.computeType(this);
- if (mainMethod.functionSignature.parameterCount != 0) {
- // The first argument could be a list of strings.
- backend.listImplementation.ensureResolved(this);
- world.registerInstantiatedType(
- backend.listImplementation.rawType, globalDependencies);
- backend.stringImplementation.ensureResolved(this);
- world.registerInstantiatedType(
- backend.stringImplementation.rawType, globalDependencies);
-
- backend.registerMainHasArguments(world);
- }
- world.addToWorkList(main);
- }
- if (verbose) {
- progress.reset();
- }
- world.forEach((WorkItem work) {
- withCurrentElement(work.element, () {
- world.applyImpact(work.element, work.run(this, world));
- });
- });
- world.queueIsClosed = true;
- assert(compilationFailed || world.checkNoEnqueuedInvokedInstanceMethods());
- }
-
- /**
- * Perform various checks of the queues. This includes checking that
- * the queues are empty (nothing was added after we stopped
- * processing the queues). Also compute the number of methods that
- * were resolved, but not compiled (aka excess resolution).
- */
- checkQueues() {
- for (Enqueuer world in [enqueuer.resolution, enqueuer.codegen]) {
- world.forEach((WorkItem work) {
- internalError(work.element, "Work list is not empty.");
- });
- }
- if (!REPORT_EXCESS_RESOLUTION) return;
- var resolved = new Set.from(enqueuer.resolution.resolvedElements);
- for (Element e in enqueuer.codegen.generatedCode.keys) {
- resolved.remove(e);
- }
- for (Element e in new Set.from(resolved)) {
- if (e.isClass ||
- e.isField ||
- e.isTypeVariable ||
- e.isTypedef ||
- identical(e.kind, ElementKind.ABSTRACT_FIELD)) {
- resolved.remove(e);
- }
- if (identical(e.kind, ElementKind.GENERATIVE_CONSTRUCTOR)) {
- resolved.remove(e);
- }
- if (backend.isBackendLibrary(e.library)) {
- resolved.remove(e);
- }
- }
- log('Excess resolution work: ${resolved.length}.');
- for (Element e in resolved) {
- reportWarning(e,
- MessageKind.GENERIC,
- {'text': 'Warning: $e resolved but not compiled.'});
- }
- }
-
- WorldImpact analyzeElement(Element element) {
- assert(invariant(element,
- element.impliesType ||
- element.isField ||
- element.isFunction ||
- element.isGenerativeConstructor ||
- element.isGetter ||
- element.isSetter,
- message: 'Unexpected element kind: ${element.kind}'));
- assert(invariant(element, element is AnalyzableElement,
- message: 'Element $element is not analyzable.'));
- assert(invariant(element, element.isDeclaration));
- ResolutionEnqueuer world = enqueuer.resolution;
- if (world.hasBeenResolved(element)) {
- return const WorldImpact();
- }
- assert(parser != null);
- Node tree = parser.parse(element);
- assert(invariant(element, !element.isSynthesized || tree == null));
- WorldImpact worldImpact = resolver.resolve(element);
- if (tree != null && !analyzeSignaturesOnly && !suppressWarnings) {
- // Only analyze nodes with a corresponding [TreeElements].
- checker.check(element);
- }
- world.registerResolvedElement(element);
- return worldImpact;
- }
-
- WorldImpact analyze(ResolutionWorkItem work, ResolutionEnqueuer world) {
- assert(invariant(work.element, identical(world, enqueuer.resolution)));
- assert(invariant(work.element, !work.isAnalyzed,
- message: 'Element ${work.element} has already been analyzed'));
- if (shouldPrintProgress) {
- // TODO(ahe): Add structured diagnostics to the compiler API and
- // use it to separate this from the --verbose option.
- if (phase == PHASE_RESOLVING) {
- log('Resolved ${enqueuer.resolution.resolvedElements.length} '
- 'elements.');
- progress.reset();
- }
- }
- AstElement element = work.element;
- if (world.hasBeenResolved(element)) {
- return const WorldImpact();
- }
- WorldImpact worldImpact = analyzeElement(element);
- backend.onElementResolved(element, element.resolvedAst.elements);
- return worldImpact;
- }
-
- WorldImpact codegen(CodegenWorkItem work, CodegenEnqueuer world) {
- assert(invariant(work.element, identical(world, enqueuer.codegen)));
- if (shouldPrintProgress) {
- // TODO(ahe): Add structured diagnostics to the compiler API and
- // use it to separate this from the --verbose option.
- log('Compiled ${enqueuer.codegen.generatedCode.length} methods.');
- progress.reset();
- }
- return backend.codegen(work);
- }
-
- void reportError(Spannable node,
- MessageKind messageKind,
- [Map arguments = const {}]) {
- reportDiagnosticInternal(
- node, messageKind, arguments, api.Diagnostic.ERROR);
- }
-
- void reportWarning(Spannable node, MessageKind messageKind,
- [Map arguments = const {}]) {
- reportDiagnosticInternal(
- node, messageKind, arguments, api.Diagnostic.WARNING);
- }
-
- void reportInfo(Spannable node, MessageKind messageKind,
- [Map arguments = const {}]) {
- reportDiagnosticInternal(node, messageKind, arguments, api.Diagnostic.INFO);
- }
-
- void reportHint(Spannable node, MessageKind messageKind,
- [Map arguments = const {}]) {
- reportDiagnosticInternal(node, messageKind, arguments, api.Diagnostic.HINT);
- }
-
- void reportDiagnosticInternal(Spannable node,
- MessageKind messageKind,
- Map arguments,
- api.Diagnostic kind) {
- if (!showPackageWarnings && node != NO_LOCATION_SPANNABLE) {
- switch (kind) {
- case api.Diagnostic.WARNING:
- case api.Diagnostic.HINT:
- Element element = elementFromSpannable(node);
- if (!inUserCode(element, assumeInUserCode: true)) {
- Uri uri = getCanonicalUri(element);
- SuppressionInfo info =
- suppressedWarnings.putIfAbsent(uri, () => new SuppressionInfo());
- if (kind == api.Diagnostic.WARNING) {
- info.warnings++;
- } else {
- info.hints++;
- }
- lastDiagnosticWasFiltered = true;
- return;
- }
- break;
- case api.Diagnostic.INFO:
- if (lastDiagnosticWasFiltered) {
- return;
- }
- break;
- }
- }
- lastDiagnosticWasFiltered = false;
- MessageTemplate template = MessageTemplate.TEMPLATES[messageKind];
- reportDiagnostic(
- node,
- template.message(arguments, terseDiagnostics),
- kind);
- }
-
- void reportDiagnostic(Spannable span,
- Message message,
- api.Diagnostic kind);
-
- void reportAssertionFailure(SpannableAssertionFailure ex) {
- String message = (ex.message != null) ? tryToString(ex.message)
- : tryToString(ex);
- reportDiagnosticInternal(
- ex.node, MessageKind.GENERIC, {'text': message}, api.Diagnostic.CRASH);
- }
-
- SourceSpan spanFromTokens(Token begin, Token end, [Uri uri]) {
- if (begin == null || end == null) {
- // TODO(ahe): We can almost always do better. Often it is only
- // end that is null. Otherwise, we probably know the current
- // URI.
- throw 'Cannot find tokens to produce error message.';
- }
- if (uri == null && currentElement != null) {
- uri = currentElement.compilationUnit.script.resourceUri;
- }
- return SourceSpan.withCharacterOffsets(begin, end,
- (beginOffset, endOffset) => new SourceSpan(uri, beginOffset, endOffset));
- }
-
- SourceSpan spanFromNode(Node node) {
- return spanFromTokens(node.getBeginToken(), node.getEndToken());
- }
-
- SourceSpan spanFromElement(Element element) {
- if (element != null && element.sourcePosition != null) {
- return element.sourcePosition;
- }
- while (element != null && element.isSynthesized) {
- element = element.enclosingElement;
- }
- if (element != null &&
- element.sourcePosition == null &&
- !element.isLibrary &&
- !element.isCompilationUnit) {
- // Sometimes, the backend fakes up elements that have no
- // position. So we use the enclosing element instead. It is
- // not a good error location, but cancel really is "internal
- // error" or "not implemented yet", so the vicinity is good
- // enough for now.
- element = element.enclosingElement;
- // TODO(ahe): I plan to overhaul this infrastructure anyways.
- }
- if (element == null) {
- element = currentElement;
- }
- if (element == null) {
- return null;
- }
-
- if (element.sourcePosition != null) {
- return element.sourcePosition;
- }
- Token position = element.position;
- Uri uri = element.compilationUnit.script.resourceUri;
- return (position == null)
- ? new SourceSpan(uri, 0, 0)
- : spanFromTokens(position, position, uri);
- }
-
- SourceSpan spanFromHInstruction(HInstruction instruction) {
- Element element = _elementFromHInstruction(instruction);
- if (element == null) element = currentElement;
- SourceInformation position = instruction.sourceInformation;
- if (position == null) return spanFromElement(element);
- return position.sourceSpan;
- }
-
- /**
- * Translates the [resolvedUri] into a readable URI.
- *
- * The [importingLibrary] holds the library importing [resolvedUri] or
- * [:null:] if [resolvedUri] is loaded as the main library. The
- * [importingLibrary] is used to grant access to internal libraries from
- * platform libraries and patch libraries.
- *
- * If the [resolvedUri] is not accessible from [importingLibrary], this method
- * is responsible for reporting errors.
- *
- * See [LibraryLoader] for terminology on URIs.
- */
- Uri translateResolvedUri(LibraryElement importingLibrary,
- Uri resolvedUri, Node node) {
- unimplemented(importingLibrary, 'Compiler.translateResolvedUri');
- return null;
- }
-
- /**
- * Reads the script specified by the [readableUri].
- *
- * See [LibraryLoader] for terminology on URIs.
- */
- Future<Script> readScript(Spannable node, Uri readableUri) {
- unimplemented(node, 'Compiler.readScript');
- return null;
- }
-
- /// Compatible with [readScript] and used by [LibraryLoader] to create
- /// synthetic scripts to recover from read errors and bad URIs.
- Future<Script> synthesizeScript(Spannable node, Uri readableUri) {
- unimplemented(node, 'Compiler.synthesizeScript');
- return null;
- }
-
- Element lookupElementIn(ScopeContainerElement container, String name) {
- Element element = container.localLookup(name);
- if (element == null) {
- throw 'Could not find $name in $container';
- }
- return element;
- }
-
- bool get isMockCompilation => false;
-
- Token processAndStripComments(Token currentToken) {
- Token firstToken = currentToken;
- Token prevToken;
- while (currentToken.kind != EOF_TOKEN) {
- if (identical(currentToken.kind, COMMENT_TOKEN)) {
- Token firstCommentToken = currentToken;
- while (identical(currentToken.kind, COMMENT_TOKEN)) {
- currentToken = currentToken.next;
- }
- commentMap[currentToken] = firstCommentToken;
- if (prevToken == null) {
- firstToken = currentToken;
- } else {
- prevToken.next = currentToken;
- }
- }
- prevToken = currentToken;
- currentToken = currentToken.next;
- }
- return firstToken;
- }
-
- void reportUnusedCode() {
- void checkLive(member) {
- if (member.isErroneous) return;
- if (member.isFunction) {
- if (!enqueuer.resolution.hasBeenResolved(member)) {
- reportHint(member, MessageKind.UNUSED_METHOD,
- {'name': member.name});
- }
- } else if (member.isClass) {
- if (!member.isResolved) {
- reportHint(member, MessageKind.UNUSED_CLASS,
- {'name': member.name});
- } else {
- member.forEachLocalMember(checkLive);
- }
- } else if (member.isTypedef) {
- if (!member.isResolved) {
- reportHint(member, MessageKind.UNUSED_TYPEDEF,
- {'name': member.name});
- }
- }
- }
- libraryLoader.libraries.forEach((LibraryElement library) {
- // TODO(ahe): Implement better heuristics to discover entry points of
- // packages and use that to discover unused implementation details in
- // packages.
- if (library.isPlatformLibrary || library.isPackageLibrary) return;
- library.compilationUnits.forEach((unit) {
- unit.forEachLocalMember(checkLive);
- });
- });
- }
-
- /// Helper for determining whether the current element is declared within
- /// 'user code'.
- ///
- /// See [inUserCode] for what defines 'user code'.
- bool currentlyInUserCode() {
- return inUserCode(currentElement);
- }
-
- /// Helper for determining whether [element] is declared within 'user code'.
- ///
- /// What constitutes 'user code' is defined by the URI(s) provided by the
- /// entry point(s) of compilation or analysis:
- ///
- /// If an entrypoint URI uses the 'package' scheme then every library from
- /// that same package is considered to be in user code. For instance, if
- /// an entry point URI is 'package:foo/bar.dart' then every library whose
- /// canonical URI starts with 'package:foo/' is in user code.
- ///
- /// If an entrypoint URI uses another scheme than 'package' then every library
- /// with that scheme is in user code. For instance, an entry point URI is
- /// 'file:///foo.dart' then every library whose canonical URI scheme is
- /// 'file' is in user code.
- ///
- /// If [assumeInUserCode] is `true`, [element] is assumed to be in user code
- /// if no entrypoints have been set.
- bool inUserCode(Element element, {bool assumeInUserCode: false}) {
- if (element == null) return false;
- Iterable<CodeLocation> userCodeLocations =
- computeUserCodeLocations(assumeInUserCode: assumeInUserCode);
- Uri libraryUri = element.library.canonicalUri;
- return userCodeLocations.any(
- (CodeLocation codeLocation) => codeLocation.inSameLocation(libraryUri));
- }
-
- Iterable<CodeLocation> computeUserCodeLocations(
- {bool assumeInUserCode: false}) {
- List<CodeLocation> userCodeLocations = <CodeLocation>[];
- if (mainApp != null) {
- userCodeLocations.add(new CodeLocation(mainApp.canonicalUri));
- }
- if (librariesToAnalyzeWhenRun != null) {
- userCodeLocations.addAll(librariesToAnalyzeWhenRun.map(
- (Uri uri) => new CodeLocation(uri)));
- }
- if (userCodeLocations.isEmpty && assumeInUserCode) {
- // Assume in user code since [mainApp] has not been set yet.
- userCodeLocations.add(const AnyLocation());
- }
- return userCodeLocations;
- }
-
- /// Return a canonical URI for the source of [element].
- ///
- /// For a package library with canonical URI 'package:foo/bar/baz.dart' the
- /// return URI is 'package:foo'. For non-package libraries the returned URI is
- /// the canonical URI of the library itself.
- Uri getCanonicalUri(Element element) {
- if (element == null) return null;
- Uri libraryUri = element.library.canonicalUri;
- if (libraryUri.scheme == 'package') {
- int slashPos = libraryUri.path.indexOf('/');
- if (slashPos != -1) {
- String packageName = libraryUri.path.substring(0, slashPos);
- return new Uri(scheme: 'package', path: packageName);
- }
- }
- return libraryUri;
- }
-
- void diagnoseCrashInUserCode(String message, exception, stackTrace) {
- // Overridden by Compiler in apiimpl.dart.
- }
-
- void forgetElement(Element element) {
- enqueuer.forgetElement(element);
- if (element is MemberElement) {
- for (Element closure in element.nestedClosures) {
- // TODO(ahe): It would be nice to reuse names of nested closures.
- closureToClassMapper.forgetElement(closure);
- }
- }
- backend.forgetElement(element);
- }
-
- bool elementHasCompileTimeError(Element element) {
- return elementsWithCompileTimeErrors.contains(element);
- }
-
- EventSink<String> outputProvider(String name, String extension) {
- if (compilationFailed) {
- if (!generateCodeWithCompileTimeErrors || testMode) {
- // Disable output in test mode: The build bot currently uses the time
- // stamp of the generated file to determine whether the output is
- // up-to-date.
- return new NullSink('$name.$extension');
- }
- }
- return userOutputProvider.createEventSink(name, extension);
- }
-}
-
-class CompilerTask {
- final Compiler compiler;
- final Stopwatch watch;
- UserTag profilerTag;
-
- CompilerTask(Compiler compiler)
- : this.compiler = compiler,
- watch = (compiler.verbose) ? new Stopwatch() : null;
-
- String get name => "Unknown task '${this.runtimeType}'";
- int get timing => (watch != null) ? watch.elapsedMilliseconds : 0;
-
- int get timingMicroseconds => (watch != null) ? watch.elapsedMicroseconds : 0;
-
- UserTag getProfilerTag() {
- if (profilerTag == null) profilerTag = new UserTag(name);
- return profilerTag;
- }
-
- measure(action()) {
- // In verbose mode when watch != null.
- if (watch == null) return action();
- CompilerTask previous = compiler.measuredTask;
- if (identical(this, previous)) return action();
- compiler.measuredTask = this;
- if (previous != null) previous.watch.stop();
- watch.start();
- UserTag oldTag = getProfilerTag().makeCurrent();
- try {
- return action();
- } finally {
- watch.stop();
- oldTag.makeCurrent();
- if (previous != null) previous.watch.start();
- compiler.measuredTask = previous;
- }
- }
-
- measureElement(Element element, action()) {
- compiler.withCurrentElement(element, () => measure(action));
- }
-}
-
-class SourceSpan implements Spannable {
- final Uri uri;
- final int begin;
- final int end;
-
- const SourceSpan(this.uri, this.begin, this.end);
-
- static withCharacterOffsets(Token begin, Token end,
- f(int beginOffset, int endOffset)) {
- final beginOffset = begin.charOffset;
- final endOffset = end.charOffset + end.charCount;
-
- // [begin] and [end] might be the same for the same empty token. This
- // happens for instance when scanning '$$'.
- assert(endOffset >= beginOffset);
- return f(beginOffset, endOffset);
- }
-
- int get hashCode {
- return 13 * uri.hashCode +
- 17 * begin.hashCode +
- 19 * end.hashCode;
- }
-
- bool operator ==(other) {
- if (identical(this, other)) return true;
- if (other is! SourceSpan) return false;
- return uri == other.uri &&
- begin == other.begin &&
- end == other.end;
- }
-
- String toString() => 'SourceSpan($uri, $begin, $end)';
-}
-
-/// Flag that can be used in assertions to assert that a code path is only
-/// executed as part of development.
-///
-/// This flag is automatically set to true if helper methods like, [debugPrint],
-/// [debugWrapPrint], [trace], and [reportHere] are called.
-bool DEBUG_MODE = false;
-
-/// Assert that [DEBUG_MODE] is `true` and provide [message] as part of the
-/// error message.
-assertDebugMode(String message) {
- assert(invariant(NO_LOCATION_SPANNABLE, DEBUG_MODE,
- message: 'Debug mode is not enabled: $message'));
-}
-
-/**
- * Throws a [SpannableAssertionFailure] if [condition] is
- * [:false:]. [condition] must be either a [:bool:] or a no-arg
- * function returning a [:bool:].
- *
- * Use this method to provide better information for assertion by calling
- * [invariant] as the argument to an [:assert:] statement:
- *
- * assert(invariant(position, isValid));
- *
- * [spannable] must be non-null and will be used to provide positional
- * information in the generated error message.
- */
-bool invariant(Spannable spannable, var condition, {var message: null}) {
- // TODO(johnniwinther): Use [spannable] and [message] to provide better
- // information on assertion errors.
- if (spannable == null) {
- throw new SpannableAssertionFailure(CURRENT_ELEMENT_SPANNABLE,
- "Spannable was null for invariant. Use CURRENT_ELEMENT_SPANNABLE.");
- }
- if (condition is Function){
- condition = condition();
- }
- if (!condition) {
- if (message is Function) {
- message = message();
- }
- throw new SpannableAssertionFailure(spannable, message);
- }
- return true;
-}
-
-/// Returns `true` when [s] is private if used as an identifier.
-bool isPrivateName(String s) => !s.isEmpty && s.codeUnitAt(0) == $_;
-
-/// Returns `true` when [s] is public if used as an identifier.
-bool isPublicName(String s) => !isPrivateName(s);
-
-/// Information about suppressed warnings and hints for a given library.
-class SuppressionInfo {
- int warnings = 0;
- int hints = 0;
-}
-
-class GenericTask extends CompilerTask {
- final String name;
-
- GenericTask(this.name, Compiler compiler)
- : super(compiler);
-}
-
-/// [CodeLocation] divides uris into different classes.
-///
-/// These are used to group uris from user code, platform libraries and
-/// packages.
-abstract class CodeLocation {
- /// Returns `true` if [uri] is in this code location.
- bool inSameLocation(Uri uri);
-
- /// Returns the uri of this location relative to [baseUri].
- String relativize(Uri baseUri);
-
- factory CodeLocation(Uri uri) {
- if (uri.scheme == 'package') {
- int slashPos = uri.path.indexOf('/');
- if (slashPos != -1) {
- String packageName = uri.path.substring(0, slashPos);
- return new PackageLocation(packageName);
- } else {
- return new UriLocation(uri);
- }
- } else {
- return new SchemeLocation(uri);
- }
- }
-}
-
-/// A code location defined by the scheme of the uri.
-///
-/// Used for non-package uris, such as 'dart', 'file', and 'http'.
-class SchemeLocation implements CodeLocation {
- final Uri uri;
-
- SchemeLocation(this.uri);
-
- bool inSameLocation(Uri uri) {
- return this.uri.scheme == uri.scheme;
- }
-
- String relativize(Uri baseUri) {
- return uri_extras.relativize(baseUri, uri, false);
- }
-}
-
-/// A code location defined by the package name.
-///
-/// Used for package uris, separated by their `package names`, that is, the
-/// 'foo' of 'package:foo/bar.dart'.
-class PackageLocation implements CodeLocation {
- final String packageName;
-
- PackageLocation(this.packageName);
-
- bool inSameLocation(Uri uri) {
- return uri.scheme == 'package' && uri.path.startsWith('$packageName/');
- }
-
- String relativize(Uri baseUri) => 'package:$packageName';
-}
-
-/// A code location defined by the whole uri.
-///
-/// Used for package uris with no package name. For instance 'package:foo.dart'.
-class UriLocation implements CodeLocation {
- final Uri uri;
-
- UriLocation(this.uri);
-
- bool inSameLocation(Uri uri) => this.uri == uri;
-
- String relativize(Uri baseUri) {
- return uri_extras.relativize(baseUri, uri, false);
- }
-}
-
-/// A code location that contains any uri.
-class AnyLocation implements CodeLocation {
- const AnyLocation();
-
- bool inSameLocation(Uri uri) => true;
-
- String relativize(Uri baseUri) => '$baseUri';
-}
-
-class _CompilerCoreTypes implements CoreTypes {
- final Compiler compiler;
-
- ClassElement objectClass;
- ClassElement boolClass;
- ClassElement numClass;
- ClassElement intClass;
- ClassElement doubleClass;
- ClassElement stringClass;
- ClassElement functionClass;
- ClassElement nullClass;
- ClassElement listClass;
- ClassElement typeClass;
- ClassElement mapClass;
- ClassElement symbolClass;
- ClassElement stackTraceClass;
- ClassElement futureClass;
- ClassElement iterableClass;
- ClassElement streamClass;
-
- _CompilerCoreTypes(this.compiler);
-
- @override
- InterfaceType get objectType => objectClass.computeType(compiler);
-
- @override
- InterfaceType get boolType => boolClass.computeType(compiler);
-
- @override
- InterfaceType get doubleType => doubleClass.computeType(compiler);
-
- @override
- InterfaceType get functionType => functionClass.computeType(compiler);
-
- @override
- InterfaceType get intType => intClass.computeType(compiler);
-
- @override
- InterfaceType listType([DartType elementType]) {
- InterfaceType type = listClass.computeType(compiler);
- if (elementType == null) {
- return listClass.rawType;
- }
- return type.createInstantiation([elementType]);
- }
-
- @override
- InterfaceType mapType([DartType keyType,
- DartType valueType]) {
- InterfaceType type = mapClass.computeType(compiler);
- if (keyType == null && valueType == null) {
- return mapClass.rawType;
- } else if (keyType == null) {
- keyType = const DynamicType();
- } else if (valueType == null) {
- valueType = const DynamicType();
- }
- return type.createInstantiation([keyType, valueType]);
- }
-
- @override
- InterfaceType get nullType => nullClass.computeType(compiler);
-
- @override
- InterfaceType get numType => numClass.computeType(compiler);
-
- @override
- InterfaceType get stringType => stringClass.computeType(compiler);
-
- @override
- InterfaceType get symbolType => symbolClass.computeType(compiler);
-
- @override
- InterfaceType get typeType => typeClass.computeType(compiler);
-
- @override
- InterfaceType iterableType([DartType elementType]) {
- InterfaceType type = iterableClass.computeType(compiler);
- if (elementType == null) {
- return iterableClass.rawType;
- }
- return type.createInstantiation([elementType]);
- }
-
- @override
- InterfaceType futureType([DartType elementType]) {
- InterfaceType type = futureClass.computeType(compiler);
- if (elementType == null) {
- return futureClass.rawType;
- }
- return type.createInstantiation([elementType]);
- }
-
- @override
- InterfaceType streamType([DartType elementType]) {
- InterfaceType type = streamClass.computeType(compiler);
- if (elementType == null) {
- return streamClass.rawType;
- }
- return type.createInstantiation([elementType]);
- }
-}
-
-typedef void InternalErrorFunction(Spannable location, String message);
« no previous file with comments | « pkg/compiler/lib/src/scanner/scannerlib.dart ('k') | pkg/compiler/lib/src/serialization/element_serialization.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698