Package com.orange.wink.ast

Source Code of com.orange.wink.ast.AstNode

/*--------------------------------------------------------
* Copyright (c) 2011, The Dojo Foundation
* This software is distributed under the "Simplified BSD license",
* the text of which is available at http://www.winktoolkit.org/licence.txt
* or see the "license.txt" file for more details.
*--------------------------------------------------------*/

/**
*
*/
package com.orange.wink.ast;

import java.io.File;
import java.util.List;

import org.mozilla.javascript.FunctionNode;
import org.mozilla.javascript.Node;
import org.mozilla.javascript.ScriptOrFnNode;
import org.mozilla.javascript.Token;

import com.orange.wink.Constants;
import com.orange.wink.exception.WinkAstException;
import com.orange.wink.util.Common;

/**
* @author Sylvain Lalande
*
*/
public class AstNode {
  /**
   *
   */
  private final Node node;
  /**
   *
   */
  private List<AstNode> childs;
  /**
   *
   */
  private final AstNode parent;
  /**
   *
   */
  private AstNode scope;
  /**
   *
   */
  private AstNode parentScope;
  /**
   *
   */
  private boolean isScriptOrFn = false;
  /**
   *
   */
  private boolean isScript = false;
  /**
   *
   */
  private boolean isFunction = false;
  /**
   *
   */
  private final boolean isLiteral = false;
  /**
   *
   */
  private boolean isRoot = false;
  /**
   *
   */
  private int depth;
  /**
   *
   */
  private List<String> parameters;
  /**
   *
   */
  private List<String> localVars;
  /**
   *
   */
  private List<String> objectIds;
  /**
   *
   */
  private int lineStart = -1;
  /**
   *
   */
  private int lineEnd = -1;
  /**
   *
   */
  private final int type;

  /**
   * @param node
   */
  public AstNode(final Node node, final AstNode parent) {
    this.node = node;
    this.parent = parent;
    type = node.getType();

    if (parent == null) {
      isRoot = true;
      depth = 0;
    } else {
      depth = parent.getDepth() + 1;
    }

    if (!isRoot) {
      lineStart = parent.getLineStart();
    }
    if (node.getLineno() > lineStart) {
      lineStart = node.getLineno();
    }

    if (node instanceof ScriptOrFnNode) {
      final ScriptOrFnNode sfn = (ScriptOrFnNode) node;
      isScriptOrFn = true;
      scope = this;
      if (!isRoot) {
        parentScope = parent.getScope();
      }
      parameters = getParams(sfn);
      localVars = getLocalVars(sfn);
      lineStart = sfn.getBaseLineno();
      lineEnd = sfn.getEndLineno();
    } else {
      scope = parent.getScope();
      parentScope = scope.getScope();
    }
    if (type == Token.SCRIPT) {
      isScript = true;
    }
    if (type == Token.FUNCTION) {
      isFunction = true;
    }
    if (type == Token.OBJECTLIT) {
      objectIds = Common.newArrayList(1);
      final Object[] props = (Object[]) node.getProp(Node.OBJECT_IDS_PROP);
      for (final Object p : props) {
        final String pName = (String) p;
        objectIds.add(pName);
      }
      Common.trimList(objectIds);
      if (objectIds.size() == 0) {
        objectIds = null;
      }
    }
    childs = Common.newArrayList(1);

    if (lineStart == -1) {
      System.err.println("WARN - Ast Node without line number : " + this);
    }
  }

  /**
   *
   */
  public void expand() throws WinkAstException {
    final List<Node> nodeChilds = getChilds(node);

    if (type == Token.OBJECTLIT) {
      List<String> oids = objectIds;
      if (oids == null) {
        oids = Common.newArrayList(0);
      }
      if (oids.size() != nodeChilds.size()) {
        throw new WinkAstException("OBJECTLIT Node: props and childs count are not equal");
      }
    }

    for (final Node c : nodeChilds) {
      Node cidentified = c;
      if (c.getType() == Token.FUNCTION) {
        final int fnIndex = c.getExistingIntProp(Node.FUNCTION_PROP);
        cidentified = scope.getAsScriptOrFn().getFunctionNode(fnIndex);
      }

      final AstNode child = new AstNode(cidentified, this);
      childs.add(child);
      child.expand();
    }
    Common.trimList(childs);
    if (childs.size() == 0) {
      childs = null;
    }
  }

