Code Inspection support for Custom Annotation (Compiler Error)

已回答
One of the problems I've encountered while using DTOs is that I often find myself shipping (accidentally) entities along with DTOs. To mitigate this problem, I created another Maven project with an annotation (@ValidDTO) and its processor that finds if a DTO annotated with @ValidDTO has @Entity annotated fields.

This is my annotation.

@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface ValidDTO {}

And, this is my processor.

@SupportedAnnotationTypes("com.aj.annotations.ValidDTO")
@SupportedSourceVersion(SourceVersion.RELEASE_11)
public class ValidDTOProcessor extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> set,
                           RoundEnvironment roundEnv) {

        List<Entity> entityFields = roundEnv.getElementsAnnotatedWith(ValidDTO.class)
                .stream()
                .filter(element -> element.getKind()==ElementKind.CLASS || element.getKind()==ElementKind.INTERFACE)
                .map(Element::getEnclosedElements)
                .flatMap(List::stream)
                .filter(element -> element.getKind()==ElementKind.FIELD)
                .map(element -> element.getAnnotation(Entity.class))
                .collect(Collectors.toList());

            if (!entityFields.isEmpty()) {
            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Types annotated with ValidDTO " +
                    "cannot have member variables that are @Entity annotated");
        }

        return true;
    }
}

This is how my POM.xml looks for the Maven project with the annotation and its processor

 <groupId>com.aj</groupId>
    <artifactId>aj-annotations</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                    <generatedSourcesDirectory>${project.build.directory}/generated-sources/
                    </generatedSourcesDirectory>
                    <proc>none</proc>
                    <annotationProcessors>
                        <annotationProcessor>
                            com.aj.annotations.processors.ValidDTOProcessor
                        </annotationProcessor>
                    </annotationProcessors>
                    <debug>true</debug>
                </configuration>
            </plugin>
        </plugins>
    </build>

So, I installed this package as a dependency in another projected and annotated a DTO with it. I purposefully added couple of entities as member variables to see the error.

@ValidDTO
public class FacilityDTO {
  private User user;
  private List<User> users;
}

where,

@Entity
@Table("User")
public class User {} 

is an entity.

Now, my custom annotation works perfectly good when I run mvn clean install or build project. I can see the expected "Types annotated with ValidDTO cannot have member variables that are @Entity annotated" in the terminal.

However, I do not see the error in IntelliJ editor. I do not see any red squiggly line underneath the annotation telling me that the DTO is invalid.

The closest expected desired behavior I can reference is a compile error when using @FunctionalInterface on an interface that has more than one abstract method.

I just need help configuring my IDE. Any help is appreciated!

2

Hello,

To have a special highlighting in the Editor you may create a custom inspection (https://www.jetbrains.com/help/idea/creating-custom-inspections.html) using two structural search templates. 

Fo example, the first search template can look as follows:

it will be a search template for `@Entity` annotated classes. 

And the second template will search for the `@ValidDTO` annotated classes that have private fields of types annotated with `@Entity`:

The created inspection can be run as common one, giving the searched results:

and providing highlighting in the Editor.

Here is more information that can help: https://www.jetbrains.com/help/idea/structural-search-and-replace.html

1
Avatar
Permanently deleted user

Olga, 

Thank you for the reply. I have a few questions. In the first template, at the very end, is that your cursor or a pipe ( | ) symbol? I Typed the second template exactly as you have in the screenshot. However, I cannot get that reference=entity class hint in my template. 

0

It's a cursor :)

Please see my templates:

the first one:

@javax.persistence.Entity class $C$ {}

and the second one:

@annot.ValidDTO
class $C$ {
private $type$ $field$;
}

here you need to put the cursor on type and add the reference filter: reference = the_name_of_first_search_template (in my case it's "entity class").

So the two templates have to be created, the first one is used as the reference in the second.

1
Avatar
Permanently deleted user

Thank you again. I'm quite close to the desired behavior. Now, I have the correct reference in my second template. 

This is my order

entity_class

Cannot have entity as member variable in a DTO

With this, I'm seeing two things

First, the Entity annotated class is highlighted as an error. That is not expected behavior. (And a deal breaker)

Second, the whole DTO class, including every single line, is highlighted when it has Entity annotated member variable. I'd like either the guilty field or the DTO class or the annotation to be highlighted in red. (Not a deal breaker)

Thanks again!

0

You need to define the "search target" = "field" in the second template so that only the field is highlighted:

and disable the created "entity class" inspection in "Configure inspections | Inspections" pane:

0
Avatar
Permanently deleted user

Olga, this looks perfect. Unfortunately, I am not working on a Mac and I do not see Structural Search Option in this list.

This is what I have. I also updated my Intellij to the latest version just few minutes ago.

0

Sorry for misleading, such a variant of the tool will be available only in 2020.2 (not yet released); in the current version and EAP (https://www.jetbrains.com/idea/nextversion/) the templates are saved only within one inspection created, so you can't  yet enable/disable individual patterns, here is the issue for it: https://youtrack.jetbrains.com/issue/IDEA-116960.

0
Avatar
Permanently deleted user

I see. I download 2020.1 beta and didn't see it either. Seems like a 2020.2 feature only.

0

请先登录再写评论。