blob: 397dacae6092de49ba471f10deac3c88a521a415 [file] [log] [blame]
/*
* Copyright 2016 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.googlejavaformat.java;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompoundAssignmentTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.IdentifierTree;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.ParenthesizedTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.TreePath;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.Pretty;
import com.sun.tools.javac.tree.TreeInfo;
import java.io.IOError;
import java.io.IOException;
import javax.lang.model.element.Name;
/** Utilities for working with {@link Tree}s. */
class Trees {
/** Returns the length of the source for the node. */
static int getLength(Tree tree, TreePath path) {
return getEndPosition(tree, path) - getStartPosition(tree);
}
/** Returns the source start position of the node. */
static int getStartPosition(Tree expression) {
return ((JCTree) expression).getStartPosition();
}
/** Returns the source end position of the node. */
static int getEndPosition(Tree expression, TreePath path) {
return ((JCTree) expression)
.getEndPosition(((JCTree.JCCompilationUnit) path.getCompilationUnit()).endPositions);
}
/** Returns the source text for the node. */
static String getSourceForNode(Tree node, TreePath path) {
CharSequence source;
try {
source = path.getCompilationUnit().getSourceFile().getCharContent(false);
} catch (IOException e) {
throw new IOError(e);
}
return source.subSequence(getStartPosition(node), getEndPosition(node, path)).toString();
}
/** Returns the simple name of a (possibly qualified) method invocation expression. */
static Name getMethodName(MethodInvocationTree methodInvocation) {
ExpressionTree select = methodInvocation.getMethodSelect();
return select instanceof MemberSelectTree
? ((MemberSelectTree) select).getIdentifier()
: ((IdentifierTree) select).getName();
}
/** Returns the receiver of a qualified method invocation expression, or {@code null}. */
static ExpressionTree getMethodReceiver(MethodInvocationTree methodInvocation) {
ExpressionTree select = methodInvocation.getMethodSelect();
return select instanceof MemberSelectTree ? ((MemberSelectTree) select).getExpression() : null;
}
/** Returns the string name of an operator, including assignment and compound assignment. */
static String operatorName(ExpressionTree expression) {
JCTree.Tag tag = ((JCTree) expression).getTag();
if (tag == JCTree.Tag.ASSIGN) {
return "=";
}
boolean assignOp = expression instanceof CompoundAssignmentTree;
if (assignOp) {
tag = tag.noAssignOp();
}
String name = new Pretty(/*writer*/ null, /*sourceOutput*/ true).operatorName(tag);
return assignOp ? name + "=" : name;
}
/** Returns the precedence of an expression's operator. */
static int precedence(ExpressionTree expression) {
return TreeInfo.opPrec(((JCTree) expression).getTag());
}
/**
* Returns the enclosing type declaration (class, enum, interface, or annotation) for the given
* path.
*/
static ClassTree getEnclosingTypeDeclaration(TreePath path) {
for (; path != null; path = path.getParentPath()) {
switch (path.getLeaf().getKind()) {
case CLASS:
case ENUM:
case INTERFACE:
case ANNOTATED_TYPE:
return (ClassTree) path.getLeaf();
default:
break;
}
}
throw new AssertionError();
}
/** Skips a single parenthesized tree. */
static ExpressionTree skipParen(ExpressionTree node) {
return ((ParenthesizedTree) node).getExpression();
}
}