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

com.google.gwt.dev.js.JsConstructExpressionVisitor Maven / Gradle / Ivy

/*
 * Copyright 2008 Google Inc.
 *
 * 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.gwt.dev.js;

import com.google.gwt.dev.js.ast.JsArrayAccess;
import com.google.gwt.dev.js.ast.JsArrayLiteral;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsExpression;
import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsInvocation;
import com.google.gwt.dev.js.ast.JsNameRef;
import com.google.gwt.dev.js.ast.JsNew;
import com.google.gwt.dev.js.ast.JsObjectLiteral;
import com.google.gwt.dev.js.ast.JsVisitable;
import com.google.gwt.dev.js.ast.JsVisitor;

/**
 * Searches for method invocations in constructor expressions that would not
 * normally be surrounded by parentheses.
 */
public class JsConstructExpressionVisitor extends JsVisitor {

  public static boolean exec(JsExpression expression) {
    if (JsPrecedenceVisitor.exec(expression) < JsPrecedenceVisitor.PRECEDENCE_NEW) {
      return true;
    }
    JsConstructExpressionVisitor visitor = new JsConstructExpressionVisitor();
    visitor.accept(expression);
    return visitor.containsInvocation;
  }

  private boolean containsInvocation = false;

  private JsConstructExpressionVisitor() {
  }

  /**
   * We only look at the array expression since the index has its own scope.
   */
  @Override
  public boolean visit(JsArrayAccess x, JsContext ctx) {
    accept(x.getArrayExpr());
    return false;
  }

  /**
   * Array literals have their own scoping.
   */
  @Override
  public boolean visit(JsArrayLiteral x, JsContext ctx) {
    return false;
  }

  /**
   * Functions have their own scoping.
   */
  @Override
  public boolean visit(JsFunction x, JsContext ctx) {
    return false;
  }

  @Override
  public boolean visit(JsInvocation x, JsContext ctx) {
    containsInvocation = true;
    return false;
  }

  @Override
  public boolean visit(JsNameRef x, JsContext ctx) {
    if (!x.isLeaf()) {
      accept(x.getQualifier());
    }
    return false;
  }

  /**
   * New constructs bind to the nearest set of parentheses.
   */
  @Override
  public boolean visit(JsNew x, JsContext ctx) {
    return false;
  }

  /**
   * Object literals have their own scope.
   */
  @Override
  public boolean visit(JsObjectLiteral x, JsContext ctx) {
    return false;
  }

  /**
   * We only look at nodes that would not normally be surrounded by parentheses.
   */
  @SuppressWarnings("cast")
  @Override
  protected  T doAccept(T node) {
    if (node instanceof JsExpression) {
      JsExpression expression = (JsExpression) node;
      int precedence = JsPrecedenceVisitor.exec(expression);
      // Only visit expressions that won't automatically be surrounded by
      // parentheses
      if (precedence < JsPrecedenceVisitor.PRECEDENCE_NEW) {
        return node;
      }
    }
    return super.doAccept(node);
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy