openrewrite / rewrite

Automated mass refactoring of source code.
https://docs.openrewrite.org
Apache License 2.0
2.03k stars 300 forks source link

Rewrite Maven: Adding xml comments within a maven POM file #1802

Closed ferblaca closed 2 years ago

ferblaca commented 2 years ago

Is it possible to add XML comments within a POM xml file?

For example, the use case would be to detect the presence of a maven dependency, and in that case add an XML comment associated to that dependency, either inside the dependency TAG or as a new TAG after or before it.

I have tried to create a recipe for this purpose but I have not been able to do it at all. The recipe is as follows:

  @Override
  protected TreeVisitor<?, ExecutionContext> getVisitor() {
    return new MavenIsoVisitor<ExecutionContext>() {
      @Override
      public Xml.Tag visitTag(final Xml.Tag tag, final ExecutionContext ctx) {
        if (this.isDependencyTag("org.jasypt", "jasypt")) {

          // xml comment
          final Xml.Comment customComment = new Xml.Comment(randomId(),
              tag.getPrefix(),
              Markers.EMPTY,
              "custom comment into dependency!!!");

          // Change Content of dependency Tag
          this.doAfterVisit(new ChangeTagContentVisitor<>(tag, Collections.singletonList(customComment)));
        }
        return super.visitTag(tag, ctx);
      }
    };
  }

But this way I only manage to mash the content of the dependency with the comment, instead of adding it to the Content groupId and artifactId...

For a POM with this content before:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.5</version>
        <relativePath/>
    </parent>
    <groupId>com.example.openrewrite.test</groupId>
    <artifactId>demoOpenrewrite</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demoOpenRewrite</name>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.jasypt</groupId>
            <artifactId>jasypt</artifactId>
            <version>1.9.3</version>
        </dependency>
    </dependencies>
</project>

The result obtained after is:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.5</version>
        <relativePath/>
    </parent>
    <groupId>com.example.openrewrite.test</groupId>
    <artifactId>demoOpenrewrite</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demoOpenRewrite</name>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <!--custom comment into dependency!!!-->
        </dependency>
    </dependencies>
</project>

When the expected/desired is:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.5</version>
        <relativePath/>
    </parent>
    <groupId>com.example.openrewrite.test</groupId>
    <artifactId>demoOpenrewrite</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demoOpenRewrite</name>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <!--custom comment into dependency!!!-->
            <groupId>org.jasypt</groupId>
            <artifactId>jasypt</artifactId>
            <version>1.9.3</version>
        </dependency>
    </dependencies>
</project>

Is it possible to do this? It would be interesting to be able to add comments, either from maven, yaml, java...

thank you very much.

traceyyoshima commented 2 years ago

Is it possible to add XML comments within a POM XML file?

Yes, it is possible with a slight adjustment. The ChangeTagContentVisitor does a replacement of the content in the tag through t = t.withContent(content);. So, you'll need to add the comment to the Tag's content in the position you'd like the comment.

// Example: tagContentWithComment = ListUtils.concat(Collections.singletonList(customComment), tag.getContent())
this.doAfterVisit(new ChangeTagContentVisitor<>(tag, tagContentWithComment));

Is it possible to do this? It would be interesting to be able to add comments, either from maven, yaml, java...

There is a recipe that marks dependencies without modifying the AST if you'd prefer to identify the dependencies without a long-lasting comment. FindDependency will add a Marker to the dependency so that it's printed in a diff, but does not change the AST.

@ferblaca does that answer your questions?

ferblaca commented 2 years ago

hi @traceyyoshima,

Yes, it is possible with a slight adjustment. The ChangeTagContentVisitor does a replacement of the content in the tag through t = t.withContent(content);. So, you'll need to add the comment to the Tag's content in the position you'd like the comment.

Yes, I tried several ways to concatenate the Xml.Comment to the tag.getContent() list without success.

For the following code:

// Change Content of dependency Tag
this.doAfterVisit(new ChangeTagContentVisitor<>(tag, ListUtils.concat(Collections.singletonList(customComment), tag.getContent())));

The compilation error is as follows:

[ERROR] /home/fbc/workspaces/ferblaca/OpenRewriteRecipe/src/main/java/com/ferblaca/openrewrite/recipes/AddCommentIntoMavenDependencyTag.java:[37,15] cannot infer type arguments for org.openrewrite.xml.ChangeTagContentVisitor<>
[ERROR]   reason: inference variable T has incompatible bounds
[ERROR]     equality constraints: org.openrewrite.xml.tree.Content
[ERROR]     lower bounds: java.util.List<capture#1 of ? extends org.openrewrite.xml.tree.Content>,org.openrewrite.xml.tree.Xml.Comment

i'm using jdk11 and maven 3.6.3.

There is a recipe that marks dependencies without modifying the AST if you'd prefer to identify the dependencies without a long-lasting comment. FindDependency will add a Marker to the dependency so that it's printed in a diff, but does not change the AST.

So it wouldn't change the AST, as a suggestion, it would be nice to be able to add comments for the different types of Sources modifying the AST.

traceyyoshima commented 2 years ago

it would be nice to be able to add comments for the different types of Sources modifying the AST.

Interesting idea! I'm not sure exactly what you mean by it would be nice to be able to add comments for the different types of Sources modifying the AST., would you mind explaining the idea in more detail?

traceyyoshima commented 2 years ago

@ferblaca What do you think about this recipe?

ferblaca commented 2 years ago

@ferblaca What do you think about this recipe?

I think it's great!

just one thing, the xPath parameter would be useful to be able to differentiate between adding a comment in managed dependencies and "normal" dependencies, right? since the recipe is totally oriented to TAGs of type dependency...

ferblaca commented 2 years ago

it would be nice to be able to add comments for the different types of Sources modifying the AST.

Interesting idea! I'm not sure exactly what you mean by it would be nice to be able to add comments for the different types of Sources modifying the AST., would you mind explaining the idea in more detail?

Yes, I mean that as XML, and I think JSON in OpenRewrite, YAML and other SourceFiles types have the possibility to add comments. Maybe it's already possible and I'm talking nonsense.

traceyyoshima commented 2 years ago

I think it's great!

Great, I updated the recipe name, the display name, and the description based on feedback. I'll merge the PR in a moment.

Yes, I mean that as XML, and I think JSON in OpenRewrite, YAML and other SourceFiles types have the possibility to add comments. Maybe it's already possible and I'm talking nonsense.

Thank you, your clarification is helpful!

Languages: XML - I openned an issue to add a similar recipe for XML. JSON - Unfortunately, no, since JSON does not support comments. YAML - It is possible to add comments to YAML already, but it is challenging in general. I think the community will need to voice a real need for the functionality before adding a recipe like this.