Eclipse JDT:如何找到 JDK MethodInvocation 和 ClassInstanceCreation
Eclipse JDT: How to find JDK MethodInvocation and ClassInstanceCreation
我正在使用 Eclipse JDT ASTVisitor 从 java 源文件中查找 Java 方法调用和 class 实例创建。
现在,我可以找到所有这些。但是我无法判断这些方法调用和class实例创建是否来自JDK库.
那么,如何获得 JDK 库方法调用(例如:InputStream.read())和 class 实例(例如:new String())?
以下是我的代码。
JdtAstUtil.java
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.CompilationUnit;
public class JdtAstUtil {
/**
* get compilation unit of source code
* @param javaFilePath
* @return CompilationUnit
*/
public static CompilationUnit getCompilationUnit(String javaFilePath){
byte[] input = null;
try {
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(javaFilePath));
input = new byte[bufferedInputStream.available()];
bufferedInputStream.read(input);
bufferedInputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
ASTParser astParser = ASTParser.newParser(AST.JLS4);
astParser.setSource(new String(input).toCharArray());
astParser.setKind(ASTParser.K_COMPILATION_UNIT);
astParser.setEnvironment(null, null, null, true);
astParser.setResolveBindings(true);
astParser.setBindingsRecovery(true);
astParser.setUnitName("any_name");
CompilationUnit result = (CompilationUnit) (astParser.createAST(null));
return result;
}
}
DemoVisitor.java
import org.eclipse.jdt.core.dom.*;
public class DemoVisitor extends ASTVisitor {
@Override
public boolean visit(MethodInvocation node) {
System.out.println("MethodInvocation:\t" + node.toString());
System.out.println("\tExpression: " + node.getExpression());
Expression expression = node.getExpression();
if(expression != null) {
ITypeBinding typeBinding = expression.resolveTypeBinding();
if (typeBinding != null) {
System.out.println("\tType: " + typeBinding.getName());
}
}
System.out.println("\tName: " + node.getName());
// System.out.println("\t" + node.resolveMethodBinding());
return true;
}
public void endVisit(ClassInstanceCreation node) {
System.out.println("ClassInstanceCreation:\t" + node.toString());
System.out.println("\tType: " + node.getType().toString());
}
}
DemoVisitorTest.java
import org.eclipse.jdt.core.dom.CompilationUnit;
public class DemoVisitorTest {
public DemoVisitorTest(String path) {
CompilationUnit comp = JdtAstUtil.getCompilationUnit(path);
DemoVisitor visitor = new DemoVisitor();
comp.accept(visitor);
}
public static void main(String args[]) {
DemoVisitorTest test = new DemoVisitorTest
("/home/luckcul/developSpace/test/test.java");
}
}
我使用上面的代码解析了下面的 test.java 文件。
test.java
package com.mtihc.minecraft.myhelppages;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
public class HelpCommandExecutor implements CommandExecutor {
/***
* Copies bytes from a large (over 2GB) InputStream to an OutputStream.
* This method uses the provided buffer, so there is no need to use a
* BufferedInputStream.
* @param input the InputStream to read from
* */
public static long copyLarge(final InputStream input,
final OutputStream output, final byte[] buffer) throws IOException {
long count = 0;
int n;
CommandExecutor t = new CommandExecutor(new String());
while (EOF != (n = input.read(buffer))) {
output.write(buffer, 0, n);
t.test();
count += n;
}
return count;
}
}
最后,我得到了这些:
ClassInstanceCreation: new String()
Type: String
ClassInstanceCreation: new CommandExecutor(new String())
Type: CommandExecutor
MethodInvocation: input.read(buffer)
Expression: input
Type: InputStream
Name: read
MethodInvocation: output.write(buffer,0,n)
Expression: output
Type: OutputStream
Name: write
MethodInvocation: t.test()
Expression: t
Type: CommandExecutor
Name: test
在这个例子中,我只想获取 new String(), InputStream.read(), OutputStream.write()
,它来自 JDK 库。
如何修改我的代码来解决我的问题?
您可能想使用 JDT 的 Java 模型来了解调用方法的声明 class。策略的基本(未经测试)草图:
ITypeBinding declaringType = invocation.resolveMethodBinding().getDeclaringClass();
IJavaProject javaProject = JavaCore.create(iProject); // assumes you have an IProject
IType type = javaProject.findType(declaringType.getQualifiedName());
IJavaElement root = type.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
IClasspathEntry cpEntry = ((IPackageFragmentRoot) root).getRawClasspathEntry();
对于JDK类型,cpEntry
应该是getEntryKind()
CPE_CONTAINER
,它的getPath()
应该以"org.eclipse.jdt.launching.JRE_CONTAINER"
开头。
我正在使用 Eclipse JDT ASTVisitor 从 java 源文件中查找 Java 方法调用和 class 实例创建。
现在,我可以找到所有这些。但是我无法判断这些方法调用和class实例创建是否来自JDK库.
那么,如何获得 JDK 库方法调用(例如:InputStream.read())和 class 实例(例如:new String())?
以下是我的代码。
JdtAstUtil.java
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.CompilationUnit;
public class JdtAstUtil {
/**
* get compilation unit of source code
* @param javaFilePath
* @return CompilationUnit
*/
public static CompilationUnit getCompilationUnit(String javaFilePath){
byte[] input = null;
try {
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(javaFilePath));
input = new byte[bufferedInputStream.available()];
bufferedInputStream.read(input);
bufferedInputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
ASTParser astParser = ASTParser.newParser(AST.JLS4);
astParser.setSource(new String(input).toCharArray());
astParser.setKind(ASTParser.K_COMPILATION_UNIT);
astParser.setEnvironment(null, null, null, true);
astParser.setResolveBindings(true);
astParser.setBindingsRecovery(true);
astParser.setUnitName("any_name");
CompilationUnit result = (CompilationUnit) (astParser.createAST(null));
return result;
}
}
DemoVisitor.java
import org.eclipse.jdt.core.dom.*;
public class DemoVisitor extends ASTVisitor {
@Override
public boolean visit(MethodInvocation node) {
System.out.println("MethodInvocation:\t" + node.toString());
System.out.println("\tExpression: " + node.getExpression());
Expression expression = node.getExpression();
if(expression != null) {
ITypeBinding typeBinding = expression.resolveTypeBinding();
if (typeBinding != null) {
System.out.println("\tType: " + typeBinding.getName());
}
}
System.out.println("\tName: " + node.getName());
// System.out.println("\t" + node.resolveMethodBinding());
return true;
}
public void endVisit(ClassInstanceCreation node) {
System.out.println("ClassInstanceCreation:\t" + node.toString());
System.out.println("\tType: " + node.getType().toString());
}
}
DemoVisitorTest.java
import org.eclipse.jdt.core.dom.CompilationUnit;
public class DemoVisitorTest {
public DemoVisitorTest(String path) {
CompilationUnit comp = JdtAstUtil.getCompilationUnit(path);
DemoVisitor visitor = new DemoVisitor();
comp.accept(visitor);
}
public static void main(String args[]) {
DemoVisitorTest test = new DemoVisitorTest
("/home/luckcul/developSpace/test/test.java");
}
}
我使用上面的代码解析了下面的 test.java 文件。
test.java
package com.mtihc.minecraft.myhelppages;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
public class HelpCommandExecutor implements CommandExecutor {
/***
* Copies bytes from a large (over 2GB) InputStream to an OutputStream.
* This method uses the provided buffer, so there is no need to use a
* BufferedInputStream.
* @param input the InputStream to read from
* */
public static long copyLarge(final InputStream input,
final OutputStream output, final byte[] buffer) throws IOException {
long count = 0;
int n;
CommandExecutor t = new CommandExecutor(new String());
while (EOF != (n = input.read(buffer))) {
output.write(buffer, 0, n);
t.test();
count += n;
}
return count;
}
}
最后,我得到了这些:
ClassInstanceCreation: new String()
Type: String
ClassInstanceCreation: new CommandExecutor(new String())
Type: CommandExecutor
MethodInvocation: input.read(buffer)
Expression: input
Type: InputStream
Name: read
MethodInvocation: output.write(buffer,0,n)
Expression: output
Type: OutputStream
Name: write
MethodInvocation: t.test()
Expression: t
Type: CommandExecutor
Name: test
在这个例子中,我只想获取 new String(), InputStream.read(), OutputStream.write()
,它来自 JDK 库。
如何修改我的代码来解决我的问题?
您可能想使用 JDT 的 Java 模型来了解调用方法的声明 class。策略的基本(未经测试)草图:
ITypeBinding declaringType = invocation.resolveMethodBinding().getDeclaringClass();
IJavaProject javaProject = JavaCore.create(iProject); // assumes you have an IProject
IType type = javaProject.findType(declaringType.getQualifiedName());
IJavaElement root = type.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
IClasspathEntry cpEntry = ((IPackageFragmentRoot) root).getRawClasspathEntry();
对于JDK类型,cpEntry
应该是getEntryKind()
CPE_CONTAINER
,它的getPath()
应该以"org.eclipse.jdt.launching.JRE_CONTAINER"
开头。