Search in sources :

Example 16 with AttrContext

use of com.sun.tools.javac.comp.AttrContext in project checker-framework by typetools.

the class DefaultReflectionResolver method getSymbol.

private Symbol getSymbol(String className, Env<AttrContext> env, Names names, Resolve resolve) {
    Method loadClass;
    try {
        loadClass = Resolve.class.getDeclaredMethod("loadClass", Env.class, Name.class, RecoveryLoadClass.class);
        loadClass.setAccessible(true);
    } catch (SecurityException | NoSuchMethodException | IllegalArgumentException e) {
        // A problem with javac is serious and must be reported.
        throw new BugInCF("Error in obtaining reflective method.", e);
    }
    try {
        RecoveryLoadClass noRecovery = (e, n) -> null;
        return (Symbol) loadClass.invoke(resolve, env, names.fromString(className), noRecovery);
    } catch (SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
        // A problem with javac is serious and must be reported.
        throw new BugInCF("Error in invoking reflective method.", e);
    }
}
Also used : MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) AnnotatedArrayType(org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType) BugInCF(org.checkerframework.javacutil.BugInCF) JavacScope(com.sun.tools.javac.api.JavacScope) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) TypeTag(com.sun.tools.javac.code.TypeTag) Trees(com.sun.source.util.Trees) Method(java.lang.reflect.Method) TreePath(com.sun.source.util.TreePath) Symbol(com.sun.tools.javac.code.Symbol) Set(java.util.Set) Env(com.sun.tools.javac.comp.Env) TreeUtils(org.checkerframework.javacutil.TreeUtils) InvocationTargetException(java.lang.reflect.InvocationTargetException) TypeKind(javax.lang.model.type.TypeKind) ParameterizedExecutableType(org.checkerframework.framework.type.AnnotatedTypeFactory.ParameterizedExecutableType) List(java.util.List) Flags(com.sun.tools.javac.code.Flags) Context(com.sun.tools.javac.util.Context) Name(com.sun.tools.javac.util.Name) Type(com.sun.tools.javac.code.Type) VariableElement(javax.lang.model.element.VariableElement) Constructor(java.lang.reflect.Constructor) AttrContext(com.sun.tools.javac.comp.AttrContext) ArrayList(java.util.ArrayList) RecoveryLoadClass(com.sun.tools.javac.comp.Resolve.RecoveryLoadClass) UnknownMethod(org.checkerframework.common.reflection.qual.UnknownMethod) NewClassTree(com.sun.source.tree.NewClassTree) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass) ElementFilter(javax.lang.model.util.ElementFilter) AnnotationUtils(org.checkerframework.javacutil.AnnotationUtils) JavacProcessingEnvironment(com.sun.tools.javac.processing.JavacProcessingEnvironment) MethodVal(org.checkerframework.common.reflection.qual.MethodVal) NewInstance(org.checkerframework.common.reflection.qual.NewInstance) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror) ElementKind(javax.lang.model.element.ElementKind) ExpressionTree(com.sun.source.tree.ExpressionTree) ExecutableElement(javax.lang.model.element.ExecutableElement) TreeMaker(com.sun.tools.javac.tree.TreeMaker) BaseTypeChecker(org.checkerframework.common.basetype.BaseTypeChecker) Names(com.sun.tools.javac.util.Names) AnnotationMirror(javax.lang.model.element.AnnotationMirror) AnnotatedTypeFactory(org.checkerframework.framework.type.AnnotatedTypeFactory) Invoke(org.checkerframework.common.reflection.qual.Invoke) TypeMirror(javax.lang.model.type.TypeMirror) AnnotationProvider(org.checkerframework.javacutil.AnnotationProvider) JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) ProcessingEnvironment(javax.annotation.processing.ProcessingEnvironment) Collections(java.util.Collections) Resolve(com.sun.tools.javac.comp.Resolve) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) Symbol(com.sun.tools.javac.code.Symbol) RecoveryLoadClass(com.sun.tools.javac.comp.Resolve.RecoveryLoadClass) Method(java.lang.reflect.Method) UnknownMethod(org.checkerframework.common.reflection.qual.UnknownMethod) Env(com.sun.tools.javac.comp.Env) BugInCF(org.checkerframework.javacutil.BugInCF) Resolve(com.sun.tools.javac.comp.Resolve) InvocationTargetException(java.lang.reflect.InvocationTargetException) Name(com.sun.tools.javac.util.Name)

