INRIA / INRIA/spoon

[Bug]: `annotationType` is not set for nested annotations

Open
#4,895 2 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Java
Stars
2k
Forks
392
Avg merge
11h 24m
Merged PRs (30d)
36

Description

### Describe the bug

Consider a field inside a type:

```java
private final ObjectProperty fadeDuration = new SimpleObjectProperty<>(this, "fadeDuration",
EditAxis.DEFAULT_ANIMATION_DURATION) {
@Override
protected void invalidated() {
Objects.requireNonNull(get(), "The " + getName() + " must not be null");
}
};
```

The annotation `@Override` has two of the many properties - `type` and `annotationType`. Firstly, I don't understand the difference between them as I asked #4894. Second, assuming there is no difference between them, I think both properties should be set to `java.lang.Override`'s reference.

I discovered this possible because of this [line](https://github.com/SpoonLabs/gumtree-spoon-ast-diff/blob/62f42c88065c6089b6b74573bbc9496a823fedbc/src/main/java/gumtree/spoon/builder/LabelFinder.java#L153) in one of Spoon's client. A `NullPointerException` was thrown since they use `type` and not `annotationType`.

### Source code you are trying to analyze/transform

```Java
// minimal example reduced from EditAxis.java in this commit - https://github.com/fair-acc/chart-fx/commit/7a6a4e2417aa52fae1aec4ea0b4a0f87ca7d8124

import java.util.Objects;

import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.layout.HBox;
import javafx.util.Duration;

public class EditAxis extends ChartPlugin {
private static final Duration DEFAULT_ANIMATION_DURATION = Duration.millis(500);

private final ObjectProperty fadeDuration = new SimpleObjectProperty<>(this, "fadeDuration",
EditAxis.DEFAULT_ANIMATION_DURATION) {
// check if this annotation has both `type` and `annotationType` set
@Override
protected void invalidated() {
Objects.requireNonNull(get(), "The " + getName() + " must not be null");
}
};
}
```

### Source code for your Spoon processing

```Java
@ModelTest("src/test/resources/NestedAnnotation.java")
void type_and_annotationTypeBothExistForCtAnnotation(Factory factory, CtModel model) {
// contract: the nested annotation has `type` and `annotationType` both set

CtField fieldWithNestedAnnotation = model.getElements(new TypeFilter<>(CtField.class)).get(1);
CtClass bodyOfField = ((CtNewClass) fieldWithNestedAnnotation.getDefaultExpression()).getAnonymousClass();
CtAnnotation nestedAnnotation = bodyOfField.getMethod("invalidated").getAnnotations().get(0);

assertThat(nestedAnnotation.getAnnotationType(), equalTo(factory.Type().createReference(Override.class)));
assertThat(nestedAnnotation.getType(), equalTo(nestedAnnotation.getAnnotationType()));
}
```

### Actual output

```Java
java.lang.AssertionError:
Expected:
but: was null
Expected :
Actual :null
```

### Expected output

```Java
Tests passes
```

### Spoon Version

`master`

### JVM Version

11

### What operating system are you using?

Ubuntu 22.04

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.