All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.javascript.jscomp.jsonml.JsonMLAst Maven / Gradle / Ivy

Go to download

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.

There is a newer version: v20240317
Show newest version
/*
 * 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;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy