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

Does Xtend work with java records? #2823

Closed
tripleo1 opened this issue Oct 18, 2023 · 27 comments · Fixed by #3037
Closed

Does Xtend work with java records? #2823

tripleo1 opened this issue Oct 18, 2023 · 27 comments · Fixed by #3037
Milestone

Comments

@tripleo1
Copy link

I am testing Xtend with a Java 17 project and it complains about record classes:

Starting a Gradle Daemon (subsequent builds will be faster)

> Task :project:generateXtext FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':project:generateXtext'.
> Cannot handle type public @SuppressWarnings("unused") record GRecord(Parm1 parm1, Parm2 parm2, Supplier<Dep2> arg3) {
plugins { id "org.xtext.xtend" version "4.0.0" }
java {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}
@cdietrich
Copy link
Member

hi, can you please provide more information what you are actually doing?

@tripleo1
Copy link
Author

hi, can you please provide more information what you are actually doing?

I just dropped the gradle plugin into an existing java project, and am trying to get a clean build.

On a side note, I don't really like records: Should I just convert the records to Xtend?

@cdietrich
Copy link
Member

cdietrich commented Oct 18, 2023

there is no record in xtend. there is also no in java source lang.
so the gradle plugin would be able to parse the java files i guess
which xtext version do you use?

@cdietrich
Copy link
Member

Caused by: java.lang.IllegalArgumentException: Cannot handle type public record MyRecord(String a, int b) {
/* Implicit */  private final String a;
/* Implicit */  private final int b;
  public MyRecord(String a, int b) {
    .a = a;
    .b = b;
  }
}
        at org.eclipse.xtext.java.resource.JavaDerivedStateComputer.createType(JavaDerivedStateComputer.java:130)
        at org.eclipse.xtext.java.resource.JavaDerivedStateComputer.installStubs(JavaDerivedStateComputer.java:107)
        at org.eclipse.xtext.java.resource.JavaResource.lambda$0(JavaResource.java:174)
        at org.eclipse.xtext.java.resource.JavaResource.initializing(JavaResource.java:190)
        at org.eclipse.xtext.java.resource.JavaResource.installStubs(JavaResource.java:173)
        at org.eclipse.xtext.java.resource.JavaResourceDescriptionManager.getResourceDescription(JavaResourceDescriptionManager.java:48)

@cdietrich
Copy link
Member

question would be if record can easily be mapped to a class
otherwise this could be a bigger thing.

@tripleo1
Copy link
Author

Caused by: java.lang.IllegalArgumentException: Cannot handle type public record MyRecord(String a, int b) {
/* Implicit */  private final String a;
/* Implicit */  private final int b;
  public MyRecord(String a, int b) {
    .a = a;
    .b = b;
  }
}
        at org.eclipse.xtext.java.resource.JavaDerivedStateComputer.createType(JavaDerivedStateComputer.java:130)
        at org.eclipse.xtext.java.resource.JavaDerivedStateComputer.installStubs(JavaDerivedStateComputer.java:107)
        at org.eclipse.xtext.java.resource.JavaResource.lambda$0(JavaResource.java:174)
        at org.eclipse.xtext.java.resource.JavaResource.initializing(JavaResource.java:190)
        at org.eclipse.xtext.java.resource.JavaResource.installStubs(JavaResource.java:173)
        at org.eclipse.xtext.java.resource.JavaResourceDescriptionManager.getResourceDescription(JavaResourceDescriptionManager.java:48)
  1. I am assuming this is the same problem that I have...
  2. it could be said then that Xtend does not support Java records?
  3. What does this even mean?

there is no record in xtend.

  1. My assumption is correct, then.
  2. I willl learn more about the language grammar.

there is also no in java source lang.

  1. I know it generates 8,
  2. (5b) but I'm not sure about anything else.

which xtext version do you use?

find ~/.gradle/caches/jars-9 -name '*xtext*.jar'
/home/user/.gradle/caches/jars-9/80e6104f623c271fb1ec71b8d3a7b8b2/org.eclipse.xtext.xbase.lib-2.17.1.jar
/home/user/.gradle/caches/jars-9/1024beae751fc6fe2dd8a11a7969799c/xtext-gradle-plugin-4.0.0.jar
/home/user/.gradle/caches/jars-9/275f80d50eb809b8abebdb57ce829556/org.eclipse.xtext.xbase.lib-2.17.1.jar
/home/user/.gradle/caches/jars-9/4c9b4dd18261ca3f0bb4f1d9bdd9bde1/xtext-gradle-plugin-4.0.0.jar

Who know which one it will choose?

@cdietrich
Copy link
Member

You don’t have an explicit xbase/xtend.lib dependency in your project ?

@cdietrich
Copy link
Member

I wonder if you face the same problem in a maven project

@tripleo1
Copy link
Author

You don’t have an explicit xbase/xtend.lib dependency in your project ?

oh, there we go:

implementation 'org.eclipse.xtend:org.eclipse.xtend.lib:2.30.0'

I wonder if you face the same problem in a maven project

what could possibly be the difference?

@cdietrich
Copy link
Member

cdietrich commented Oct 18, 2023

Maven links against class files and not java files
Thus we might be better at eating records but I don’t know
(at least until you use the record)

@rasifix
Copy link

rasifix commented Nov 9, 2023

We are also having the same issue with records. The records are consumed by Xtext when building the index for Java classes. I see two possible solutions:

  1. xtext ignores records and issues a warning (in many cases those records are irrelevant for Xtext code generation)
  2. xtext learns how to deal with records

Point two should not be a big issue as records are really just syntactic sugar. i.e. they are just normal Java classes with some special properties (fields are final, accessor methods, constructor with all properties, ...). So, IMHO, this would be a straightforward and desirable fix.

@LorenzoBettini
Copy link
Contributor

If I understand correctly, the Ecore model of Xtext Java bundle should be updated with records first, shouldn't it?

@rasifix
Copy link

rasifix commented Nov 9, 2023

I don't think this is really necessary. Records are just Java classes.

@cdietrich
Copy link
Member

we at least need to transform them to classes.
am not sure what @szarnekow recommends

@LorenzoBettini
Copy link
Contributor

At least, this switch, which throws the exception,

, should be updated somehow accordingly.

@cdietrich
Copy link
Member

yes but this also affect the code that runs in eclipse
JdtTypeProvider or something the like

@rasifix
Copy link

rasifix commented Nov 9, 2023

At least, this switch, which throws the exception,

, should be updated somehow accordingly.

that is exactly where I am looking at. The "record" has to be handled there.

@cdietrich
Copy link
Member

ping @szarnekow

@rasifix
Copy link

rasifix commented Nov 18, 2023

I was trying to fix this issue, but I have stumbled over additional problems. I have been experimenting with the domain language example:

  • created a record class
  • tried to reference it from the domain model

The record cannot be resolved. What I found out after a longer debugging session: JdtBasedTypeFactory constructs a ASTParser with JLS 3. This obviously does not support records, as records have not been part of JLS 3 (Java 5!?). Changing that to something more up to date at least fixes this issue. Why is this fixed to such a legacy version of Java?

Aside of that (shall I open a defect for it?), I do not get to the JavaDerivedStateComputer and verify that just adding "records" to the type switch fixes the issue. I would need some hints to further debug and test this.

@cdietrich
Copy link
Member

cdietrich commented Nov 18, 2023

i cannot tell you anything about why.
maybe @szarnekow can.
what happens if you bump that? (getJLSLatest)

@rasifix
Copy link

rasifix commented Nov 18, 2023

when I bump the version to e.g. AST.getJLSLatest() the Xtext properly resolves the reference to the record from the domain model DSL

@cdietrich
Copy link
Member

cdietrich commented Nov 18, 2023

with or without changes to the Type factories?

@rasifix
Copy link

rasifix commented Nov 18, 2023

all I did was bump the JLS version in JdtBasedTypeFactory#157; no other changes so far

@cdietrich
Copy link
Member

I would have expected to find a similar switch there too

@cdietrich
Copy link
Member

maybe its working cause
protected JvmDeclaredType createType(ITypeBinding typeBinding, String handleIdentifier, List<String> path, StringBuilder fqn) {
has no switch with default throw exception
as the other place has

@szarnekow
Copy link
Contributor

I think back then there was no AST.getLastest available. We use much more recent JDT now, so that can be fixed

@LorenzoBettini
Copy link
Contributor

Some updates:

by setting

	/**
	 * A cached AST parser that's reused by top-level type {@link #createType(IType) creation}.
	 */
	@SuppressWarnings("all")
	private final ASTParser parser = ASTParser.newParser(AST.getJLSLatest());

in org.eclipse.xtext.common.types.access.jdt.JdtBasedTypeFactory, running another instance of Eclipse, create a plug-in project with JavaSE-21, the Xtend file can seamlessly use Java records:

Screenshot from 2024-04-23 14-53-05

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants