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

feat: allow spoon to support multi-class definitions #2772

Merged
merged 3 commits into from
Dec 15, 2018

Conversation

tdurieux
Copy link
Collaborator

fix #2770

spoon.addInputResource("src/test/resources/multiclass/module2");
spoon.getEnvironment().setAllowMutliTypeDefinition(true);
spoon.buildModel();
assertNotNull(spoon.getFactory().Class().get("A"));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which one do you get and which one do you expect?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no way to know, it is jdt that handles it

@spoon-bot
Copy link
Collaborator

API changes: 2 (Detected by Revapi)

Old API: fr.inria.gforge.spoon:spoon-core:jar:7.2.0-20181120.234134-99 / New API: fr.inria.gforge.spoon:spoon-core:jar:7.2.0-SNAPSHOT

Method was added to an interface.
Old none
New method Environment#isAllowMultiTypeDefinitions()
Breaking binary: non_breaking,
Method was added to an interface.
Old none
New method Environment#setAllowMultiTypeDefinitions(boolean)
Breaking binary: non_breaking,


@Override
public void setAllowMultiTypeDefinitions(boolean allowMultiTypeDefinitions) {
this.allowMultiTypeDefinitions = allowMultiTypeDefinitions;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this mode associated with noclasspath by default?
Because if you're using it, basically according to your test you will ignore one of the declaration. That means you might do getDeclaration() on an element which is not available in the decl since it's not necessarily the right declaration.
IMO noclasspath will make Spoon more tolerant with such problems. WDYT?

Copy link
Collaborator Author

@tdurieux tdurieux Nov 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it does not work like that since it is the same signature the model should correct (at least in the type level).
It is basically the same behaviour as the runtime environment of java. When the same class is declared several times only one is loaded is considered (and depends on the order of classpath).
It is not perfect because people do dirty stuff that but it is unrelated to noclasspath.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the signature of the class is the same, but inside the class you can have different members, can't you?
Like in your example, what happens if you have one A with method foo() and another with bar() and let's say you want to spoon the model to check invocations of bar()?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you realize that this would completely break the execution of the application?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pretty much like when you don't load the right logger implementation yes. :)
I don't know your usecase here, maybe you're trying to load multiple version of the same project with small differences between them, so it'll be wrong in that case.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm just trying to spoon some multi-modules projects (maven, gradle, ant multi modules). ANd yes you can declare several times the same classes.

It also happens with generated-sources. It is an unknown usecase but it does not seem that rare

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok. I think a better name can be good for the option then: I misunderstood its goals at first :)
Something like allowIdenticalDeclarations? WDYT?

@monperrus
Copy link
Collaborator

LGTM. Will be super useful for large scale automated analysis of big repos.

@pvojtechovsky
Copy link
Collaborator

spoon.getFactory().Class().get("A")
Which one do you get and which one do you expect?

That is the core problem of this PR. I think it is not enough to let JDT to produce two models of class with name A and put them somehow into one position in the model. I think we have to change API of Spoon to be able to ask for a class of a module.

If I understand use case well there is possible to have internal invisible classes in modules. Because they are internal and invisible to others it is also possible that even if they have the same qualified name, these classes are completely different and independent.
So we should be able to create such independent models too.

WDYT?

Do I understand that use case well?

@surli
Copy link
Collaborator

surli commented Nov 22, 2018

even if they have the same qualified name, these classes are completely different and independent.

According to @tdurieux comment here #2772 (comment) he's talking about a usecase where the class are exactly the same. That's why I suggested to change the name of the option to avoid confusion.

@pvojtechovsky
Copy link
Collaborator

So then this PR should include some check that both classes are 100% equal ... to avoid confusion in case I was speaking about.

@tdurieux
Copy link
Collaborator Author

JDT does not really create two model of the class. The binding of one of them is null it means that it just created the ast of it but never considered it in the model.
All the references will always link to only one class. This is a big limitation if one day we want to support properly multi-modules (not java one).

So then this PR should include some check that both classes are 100% equal ... to avoid confusion in case I was speaking about.

And when there are not equals what do we do?

@pvojtechovsky
Copy link
Collaborator

And when there are not equals what do we do?

I do not know your use case well. I just suggest to early warn about the situation when parsed sources contains two different classes with same unique name. So may be we should throw an exception.

@tdurieux
Copy link
Collaborator Author

I don't really like the idea of throwing an exception because there is no workaround.
This exception would make spoon completely incompatible with some projects.

@surli
Copy link
Collaborator

surli commented Nov 22, 2018

+1 for the exception

This exception would make spoon completely incompatible with some projects.

if the case occurs, it will most certainly return wrong results for the user and it will be a real pain to debug. Now what we might do to help this case is to provide a list of source files to ignore in the environment.

Then the user on the first run will get an exception with the full path of the conflicting file, and will be able to properly ignore it by adding a new argument.

@pvojtechovsky
Copy link
Collaborator

if the case occurs...

and it occurs. See first comment of #2761 ... where one class was, by configuration mistake, found twice.

@tdurieux
Copy link
Collaborator Author

That is why I put an option and not activated it by default

@pvojtechovsky
Copy link
Collaborator

Is the JDK compiler configured well to compile Java9 modules? It seems to me strange that it cannot compile and resolve dependencies of each module individually.

Is the situation same if you extended the test case and add real module definition, which marks the package with A class as internal?

@tdurieux
Copy link
Collaborator Author

This feature is to support maven modules (not Java 9 modules), the compiler has no way to do the difference between each class.

@pvojtechovsky
Copy link
Collaborator

pvojtechovsky commented Nov 24, 2018

ok, then forgot all my comments. It is then different situation.

@monperrus
Copy link
Collaborator

@surli do you merge?

@surli
Copy link
Collaborator

surli commented Nov 27, 2018

As I suggested I'd like that we change the name of the option: for me it's ambiguous regarding the real usecase. I proposed to use allowIdenticalDeclarations.

@tdurieux
Copy link
Collaborator Author

I'm not a big fan of allowIdenticalDeclarations since spoon just ignores some definitions.
I prefer something like ignoreDuplicateDeclarations

@surli
Copy link
Collaborator

surli commented Nov 27, 2018

I prefer something like ignoreDuplicateDeclarations

ok for me

@tdurieux
Copy link
Collaborator Author

I just rename the method

@monperrus monperrus merged commit 3e0589c into INRIA:master Dec 15, 2018
@monperrus
Copy link
Collaborator

Thanks @tdurieux !

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

Successfully merging this pull request may close these issues.

Multi-modules projects and spoon
5 participants