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

Incompatibility with Maven Polyglot leads to ParseError #649

Open
laeubi opened this issue Nov 1, 2023 · 15 comments
Open

Incompatibility with Maven Polyglot leads to ParseError #649

laeubi opened this issue Nov 1, 2023 · 15 comments
Labels
bug Something isn't working

Comments

@laeubi
Copy link

laeubi commented Nov 1, 2023

What version of OpenRewrite are you using?

I am using

  • Maven plugin v5.9.1

How are you running OpenRewrite?

I am using the Maven plugin, and my project is a multi module project.

<plugins>
	<plugin>
		<groupId>org.openrewrite.maven</groupId>
		<artifactId>rewrite-maven-plugin</artifactId>
		<version>5.9.1</version>
		<configuration>
			<activeRecipes>
				<recipe>org.eclipse.ui.PlatformUISetHelp</recipe>
			</activeRecipes>
		</configuration>
	</plugin>
</plugins>

The project is hosted here:
https://github.com/eclipse-platform/eclipse.platform

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

I added the above snippet to the root pom.xml
I created a rewrite.yml like this:

---
type: specs.openrewrite.org/v1beta/recipe
name: org.eclipse.ui.PlatformUISetHelp
displayName: Replace calls of PlatformUI.getWorkbench().getHelpSystem() with PlatformUI.getWorkbench().getHelpSystem().setHelp(...) with e4 safe PlatformUI.setHelp(...) variant
recipeList:
  - org.openrewrite.java.SimplifyMethodChain:
      methodPatternChain: ['org.eclipse.ui.PlatformUI getWorkbench()', 'org.eclipse.ui.IWorkbench getHelpSystem()', 'org.eclipse.ui.help.IWorkbenchHelpSystem setHelp(..)']
      newMethodName: setHelp
      matchOverrides: false

then I go to debug/org.eclipse.debug.ui in the project and call mvn rewrite:run

What is the full stack trace of any errors you encountered?

[INFO] --- rewrite:5.9.1:run (default-cli) @ org.eclipse.debug.ui ---
[INFO] Using active recipe(s) [org.eclipse.ui.PlatformUISetHelp]
[INFO] Using active styles(s) []
[INFO] Validating active recipes...
[INFO] Project [[bundle] Debug UI] Resolving Poms...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  21.543 s (Wall Clock)
[INFO] Finished at: 2023-11-01T17:27:01+01:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.openrewrite.maven:rewrite-maven-plugin:5.9.1:run (default-cli) on project org.eclipse.debug.ui: A type incompatibility occurred while executing org.openrewrite.maven:rewrite-maven-plugin:5.9.1:run: class org.openrewrite.tree.ParseError cannot be cast to class org.openrewrite.xml.tree.Xml$Document (org.openrewrite.tree.ParseError and org.openrewrite.xml.tree.Xml$Document are in unnamed module of loader org.codehaus.plexus.classworlds.realm.ClassRealm @75c258f9)

Are you interested in contributing a fix to OpenRewrite?

This might be because the project uses a polyglot build.

@laeubi laeubi added the bug Something isn't working label Nov 1, 2023
@timtebeek
Copy link
Contributor

Hi @laeubi ; Sorry to hear you're having these issues! I'm looking at these now and can at least confirm your issue; to replicate I've created a rewrite.yml file in the root and ran this command in debug/org.eclipse.debug.ui

mvn -U org.openrewrite.maven:rewrite-maven-plugin:5.10.0:run \
  -DactiveRecipes=org.eclipse.ui.PlatformUISetHelp -X | grep -v DEBUG

It's a convenient shorthand instead of updating the pom.xml.

@timtebeek
Copy link
Contributor

Using the above I get the following rough output:

org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.openrewrite.maven:rewrite-maven-plugin:5.10.0:run (default-cli) on project org.eclipse.debug.ui: A type incompatibility occurred while executing org.openrewrite.maven:rewrite-maven-plugin:5.10.0:run: class org.openrewrite.tree.ParseError cannot be cast to class org.openrewrite.xml.tree.Xml$Document (org.openrewrite.tree.ParseError and org.openrewrite.xml.tree.Xml$Document are in unnamed module of loader org.codehaus.plexus.classworlds.realm.ClassRealm @527bce68)
-----------------------------------------------------
realm =    plugin>org.openrewrite.maven:rewrite-maven-plugin:5.10.0
strategy = org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy
Number of foreign imports: 1
import: Entry[import  from realm ClassRealm[project>org.eclipse.platform:org.eclipse.debug.ui:3.18.200-SNAPSHOT, parent: ClassRealm[maven.api, parent: null]]]

