
com.google.javascript.jscomp.AbstractCompiler Maven / Gradle / Ivy
/*
* Copyright 2009 The Closure Compiler Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.javascript.jscomp.ReferenceCollectingCallback.ReferenceCollection;
import com.google.javascript.jscomp.TypeValidator.TypeMismatch;
import com.google.javascript.jscomp.parsing.Config;
import com.google.javascript.jscomp.parsing.parser.trees.Comment;
import com.google.javascript.jscomp.type.ReverseAbstractInterpreter;
import com.google.javascript.rhino.ErrorReporter;
import com.google.javascript.rhino.InputId;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.TypeIRegistry;
import com.google.javascript.rhino.jstype.JSTypeRegistry;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
/**
* An abstract compiler, to help remove the circular dependency of
* passes on JSCompiler.
*
* This is an abstract class, so that we can make the methods package-private.
*
* @author [email protected] (Nick Santos)
*/
public abstract class AbstractCompiler implements SourceExcerptProvider {
static final DiagnosticType READ_ERROR = DiagnosticType.error(
"JSC_READ_ERROR", "Cannot read: {0}");
boolean needsEs6Runtime = false;
boolean needsEs6DartRuntime = false;
/**
* Will be called before each pass runs.
*/
void beforePass(String passName) {}
/**
* Will be called after each pass finishes.
*/
void afterPass(String passName) {}
private LifeCycleStage stage = LifeCycleStage.RAW;
// TODO(nicksantos): Decide if all of these are really necessary.
// Many of them are just accessors that should be passed to the
// CompilerPass's constructor.
/**
* Looks up an input (possibly an externs input) by input id.
* May return null.
*/
public abstract CompilerInput getInput(InputId inputId);
/**
* Looks up a source file by name. May return null.
*/
abstract SourceFile getSourceFileByName(String sourceName);
/**
* Gets the module graph. May return null if there aren't at least two
* modules.
*/
abstract JSModuleGraph getModuleGraph();
/**
* Gets the inputs in the order in which they are being processed.
* Only for use by {@code AbstractCompilerRunner}.
*/
abstract List getInputsInOrder();
/**
* Gets a central registry of type information from the compiled JS.
*/
public abstract JSTypeRegistry getTypeRegistry();
public abstract TypeIRegistry getTypeIRegistry();
abstract void forwardDeclareType(String typeName);
/**
* Gets a memoized scope creator with type information. Only used by jsdev.
*/
abstract ScopeCreator getTypedScopeCreator();
/**
* Gets the top scope.
*/
public abstract TypedScope getTopScope();
/**
* Report an error or warning.
*/
public abstract void report(JSError error);
/**
* Report an internal error.
*/
abstract void throwInternalError(String msg, Exception cause);
/**
* Gets the current coding convention.
*/
public abstract CodingConvention getCodingConvention();
/**
* Report code changes.
*
* Passes should call reportCodeChange when they alter the JS tree. This is
* verified by CompilerTestCase. This allows us to optimize to a fixed point.
*/
public abstract void reportCodeChange();
/**
* Logs a message under a central logger.
*/
abstract void addToDebugLog(String message);
/**
* Sets the CssRenamingMap.
*/
abstract void setCssRenamingMap(CssRenamingMap map);
/**
* Gets the CssRenamingMap.
*/
abstract CssRenamingMap getCssRenamingMap();
/**
* Gets a suitable SCRIPT node to serve as a parent for code insertion. If
* {@code module} contains any inputs, the returned node will be the SCRIPT
* node corresponding to its first input. If {@code module} is empty, on the
* other hand, then the returned node will be the first SCRIPT node in a
* non-empty module that {@code module} depends on (the deepest one possible).
*
* @param module A module. If null, will return the first SCRIPT node of all
* modules.
* @return A SCRIPT node (never null).
*/
abstract Node getNodeForCodeInsertion(JSModule module);
/**
* Only used by passes in the old type checker.
*/
abstract TypeValidator getTypeValidator();
/**
* Gets the central registry of type violations.
*/
abstract Iterable getTypeMismatches();
/**
* Gets all types that are used implicitly as a
* matching structural interface type. These are
* recorded as TypeMismatchs only for convenience
*/
abstract Iterable getImplicitInterfaceUses();
/**
* Used only by the new type inference
*/
abstract GlobalTypeInfo getSymbolTable();
abstract void setSymbolTable(GlobalTypeInfo symbolTable);
/**
* Used by three passes that run in sequence (optimize-returns,
* optimize-parameters, remove-unused-variables), to avoid having them
* recompute it independently.
*/
abstract SimpleDefinitionFinder getSimpleDefinitionFinder();
abstract void setSimpleDefinitionFinder(SimpleDefinitionFinder defFinder);
/**
* Parses code for injecting.
*/
abstract Node parseSyntheticCode(String code);
/**
* Parses code for injecting, and associate it with a given source file.
*/
abstract Node parseSyntheticCode(String filename, String code);
/**
* Parses code for testing.
*/
abstract Node parseTestCode(String code);
/**
* Prints a node to source code.
*/
public abstract String toSource(Node root);
/**
* Gets a default error reporter for injecting into Rhino.
*/
abstract ErrorReporter getDefaultErrorReporter();
/**
* Get an interpreter for type analysis.
*/
public abstract ReverseAbstractInterpreter getReverseAbstractInterpreter();
/**
* @return The current life-cycle stage of the AST we're working on.
*/
LifeCycleStage getLifeCycleStage() {
return stage;
}
/**
* Generates unique ids.
*/
abstract Supplier getUniqueNameIdSupplier();
/**
* @return Whether any errors have been encountered that
* should stop the compilation process.
*/
abstract boolean hasHaltingErrors();
/**
* Register a listener for code change events.
*/
abstract void addChangeHandler(CodeChangeHandler handler);
/**
* Remove a listener for code change events.
*/
abstract void removeChangeHandler(CodeChangeHandler handler);
/** Let the PhaseOptimizer know which scope a pass is currently analyzing */
abstract void setScope(Node n);
/** Returns the root of the source tree, ignoring externs */
abstract Node getJsRoot();
/** True iff a function changed since the last time a pass was run */
abstract boolean hasScopeChanged(Node n);
/** Passes that do cross-scope modifications use this (eg, InlineVariables) */
abstract void reportChangeToEnclosingScope(Node n);
/**
* Returns true if compiling in IDE mode.
*/
abstract boolean isIdeMode();
/**
* Represents the different contexts for which the compiler could have
* distinct configurations.
*/
static enum ConfigContext {
/**
* Normal JavaScript.
*/
DEFAULT,
/**
* Externs files.
*/
EXTERNS
}
/**
* Returns the parser configuration for the specified context.
*/
abstract Config getParserConfig(ConfigContext context);
/**
* Normalizes the types of AST nodes in the given tree, and
* annotates any nodes to which the coding convention applies so that passes
* can read the annotations instead of using the coding convention.
*/
abstract void prepareAst(Node root);
/**
* Gets the error manager.
*/
public abstract ErrorManager getErrorManager();
/**
* Set the current life-cycle state.
*/
void setLifeCycleStage(LifeCycleStage stage) {
this.stage = stage;
}
/**
* Are the nodes equal for the purpose of inlining?
* If type aware optimizations are on, type equality is checked.
*/
abstract boolean areNodesEqualForInlining(Node n1, Node n2);
/**
* Set if RegExp global properties are used.
* @param references Whether there are references to the RegExp global object
* properties.
*/
abstract void setHasRegExpGlobalReferences(boolean references);
/**
* @return Whether the AST contains references to the RegExp global object
* properties.
*/
abstract boolean hasRegExpGlobalReferences();
/**
* @return The error level the given error object will be reported at.
*/
abstract CheckLevel getErrorLevel(JSError error);
static enum LifeCycleStage {
RAW,
// See constraints put on the tree by Normalize.java
NORMALIZED,
// The normalize pass has put constraints on the tree,
// but variables and properties have been renamed so
// coding conventions no longer apply.
NORMALIZED_OBFUSCATED;
boolean isNormalized() {
return this == NORMALIZED || this == NORMALIZED_OBFUSCATED;
}
boolean isNormalizedUnobfuscated() {
return this == NORMALIZED;
}
boolean isNormalizedObfuscated() {
return this == NORMALIZED_OBFUSCATED;
}
}
/**
* Runs a given compiler-pass by calling its {@code process()} method.
* @param pass The pass to be run.
*/
abstract void process(CompilerPass pass);
/**
* Returns the root node of the AST, which includes both externs and source.
*/
abstract Node getRoot();
abstract CompilerOptions getOptions();
/**
* The language mode of the current root node. This will match the languageIn
* field of the {@link CompilerOptions} before transpilation happens, and
* match the languageOut field after transpilation.
*/
abstract CompilerOptions.LanguageMode getLanguageMode();
abstract void setLanguageMode(CompilerOptions.LanguageMode mode);
// TODO(bashir) It would be good to extract a single dumb data object with
// only getters and setters that keeps all global information we keep for a
// compiler instance. Then move some of the functions of this class there.
/**
* Updates the list of references for variables in global scope.
*
* @param refMapPatch Maps each variable to all of its references; may contain
* references collected from the whole AST or only a SCRIPT sub-tree.
* @param collectionRoot The root of sub-tree in which reference collection
* has been done. This should either be a SCRIPT node (if collection is
* done on a single file) or it is assumed that collection is on full AST.
*/
abstract void updateGlobalVarReferences(Map
refMapPatch, Node collectionRoot);
/**
* This can be used to get the list of all references to all global variables
* based on all previous calls to {@code updateGlobalVarReferences}.
*
* @return The reference collection map associated to global scope variable.
*/
abstract GlobalVarReferenceMap getGlobalVarReferences();
/**
* @return a CompilerInput that can be modified to add additional extern
* definitions to the beginning of the externs AST
*/
abstract CompilerInput getSynthesizedExternsInput();
/**
* @return a CompilerInput that can be modified to add additional extern
* definitions to the end of the externs AST
*/
abstract CompilerInput getSynthesizedExternsInputAtEnd();
/**
* @return a number in [0,1] range indicating an approximate progress of the
* last compile. Note this should only be used as a hint and no assumptions
* should be made on accuracy, even a completed compile may choose not to set
* this to 1.0 at the end.
*/
public abstract double getProgress();
/**
* Gets the last pass name set by setProgress.
*/
abstract String getLastPassName();
/**
* Sets the progress percentage as well as the name of the last pass that
* ran (if available).
* @param progress A precentage expressed as a double in the range [0, 1].
* Use -1 if you just want to set the last pass name.
*/
abstract void setProgress(double progress, @Nullable String lastPassName);
/**
* The subdir js/ contains libraries of code that we inject
* at compile-time only if requested by this function.
*
* Notice that these libraries will almost always create global symbols.
*
* @param resourceName The name of the library. For example, if "base" is
* is specified, then we load js/base.js
* @param normalizeAndUniquifyNames Whether to normalize the library code and make
* names unique.
* @return If new code was injected, returns the last expression node of the
* library. If the caller needs to add additional code, they should add
* it as the next sibling of this node. If new code was not injected,
* returns null.
*/
abstract Node ensureLibraryInjected(String resourceName,
boolean normalizeAndUniquifyNames);
/**
* Sets the names of the properties defined in externs.
* @param externProperties The set of property names defined in externs.
*/
abstract void setExternProperties(Set externProperties);
/**
* Gets the names of the properties defined in externs or null if
* GatherExternProperties pass was not run yet.
*/
abstract Set getExternProperties();
abstract void addComments(String filename, List comments);
/**
* Returns all the comments from the given file.
*/
abstract List getComments(String filename);
/**
* Stores a map of default @define values. These values
* can be overriden by values specifically set in the CompilerOptions.
*/
abstract void setDefaultDefineValues(ImmutableMap values);
/**
* Gets a map of default @define values. These values
* can be overriden by values specifically set in the CompilerOptions.
*/
abstract ImmutableMap getDefaultDefineValues();
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy