@GwtIncompatible(value="JsMessage, java.util.regex") public abstract class JsMessageVisitor extends NodeTraversal.AbstractPostOrderCallback implements CompilerPass
processJsMessage(JsMessage, JsMessageDefinition)
.Modifier and Type | Class and Description |
---|---|
(package private) static class |
JsMessageVisitor.MalformedException |
private static class |
JsMessageVisitor.MessageLocation |
Modifier and Type | Field and Description |
---|---|
(package private) static DiagnosticType |
BAD_FALLBACK_SYNTAX |
private static Pattern |
CAMELCASE_PATTERN |
private CheckLevel |
checkLevel |
(package private) AbstractCompiler |
compiler |
private static java.lang.String |
DESC_SUFFIX |
(package private) static DiagnosticType |
FALLBACK_ARG_ERROR |
private java.util.Set<Node> |
googMsgNodes
List of found goog.getMsg call nodes.
|
(package private) static java.lang.String |
HIDDEN_DESC_PREFIX |
private JsMessage.IdGenerator |
idGenerator |
(package private) static DiagnosticType |
MESSAGE_DUPLICATE_KEY |
(package private) static DiagnosticType |
MESSAGE_HAS_NO_DESCRIPTION |
(package private) static DiagnosticType |
MESSAGE_HAS_NO_TEXT |
(package private) static DiagnosticType |
MESSAGE_HAS_NO_VALUE |
(package private) static DiagnosticType |
MESSAGE_NODE_IS_ORPHANED |
(package private) static DiagnosticType |
MESSAGE_NOT_INITIALIZED_USING_NEW_SYNTAX |
(package private) static DiagnosticType |
MESSAGE_TREE_MALFORMED |
private java.util.Map<java.lang.String,JsMessageVisitor.MessageLocation> |
messageNames
The names encountered associated with their defining node and source.
|
private static java.lang.String |
MSG_FALLBACK_FUNCTION_NAME |
private static java.lang.String |
MSG_FUNCTION_NAME |
(package private) static java.lang.String |
MSG_PREFIX |
private static Pattern |
MSG_UNNAMED_PATTERN
Pattern for unnamed messages.
|
private boolean |
needToCheckDuplications |
private static java.lang.String |
PH_JS_PREFIX |
private static java.lang.String |
PH_JS_SUFFIX |
private JsMessage.Style |
style |
private java.util.Map<Var,JsMessage> |
unnamedMessages |
Modifier | Constructor and Description |
---|---|
protected |
JsMessageVisitor(AbstractCompiler compiler,
boolean needToCheckDuplications,
JsMessage.Style style,
JsMessage.IdGenerator idGenerator)
Creates JS message visitor.
|
Modifier and Type | Method and Description |
---|---|
private void |
checkIfMessageDuplicated(java.lang.String msgName,
Node msgNode)
Checks if message already processed.
|
protected void |
checkNode(Node node,
int type)
Checks a node's type.
|
private void |
extractFromCallNode(JsMessage.Builder builder,
Node node)
Initializes a message builder from a CALL node.
|
private void |
extractFromFunctionNode(JsMessage.Builder builder,
Node node)
Initializes a message builder from a FUNCTION node.
|
private static void |
extractFromReturnDescendant(JsMessage.Builder builder,
Node node)
Appends value parts to the message builder by traversing the descendants
of the given RETURN node.
|
private void |
extractMessageFrom(JsMessage.Builder builder,
Node valueNode,
Node docNode)
Creates a
JsMessage for a JS message defined using an assignment to
a qualified name (e.g a.b.MSG_X = goog.getMsg(...); ). |
private void |
extractMessageFromVariable(JsMessage.Builder builder,
Node nameNode,
Node parentNode,
Node grandParentNode)
Creates a
JsMessage for a JS message defined using a JS variable
declaration (e.g var MSG_X = ...; ). |
private static java.lang.String |
extractStringFromStringExprNode(Node node)
Returns the string value associated with a node representing a JS string or
several JS strings added together (e.g.
|
private static java.lang.String |
getReadableTokenName(Node node)
Returns human-readable name of the given node's type.
|
private JsMessage |
getTrackedMessage(NodeTraversal t,
java.lang.String msgName)
Get a previously tracked message.
|
(package private) static boolean |
isLowerCamelCaseWithNumericSuffixes(java.lang.String input)
Returns whether a string is nonempty, begins with a lowercase letter, and
contains only digits and underscores after the first underscore.
|
(package private) boolean |
isMessageName(java.lang.String identifier,
boolean isNewStyleMessage)
Returns whether the given JS identifier is a valid JS message name.
|
private static boolean |
isUnnamedMessageName(java.lang.String identifier)
Returns whether the given message name is in the unnamed namespace.
|
private static boolean |
maybeInitMetaDataFromHelpVar(JsMessage.Builder builder,
Node sibling)
Initializes the meta data in a JsMessage by examining a node just before or
after a message VAR node.
|
private static boolean |
maybeInitMetaDataFromJsDoc(JsMessage.Builder builder,
Node node)
Initializes the meta data in a message builder given a node that may
contain JsDoc properties.
|
private void |
maybeInitMetaDataFromJsDocOrHelpVar(JsMessage.Builder builder,
Node varNode,
Node parentOfVarNode)
Initializes the meta data in a JsMessage by examining the nodes just before
and after a message VAR node.
|
private static void |
parseMessageTextNode(JsMessage.Builder builder,
Node node)
Appends the message parts in a JS message value extracted from the given
text node.
|
void |
process(Node externs,
Node root)
Process the JS with root node root.
|
protected abstract void |
processJsMessage(JsMessage message,
JsMessageDefinition definition)
Processes found JS message.
|
(package private) void |
processMessageFallback(Node callNode,
JsMessage message1,
JsMessage message2)
Processes the goog.getMsgWithFallback primitive.
|
(package private) static java.lang.String |
toLowerCamelCaseWithNumericSuffixes(java.lang.String input)
Converts the given string from upper-underscore case to lower-camel case,
preserving numeric suffixes.
|
private void |
trackMessage(NodeTraversal t,
JsMessage message,
java.lang.String msgName,
Node msgNode,
boolean isUnnamedMessage)
Track a message for later retrieval.
|
void |
visit(NodeTraversal traversal,
Node node,
Node parent)
Visits a node in postorder (after its children have been visited).
|
private void |
visitFallbackFunctionCall(NodeTraversal t,
Node call)
Visit a call to goog.getMsgWithFallback.
|
shouldTraverse
private static final java.lang.String MSG_FUNCTION_NAME
private static final java.lang.String MSG_FALLBACK_FUNCTION_NAME
static final DiagnosticType MESSAGE_HAS_NO_DESCRIPTION
static final DiagnosticType MESSAGE_HAS_NO_TEXT
static final DiagnosticType MESSAGE_TREE_MALFORMED
static final DiagnosticType MESSAGE_HAS_NO_VALUE
static final DiagnosticType MESSAGE_DUPLICATE_KEY
static final DiagnosticType MESSAGE_NODE_IS_ORPHANED
static final DiagnosticType MESSAGE_NOT_INITIALIZED_USING_NEW_SYNTAX
static final DiagnosticType BAD_FALLBACK_SYNTAX
static final DiagnosticType FALLBACK_ARG_ERROR
private static final java.lang.String PH_JS_PREFIX
private static final java.lang.String PH_JS_SUFFIX
static final java.lang.String MSG_PREFIX
private static final Pattern MSG_UNNAMED_PATTERN
All JS messages in JS code should have unique name but messages in generated code (i.e. from soy template) could have duplicated message names. Later we replace the message names with ids constructed as a hash of the message content.
Soy generates messages with names MSG_UNNAMED_
private static final Pattern CAMELCASE_PATTERN
static final java.lang.String HIDDEN_DESC_PREFIX
private static final java.lang.String DESC_SUFFIX
private final boolean needToCheckDuplications
private final JsMessage.Style style
private final JsMessage.IdGenerator idGenerator
final AbstractCompiler compiler
private final java.util.Map<java.lang.String,JsMessageVisitor.MessageLocation> messageNames
private final java.util.Set<Node> googMsgNodes
private final CheckLevel checkLevel
protected JsMessageVisitor(AbstractCompiler compiler, boolean needToCheckDuplications, JsMessage.Style style, JsMessage.IdGenerator idGenerator)
compiler
- the compiler instanceneedToCheckDuplications
- whether to check duplicated messages in
traversedstyle
- style that should be used during parsingidGenerator
- generator that used for creating unique ID for the
messagepublic void process(Node externs, Node root)
CompilerPass
process
in interface CompilerPass
externs
- Top of external JS treeroot
- Top of JS treepublic void visit(NodeTraversal traversal, Node node, Node parent)
NodeTraversal.Callback
Visits a node in postorder (after its children have been visited).
A node is visited only if all its parents should be traversed
(NodeTraversal.Callback.shouldTraverse(NodeTraversal, Node, Node)
).
Implementations can have side effects (e.g. modifying the parse tree).
visit
in interface NodeTraversal.Callback
private void trackMessage(NodeTraversal t, JsMessage message, java.lang.String msgName, Node msgNode, boolean isUnnamedMessage)
private JsMessage getTrackedMessage(NodeTraversal t, java.lang.String msgName)
private void checkIfMessageDuplicated(java.lang.String msgName, Node msgNode)
msgName
- the name of the messagemsgNode
- the node that represents JS messageprivate void extractMessageFromVariable(JsMessage.Builder builder, Node nameNode, Node parentNode, @Nullable Node grandParentNode) throws JsMessageVisitor.MalformedException
JsMessage
for a JS message defined using a JS variable
declaration (e.g var MSG_X = ...;
).builder
- the message buildernameNode
- a NAME node for a JS message variableparentNode
- a VAR node, parent of nameNode
grandParentNode
- the grandparent of nameNode
. This node is
only used to get meta data about the message that might be
surrounding it (e.g. a message description). This argument may be
null if the meta data is not needed.JsMessageVisitor.MalformedException
- if varNode
does not
correspond to a valid JS message VAR nodeprivate void extractMessageFrom(JsMessage.Builder builder, Node valueNode, Node docNode) throws JsMessageVisitor.MalformedException
JsMessage
for a JS message defined using an assignment to
a qualified name (e.g a.b.MSG_X = goog.getMsg(...);
).builder
- the message buildervalueNode
- a node in a JS message valuedocNode
- the node containing the jsdoc.JsMessageVisitor.MalformedException
- if getPropNode
does not
correspond to a valid JS message nodeprivate void maybeInitMetaDataFromJsDocOrHelpVar(JsMessage.Builder builder, Node varNode, @Nullable Node parentOfVarNode) throws JsMessageVisitor.MalformedException
builder
- the message builder whose meta data will be initializedvarNode
- the message VAR nodeparentOfVarNode
- varNode
's parent nodeJsMessageVisitor.MalformedException
private static boolean maybeInitMetaDataFromHelpVar(JsMessage.Builder builder, @Nullable Node sibling) throws JsMessageVisitor.MalformedException
builder
- the message builder whose meta data will be initializedsibling
- a node adjacent to the message VAR nodeJsMessageVisitor.MalformedException
private static boolean maybeInitMetaDataFromJsDoc(JsMessage.Builder builder, Node node)
builder
- the message builder whose meta data will be initializednode
- the node with the message's JSDoc propertiesprivate static java.lang.String extractStringFromStringExprNode(Node node) throws JsMessageVisitor.MalformedException
'str'
or 's' + 't' +
'r'
).node
- the node from where we extract the stringJsMessageVisitor.MalformedException
- if the parsed message is invalidprivate void extractFromFunctionNode(JsMessage.Builder builder, Node node) throws JsMessageVisitor.MalformedException
The tree should look something like: function |-- name |-- lp | |-- name| -- name -- block | --return | --add |-- string foo -- name
builder
- the message buildernode
- the function node that contains a messageJsMessageVisitor.MalformedException
- if the parsed message is invalidprivate static void extractFromReturnDescendant(JsMessage.Builder builder, Node node) throws JsMessageVisitor.MalformedException
builder
- the message buildernode
- the node from where we extract a messageJsMessageVisitor.MalformedException
- if the parsed message is invalidprivate void extractFromCallNode(JsMessage.Builder builder, Node node) throws JsMessageVisitor.MalformedException
The tree should look something like:
call |-- getprop | |-- name 'goog' | +-- string 'getMsg' | |-- string 'Hi {$userName}! Welcome to {$product}.' +-- objlit |-- string 'userName' |-- name 'someUserName' |-- string 'product' +-- call +-- name 'getProductName'
builder
- the message buildernode
- the call node from where we extract the messageJsMessageVisitor.MalformedException
- if the parsed message is invalidprivate static void parseMessageTextNode(JsMessage.Builder builder, Node node) throws JsMessageVisitor.MalformedException
builder
- the JS message builder to append parts tonode
- the node with string literal that contains the message textJsMessageVisitor.MalformedException
- if value
contains a reference to
an unregistered placeholderprivate void visitFallbackFunctionCall(NodeTraversal t, Node call)
protected abstract void processJsMessage(JsMessage message, JsMessageDefinition definition)
message
- the found messagedefinition
- the definition of the object and usually contains all
additional message information like message node/parent's nodevoid processMessageFallback(Node callNode, JsMessage message1, JsMessage message2)
boolean isMessageName(java.lang.String identifier, boolean isNewStyleMessage)
private static boolean isUnnamedMessageName(java.lang.String identifier)
static boolean isLowerCamelCaseWithNumericSuffixes(java.lang.String input)
private static java.lang.String getReadableTokenName(Node node)
static java.lang.String toLowerCamelCaseWithNumericSuffixes(java.lang.String input)
protected void checkNode(@Nullable Node node, int type) throws JsMessageVisitor.MalformedException
JsMessageVisitor.MalformedException
- if the node is null or the wrong type