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);
}
}
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;
}
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;
}
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;
}
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);
}
}
Aggregations