micronaut-core icon indicating copy to clipboard operation
micronaut-core copied to clipboard

Micronaut 4 Groovy projects fail Intellij compilation

Open j1m-renwick opened this issue 2 years ago • 11 comments

Expected Behavior

All information on https://youtrack.jetbrains.com/issue/IDEA-331174 as I initially believed this to be an Intellij-specific issue.

Example project included in this ticket: groovy-compile-bug.zip

Actual Behaviour

Compilation fails when building Micronaut 4 groovy projects using Intellij's compiler, that have annotations that are defined in Groovy files.

Steps To Reproduce

All information on https://youtrack.jetbrains.com/issue/IDEA-331174 as I initially believed this to be an Intellij-specific issue.

They state that the problem is caused by the library io.micronaut:micronaut-inject-groovy starting from version 4.0.0, so raising it here for further investigation.

Environment Information

Operating System: MacOS Ventura, Version 13.4 JDK Version: Coretto 17

Example Application

see attached

Version

4.0.3

j1m-renwick avatar Sep 24 '23 15:09 j1m-renwick

Reproducer:

// Annotation.groovy
import java.lang.annotation.ElementType
import java.lang.annotation.Target

@Target(ElementType.FIELD)
@interface Annotation {
}
// Usage.groovy
class Usage {
    @Annotation
    String field
}

Then

groovyc Usage.groovy Annotation.groovy -cp micronaut-inject-groovy-4.1.6.jar:micronaut-core-4.1.6.jar:micronaut-core-processor-4.1.6.jar:micronaut-inject-4.1.6.jar:jakarta.annotation-api-2.1.1.jar:jakarta.inject-api-2.0.1.jar:micronaut-aop-4.1.6.jar:asm-9.5.jar:asm-commons-9.5.jar

Results with

Invalid duplicate class definition of class Annotation : The sources file:/Users/_/Annotation.groovy and Annotation.groovy each contain a class with the name Annotation.

The problem is that io.micronaut.ast.groovy.annotation.GroovyAnnotationMetadataBuilder#getAnnotationMirror tries to find ClassNodes when there are none, and it results in generation of additional SourceUnit for Annotation. Maybe the annotation processing occurrs too early?

knisht avatar Sep 24 '23 20:09 knisht

does it work when building with gradle? you should let intellij delegate build tasks to gradle

yawkat avatar Sep 25 '23 06:09 yawkat

Please, configure your IDE according to USING INTELLIJ IDEA TO DEVELOP MICRONAUT APPLICATIONS and let us know if the issue is still present.

sdelamo avatar Sep 25 '23 06:09 sdelamo

When I specify the Gradle option in the IDE setup it works, as specified on that link - this is the workaround I currently have to use for the project:

image

However, pre Micronaut 4 the Intellij compiler option worked as well, and makes for a much faster dev experience in terms of build and start times:

image

j1m-renwick avatar Sep 25 '23 08:09 j1m-renwick

Looks like a bug in the IntelliJ compiler or the Groovy compiler. None of the methods we use is supposted to create an additional class.

dstepanov avatar Sep 25 '23 08:09 dstepanov

Got a standalone script (just requires Groovy and Bash to be installed) to reproduce the issue

#!/usr/bin/env bash

MICRONAUT_CORE_VERSION=4.1.6
REQUIRED_MICRONAUT_CORE_LIBS="\
inject-groovy \
core-processor \
inject \
aop \
core"

EXTRA_LIBS="\
org.ow2.asm:asm-commons:9.5 \
org.ow2.asm:asm:9.5 \
jakarta.annotation:jakarta.annotation-api:2.1.1 \
jakarta.inject:jakarta.inject-api:2.0.1"

CP="."

mkdir -p libs

for lib in $REQUIRED_MICRONAUT_CORE_LIBS; do
  if [ ! -f libs/micronaut-$lib-$MICRONAUT_CORE_VERSION.jar ]; then
    echo "Downloading $lib"
    mvn dependency:get -Dartifact=io.micronaut:micronaut-$lib:$MICRONAUT_CORE_VERSION -Ddest=./libs/ > /dev/null
  else
    echo "Already got $lib"
  fi
  CP="$CP:libs/micronaut-$lib-$MICRONAUT_CORE_VERSION.jar"
done

for lib in $EXTRA_LIBS; do
  FN="$(echo $lib | cut -d: -f2 -f3 | tr ':' "-").jar"
  if [ ! -f libs/$FN ]; then
    echo "Downloading $lib"
    mvn dependency:get -Dartifact=$lib -Ddest=./libs/ > /dev/null
  else
    echo "Already got $lib"
  fi
  CP="$CP:libs/$FN"
done

if [ ! -f Annotation.groovy ]; then
  echo "Generating Annotation.groovy"
  cat <<EOF > Annotation.groovy
import java.lang.annotation.ElementType
import java.lang.annotation.Target

@Target(ElementType.FIELD)
@interface Annotation {
}
EOF
else
  echo "Already got Annotation.groovy"
fi
if [ ! -f Usage.groovy ]; then
  echo "Generating Usage.groovy"
  cat <<EOF > Usage.groovy
// Usage.groovy
class Usage {
    @Annotation
    String field
}
EOF
else
  echo "Already got Usage.groovy"
fi

echo "Running groovyc -e -cp $CP Usage.groovy Annotation.groovy"
groovyc -e -cp $CP Usage.groovy Annotation.groovy

timyates avatar Sep 25 '23 10:09 timyates

@dstepanov If I revert this PR https://github.com/micronaut-projects/micronaut-core/pull/9232 the compilation passes, but I am not sure what is causing the problem

timyates avatar Sep 26 '23 15:09 timyates

That is fixing some other stuff

dstepanov avatar Sep 26 '23 16:09 dstepanov

Can you create a test inside the core?

dstepanov avatar Sep 26 '23 16:09 dstepanov

@dstepanov Reproducer here: https://github.com/micronaut-projects/micronaut-core/pull/9925

(this took more effort that it may seem from looking at it 😉)

timyates avatar Sep 27 '23 11:09 timyates

Hey, is there any way of progressing this? As far as I can see it's still an issue in the latest Micronaut release

j1m-renwick avatar Jun 05 '24 09:06 j1m-renwick