-----------------------------------------------------

    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:333)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:316)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:212)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:174)
    at org.apache.maven.lifecycle.internal.MojoExecutor.access$000 (MojoExecutor.java:75)
    at org.apache.maven.lifecycle.internal.MojoExecutor$1.run (MojoExecutor.java:162)
    at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute (DefaultMojosExecutionStrategy.java:39)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:159)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:105)
    at io.takari.maven.builder.smart.SmartBuilderImpl.buildProject (SmartBuilderImpl.java:209)
    at io.takari.maven.builder.smart.SmartBuilderImpl$ProjectBuildTask.run (SmartBuilderImpl.java:81)
    at java.util.concurrent.Executors$RunnableAdapter.call (Executors.java:539)
    at java.util.concurrent.FutureTask.run (FutureTask.java:264)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1136)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:635)
    at java.lang.Thread.run (Thread.java:833)
Caused by: org.apache.maven.plugin.PluginExecutionException: A type incompatibility occurred while executing org.openrewrite.maven:rewrite-maven-plugin:5.10.0:run: class org.openrewrite.tree.ParseError cannot be cast to class org.openrewrite.xml.tree.Xml$Document (org.openrewrite.tree.ParseError and org.openrewrite.xml.tree.Xml$Document are in unnamed module of loader org.codehaus.plexus.classworlds.realm.ClassRealm @527bce68)
-----------------------------------------------------
realm =    plugin>org.openrewrite.maven:rewrite-maven-plugin:5.10.0
strategy = org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy
Number of foreign imports: 1
import: Entry[import  from realm ClassRealm[project>org.eclipse.platform:org.eclipse.debug.ui:3.18.200-SNAPSHOT, parent: ClassRealm[maven.api, parent: null]]]

-----------------------------------------------------

    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:176)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:328)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:316)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:212)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:174)
    at org.apache.maven.lifecycle.internal.MojoExecutor.access$000 (MojoExecutor.java:75)
    at org.apache.maven.lifecycle.internal.MojoExecutor$1.run (MojoExecutor.java:162)
    at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute (DefaultMojosExecutionStrategy.java:39)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:159)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:105)
    at io.takari.maven.builder.smart.SmartBuilderImpl.buildProject (SmartBuilderImpl.java:209)
    at io.takari.maven.builder.smart.SmartBuilderImpl$ProjectBuildTask.run (SmartBuilderImpl.java:81)
    at java.util.concurrent.Executors$RunnableAdapter.call (Executors.java:539)
    at java.util.concurrent.FutureTask.run (FutureTask.java:264)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1136)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:635)
    at java.lang.Thread.run (Thread.java:833)
Caused by: java.lang.ClassCastException: class org.openrewrite.tree.ParseError cannot be cast to class org.openrewrite.xml.tree.Xml$Document (org.openrewrite.tree.ParseError and org.openrewrite.xml.tree.Xml$Document are in unnamed module of loader org.codehaus.plexus.classworlds.realm.ClassRealm @527bce68)
    at org.openrewrite.maven.MavenMojoProjectParser.parseMaven (MavenMojoProjectParser.java:504)
    at org.openrewrite.maven.MavenMojoProjectParser.listSourceFiles (MavenMojoProjectParser.java:150)
    at org.openrewrite.maven.AbstractRewriteMojo.loadSourceSet (AbstractRewriteMojo.java:257)
    at org.openrewrite.maven.AbstractRewriteMojo.listResults (AbstractRewriteMojo.java:239)
    at org.openrewrite.maven.AbstractRewriteRunMojo.execute (AbstractRewriteRunMojo.java:53)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:126)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:328)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:316)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:212)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:174)
    at org.apache.maven.lifecycle.internal.MojoExecutor.access$000 (MojoExecutor.java:75)
    at org.apache.maven.lifecycle.internal.MojoExecutor$1.run (MojoExecutor.java:162)
    at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute (DefaultMojosExecutionStrategy.java:39)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:159)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:105)
    at io.takari.maven.builder.smart.SmartBuilderImpl.buildProject (SmartBuilderImpl.java:209)
    at io.takari.maven.builder.smart.SmartBuilderImpl$ProjectBuildTask.run (SmartBuilderImpl.java:81)
    at java.util.concurrent.Executors$RunnableAdapter.call (Executors.java:539)
    at java.util.concurrent.FutureTask.run (FutureTask.java:264)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1136)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:635)
    at java.lang.Thread.run (Thread.java:833)