Example 17 with AttrContext

use of com.sun.tools.javac.comp.AttrContext 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();
    boolean unknown = isUnknownMethod(tree);
    AnnotationMirror estimate = getMethodVal(tree);
    if (estimate == null) {
        debugReflection("MethodVal is unknown for: " + tree);
        debugReflection("UnknownMethod annotation: " + unknown);
        return Collections.emptyList();
    }
    debugReflection("MethodVal type system annotations: " + estimate);
    List<String> listClassNames = AnnotationUtils.getElementValueArray(estimate, reflectionFactory.methodValClassNameElement, String.class);
    List<String> listMethodNames = AnnotationUtils.getElementValueArray(estimate, reflectionFactory.methodValMethodNameElement, String.class);
    List<Integer> listParamLengths = AnnotationUtils.getElementValueArray(estimate, reflectionFactory.methodValParamsElement, Integer.class);
    assert listClassNames.size() == listMethodNames.size() && listClassNames.size() == listParamLengths.size();
    List<MethodInvocationTree> methods = new ArrayList<>();
    for (int i = 0; i < listClassNames.size(); ++i) {
        String className = listClassNames.get(i);
        String methodName = listMethodNames.get(i);
        int paramLength = listParamLengths.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 (!processingEnv.getTypeUtils().isSubtype(receiver.type, symbol.owner.type)) {
                continue;
            }
            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 AttrContext

use of com.sun.tools.javac.comp.AttrContext 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();
    AnnotationMirror estimate = getMethodVal(tree);
    if (estimate == null) {
        debugReflection("MethodVal is unknown for: " + tree);
        debugReflection("UnknownMethod annotation: " + isUnknownMethod(tree));
        return Collections.emptyList();
    }
    debugReflection("MethodVal type system annotations: " + estimate);
    List<String> listClassNames = AnnotationUtils.getElementValueArray(estimate, reflectionFactory.methodValClassNameElement, String.class);
    List<Integer> listParamLengths = AnnotationUtils.getElementValueArray(estimate, reflectionFactory.methodValParamsElement, Integer.class);
    assert listClassNames.size() == listParamLengths.size();
    List<JCNewClass> constructors = new ArrayList<>();
    for (int i = 0; i < listClassNames.size(); ++i) {
        String className = listClassNames.get(i);
        int paramLength = listParamLengths.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 AttrContext

use of com.sun.tools.javac.comp.AttrContext in project checker-framework by typetools.

the class DefaultReflectionResolver method getConstructorSymbolsfor.

/**
 * Get set of Symbols for constructors based on class name and parameter length.
 *
 * @return the (potentially empty) set of corresponding constructor Symbol(s)
 */
private List<Symbol> getConstructorSymbolsfor(String className, int paramLength, Env<AttrContext> env) {
    Context context = ((JavacProcessingEnvironment) processingEnv).getContext();
    Resolve resolve = Resolve.instance(context);
    Names names = Names.instance(context);
    Symbol symClass = getSymbol(className, env, names, resolve);
    if (!symClass.exists()) {
        debugReflection("Unable to resolve class: " + className);
        return Collections.emptyList();
    }
    // TODO: Should this be used instead of the below??
    ElementFilter.constructorsIn(symClass.getEnclosedElements());
    // The common case is probably that `result` is a singleton at method exit.
    List<Symbol> result = new ArrayList<>();
    for (Symbol s : symClass.getEnclosedElements()) {
        // Check all constructors
        if (s.getKind() == ElementKind.CONSTRUCTOR) {
            // Check for number of parameters
            if (((MethodSymbol) s).getParameters().size() == paramLength) {
                result.add(s);
            }
        }
    }
    if (result.isEmpty()) {
        debugReflection("Unable to resolve constructor!");
    }
    return result;
}
Also used : Context(com.sun.tools.javac.util.Context) AttrContext(com.sun.tools.javac.comp.AttrContext) Names(com.sun.tools.javac.util.Names) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) Symbol(com.sun.tools.javac.code.Symbol) JavacProcessingEnvironment(com.sun.tools.javac.processing.JavacProcessingEnvironment) ArrayList(java.util.ArrayList) Resolve(com.sun.tools.javac.comp.Resolve)

Example 20 with AttrContext

use of com.sun.tools.javac.comp.AttrContext in project error-prone by google.

the class FindIdentifiers method findIdent.

/**
 * Finds a declaration with the given name and type that is in scope at the current location.
 */
public static Symbol findIdent(String name, VisitorState state, KindSelector kind) {
    ClassType enclosingClass = ASTHelpers.getType(state.findEnclosing(ClassTree.class));
    if (enclosingClass == null || enclosingClass.tsym == null) {
        return null;
    }
    Env<AttrContext> env = Enter.instance(state.context).getClassEnv(enclosingClass.tsym);
    MethodTree enclosingMethod = state.findEnclosing(MethodTree.class);
    if (enclosingMethod != null) {
        env = MemberEnter.instance(state.context).getMethodEnv((JCMethodDecl) enclosingMethod, env);
    }
    try {
        Method method = Resolve.class.getDeclaredMethod("findIdent", Env.class, Name.class, KindSelector.class);
        method.setAccessible(true);
        Symbol result = (Symbol) method.invoke(Resolve.instance(state.context), env, state.getName(name), kind);
        return result.exists() ? result : null;
    } catch (ReflectiveOperationException e) {
        throw new LinkageError(e.getMessage(), e);
    }
}
Also used : JCMethodDecl(com.sun.tools.javac.tree.JCTree.JCMethodDecl) MethodTree(com.sun.source.tree.MethodTree) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol) Symbol(com.sun.tools.javac.code.Symbol) PackageSymbol(com.sun.tools.javac.code.Symbol.PackageSymbol) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) NewClassTree(com.sun.source.tree.NewClassTree) ClassTree(com.sun.source.tree.ClassTree) Method(java.lang.reflect.Method) ClassType(com.sun.tools.javac.code.Type.ClassType) AttrContext(com.sun.tools.javac.comp.AttrContext)

