Skip to content

Instantly share code, notes, and snippets.

@edwardmp
Created June 9, 2016 17:20
Show Gist options
  • Save edwardmp/aa11989194a85cdb0dd9febe91ecda1f to your computer and use it in GitHub Desktop.
Save edwardmp/aa11989194a85cdb0dd9febe91ecda1f to your computer and use it in GitHub Desktop.
Example Eclipse JDT AST visitation
package eu.sig.aevas;
import eu.sig.aevas.dependencymanager.maven.MavenDependency;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.dom.*;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Created by Edward Poot on 02/06/16.
*/
public class InvokedLibraryMethods {
private static final Logger log = Logger.getLogger(InvokedLibraryMethods.class);
private Set<String> allDependencyPackageNames = new HashSet<>();
private Set<String> invokedMethods = new HashSet<>();
private String[] dependencyJarPaths;
protected Set<String> obtainMethods(String systemPath, Set<MavenDependency> mavenDependencies) {
dependencyJarPaths = mavenDependencies.stream().map(dependency -> dependency.pathToJar()).toArray(String[]::new);
mavenDependencies.stream().forEach(mavenDependency -> allDependencyPackageNames.addAll(mavenDependency.getPackageNames()));
parseSourceCode(systemPath);
return invokedMethods;
}
protected void parseSourceCode(String systemPath) {
File srcDir = new File(systemPath);
String[] sourceFiles = FileUtils.listFiles(srcDir, new String[]{"java"}, true).stream().map(srcFile -> srcFile.getAbsolutePath()).toArray(String[]::new);
final ASTParser parser = ASTParser.newParser(AST.JLS8);
parser.setResolveBindings(true);
//parser.setBindingsRecovery(true);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setEnvironment(dependencyJarPaths, null, null, false);
Map options = JavaCore.getOptions();
options.put(JavaCore.COMPILER_SOURCE, "1.8");
parser.setCompilerOptions(options);
parser.createASTs(sourceFiles, null, new String[0], new FileRequestor(), null);
log.info(String.format("Found %d directly invoked library methods", invokedMethods.size()));
}
class FileRequestor extends FileASTRequestor {
@Override
public void acceptAST(String source, CompilationUnit ast) {
ast.accept(new TypeFinderVisitor());
}
}
class TypeFinderVisitor extends ASTVisitor {
protected boolean isAnyNeededElementNull(MethodInvocation node) {
IMethodBinding binding = node.resolveMethodBinding();
if (binding == null) {
return true;
}
Expression expression = node.getExpression();
if (expression == null) {
return true;
}
ITypeBinding typeBinding = expression.resolveTypeBinding();
if (typeBinding == null) {
return true;
}
if (typeBinding.getPackage() == null) {
return true;
}
return false;
}
@Override
public boolean visit(MethodInvocation node) {
if (isAnyNeededElementNull(node)) {
return false;
}
IMethodBinding binding = node.resolveMethodBinding();
Expression expression = node.getExpression();
ITypeBinding typeBinding = expression.resolveTypeBinding();
String methodName = String.format("%s:%s", typeBinding.getQualifiedName(), node.getName().getIdentifier());
String packageName = typeBinding.getPackage().getName();
if (StringUtils.isEmpty(packageName)) {
return false;
}
if (allDependencyPackageNames.contains(packageName)) {
Stream<ITypeBinding> parameterStream = Arrays.stream(binding.getParameterTypes());
List<String> parameterTypes = parameterStream.map(parameterTypeBinding -> parameterTypeBinding.getQualifiedName()).collect(Collectors.toList());
parameterStream.close();
String returnType = binding.getReturnType().getQualifiedName();
returnType = returnType.equals("void") ? "V" : returnType;
String methodSignature = String.format("%s(%s)%s", methodName, StringUtils.join(parameterTypes, ", "), returnType);
invokedMethods.add(methodSignature);
log.debug(String.format("Found invoked library method %s", methodSignature));
}
return true;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment