3

I try to work a bit with Xtend and Xcore for a student project. For that, I configured a Maven project with dependencies to generate xtend/xcore sources by the Maven generate-sources phase. Xtend classes and Xcore models are well compiled to Java, but it seems that a Xtend constant (val) in a try-with-resource is not compile to a final variable in Java when I execute the mvn clean generate-sources command. However, when Eclipse compile the xtend/xcore classes, this problem does not appear. I reproducted the problem in a minimal project:

Bar Xtend class:

class Bar {
    
    def static void main(String... args) {
        try(val foo = new BufferedInputStream(System.in)) {
            val bar = [| bar(foo)]
            bar.apply
        }
    }
    
    def static void bar(BufferedInputStream bis) {
        System.out.println(new BufferedReader((new InputStreamReader(bis))).lines().collect(Collectors.joining("\n")))
    }
    
}

Product code by Maven:

public class Bar {
  public static void main(final String... args) {
    try {
      List<Throwable> _ts = new ArrayList<Throwable>();
      BufferedInputStream foo = null;
      try {
        foo = new BufferedInputStream(System.in);
        final Procedure0 _function = new Procedure0() {
          public void apply() {
            Bar.bar(foo);
          }
        };
        final Procedure0 bar = _function;
        bar.apply();
      } finally {
        if (foo != null) {
          try {
            foo.close();
          } catch (Throwable _t) {
            _ts.add(_t);
          }
        }
        if(!_ts.isEmpty()) throw Exceptions.sneakyThrow(_ts.get(0));
      }
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  public static void bar(final BufferedInputStream bis) {
    InputStreamReader _inputStreamReader = new InputStreamReader(bis);
    System.out.println(new BufferedReader(_inputStreamReader).lines().collect(Collectors.joining("\n")));
  }
}

The product code has a compilation error. Indeed, the line 10 (Bar.bar(foo);), throw Local variable foo defined in an enclosing scope must be final or effectively final.

To compare, product code by Eclipse:

@SuppressWarnings("all")
public class Bar {
  public static void main(final String... args) {
    try {
      try (final BufferedInputStream foo = new BufferedInputStream(System.in)) {
        final Procedure0 _function = () -> {
          Bar.bar(foo);
        };
        final Procedure0 bar = _function;
        bar.apply();
      }
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  public static void bar(final BufferedInputStream bis) {
    InputStreamReader _inputStreamReader = new InputStreamReader(bis);
    System.out.println(new BufferedReader(_inputStreamReader).lines().collect(Collectors.joining("\n")));
  }
}

I have the impression that Maven does not compile to Java 8 code but I think I set up the version in the pom.xml.

My pom.xml for the minimal project:

<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>
    <groupId>fr.theogiraudet</groupId>
    <version>1.0.0-SNAPSHOT</version>
    <artifactId>fr.theogiraudet.foo</artifactId>

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

        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>

        <core-resources-version>3.7.100</core-resources-version>
        <emf-version>2.23.0</emf-version>
        <emf-common-version>2.21.0</emf-common-version>
        <xtext-version>2.24.0</xtext-version>
        <ecore-xtext-version>1.5.0</ecore-xtext-version>
        <ecore-xcore-version>1.16.0</ecore-xcore-version>
        <ecore-xcore-lib-version>1.5.0</ecore-xcore-lib-version>
        
        <xtend-path>${basedir}/src/main/xtend</xtend-path>
        <xcore-path>${basedir}/model</xcore-path>
        <xtend-gen-path>${basedir}/src/main/javagen</xtend-gen-path>
        <xcore-gen-path>${basedir}/src/main/javagen</xcore-gen-path>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.eclipse.emf</groupId>
            <artifactId>org.eclipse.emf.common</artifactId>
            <version>${emf-common-version}</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.emf</groupId>
            <artifactId>org.eclipse.emf.ecore</artifactId>
            <version>${emf-version}</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.emf</groupId>
            <artifactId>org.eclipse.emf.ecore.xcore.lib</artifactId>
            <version>${ecore-xcore-lib-version}</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.xtext</groupId>
            <artifactId>org.eclipse.xtext.xbase.lib</artifactId>
            <version>${xtext-version}</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.xtend</groupId>
            <artifactId>org.eclipse.xtend.lib</artifactId>
            <version>${xtext-version}</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.emf</groupId>
            <artifactId>org.eclipse.emf.ecore.xmi</artifactId>
            <version>2.16.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
            </plugin>

            <plugin>
                <artifactId>maven-clean-plugin</artifactId>
                <version>2.6.1</version>
                <configuration>
                    <filesets>
                        <fileset>
                            <excludes>
                                <exclude>.dummy.txt</exclude>
                            </excludes>
                            <directory>${xtend-gen-path}</directory>
                        </fileset>
                        <fileset>
                            <excludes>
                                <exclude>.dummy.txt</exclude>
                            </excludes>
                            <directory>${xtend-gen-path}</directory>
                        </fileset>
                    </filesets>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <version>1.9.1</version>
                <executions>
                    <execution>
                        <id>add-source</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>add-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>${xtend-gen-path}</source>
                            </sources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <groupId>org.eclipse.xtext</groupId>
                <artifactId>xtext-maven-plugin</artifactId>
                <version>${xtext-version}</version>
                <executions>
                    <execution>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <languages>
                        <language>
                            <setup>org.eclipse.emf.codegen.ecore.xtext.GenModelSupport</setup>
                        </language>
                        <language>
                            <setup>org.eclipse.xtend.core.XtendStandaloneSetup</setup>
                            <outputConfigurations>
                                <outputConfiguration>
                                    <outputDirectory>${xtend-gen-path}</outputDirectory>
                                </outputConfiguration>
                            </outputConfigurations>
                        </language>
                        <language>
                            <setup>org.eclipse.emf.ecore.xcore.XcoreStandaloneSetup</setup>
                            <outputConfigurations>
                                <outputConfiguration>
                                    <outputDirectory>${xcore-gen-path}</outputDirectory>
                                </outputConfiguration>
                            </outputConfigurations>

                        </language>
                    </languages>
                    <sourceRoots>
                        <root>${xtend-path}</root>
                        <root>${xcore-path}</root>
                    </sourceRoots>
                    <javaSourceVersion>1.8</javaSourceVersion>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.eclipse.core</groupId>
                        <artifactId>org.eclipse.core.resources</artifactId>
                        <version>${core-resources-version}</version>
                    </dependency>
                    <dependency>
                        <groupId>org.eclipse.xtend</groupId>
                        <artifactId>org.eclipse.xtend.core</artifactId>
                        <version>${xtext-version}</version>
                    </dependency>
                    <dependency>
                        <groupId>org.eclipse.emf</groupId>
                        <artifactId>org.eclipse.emf.codegen.ecore.xtext</artifactId>
                        <version>${ecore-xtext-version}</version>
                    </dependency>
                    <dependency>
                        <groupId>org.eclipse.emf</groupId>
                        <artifactId>org.eclipse.emf.ecore.xcore</artifactId>
                        <version>${ecore-xcore-version}</version>
                    </dependency>
                    <dependency>
                        <groupId>org.eclipse.emf</groupId>
                        <artifactId>org.eclipse.emf.ecore.xcore.lib</artifactId>
                        <version>${ecore-xcore-lib-version}</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>

</project>

For Eclipse, I use:

  • Xtend IDE plugin (v.2.24.0)
  • Xtext Complete SDK (v.2.24.0)
  • EMF - Eclipse Modeling Framework Xcore SDK (v.1.16.0)

You can clone the minimal project here: https://github.com/theogiraudet/XtendMinimalProject.git

Thank you in advance for your help!

Oromis
  • 196
  • 2
  • 13
  • 1
    i assume this is https://github.com/eclipse/xtext-maven/issues/11. i think that javaSourceVersion wont be set to java 8 and thus strange stuff will be generated. you may remote debug into that – Christian Dietrich Jan 30 '21 at 15:09
  • However, "xtext-maven-plugin:2.24.0:generate" tells me that the compiler source and target levels are 1.8... :/ @ChristianDietrich – Oromis Jan 30 '21 at 15:29
  • this wont help if nobody passes it to GeneratorConfig class – Christian Dietrich Jan 30 '21 at 16:31
  • see also https://github.com/eclipse/xtext-extras/issues/113 – Christian Dietrich Jan 30 '21 at 16:32
  • Yeah, starting from the information of your first link, I also came to the second one. There is no way to bypass this issue by using another Maven plugin for example? – Oromis Jan 30 '21 at 16:39
  • 1
    you could try to craft a subclass of XtendStandaloneSetup that binds a custom GeneratorConfigProvider in a custom module, package that to a own jar and mention the new class in the maven config – Christian Dietrich Jan 30 '21 at 16:41
  • of course you could also try to partition the code in xtend and xcore to different projects and use the xtend-maven-plugin but i assume your intent is to use them in the same module – Christian Dietrich Jan 30 '21 at 16:54
  • Yeah, I would like to have both in the same module :/ Your idea about creating a subclass is interesting, but I'm afraid I don't have enough knowledges and skills to do that... I'm still going to look a little bit this way – Oromis Jan 30 '21 at 17:12

0 Answers0