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

Problem with qualified names of CtTypeReference when using setNoClasspath(true) #465

Closed
worblehat opened this issue Dec 27, 2015 · 11 comments

Comments

@worblehat
Copy link

When settings setNoClasspath(true) on the environment, unresolved type references don't have the correct qualified name. getQualifiedName() returns the simple name (without the package prefix) instead.

I discovered that behaviour with this processor:

class TypeReferenceProcessor extends AbstractProcessor<CtType<?>> {

    @Override
    public void process(CtType<?> spType) {
        for (CtTypeReference<?> spRef : spType.getReferencedTypes()) {
            System.out.println(spRef.getQualifiedName());
        }
    }
}
@worblehat worblehat changed the title Problem with qualified names of CtTypeRererence when using setNoClasspath(true) Problem with qualified names of CtTypeReference when using setNoClasspath(true) Dec 27, 2015
@tdurieux
Copy link
Collaborator

It's not always possible to determine the qualified name of a reference when the reference type is not in the classpath.
When the reference type is not in the classpath, Spoon tries to resolve the package of the type by looking the imports but it's not always possible (for example with start imports).

Please provides the code that you try to Spoon so that we can verify the behavior of Spoon on your specific case.

@worblehat
Copy link
Author

This is a minimal example program that uses an external library:

package example;

import com.google.common.base.Joiner;

public class Demo {

    public static void main(String[] args) {
        System.out.println(Joiner.on(" ").join("Hello", "World!"));
    }
}

I use this code to analyze it with spoon:

package analysis;

import java.io.File;
import java.util.Arrays;

import spoon.Launcher;
import spoon.SpoonModelBuilder;
import spoon.processing.AbstractProcessor;
import spoon.reflect.declaration.CtType;
import spoon.reflect.reference.CtTypeReference;

public class Analyzer {

    public static void main(String[] args) {
        Launcher spLauncher = new Launcher();
        spLauncher.getEnvironment().setNoClasspath(true);
        SpoonModelBuilder spModelBuilder = spLauncher.createCompiler();
        spModelBuilder.addInputSource(new File("../TestProject/src"));
        spModelBuilder.build();
        spModelBuilder.process(Arrays.asList(new TypeReferenceProcessor()));
    }

    private static class TypeReferenceProcessor extends AbstractProcessor<CtType<?>> {

        @Override
        public void process(CtType<?> spType) {
            for (CtTypeReference<?> spRef : spType.getReferencedTypes()) {
                System.out.println(spRef.getQualifiedName());
            }
        }
    }
}

The output from the above Analyzer-class is:

example.Demo
void
Joiner
java.lang.System
java.lang.Object
java.lang.String

The qualified name of the reference to Joiner does not contain the package, although it was explicitly imported.

@worblehat
Copy link
Author

I am using Spoon 4.4.1 by the way...

@tdurieux
Copy link
Collaborator

I Created a PR that fix your problem, unfortunately I found an other related issue that I was not able to resolve.

@worblehat
Copy link
Author

Thank you very much for the quick solution!

Will there be a bug fix release or will this only be available in the next major/minor release?

@tdurieux
Copy link
Collaborator

No problem.

For the release date, I don't know. The spoon maintainers are on holidays until next week.

There is still an issue with static fields that are not in the classpath, the current spoon model is not correct... I need to discuss with the maintainers to solve this issue.

@worblehat
Copy link
Author

Alright. I will try to build Spoon including your patch by myself then. Is there any documentation with instructions on how to build Spoon from source?

@tdurieux
Copy link
Collaborator

I thought yes, but I can not find the instructions.

Build instructions

  1. clone my repository https://github.com/tdurieux/spoon.git
  2. go to the branch package-typeref-noclasspath: git checkout package-typeref-noclasspath
  3. Build spoon: mvn clean install -Dmaven.test.skip=true ( -Dmaven.test.skip=true because one test fails)
  4. copies the jar to your project: cp target/spoon-core-5.0.0-SNAPSHOT-jar-with-dependencies.jar <your_project_dir> or uses the spoon snapshot in your project.

@worblehat
Copy link
Author

Thank you very much for these detailed instructions! It works :)

@worblehat
Copy link
Author

I discovered a use case where the problem still occurs .

I extended the above example code by implementing an Interface:

package example;

import com.google.common.base.Function;
import com.google.common.base.Joiner;

public class Demo implements Function<String, String> {

    public static void main(String[] args) {
        System.out.println(Joiner.on(" ").join("Hello", "World!"));
    }

    @Override
    public String apply(String input) {
        return input;
    }
}

The result of the processor is now:

example.Demo
java.io.PrintStream
Function
java.lang.Override
void
java.lang.System
java.lang.String
com.google.common.base.Joiner

As you can see Joiner has the correct package prefix now, but Function has not. I found out this happens whenever I implement an interface, but also when I use a Type as parameter to a method like this:

public void foo(Function<> f) {

}

Now when I also add a member Variable of that type...

package example;

import com.google.common.base.Function;
import com.google.common.base.Joiner;

public class Demo implements Function<String, String> {

    private Function f;

    public static void main(String[] args) {
        System.out.println(Joiner.on(" ").join("Hello", "World!"));
    }

    @Override
    public String apply(String input) {
        return input;
    }
}

the corresponding reference will contain the package name, which leads to two different CtTypeReferences:

...
Function
com.google.common.base.Function
...

So, from an outsider's point of view, it looks like Spoon doesn't relate the import statement with type references from implements and parameters.

@GerardPaligot GerardPaligot reopened this Jan 8, 2016
@GerardPaligot
Copy link
Contributor

Thanks, we will work on it.

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