Search in sources :

Example 16 with JCMethodInvocation

use of com.sun.tools.javac.tree.JCTree.JCMethodInvocation in project checker-framework by typetools.

the class TreeUtils method constructor.

/**
 * Determines the symbol for a constructor given an invocation via {@code new}.
 *
 * <p>If the tree is a declaration of an anonymous class, then method returns constructor that
 * gets invoked in the extended class, rather than the anonymous constructor implicitly added by
 * the constructor (JLS 15.9.5.1)
 *
 * @see #elementFromUse(NewClassTree)
 * @param tree the constructor invocation
 * @return the {@link ExecutableElement} corresponding to the constructor call in {@code tree}
 */
public static ExecutableElement constructor(NewClassTree tree) {
    if (!(tree instanceof JCTree.JCNewClass)) {
        ErrorReporter.errorAbort("InternalUtils.constructor: not a javac internal tree");
        // dead code
        return null;
    }
    JCNewClass newClassTree = (JCNewClass) tree;
    if (tree.getClassBody() != null) {
        // anonymous constructor bodies should contain exactly one statement
        // in the form:
        // super(arg1, ...)
        // or
        // o.super(arg1, ...)
        // 
        // which is a method invocation (!) to the actual constructor
        // the method call is guaranteed to return nonnull
        JCMethodDecl anonConstructor = (JCMethodDecl) TreeInfo.declarationFor(newClassTree.constructor, newClassTree);
        assert anonConstructor != null;
        assert anonConstructor.body.stats.size() == 1;
        JCExpressionStatement stmt = (JCExpressionStatement) anonConstructor.body.stats.head;
        JCTree.JCMethodInvocation superInvok = (JCMethodInvocation) stmt.expr;
        return (ExecutableElement) TreeInfo.symbol(superInvok.meth);
    } else {
        Element e = newClassTree.constructor;
        return (ExecutableElement) e;
    }
}
Also used : JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) JCMethodDecl(com.sun.tools.javac.tree.JCTree.JCMethodDecl) ExecutableElement(javax.lang.model.element.ExecutableElement) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass) JCTree(com.sun.tools.javac.tree.JCTree) JCExpressionStatement(com.sun.tools.javac.tree.JCTree.JCExpressionStatement) JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation)

Example 17 with JCMethodInvocation

use of com.sun.tools.javac.tree.JCTree.JCMethodInvocation in project checker-framework by typetools.

the class DefaultReflectionResolver method resolveReflectiveMethod.

/**
 * Resolves a reflective method call and returns all possible corresponding method calls.
 *
 * @param tree the MethodInvocationTree node that is to be resolved (Method.invoke)
 * @return a (potentially empty) list of all resolved MethodInvocationTrees
 */
private List<MethodInvocationTree> resolveReflectiveMethod(MethodInvocationTree tree, AnnotatedTypeFactory reflectionFactory) {
    assert isReflectiveMethodInvocation(tree);
    JCMethodInvocation methodInvocation = (JCMethodInvocation) tree;
    Context context = ((JavacProcessingEnvironment) processingEnv).getContext();
    TreeMaker make = TreeMaker.instance(context);
    TreePath path = reflectionFactory.getPath(tree);
    JavacScope scope = (JavacScope) trees.getScope(path);
    Env<AttrContext> env = scope.getEnv();
    List<MethodInvocationTree> methods = new ArrayList<>();
    boolean unknown = isUnknownMethod(tree);
    AnnotationMirror estimate = getMethodVal(tree);
    if (estimate == null) {
        debugReflection("MethodVal is unknown for: " + tree);
        debugReflection("UnknownMethod annotation: " + unknown);
        return methods;
    }
    debugReflection("MethodVal type system annotations: " + estimate);
    List<String> listClassNames = AnnotationUtils.getElementValueArray(estimate, "className", String.class, true);
    List<String> listMethodNames = AnnotationUtils.getElementValueArray(estimate, "methodName", String.class, true);
    List<Integer> listParamLenghts = AnnotationUtils.getElementValueArray(estimate, "params", Integer.class, true);
    assert listClassNames.size() == listMethodNames.size() && listClassNames.size() == listParamLenghts.size();
    for (int i = 0; i < listClassNames.size(); ++i) {
        String className = listClassNames.get(i);
        String methodName = listMethodNames.get(i);
        int paramLength = listParamLenghts.get(i);
        // Get receiver, which is always the first argument of the invoke
        // method
        JCExpression receiver = methodInvocation.args.head;
        // The remaining list contains the arguments
        com.sun.tools.javac.util.List<JCExpression> args = methodInvocation.args.tail;
        // Resolve the Symbol(s) for the current method
        for (Symbol symbol : getMethodSymbolsfor(className, methodName, paramLength, env)) {
            if ((symbol.flags() & Flags.PUBLIC) > 0) {
                debugReflection("Resolved public method: " + symbol.owner + "." + symbol);
            } else {
                debugReflection("Resolved non-public method: " + symbol.owner + "." + symbol);
            }
            JCExpression method = make.Select(receiver, symbol);
            args = getCorrectedArgs(symbol, args);
            // Build method invocation tree depending on the number of
            // parameters
            JCMethodInvocation syntTree = paramLength > 0 ? make.App(method, args) : make.App(method);
            // add method invocation tree to the list of possible methods
            methods.add(syntTree);
        }
    }
    return methods;
}
Also used : Context(com.sun.tools.javac.util.Context) AttrContext(com.sun.tools.javac.comp.AttrContext) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) Symbol(com.sun.tools.javac.code.Symbol) ArrayList(java.util.ArrayList) JavacScope(com.sun.tools.javac.api.JavacScope) AttrContext(com.sun.tools.javac.comp.AttrContext) JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) AnnotationMirror(javax.lang.model.element.AnnotationMirror) TreeMaker(com.sun.tools.javac.tree.TreeMaker) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) TreePath(com.sun.source.util.TreePath) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) JavacProcessingEnvironment(com.sun.tools.javac.processing.JavacProcessingEnvironment)