Aggregations

AttrContext (com.sun.tools.javac.comp.AttrContext)25 Symbol (com.sun.tools.javac.code.Symbol)10 Log (com.sun.tools.javac.util.Log)10 ClassSymbol (com.sun.tools.javac.code.Symbol.ClassSymbol)9 VariableElement (javax.lang.model.element.VariableElement)9 MethodSymbol (com.sun.tools.javac.code.Symbol.MethodSymbol)8 Element (javax.lang.model.element.Element)8 JavacScope (com.sun.tools.javac.api.JavacScope)6 JCTree (com.sun.tools.javac.tree.JCTree)6 ExecutableElement (javax.lang.model.element.ExecutableElement)6 Type (com.sun.tools.javac.code.Type)5 JavacProcessingEnvironment (com.sun.tools.javac.processing.JavacProcessingEnvironment)5 Context (com.sun.tools.javac.util.Context)5 Names (com.sun.tools.javac.util.Names)5 ArrayList (java.util.ArrayList)5 Nullable (org.checkerframework.checker.nullness.qual.Nullable)5 TreePath (com.sun.source.util.TreePath)4 Name (com.sun.tools.javac.util.Name)4 NewClassTree (com.sun.source.tree.NewClassTree)3 PackageSymbol (com.sun.tools.javac.code.Symbol.PackageSymbol)3