spoon
spoon copied to clipboard
[Bug] Spoon metamodel does not consider certain model classes when getting the concept name for a class
Describe the bug
The spoon metamodel does not seem to consider the CtUnnamedModule
, CtRootPackage
and CtUnresolvedImport
classes at the moment, which gave me some trouble when doing some metamodel queries (to do processor filtering).
To Reproduce
Just try giving Metamodel.getConceptName()
an instance of one of these types:
Metamodel.getConceptName(factory.getModel().getRootPackage().getClass());
This call will fail with an exception because CtRootPackage does not directly inherit from CtPackage; it inherits from CtPackageImpl.
I have a fork where I've implemented a fix for this, but it essentially just involves special casing the names of these specific types within Metamodel.getConceptName()
. I also ended up removing the (deprecated) CompilationUnit
and CompilationUnitImpl
classes when I did this, but those changes can probably be isolated from this.
private static String getConceptName(String simpleName) {
if (simpleName.endsWith(CLASS_SUFFIX)) {
simpleName = simpleName.substring(0, simpleName.length() - CLASS_SUFFIX.length());
// The unnamed module and certain other classes are a special case due to their names
} else if (simpleName.equals("CtUnnamedModule")) {
simpleName = "CtModule";
} else if (simpleName.equals("CtRootPackage")) {
simpleName = "CtPackage";
} else if (simpleName.equals("CtUnresolvedImport")) {
simpleName = "CtImport";
}
return simpleName;
}
Operating system, JDK and Spoon version used
- OS: MacOS Monterey (M1)
- JDK: 11
- Spoon version: 10.1.0
Metamodel
only has getConceptName
methods for CtType
and Class
. Do you have more changes allowing you a CtPackage
there? Or are you using Metamodel.getConceptName(factory.getModel().getRootPackage().getClass());
?
oops, yes. that's what I meant. sorry for the misunderstanding. I've edited the original comment to add the .getClass()
call.
The behavior is clearly wrong here I'd say. Your solution would be a good fix, however it might make sense to have an annotation instead, like @Concept("CtModule")
and check for that before calling the method that takes a simple name. WDYT?
True, that would work, and make the "concept" system more explicit as well. If the annotation were applied everywhere, it could bloat the size of the change though, would it be ok to do that gradually (annotate only exceptional cases first)?
The old method seems to be a bit too magical to me as well, a bit non-obvious.
Sorry for the late reply!
If the annotation were applied everywhere, it could bloat the size of the change though, would it be ok to do that gradually (annotate only exceptional cases first)?
Yes, I think the working defaults don't need to be changed for now.
Note that this might also be helpful when considering #4667 if such immutable model is designed with its own classes.
yeah... I was thinking about that as well. my idea was to just instantiate anonymous classes for each of them, at which point I wondered about how to get metamodel concepts for them.