Example 18 with JCMethodInvocation

use of com.sun.tools.javac.tree.JCTree.JCMethodInvocation in project checker-framework by typetools.

the class DefaultReflectionResolver method resolveReflectiveConstructor.

/**
 * Resolves a reflective constructor call and returns all possible corresponding constructor
 * calls.
 *
 * @param tree the MethodInvocationTree node that is to be resolved (Constructor.newInstance)
 * @return a (potentially empty) list of all resolved MethodInvocationTrees
 */
private List<JCNewClass> resolveReflectiveConstructor(MethodInvocationTree tree, AnnotatedTypeFactory reflectionFactory) {
    assert isReflectiveMethodInvocation(tree);
    JCMethodInvocation methodInvocation = (JCMethodInvocation) tree;
    Context context = ((JavacProcessingEnvironment) processingEnv).getContext();
    TreeMaker make = TreeMaker.instance(context);
    TreePath path = reflectionFactory.getPath(tree);
    JavacScope scope = (JavacScope) trees.getScope(path);
    Env<AttrContext> env = scope.getEnv();
    List<JCNewClass> constructors = new ArrayList<>();
    AnnotationMirror estimate = getMethodVal(tree);
    if (estimate == null) {
        debugReflection("MethodVal is unknown for: " + tree);
        debugReflection("UnknownMethod annotation: " + isUnknownMethod(tree));
        return constructors;
    }
    debugReflection("MethodVal type system annotations: " + estimate);
    List<String> listClassNames = AnnotationUtils.getElementValueArray(estimate, "className", String.class, true);
    List<Integer> listParamLenghts = AnnotationUtils.getElementValueArray(estimate, "params", Integer.class, true);
    assert listClassNames.size() == listParamLenghts.size();
    for (int i = 0; i < listClassNames.size(); ++i) {
        String className = listClassNames.get(i);
        int paramLength = listParamLenghts.get(i);
        // Resolve the Symbol for the current constructor
        for (Symbol symbol : getConstructorSymbolsfor(className, paramLength, env)) {
            debugReflection("Resolved constructor: " + symbol.owner + "." + symbol);
            JCNewClass syntTree = (JCNewClass) make.Create(symbol, methodInvocation.args);
            // add constructor invocation tree to the list of possible
            // constructors
            constructors.add(syntTree);
        }
    }
    return constructors;
}
Also used : Context(com.sun.tools.javac.util.Context) AttrContext(com.sun.tools.javac.comp.AttrContext) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) Symbol(com.sun.tools.javac.code.Symbol) ArrayList(java.util.ArrayList) JavacScope(com.sun.tools.javac.api.JavacScope) AttrContext(com.sun.tools.javac.comp.AttrContext) JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) AnnotationMirror(javax.lang.model.element.AnnotationMirror) TreeMaker(com.sun.tools.javac.tree.TreeMaker) TreePath(com.sun.source.util.TreePath) JavacProcessingEnvironment(com.sun.tools.javac.processing.JavacProcessingEnvironment) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass)

Example 19 with JCMethodInvocation

use of com.sun.tools.javac.tree.JCTree.JCMethodInvocation in project st-js by st-js.

the class InternalUtils method constructor.