@laeubi
Copy link
Author

laeubi commented Nov 3, 2023

It's a convenient shorthand instead of updating the pom.xml.

Thanks for the hint, I didn't find that in the documentation, maybe its worth to add it here:
https://docs.openrewrite.org/running-recipes/getting-started#step-5-run-a-recipe-with-yaml-configuration

because it suggest adding it to the pom :-)

@timtebeek
Copy link
Contributor

Ah yes; we don't add that shorthand to every guide; we do add it to the individual recipe pages, such that it should be easy to find when you explore recipes.

Just before the above exception I also see

[INFO] Project [[bundle] Debug UI] Resolving Poms...
java.util.NoSuchElementException
    at java.util.Spliterators$1Adapter.next (Spliterators.java:688)
    at org.openrewrite.maven.MavenParser.parseInputs (MavenParser.java:87)
    at org.openrewrite.Parser.parse (Parser.java:58)
    at org.openrewrite.maven.MavenMojoProjectParser.parseMaven (MavenMojoProjectParser.java:478)
    at org.openrewrite.maven.MavenMojoProjectParser.listSourceFiles (MavenMojoProjectParser.java:150)
    at org.openrewrite.maven.AbstractRewriteMojo.loadSourceSet (AbstractRewriteMojo.java:257)
    at org.openrewrite.maven.AbstractRewriteMojo.listResults (AbstractRewriteMojo.java:239)
    at org.openrewrite.maven.AbstractRewriteRunMojo.execute (AbstractRewriteRunMojo.java:53)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:126)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:328)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:316)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:212)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:174)
    at org.apache.maven.lifecycle.internal.MojoExecutor.access$000 (MojoExecutor.java:75)
    at org.apache.maven.lifecycle.internal.MojoExecutor$1.run (MojoExecutor.java:162)
    at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute (DefaultMojosExecutionStrategy.java:39)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:159)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:105)
    at io.takari.maven.builder.smart.SmartBuilderImpl.buildProject (SmartBuilderImpl.java:209)
    at io.takari.maven.builder.smart.SmartBuilderImpl$ProjectBuildTask.run (SmartBuilderImpl.java:81)
    at java.util.concurrent.Executors$RunnableAdapter.call (Executors.java:539)
    at java.util.concurrent.FutureTask.run (FutureTask.java:264)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1136)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:635)
    at java.lang.Thread.run (Thread.java:833)

@timtebeek
Copy link
Contributor

Looks like the Maven parser has an issue with there not being a Maven project in debug/org.eclipse.debug.ui. Perhaps you'd be interested in trying out either the Moderne platform or the Moderne CLI? Those also pick up Java classes outside Maven projects, which it looks like you'd need here.

For the Moderne platform I'd first need to ingest those projects before I can make them available; the Moderne CLI you can already download and try on your own machine.

@laeubi
Copy link
Author

laeubi commented Nov 3, 2023

@timtebeek just in case you want to improve the plugin org.apache.maven.model.locator.ModelLocator / org.apache.maven.model.io.ModelReader should be the way to read the pom for a project.

Its still strange that there is no error but these classcast exceptions.

@timtebeek
Copy link
Contributor

Never worked with those classes, and a bit unsure how to fit them in; would that help pick up a build file in debug/org.eclipse.debug.ui? Curious to know which file that refers to, just to learn more.

We currently have Maven tell us which projects there are, but I guess that breaks down when running on a sub module folder.

