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

review fix(annotation): bug when using an annotation targeting declaration and types #1774

Merged
merged 13 commits into from
Dec 12, 2017

Conversation

surli
Copy link
Collaborator

@surli surli commented Dec 5, 2017

Fix #1773

In this case the JLS says that: "It is possible for @foo to be both a declaration annotation and a type annotation simultaneously." So we should attach the annotation to the field/method AND to the type in Spoon model.
Then in this case we don't want to print it twice: we print it only for the field/method.

@surli surli closed this Dec 5, 2017
@surli surli reopened this Dec 8, 2017
@surli surli changed the title WiP fix(annotation): bug when using an annotation targeting field and types review fix(annotation): bug when using an annotation targeting field and types Dec 8, 2017
@surli surli changed the title review fix(annotation): bug when using an annotation targeting field and types WiP fix(annotation): bug when using an annotation targeting field and types Dec 8, 2017
@surli surli changed the title WiP fix(annotation): bug when using an annotation targeting field and types WiP fix(annotation): bug when using an annotation targeting declaration and types Dec 8, 2017
@surli surli changed the title WiP fix(annotation): bug when using an annotation targeting declaration and types review fix(annotation): bug when using an annotation targeting declaration and types Dec 8, 2017
@surli
Copy link
Collaborator Author

surli commented Dec 8, 2017

This PR is now ready to be reviewed @pvojtechovsky @monperrus

Please note that the PR is potentially breaking.

When using a code like:

@MyAnnotation
String myField;

@Target({ElementType.TYPE_USE, ElementType.FIELD})
public @interface MyAnnotation {}

the model will now contain MyAnnotation annotation on the field AND on the type reference String.
This has been done according to the following sentence of the JLS:

@foo int f;
@foo is a declaration annotation on f if Foo is meta-annotated by @target(ElementType.FIELD), and a type annotation on int if Foo is meta-annotated by @target(ElementType.TYPE_USE). It is possible for @foo to be both a declaration annotation and a type annotation simultaneously.

So this is not true only for fields, but for all declaration.
Moreover, in case of the usage of a an annotation without @Target the JLS says that

If an annotation of type java.lang.annotation.Target is not present on the declaration of an annotation type T, then T is applicable in all declaration contexts except type parameter declarations, and in no type contexts.

So I considered those exceptions for adding the annotation or not.
It means that in no classpath, if we have no information about the annotation type, MyAnnotation would be only attached to the field on the example below: this is the previous Spoon behaviour.

@@ -77,6 +78,10 @@ public ElementPrinterHelper(TokenWriter printerTokenWriter, DefaultJavaPrettyPri
*/
public void writeAnnotations(CtElement element) {
for (CtAnnotation<?> annotation : element.getAnnotations()) {
if (element.isParentInitialized() && element instanceof CtTypeReference && (element.getParent() instanceof CtTypedElement) && element.getParent().getAnnotations().contains(annotation)) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

explain this complex condition with a fat comment?

@@ -165,4 +167,42 @@
@Override
@UnsettableProperty
<C extends CtExpression<A>> C setTypeCasts(List<CtTypeReference<?>> types);

static CtAnnotatedElementType getAnnotatedElementTypeForCtElement(CtElement element) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

use an anonymous scanner to avoid multiple instanceof?

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 don't see how to use easily an anonymous scanner here: I must return a variable and I cannot store it as a local variable if I use the anonymous scanner. And I don't have any method to call to setup the value.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I agree, it's not straightforward.

I must return a variable and I cannot store it as a local variable if I use the anonymous scanner

Unless you create an inline class

class Result { CtVariable v }
final Result result = new Result();
// then the anonymous class

}
}
}
return false;

// true here means that the target annotation is not mandatory and we don't have found it
Copy link
Contributor

Choose a reason for hiding this comment

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

don't have -> have not

CtAnnotatedElementType annotatedElementType = CtAnnotation.getAnnotatedElementTypeForCtElement(e);
annotatedElementType = (e instanceof CtTypeParameter || e instanceof CtTypeParameterReference) ? CtAnnotatedElementType.TYPE_USE : annotatedElementType;

// in case of noclasspath, we can be 100% sure, so we guess it must be attached...
Copy link
Contributor

Choose a reason for hiding this comment

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

"can be sure" or "cannot be sure"?

@monperrus
Copy link
Collaborator

merge?

@surli
Copy link
Collaborator Author

surli commented Dec 12, 2017

merge?

ok for me

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

Successfully merging this pull request may close these issues.

3 participants