Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to find CtCompilationUnit with spoon? #4103

Open
zhizhixiongxuwei opened this issue Aug 19, 2021 · 7 comments
Open

How to find CtCompilationUnit with spoon? #4103

zhizhixiongxuwei opened this issue Aug 19, 2021 · 7 comments

Comments

@zhizhixiongxuwei
Copy link

As I known, each java file can be parsed as a single CompilationUnit in eclipse jdt. I find that spoon has CtCompilationUnit
but It doesn't work. I don't know where is the problem.Here is my test code.

public class Demo {

    public static void main(String[] args) {
        Node node = new Node();
        node.run();
    }
    public void run() {
        System.out.println("Demo run");
    }
}
class Node {
    public void run() {
        System.out.println("run");
    }
}

I can use spoon to get each CtMethod info like this.

        CtPackage rootPackage = model.getRootPackage();
        model.getElements(new AbstractFilter<CtMethod>() {  //CtCompilationUnit will get nothing?
            @Override public boolean matches(CtMethod element) {
                System.out.println(element.getPosition());
                return true;
            }
        });

However, If i use filter to collect CtCompilationUnit, I get nothing. Anyone can tell me if I miss something?

@slarse
Copy link
Collaborator

slarse commented Aug 19, 2021

Hi @zhizhixiongxuwei,

A compilation unit is not quite part of the model in the same sense that other elements are. It's a compiler concept, while Spoon models the language syntax and semantics. It CtCompilationUnit is relatively new, and it hasn't been super well integrated into the API yet (we're looking at solutions for that, see #3942).

That being said, you can reach the original compilation unit of any element with a position.

CtElement element = ...; // some element
if (element.getPosition().isValidPosition()) {
    CtCompilationUnit cu = element.getPosition().getCompilationUnit();
}

You can also get all compilation units from the CompilationUnitFactory:

Launcher launcher = new Launcher();
// do Spoon stuff
Map<String, CompilationUnit> compilationUnits = launcher.getFactory().CompilationUnit().getMap();

Note that the factory uses the older and deprecated CompilationUnit type (which is an empty subtype of CtCompilationUnit that's just there for backwards compatibility).

@zhizhixiongxuwei
Copy link
Author

Thanks for your reply. I want to know the exact AST info if I got the offset and length token info, So that's why I search CompilationUnit in spoon. I do it with Eclipse-JDT before and I am sure I can find the target node with offset and length in CompilationUnit with JDT. I check Navigation and Query and can't find the API I need.

@slarse
Copy link
Collaborator

slarse commented Aug 26, 2021

I want to know the exact AST info

I don't know what you mean by this. Could you give a concrete example?

if I got the offset and length token info

Tokens, in the lexer sense of the word, are not carried over one-to-one to Spoon. For example, class SomeClass { } consists of four individual tokens, but in Spoon's AST it is simply one class declaration. You can get the source position of that entire class declaration, but you can't get the position of an individual token, for example class or }. To investigate tokens, you need to go lower-level than an AST.

If you by token you mean something else, then do clarify and I'll try to answer again.

@zhizhixiongxuwei
Copy link
Author

There is a helper class in eclipse-jdt called NodeFinder

/**
	 * Maps a selection to an ASTNode, where the selection is defined using a start and a length.
	 * The result node is determined as follows:
	 * <ul>
	 *   <li>First, tries to find a node whose range is the exactly the given selection.
	 *       If multiple matching nodes are found, the innermost is returned.</li>
	 *   <li>If no such node exists, then the last node in a preorder traversal of the AST is returned, where
	 *       the node range fully contains the selection.
	 *       If the length is zero, then ties between adjacent nodes are broken by choosing the right side.</li>
	 * </ul>
	 *
	 * @param root the root node from which the search starts
	 * @param start the start of the selection
	 * @param length the length of the selection
	 *
	 * @return the innermost node that exactly matches the selection, or the first node that contains the selection
	 */
	public static ASTNode perform(ASTNode root, int start, int length) {
		NodeFinder finder = new NodeFinder(root, start, length);
		ASTNode result= finder.getCoveredNode();
		if (result == null || result.getStartPosition() != start || result.getLength() != length) {
			return finder.getCoveringNode();
		}
		return result;
	}

I can use this API to find a target ASTNode and then I can use this information do something like navigation or go to declaration with Binding if it is possible.
I read part of spoon userguide and I know that spoon can also provide powerful navigation feature, but now I need to get a target AST according to a CompilationUnit, offset,and length.

@zhizhixiongxuwei
Copy link
Author

I just want to know if there are some similar methods like this. I hope the needed AST can be located with offset,and length .

@monperrus
Copy link
Collaborator

A class SpoonNodeFinder similar to JDT's NodeFinder would not be hard to implement.

@slarse
Copy link
Collaborator

slarse commented Aug 26, 2021

So, yes, matching a Spoon AST element to a source position is possible, but not currently provided by Spoon. We do something very similar to this in Sorald, in our BestFitScanner. It would probably be feasible to generalize said scanner and put it into Spoon, while providing the API needed for Sorald to do it's more specialized matchings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants