0

I am working with Spoon Inria to parse and analyze Java applications. Currently, I am using the below code to create input project model. This code works when project files are saved in the disk.

Launcher spoonAPI = new Launcher();
spoonAPI.addInputResource(projectDirectory);  //The path to the project root directory
spoonAPI.buildModel();
CtModel ctModel = spoonAPI.getModel();

However, currently I have contents of Java files (classes) in the memory and I do not want to write them in the disk as it takes ages. I was wondering if there is a way using Spoon that I can pass file contents to the parser. For example, a code as below.

//Key is name of class and value is its content
Map<String, String> JavafileContents= new HashMap<String, String>();

for (String filePath : JavafileContents.keySet()) {
  spoonAPI.parse(JavafileContents.get(filePath ));
}
CtModel ctModel = spoonAPI.getModel(); //The extracted model should contains all parsed files.

Like a similar solution provided in JDT.

ASTParser parser = ASTParser.newParser(AST.JLS14);
parser.setSource(javaFileContents.get(filePath).toCharArray());
CompilationUnit compilationUnit = (CompilationUnit)parser.createAST(null);
Iman
  • 91
  • 7

1 Answers1

1

I'm also looking for the functionality, I found the following code may meet your requirement.

    import spoon.support.compiler.VirtualFile;
    ...
    public static CtClass<?> parseClass(String code) {
       Launcher launcher = new Launcher();
       launcher.addInputResource(new VirtualFile(code));
       launcher.getEnvironment().setNoClasspath(true);
       launcher.getEnvironment().setAutoImports(true);
    ...

The source is https://github.com/INRIA/spoon/blob/spoon-core-8.2.0/src/main/java/spoon/Launcher.java#L856.

Alternatively, one can use APIs like createCodeSnippetStatement

Factory factory = new Launcher().createFactory();
CtStatement tmpStmt = factory.Code().createCodeSnippetStatement(code);

The way of choosing an API depends on the type of your code snippet (e.g., expression or statement).

Yu Wang
  • 21
  • 3
  • Thanks, but the second solution does not work when input "code" is a class. The first solution also crashes. It is useful when there is one class, but in my case I have thousand of classes in the memory. – Iman Sep 07 '20 at 16:06
  • I think there is no direct way to do what you want. Even though I didn't try it, it may be feasible to modify all classes to 'private' just like a regular Java file. – Yu Wang Sep 08 '20 at 01:57
  • Yu Wang"s first solution is correct :) if it crashes, it's a bug, would you report it on Githu! – Martin Monperrus Sep 08 '20 at 05:35
  • @MartinMonperrus Hi, may I ask how to parse a single statement? Just like what I want to do in my second solution, but I found the created code snippet is not the same as it in CtMethod. – Yu Wang Sep 14 '20 at 07:17