com.google.javascript.jscomp.jsonml.JsonMLAst Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of closure-compiler Show documentation
Show all versions of closure-compiler Show documentation
Closure Compiler is a JavaScript optimizing compiler. It parses your
JavaScript, analyzes it, removes dead code and rewrites and minimizes
what's left. It also checks syntax, variable references, and types, and
warns about common JavaScript pitfalls. It is used in many of Google's
JavaScript apps, including Gmail, Google Web Search, Google Maps, and
Google Docs.
/*
* Copyright 2010 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.jsonml;
import com.google.common.base.Preconditions;
import com.google.javascript.jscomp.AbstractCompiler;
import com.google.javascript.jscomp.AstValidator;
import com.google.javascript.jscomp.SourceAst;
import com.google.javascript.jscomp.SourceFile;
import com.google.javascript.rhino.InputId;
import com.google.javascript.rhino.Node;
import java.util.ArrayDeque;
import java.util.Deque;
/**
* Generates an AST from a JsonML source file.
*
* JsonML format for representation of JavaScript is specified
* here.
*
* @author [email protected] (Daniel Hans)
*
*/
public class JsonMLAst implements SourceAst {
private static final long serialVersionUID = 1L;
private static final String DEFAULT_SOURCE_NAME = "[[jsonmlsource]]";
/*
* Root element of JavaScript source which is represented by a JsonML tree.
* See JsonML class for more details.
*/
private JsonML jsonml;
/*
* Root node of internal JS Compiler AST which represents the same source.
* In order to get the tree, getAstRoot() has to be called.
*/
private Node root;
private final SourceFile sourceFile;
private final InputId inputId;
public JsonMLAst(JsonML jsonml) {
this.jsonml = jsonml;
this.inputId = new InputId(getSourceName());
this.sourceFile = new SourceFile(getSourceName());
}
@Override
public void clearAst() {
root = null;
}
/**
* Generates AST based on AST representation
* @see com.google.javascript.jscomp.SourceAst#getAstRoot(AbstractCompiler)
*/
@Override
public Node getAstRoot(AbstractCompiler compiler) {
if (root == null) {
createAst(compiler);
}
return root;
}
@Override
public SourceFile getSourceFile() {
return null;
}
@Override
public void setSourceFile(SourceFile file) {
throw new UnsupportedOperationException(
"JsonMLAst cannot be associated with a SourceFile instance.");
}
public String getSourceName() {
Object obj = jsonml.getAttribute(TagAttr.SOURCE);
if (obj instanceof String) {
return (String) obj;
} else {
return DEFAULT_SOURCE_NAME;
}
}
private void createAst(AbstractCompiler compiler) {
Reader translator = new Reader();
translator.setRootElement(jsonml);
try {
root = translator.parse(compiler);
root.setInputId(inputId);
root.setStaticSourceFile(sourceFile);
new AstValidator().validateScript(root);
} catch (JsonMLException e) {
// compiler should already have JSErrors
}
}
public JsonML convertToJsonML () {
if (root != null) {
Writer converter = new Writer();
return converter.processAst(root);
}
return null;
}
/**
* Returns a JsonML element with the specified number from the tree in
* pre-order walk.
*
* @return nth node or null if the node does not exists
*/
public JsonML getElementPreOrder(int n) {
Preconditions.checkState(jsonml != null);
if (n == 0) {
return jsonml;
}
Deque stack =
new ArrayDeque();
stack.push(new WalkHelper(jsonml, 0));
int i = 0;
while (i <= n && !stack.isEmpty()) {
WalkHelper current = stack.pop();
JsonML element = current.element;
Integer childno = current.childno;
// not all the children of this node have been visited
if (childno < element.childrenSize()) {
stack.push(new WalkHelper(element, childno + 1));
// we visit the next child
i++;
element = element.getChild(childno);
if (i == n) {
return element;
}
// put the next child on the stack to preserve pre-order
stack.push(new WalkHelper(element, 0));
}
}
return null;
}
/*
* Represents a walk step while the JsonML tree is traversed.
*/
private static class WalkHelper {
// JsonML element that corresponds to this step
final JsonML element;
// number of children of the element which has already been visited
final int childno;
WalkHelper(JsonML element, int childno) {
this.element = element;
this.childno = childno;
}
}
@Override
public InputId getInputId() {
return inputId;
}
}