[groovy] IDEA-279830: Don't apply groovy object transformation if there is an enabled @POJO annotation

This way it precisely mimics groovy compiler's behavior: no GroovyObject support is invoked for type definition if it is under @POJO.

GitOrigin-RevId: 4ca5e1f399fa47d09aa135302bc5cc6ee56dd499
This commit is contained in:
Konstantin Nisht
2021-10-07 13:54:05 +03:00
committed by intellij-monorepo-bot
parent 7f0ff97509
commit 345dff723a
4 changed files with 49 additions and 7 deletions

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
@file:JvmName("CompileStaticUtil")
package org.jetbrains.plugins.groovy.lang.psi.util
@@ -9,6 +9,9 @@ import com.intellij.psi.PsiMember
import com.intellij.psi.PsiReference
import com.intellij.psi.util.CachedValuesManager
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi.util.parentsOfType
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.*
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil.isEnumConstant
@@ -17,6 +20,19 @@ fun isCompileStatic(e: PsiElement): Boolean {
return containingMember != null && isCompileStatic(containingMember)
}
/**
* Returns `@POJO` annotation or `null` if this annotation is absent or has no effect
*/
fun getPOJO(typedef : GrTypeDefinition): PsiAnnotation? {
// we are interested in static compilation here, not in static typechecker
val inCSContext = typedef.parentsOfType<GrMember>(true).any { it.hasAnnotation(GROOVY_TRANSFORM_COMPILE_STATIC) }
if (inCSContext) {
return typedef.getAnnotation(GROOVY_TRANSFORM_STC_POJO)
} else {
return null
}
}
fun isCompileStatic(member: PsiMember): Boolean {
return CachedValuesManager.getProjectPsiDependentCache(member, ::isCompileStaticInner)
}

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.plugins.groovy.transformations.impl
import com.intellij.openapi.util.Key
@@ -10,6 +10,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUt
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrMethodWrapper
import org.jetbrains.plugins.groovy.lang.psi.util.GrTraitUtil
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_OBJECT
import org.jetbrains.plugins.groovy.lang.psi.util.getPOJO
import org.jetbrains.plugins.groovy.transformations.AstTransformationSupport
import org.jetbrains.plugins.groovy.transformations.TransformationContext
@@ -26,6 +27,7 @@ class GroovyObjectTransformationSupport : AstTransformationSupport {
override fun applyTransformation(context: TransformationContext) {
if (context.codeClass.isInterface) return
if (context.superClass?.language == GroovyLanguage) return
if (getPOJO(context.codeClass) != null) return
val groovyObject = context.findClass(GROOVY_OBJECT)
if (groovyObject == null || !GrTraitUtil.isInterface(groovyObject)) return

View File

@@ -7,22 +7,22 @@ import com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiMember
import com.intellij.psi.util.parentOfType
import com.intellij.psi.util.parentsOfType
import org.jetbrains.plugins.groovy.GroovyBundle
import org.jetbrains.plugins.groovy.codeInspection.BaseInspection
import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_TRANSFORM_COMPILE_STATIC
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_TRANSFORM_STC_POJO
import org.jetbrains.plugins.groovy.lang.psi.util.getPOJO
class GrPOJOInspection : BaseInspection() {
override fun buildVisitor() = object : BaseInspectionVisitor() {
override fun visitTypeDefinition(typeDefinition: GrTypeDefinition) {
val pojo = typeDefinition.getAnnotation(GROOVY_TRANSFORM_STC_POJO) ?: return
if (typeDefinition.parentsOfType<PsiMember>(true).all { !it.hasAnnotation(GROOVY_TRANSFORM_COMPILE_STATIC) }) {
registerError(pojo, GENERIC_ERROR_OR_WARNING)
val actualPojo = typeDefinition.getAnnotation(GROOVY_TRANSFORM_STC_POJO) ?: return
val enabledPojo = getPOJO(typeDefinition)
if (enabledPojo == null) {
registerError(actualPojo, GENERIC_ERROR_OR_WARNING)
}
}
}

View File

@@ -0,0 +1,24 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.plugins.groovy.lang.highlighting
import com.intellij.testFramework.LightProjectDescriptor
import groovy.transform.CompileStatic
import org.jetbrains.plugins.groovy.GroovyProjectDescriptors
import org.jetbrains.plugins.groovy.LightGroovyTestCase
import org.jetbrains.plugins.groovy.codeInspection.cs.GrPOJOInspection
import org.jetbrains.plugins.groovy.util.HighlightingTest
@CompileStatic
class GroovyRecordHighlightingTest extends LightGroovyTestCase implements HighlightingTest {
final LightProjectDescriptor projectDescriptor = GroovyProjectDescriptors.GROOVY_4_0_REAL_JDK
void 'test pojo without cs'() {
highlightingTest '''
import groovy.transform.stc.POJO
<warning>@POJO</warning>
class A {}
''', GrPOJOInspection
}
}