  /**
   * @return
   */
  public String getFunctionName() {
    String identifier = null;
    if (isFunction) {
      FunctionNode n = null;
      try {
        n = getAsFunctionNode();
      } catch (final WinkAstException e) {
        e.printStackTrace();
        return null;
      }
      if (n.getFunctionName() != null && n.getFunctionName() != "") {
        identifier = n.getFunctionName();
      }
      if (identifier == null) {
        final StringBuffer sb = new StringBuffer();
        sb.append(Constants.ANONYMOUS_FUNCTION_PREFIX);
        sb.append("-");
        sb.append(new File(n.getSourceName()).getName());
        sb.append("[");
        sb.append(lineStart);
        sb.append(",");
        sb.append(lineEnd);
        sb.append("]");
        identifier = sb.toString();
      }
    }
    return identifier;
  }

  /**
   * @return
   * @throws WinkAstException
   */
  public ScriptOrFnNode getAsScriptOrFn() throws WinkAstException {
    if (isScriptOrFn) {
      return (ScriptOrFnNode) node;
    } else {
      throw new WinkAstException("Cannot invoke getAsScriptOrFn : not a ScriptOrFnNode");
    }
  }

  /**
   * @return
   * @throws WinkAstException
   */
  public FunctionNode getAsFunctionNode() throws WinkAstException {
    if (isFunction) {
      return (FunctionNode) node;
    } else {
      throw new WinkAstException("Cannot invoke getAsFunctionNode : not a FunctionNode");
    }
  }

  /**
   * @see java.lang.Object#equals(java.lang.Object)
   */
  @Override
  public boolean equals(final Object obj) {
    if (!(obj instanceof AstNode)) {
      return false;
    }
    return ((AstNode) obj).getNode() == node;
  }

  /**
   * @return
   */
  public String asString() {
    if (type == Token.NUMBER) {
      return String.valueOf(node.getDouble());
    }
    return node.getString();
  }

  /**
   * @see java.lang.Object#toString()
   */
  @Override
  public String toString() {
    final StringBuffer sb = new StringBuffer();

    if (isRoot) {
      sb.append("ROOT - ");
    }
    sb.append(Ast.tokenName(type));

    if (type == Token.NAME || type == Token.STRING || type == Token.GETVAR || type == Token.NUMBER || type == Token.BINDNAME) {
      sb.append(" ").append(asString());
    }

    if (parameters != null && parameters.size() > 0) {
      sb.append(" (");
      for (int i = 0; i < parameters.size(); i++) {
        sb.append(parameters.get(i));
        if (i < parameters.size() - 1) {
          sb.append(", ");
        }
      }
      sb.append(")");
    }
    if (localVars != null && localVars.size() > 0) {
      sb.append(" [");
      for (int i = 0; i < localVars.size(); i++) {
        sb.append(localVars.get(i));
        if (i < localVars.size() - 1) {
          sb.append(", ");
        }
      }
      sb.append("]");
    }
    if (objectIds != null && objectIds.size() > 0) {
      sb.append(" [");
      for (int i = 0; i < objectIds.size(); i++) {
        sb.append(objectIds.get(i));
        if (i < objectIds.size() - 1) {
          sb.append(", ");
        }
      }
      sb.append("]");
    }

    if (isScript) {
      final ScriptOrFnNode sfn = (ScriptOrFnNode) node;
      final String sourceName = sfn.getSourceName();
      if (sourceName != null) {
        final String[] sp = sourceName.split("/");
        sb.append(" |").append(sp[sp.length - 1]).append("| ");
      }
    }

    if (isScriptOrFn || isLiteral) {
      final String ls = (lineStart == -1) ? "?" : new Integer(lineStart).toString();
      final String le = (lineEnd == -1) ? "?" : new Integer(lineEnd).toString();
      sb.append(" [L:").append(ls).append(" - ").append(le).append("]");
    }

    if (isFunction) {
      FunctionNode n = null;
      try {
        n = getAsFunctionNode();
      } catch (final WinkAstException e) {
        e.printStackTrace();
      }
      sb.append(" [").append(Ast.functionTypeName(n.getFunctionType())).append("]");
    }

    return sb.toString();
  }

