openrewrite / rewrite-gradle-plugin

OpenRewrite's Gradle plugin.
Apache License 2.0
60 stars 37 forks source link

CreateTextFile recipe operates in root dir instead of module #258

Open abetaev-equinix opened 8 months ago

abetaev-equinix commented 8 months ago

What version of OpenRewrite are you using?

I am using

How are you running OpenRewrite?

I am using the Gradle plugin, and my project is a multi-module project. I have

root
|- module
|  |- ...
|  '- submodule
|- ...
|- gradlew
|- rewrite.yaml
|- init.gradle
'- build.gradle.kts

What is the smallest, simplest way to reproduce the problem?

type: specs.openrewrite.org/v1beta/recipe
name: com.example.CreateGradleProperties
recipeList:
  - org.openrewrite.text.CreateTextFile:
      relativeFileName: gradle.properties
      fileContents: |
        group={{groupId}}
        rdomain={{rdomain}}
./gradlew module:submodule:rewriteRun --init gradle.init

What did you expect to see?

gradle.properties is created in module/submodule/ directory.

What did you see instead?

gradle.properties is created in root directory.

Are you interested in contributing a fix to OpenRewrite?

If this is a bug, I can think of how this can be fixed. The plugin's documentation does not state what is path relative to. I would expect the module where task runs, as per the Gradle plugin documentation:

When applied to a multi-project build, plugin behavior differs depending on whether the plugin is applied to the root project or to a sub-project. Applied to the root project, the plugin will parse and refactor all sources from all projects. Applied to any project other than the root project, the plugin will parse and refactor only sources from that project.

timtebeek commented 8 months ago

Hi @abetaev-equinix ; Generally we recommend folks apply the plugin to the root project and any subprojects through that, as recipes that parse for instance classes often need the output of other modules too for type resolution. Your case here is of course an exception where things are simplfied to a great extent. I'm not sure if we can generalize the case for running against a submodule that easily, with an eye towards more complex recipes and type resolution, but you're welcome to help explore that.

abetaev-equinix commented 8 months ago

while looking for a way to walk this around i have noticed even weirder behavior: i have

root
|-module
|  |-submodule
|  |  |- ...
|  |  |- gradlew
|  |  |- settings.gradle.kts
|  |  |- rewrite.yml
|  |  '- init.gradle
|  '- ...
|- ...
'- settings.gradle.kts

and when i run ./gradlew while module/submodule is being CWD, it still creates that gradle.properties on top-level project, i.e. near top-level settings.gradle.kts file.

this is definitely not the way it supposed to work: settings.gradle.kts indicates root project for gradle.

and that module/submodule is not even in top-level settings file...

vlsi commented 8 months ago

as recipes that parse for instance classes often need the output of other modules too for type resolution

@timtebeek , I am afraid that is not exactly the reason. The parser does not use source files for dependencies, and it always uses .class files for both third-party, inter-project, and same-project dependencies. In other words, it is fine if parsing one of the projects requires compilation of something else, however, it does not mean the parser must observe all the sources at once every time.