/**
 * Determines the symbol for a constructor given an invocation via {@code new}. If the tree is a declaration of an
 * anonymous class, then method returns constructor that gets invoked in the extended class, rather than the
 * anonymous constructor implicitly added by the constructor (JLS 15.9.5.1)
 *
 * @param tree
 *            the constructor invocation
 * @return the {@link javax.lang.model.element.ExecutableElement} corresponding to the constructor call in
 *         {@code tree}
 */
public static ExecutableElement constructor(NewClassTree tree) {
    if (!(tree instanceof JCTree.JCNewClass)) {
        ErrorReporter.errorAbort("InternalUtils.constructor: not a javac internal tree");
        // dead code
        return null;
    }
    JCNewClass newClassTree = (JCNewClass) tree;
    if (RETURN_INVOKE_CONSTRUCTOR && tree.getClassBody() != null) {
        // anonymous constructor bodies should contain exactly one statement
        // in the form:
        // super(arg1, ...)
        // or
        // o.super(arg1, ...)
        // 
        // which is a method invocation (!) to the actual constructor
        // the method call is guaranteed to return nonnull
        JCMethodDecl anonConstructor = (JCMethodDecl) TreeInfo.declarationFor(newClassTree.constructor, newClassTree);
        assert anonConstructor != null;
        assert anonConstructor.body.stats.size() == 1;
        JCExpressionStatement stmt = (JCExpressionStatement) anonConstructor.body.stats.head;
        JCTree.JCMethodInvocation superInvok = (JCMethodInvocation) stmt.expr;
        return (ExecutableElement) TreeInfo.symbol(superInvok.meth);
    }
    Element e = newClassTree.constructor;
    assert e instanceof ExecutableElement;
    return (ExecutableElement) e;
}
Also used : JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) JCMethodDecl(com.sun.tools.javac.tree.JCTree.JCMethodDecl) ExecutableElement(javax.lang.model.element.ExecutableElement) PackageElement(javax.lang.model.element.PackageElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass) JCTree(com.sun.tools.javac.tree.JCTree) JCExpressionStatement(com.sun.tools.javac.tree.JCTree.JCExpressionStatement) JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation)

Example 20 with JCMethodInvocation

use of com.sun.tools.javac.tree.JCTree.JCMethodInvocation in project error-prone by google.

the class ShouldHaveEvenArgs method matchMethodInvocation.

@Override
public Description matchMethodInvocation(MethodInvocationTree methodInvocationTree, VisitorState state) {
    if (!MATCHER.matches(methodInvocationTree, state)) {
        return Description.NO_MATCH;
    }
    if (methodInvocationTree.getArguments().size() % 2 == 0) {
        return Description.NO_MATCH;
    }
    JCMethodInvocation methodInvocation = (JCMethodInvocation) methodInvocationTree;
    List<JCExpression> arguments = methodInvocation.getArguments();
    Type typeVargs = methodInvocation.varargsElement;
    if (typeVargs == null) {
        return Description.NO_MATCH;
    }
    Type typeVarargsArr = state.arrayTypeForType(typeVargs);
    Type lastArgType = ASTHelpers.getType(Iterables.getLast(arguments));
    if (typeVarargsArr.equals(lastArgType)) {
        return Description.NO_MATCH;
    }
    return describeMatch(methodInvocationTree);
}
Also used : JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) Type(com.sun.tools.javac.code.Type) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression)

Aggregations

JCMethodInvocation (com.sun.tools.javac.tree.JCTree.JCMethodInvocation)26 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)15 JCTree (com.sun.tools.javac.tree.JCTree)10 JCVariableDecl (com.sun.tools.javac.tree.JCTree.JCVariableDecl)8 JCExpressionStatement (com.sun.tools.javac.tree.JCTree.JCExpressionStatement)7 JCNewClass (com.sun.tools.javac.tree.JCTree.JCNewClass)6 JCStatement (com.sun.tools.javac.tree.JCTree.JCStatement)6 JCFieldAccess (com.sun.tools.javac.tree.JCTree.JCFieldAccess)5 JCMethodDecl (com.sun.tools.javac.tree.JCTree.JCMethodDecl)5 ArrayList (java.util.ArrayList)5 JCAnnotation (com.sun.tools.javac.tree.JCTree.JCAnnotation)4 JCBlock (com.sun.tools.javac.tree.JCTree.JCBlock)4 JCIdent (com.sun.tools.javac.tree.JCTree.JCIdent)4 Name (com.sun.tools.javac.util.Name)4 JavacTreeMaker (lombok.javac.JavacTreeMaker)4 ExpressionTree (com.sun.source.tree.ExpressionTree)3 Symbol (com.sun.tools.javac.code.Symbol)3 ClassSymbol (com.sun.tools.javac.code.Symbol.ClassSymbol)3 MethodSymbol (com.sun.tools.javac.code.Symbol.MethodSymbol)3 Type (com.sun.tools.javac.code.Type)3