public final class SymbolTable
extends java.lang.Object
StaticSymbolTable
of all variable references,
and another class might have a StaticSymbolTable
of all type names
in JSDoc comments. This class allows you to combine them into a unified
index.
Most passes build their own "partial" symbol table that implements the same
interface (StaticSymbolTable, StaticSlot, and friends). Individual compiler
passes usually need more or less metadata about the certainty of symbol
information. Building a complete symbol table with all the necessary metadata
for all passes would be too slow. However, as long as these "partial" symbol
tables implement the proper interfaces, we should be able to add them to this
symbol table to make it more complete.
If clients want fast lookup, they should build their own wrapper around
this symbol table that indexes symbols or references by the desired lookup
key.
By design, when this symbol table creates symbols for types, it tries
to mimic the symbol table you would get in an OO language. For example,
the "type Foo" and "the constructor that creates objects of type Foo"
are the same symbol. The types of "Foo.prototype" and "new Foo()" also
have the same symbol. Although JSCompiler internally treats these as
distinct symbols, we assume that most clients will not care about
the distinction.Modifier and Type | Class and Description |
---|---|
private class |
SymbolTable.JSDocInfoCollector
Collects references to types in JSDocInfo.
|
private class |
SymbolTable.PropertyRefCollector |
static class |
SymbolTable.Reference
Reference
|
static class |
SymbolTable.Symbol
A symbol-table entry
|
static class |
SymbolTable.SymbolScope
Scope of a symbol
|
private class |
SymbolTable.ThisRefCollector |
private class |
SymbolTable.VisibilityCollector
Collects the visibility information for each name/property.
|
Modifier and Type | Field and Description |
---|---|
private java.util.List<Node> |
docInfos
All Nodes with JSDocInfo in the program.
|
static java.lang.String |
GLOBAL_THIS
The name we use for the JavaScript built-in Global object.
|
private SymbolTable.SymbolScope |
globalScope |
private com.google.common.collect.Ordering<SymbolTable.SymbolScope> |
lexicalScopeOrdering |
private static java.util.logging.Logger |
logger |
private com.google.common.collect.Ordering<Node> |
nodeOrdering |
private JSTypeRegistry |
registry |
private java.util.Map<Node,SymbolTable.SymbolScope> |
scopes
All syntactic scopes in the program, uniquely identified by the node where
they're declared.
|
private com.google.common.collect.Ordering<java.lang.String> |
sourceNameOrdering |
private com.google.common.collect.Ordering<SymbolTable.Symbol> |
symbolOrdering |
private com.google.common.collect.Table<Node,java.lang.String,SymbolTable.Symbol> |
symbols
All symbols in the program, uniquely identified by the node where
they're declared and their name.
|
Constructor and Description |
---|
SymbolTable(JSTypeRegistry registry)
Clients should get a symbol table by asking the compiler at the end
of a compilation job.
|
Modifier and Type | Method and Description |
---|---|
void |
addAnonymousFunctions()
Finds anonymous functions in local scopes, and gives them names
and symbols.
|
private void |
addAnonymousFunctionsInScope(SymbolTable.SymbolScope scope) |
(package private) <S extends StaticScope> |
addScopes(java.util.Collection<S> scopes)
Make sure all the given scopes in
otherSymbolTable
are in this symbol table. |
private SymbolTable.Symbol |
addSymbol(java.lang.String name,
JSType type,
boolean inferred,
SymbolTable.SymbolScope scope,
Node declNode) |
(package private) <S extends StaticSlot,R extends StaticRef> |
addSymbolsFrom(StaticSymbolTable<S,R> otherSymbolTable)
Make sure all the symbols and references in
otherSymbolTable
are in this symbol table. |
private SymbolTable.Symbol |
copySymbolTo(StaticSlot sym,
Node declNode,
SymbolTable.SymbolScope scope) |
private SymbolTable.Symbol |
copySymbolTo(StaticSlot sym,
SymbolTable.SymbolScope scope) |
private void |
createPropertyScopeFor(SymbolTable.Symbol s)
Build a property scope for the given symbol.
|
private SymbolTable.SymbolScope |
createScopeFrom(StaticScope otherScope)
Given a scope from another symbol table, returns the
SymbolScope
rooted at the same node. |
SymbolTable.Symbol |
declareInferredSymbol(SymbolTable.SymbolScope scope,
java.lang.String name,
Node declNode)
Declare a symbol after the main symbol table was constructed.
|
private SymbolTable.Symbol |
declareSymbol(java.lang.String name,
JSType type,
boolean inferred,
SymbolTable.SymbolScope scope,
Node declNode,
JSDocInfo info) |
(package private) void |
fillJSDocInfo(AbstractCompiler compiler,
Node externs,
Node root)
Index JSDocInfo.
|
(package private) void |
fillNamespaceReferences()
Not all symbol tables record references to "namespace" objects.
|
(package private) void |
fillPropertyScopes() |
(package private) void |
fillPropertySymbols(AbstractCompiler compiler,
Node externs,
Node root)
Create symbols and references for all properties of types in
this symbol table.
|
(package private) void |
fillSymbolVisibility(AbstractCompiler compiler,
Node externs,
Node root)
Records the visibility of each symbol.
|
(package private) void |
fillThisReferences(AbstractCompiler compiler,
Node externs,
Node root)
Fill in references to "this" variables.
|
private <S extends StaticSlot,R extends StaticRef> |
findBestDeclToAdd(StaticSymbolTable<S,R> otherSymbolTable,
S slot)
Helper for addSymbolsFrom, to determine the best declaration spot.
|
(package private) void |
findScopes(AbstractCompiler compiler,
Node externs,
Node root)
Finds all the scopes and adds them to this symbol table.
|
private SymbolTable.Symbol |
findSymbolForScope(SymbolTable.SymbolScope scope)
Find the symbol associated with the given scope.
|
java.util.Collection<Node> |
getAllJSDocInfoNodes() |
java.util.Collection<SymbolTable.SymbolScope> |
getAllScopes()
Gets all the scopes in this symbol table.
|
java.lang.Iterable<SymbolTable.Symbol> |
getAllSymbols() |
java.util.List<SymbolTable.Symbol> |
getAllSymbolsForType(JSType type)
Gets all symbols associated with the given type.
|
java.lang.Iterable<SymbolTable.Symbol> |
getAllSymbolsForTypeOf(SymbolTable.Symbol sym)
Get all symbols associated with the type of the given symbol.
|
java.util.List<SymbolTable.Symbol> |
getAllSymbolsSorted()
Get the symbols in their natural ordering.
|
SymbolTable.SymbolScope |
getEnclosingScope(Node n)
Gets the scope that contains the given node.
|
SymbolTable.SymbolScope |
getGlobalScope()
Returns the global scope.
|
private int |
getLexicalScopeDepth(SymbolTable.SymbolScope scope)
For a lexical scope, just returns the normal scope depth.
|
com.google.common.collect.Ordering<SymbolTable.Symbol> |
getNaturalSymbolOrdering()
Gets the 'natural' ordering of symbols.
|
SymbolTable.Symbol |
getParameterInFunction(SymbolTable.Symbol sym,
java.lang.String paramName)
If
sym is a function, try to find a Symbol for
a parameter with the given name. |
java.util.List<SymbolTable.Reference> |
getReferenceList(SymbolTable.Symbol symbol) |
java.lang.Iterable<SymbolTable.Reference> |
getReferences(SymbolTable.Symbol symbol) |
SymbolTable.SymbolScope |
getScope(SymbolTable.Symbol slot) |
private SymbolTable.SymbolScope |
getScopeInFunction(SymbolTable.Symbol sym) |
SymbolTable.Symbol |
getSymbolDeclaredBy(EnumType enumType)
Gets the symbol for the given enum.
|
SymbolTable.Symbol |
getSymbolDeclaredBy(FunctionType fn)
Gets the symbol for the given constructor or interface.
|
SymbolTable.Symbol |
getSymbolForInstancesOf(FunctionType fn)
Gets the symbol for the prototype of the given constructor or interface.
|
SymbolTable.Symbol |
getSymbolForInstancesOf(SymbolTable.Symbol sym)
Gets the symbol for the prototype if this is the symbol for a constructor
or interface.
|
private SymbolTable.Symbol |
getSymbolForName(Node source,
java.lang.String name) |
SymbolTable.Symbol |
getSymbolForScope(SymbolTable.SymbolScope scope)
All local scopes are associated with a function, and some functions
are associated with a symbol.
|
private SymbolTable.Symbol |
getSymbolForTypeHelper(JSType type,
boolean linkToCtor)
Gets all symbols associated with the given type.
|
private JSType |
getType(StaticSlot sym) |
private JSType |
getTypeOfThis(StaticScope s) |
private SymbolTable.Symbol |
isAnySymbolDeclared(java.lang.String name,
Node declNode,
SymbolTable.SymbolScope scope)
Checks if any symbol is already declared at the given node and scope
for the given name.
|
private boolean |
isGoodRefToAdd(StaticRef ref)
Helper for addSymbolsFrom, to determine whether a reference is
acceptable.
|
private boolean |
isTypeInferred(StaticSlot sym) |
private boolean |
needsPropertyScope(SymbolTable.Symbol sym) |
(package private) void |
pruneOrphanedNames()
Removes symbols where the namespace they're on has been removed.
|
private void |
removeSymbol(SymbolTable.Symbol s) |
java.lang.String |
toDebugString() |
private void |
toDebugString(java.lang.StringBuilder builder,
SymbolTable.Symbol symbol) |
private static final java.util.logging.Logger logger
public static final java.lang.String GLOBAL_THIS
private final com.google.common.collect.Table<Node,java.lang.String,SymbolTable.Symbol> symbols
private final java.util.Map<Node,SymbolTable.SymbolScope> scopes
private final java.util.List<Node> docInfos
private SymbolTable.SymbolScope globalScope
private final JSTypeRegistry registry
private final com.google.common.collect.Ordering<java.lang.String> sourceNameOrdering
private final com.google.common.collect.Ordering<Node> nodeOrdering
private final com.google.common.collect.Ordering<SymbolTable.SymbolScope> lexicalScopeOrdering
private final com.google.common.collect.Ordering<SymbolTable.Symbol> symbolOrdering
SymbolTable(JSTypeRegistry registry)
public java.lang.Iterable<SymbolTable.Reference> getReferences(SymbolTable.Symbol symbol)
public java.util.List<SymbolTable.Reference> getReferenceList(SymbolTable.Symbol symbol)
public java.lang.Iterable<SymbolTable.Symbol> getAllSymbols()
public java.util.List<SymbolTable.Symbol> getAllSymbolsSorted()
public com.google.common.collect.Ordering<SymbolTable.Symbol> getNaturalSymbolOrdering()
public SymbolTable.SymbolScope getScope(SymbolTable.Symbol slot)
public java.util.Collection<Node> getAllJSDocInfoNodes()
public SymbolTable.Symbol declareInferredSymbol(SymbolTable.SymbolScope scope, java.lang.String name, Node declNode)
public SymbolTable.SymbolScope getEnclosingScope(Node n)
n
is a function name, we return the scope that contains the
function, not the function itself.public SymbolTable.Symbol getParameterInFunction(SymbolTable.Symbol sym, java.lang.String paramName)
sym
is a function, try to find a Symbol for
a parameter with the given name.
Returns null if we couldn't find one.
Notice that this just makes a best effort, and may not be able
to find parameters for non-conventional function definitions.
For example, we would not be able to find "y" in this code:
var x = x() ? function(y) {} : function(y) {};
private SymbolTable.SymbolScope getScopeInFunction(SymbolTable.Symbol sym)
public SymbolTable.Symbol getSymbolForScope(SymbolTable.SymbolScope scope)
private SymbolTable.Symbol findSymbolForScope(SymbolTable.SymbolScope scope)
public java.lang.Iterable<SymbolTable.Symbol> getAllSymbolsForTypeOf(SymbolTable.Symbol sym)
public SymbolTable.SymbolScope getGlobalScope()
public SymbolTable.Symbol getSymbolDeclaredBy(FunctionType fn)
public SymbolTable.Symbol getSymbolDeclaredBy(EnumType enumType)
public SymbolTable.Symbol getSymbolForInstancesOf(SymbolTable.Symbol sym)
public SymbolTable.Symbol getSymbolForInstancesOf(FunctionType fn)
private SymbolTable.Symbol getSymbolForName(Node source, java.lang.String name)
public java.util.List<SymbolTable.Symbol> getAllSymbolsForType(JSType type)
private SymbolTable.Symbol getSymbolForTypeHelper(JSType type, boolean linkToCtor)
type
- The type.linkToCtor
- If true, we should link instance types back
to their constructor function. If false, we should link
instance types back to their prototype. See the comments
at the top of this file for more information on how
our internal type system is more granular than Symbols.public java.lang.String toDebugString()
private void toDebugString(java.lang.StringBuilder builder, SymbolTable.Symbol symbol)
<S extends StaticScope> void addScopes(java.util.Collection<S> scopes)
otherSymbolTable
are in this symbol table.void findScopes(AbstractCompiler compiler, Node externs, Node root)
public java.util.Collection<SymbolTable.SymbolScope> getAllScopes()
public void addAnonymousFunctions()
private void addAnonymousFunctionsInScope(SymbolTable.SymbolScope scope)
<S extends StaticSlot,R extends StaticRef> void addSymbolsFrom(StaticSymbolTable<S,R> otherSymbolTable)
otherSymbolTable
are in this symbol table.
Uniqueness of symbols and references is determined by the associated
node.
If multiple symbol tables are mixed in, we do not check for consistency
between symbol tables. The first symbol we see dictates the type
information for that symbol.private SymbolTable.Symbol isAnySymbolDeclared(java.lang.String name, Node declNode, SymbolTable.SymbolScope scope)
private <S extends StaticSlot,R extends StaticRef> StaticRef findBestDeclToAdd(StaticSymbolTable<S,R> otherSymbolTable, S slot)
private boolean isGoodRefToAdd(@Nullable StaticRef ref)
private SymbolTable.Symbol copySymbolTo(StaticSlot sym, SymbolTable.SymbolScope scope)
private SymbolTable.Symbol copySymbolTo(StaticSlot sym, Node declNode, SymbolTable.SymbolScope scope)
private SymbolTable.Symbol addSymbol(java.lang.String name, JSType type, boolean inferred, SymbolTable.SymbolScope scope, Node declNode)
private SymbolTable.Symbol declareSymbol(java.lang.String name, JSType type, boolean inferred, SymbolTable.SymbolScope scope, Node declNode, JSDocInfo info)
private void removeSymbol(SymbolTable.Symbol s)
void fillNamespaceReferences()
void fillPropertyScopes()
private boolean needsPropertyScope(SymbolTable.Symbol sym)
void pruneOrphanedNames()
void fillPropertySymbols(AbstractCompiler compiler, Node externs, Node root)
SymbolTable symbolTable = for("var x = new Foo();");
Symbol x = symbolTable.getGlobalScope().getSlot("x");
Symbol type = symbolTable.getAllSymbolsForType(getType(x)).get(0);
Then type.getPropertyScope() will have the properties of the
constructor "Foo". To get the properties of instances of "Foo",
you will need to call:
Symbol instance = symbolTable.getSymbolForInstancesOf(type);
As described at the top of this file, notice that "new Foo()" and
"Foo.prototype" are represented by the same symbol.void fillJSDocInfo(AbstractCompiler compiler, Node externs, Node root)
void fillSymbolVisibility(AbstractCompiler compiler, Node externs, Node root)
private void createPropertyScopeFor(SymbolTable.Symbol s)
void fillThisReferences(AbstractCompiler compiler, Node externs, Node root)
private SymbolTable.SymbolScope createScopeFrom(StaticScope otherScope)
SymbolScope
rooted at the same node. Creates one if it doesn't exist yet.private int getLexicalScopeDepth(SymbolTable.SymbolScope scope)
private JSType getType(StaticSlot sym)
private JSType getTypeOfThis(StaticScope s)
private boolean isTypeInferred(StaticSlot sym)