use of com.sun.tools.javac.processing.JavacProcessingEnvironment 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.processing.JavacProcessingEnvironment 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.processing.JavacProcessingEnvironment 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.processing.JavacProcessingEnvironment in project checker-framework by typetools.
the class SignaturePrinter method main.
public static void main(String[] args) {
if (!(args.length == 1 && !args[0].startsWith(CHECKER_ARG)) && !(args.length == 2 && args[0].startsWith(CHECKER_ARG))) {
printUsage();
return;
}
// process arguments
String checkerName = null;
if (args[0].startsWith(CHECKER_ARG)) {
checkerName = args[0].substring(CHECKER_ARG.length());
if (!Signatures.isBinaryName(checkerName)) {
throw new UserError("Bad checker name \"%s\"", checkerName);
}
}
// Setup compiler environment
Context context = new Context();
JavacProcessingEnvironment env = JavacProcessingEnvironment.instance(context);
SignaturePrinter printer = new SignaturePrinter();
printer.init(env, checkerName);
String className = args[args.length - 1];
TypeElement elem = env.getElementUtils().getTypeElement(className);
if (elem == null) {
System.err.println("Couldn't find class: " + className);
return;
}
printer.typeProcess(elem, null);
}
use of com.sun.tools.javac.processing.JavacProcessingEnvironment in project ceylon-compiler by ceylon.
the class TestContext method process.
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
round++;
JavacProcessingEnvironment jpe = (JavacProcessingEnvironment) processingEnv;
Context c = jpe.getContext();
check(c.get(JavacElements.class), eltUtils);
check(c.get(JavacTypes.class), typeUtils);
check(c.get(JavacTrees.class), treeUtils);
final int MAXROUNDS = 3;
if (round < MAXROUNDS)
generateSource("Gen" + round);
return true;
}
Aggregations