if (runPerSubmodule) {
//If running per submodule, parse the source files for only the current project.
List<Marker> projectProvenance = generateProvenance(mavenProject);
Xml.Document maven = parseMaven(mavenProject, projectProvenance, ctx);
return listSourceFiles(mavenProject, maven, projectProvenance, styles, ctx);
} else {
//If running across all project, iterate and parse source files from each project
Map<MavenProject, List<Marker>> projectProvenances = mavenSession.getProjects().stream()
.collect(Collectors.toMap(Function.identity(), this::generateProvenance));
Map<MavenProject, Xml.Document> projectMap = parseMaven(mavenSession.getProjects(), projectProvenances, ctx);
return mavenSession.getProjects().stream()

Any suggestions for improvement welcome, always good to learn more and expand our coverage.

For larger (and especially OSS) projects we do recommend the Moderne UI and CLI though, as that allows you to use pre-built models of your code, to speed things up and allow runs against large projects as a whole.

@laeubi
Copy link
Author

laeubi commented Nov 3, 2023

I just guessing from the location of the exception mention org.openrewrite.maven.MavenParser.parseInputs, but not sure for what purpose one needs to really parse the poms (I suppose maybe for refactoring them), so probably there is something the parser don't like.

In general polyglot works by choosing another file than the default pom.xml as the materialized project-object-model, with ModelLocator you can locate such alternative names, you can output the generated pom by using:

-Dpolyglot.dump.pom=generated_pom.xml

You find other "dialects" here: https://github.com/takari/polyglot-maven

@timtebeek
Copy link
Contributor

Thanks for background there on polyglot; I'd vaguely been aware of that up to now; hadn't encountered it yet, nor can I find how you're using it for that particular folder.

We parse the Maven build files to resolve dependencies, such that we have all types available to attribute LST elements. We need those types for our matchers before we can do replacements; missing dependencies, and thus types, would result in changes not being applied where you would otherwise expect them. That's also why we recommend to run against the full project, rather than a sub module only, as there's likely inter module dependencies there.

Running against the project as a whole might then also have Maven discover the projects that use polyglot, although that's merely my expectation, not something that I've tried. We'll see how the ingestion into app.moderne,io goes, and I'll keep you posted if you can do recipe runs there.

@laeubi
Copy link
Author

laeubi commented Nov 3, 2023

Great, if you need any further information about polyglot let me know, Tycho makes heavy use of that an I currently try to get open-rewrite going in the Eclipse universe, in general you should get all dependencies from the model you don't need to parse the pom as it (especially for Tycho case) only has an incomplete set of dependencies.

@laeubi
Copy link
Author

laeubi commented Nov 3, 2023

@timtebeek I just found how Tycho loads the pom for modifications:

https://github.com/eclipse-tycho/tycho/blob/811d3895a1714003d580a0c6e40553db1d839d4c/tycho-versions-plugin/src/main/java/org/eclipse/tycho/versions/engine/ProjectMetadataReader.java#L106-L123

to see if this is a generated pom (aka not modifiable) we check for the file to start with .polyglot on some places.

@praveensrao
Copy link

I have the same error even with moderne CLI

[ERROR] Failed to execute goal io.moderne:moderne-lst-maven-plugin:2.5.0:compileLst (default-cli) on project postDeployTasks: A type incompatibility occurred while executing io.moderne:moderne-lst-maven-plugin:2.5.0:compileLst: class org.openrewrite.tree.ParseError cannot be cast to class org.openrewrite.xml.tree.Xml$Document (org.openrewrite.tree.ParseError and org.openrewrite.xml.tree.Xml$Document are in unnamed module of loader org.codehaus.plexus.classworlds.realm.ClassRealm @6987a133)

@timtebeek timtebeek changed the title A type incompatibility occurred while executing org.openrewrite.maven:rewrite-maven-plugin:5.9.1:run Incompatibility with Maven Polyglot leads to ParseError Jan 24, 2024
@timtebeek
Copy link
Contributor

Thanks both! I've renamed the issue to better match what's going on as we've learned more; If I understood correctly we can use the PlexusContainer to get the ModelProcessor to locate the generated(?) pom files, which then help parse the project. I'm not sure I can fit that in myself on short term, but open to go over any PR that adds this to the plugin here.

Once we parse those generated pom files we might incidentally also end up modifying them with recipes; not sure if that's an expected issue, but figured point it out just in case.

@timtebeek
Copy link
Contributor

Also came across this snippet in the MavenMojoProjectParser that might factor in here; although it was already in the version reported above: 12ff85a

@laeubi
Copy link
Author

laeubi commented Jan 25, 2024

@timtebeek yes in the end there is a pom file generated, but in general you should not need to read the file directly as the modelreader can do so. What makes me wonder why not use the MavenProject#getModel in the first place?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
Status: Backlog
Development

Successfully merging a pull request may close this issue.

3 participants