  /**
   * @param n
   * @return
   */
  private List<Node> getChilds(final Node n) {
    final List<Node> nodes = Common.newArrayList(1);
    for (Node child = n.getFirstChild(); child != null; child = child.getNext()) {
      nodes.add(child);
    }
    Common.trimList(nodes);
    return nodes;
  }

  /**
   * @param n
   * @return
   */
  private List<String> getParams(final ScriptOrFnNode n) {
    final List<String> params = Common.newArrayList(1);
    final int pvc = n.getParamAndVarCount();
    if (pvc > 0) {
      final int pc = n.getParamCount();
      final String[] pvn = n.getParamAndVarNames();
      for (int i = 0; i < pvn.length; i++) {
        if (i < pc) {
          params.add(pvn[i]);
        }
      }
    }
    Common.trimList(params);
    if (params.size() == 0) {
      return null;
    }
    return params;
  }

  /**
   * @param n
   * @return
   */
  private List<String> getLocalVars(final ScriptOrFnNode n) {
    final List<String> vars = Common.newArrayList(1);
    final int pvc = n.getParamAndVarCount();
    if (pvc > 0) {
      final int pc = n.getParamCount();
      final String[] pvn = n.getParamAndVarNames();
      for (int i = 0; i < pvn.length; i++) {
        if (i >= pc) {
          vars.add(pvn[i]);
        }
      }
    }
    Common.trimList(vars);
    if (vars.size() == 0) {
      return null;
    }
    return vars;
  }

  /**
   * @return the node
   */
  public Node getNode() {
    return node;
  }

  /**
   * @return the parent
   */
  public AstNode getParent() {
    return parent;
  }

  /**
   * @return the isScriptOrFn
   */
  public boolean isScriptOrFn() {
    return isScriptOrFn;
  }

  /**
   * @return the isScript
   */
  public boolean isScript() {
    return isScript;
  }

  /**
   * @return the isFunction
   */
  public boolean isFunction() {
    return isFunction;
  }

  /**
   * @return the isLiteral
   */
  public boolean isLiteral() {
    return isLiteral;
  }

  /**
   * @return the isRoot
   */
  public boolean isRoot() {
    return isRoot;
  }

  /**
   * @return the scope
   */
  public AstNode getScope() {
    return scope;
  }

  /**
   * @return the parentScope
   */
  public AstNode getParentScope() {
    return parentScope;
  }

  /**
   * @return the depth
   */
  public int getDepth() {
    return depth;
  }

  /**
   * @return the parameters
   */
  public List<String> getParameters() {
    if (parameters == null) {
      return Common.newArrayList(0);
    }
    return parameters;
  }

  /**
   * @return the localVars
   */
  public List<String> getLocalVars() {
    if (localVars == null) {
      return Common.newArrayList(0);
    }
    return localVars;
  }

  /**
   * @return the childs
   */
  public List<AstNode> getChilds() {
    if (childs == null) {
      return Common.newArrayList(0);
    }
    return childs;
  }

  /**
   * @return the lineStart
   */
  public int getLineStart() {
    return lineStart;
  }

  /**
   * @param lineStart
   *            the lineStart to set
   */
  public void setLineStart(final int lineStart) {
    this.lineStart = lineStart;
  }

  /**
   * @return the lineEnd
   */
  public int getLineEnd() {
    return lineEnd;
  }

  /**
   * @param lineEnd
   *            the lineEnd to set
   */
  public void setLineEnd(final int lineEnd) {
    this.lineEnd = lineEnd;
  }

  /**
   * @return the objectIds
   */
  public List<String> getObjectIds() {
    return objectIds;
  }

  /**
   * @return the type
   */
  public int getType() {
    return type;
  }
}
TOP

Related Classes of com.orange.wink.ast.AstNode

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.