This is an automated email from the ASF dual-hosted git repository.
jdaugherty pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/grails-intellij-plugin.git
The following commit(s) were added to refs/heads/main by this push:
new 44489f5 Fix GORM member resolution for class-reference qualifiers on
2026.2
44489f5 is described below
commit 44489f51215608e1687aa60aec762157751208ec
Author: James Daugherty <[email protected]>
AuthorDate: Sat Jul 18 22:38:54 2026 -0400
Fix GORM member resolution for class-reference qualifiers on 2026.2
Since the IntelliJ 2026.2 platform bump, a bare class-reference qualifier
(e.g. `Domain.findAllBy...`) no longer carries a class type:
getQualifierType()
returns null and NonCodeMembersContributor is invoked with psiClass=null
and an
Object qualifier type. This silently disabled every Grails contributor
gated on
the domain class, breaking dynamic-finder completion, resolution,
highlighting,
rename, and related features.
- GormDynamicFinderCompletionProvider: resolve the domain class from the
static
qualifier reference instead of from the now-null qualifier type.
- GrailsArtifactNonCodeMemberProcessor: when the platform passes
psiClass=null,
recover the class from the static qualifier reference (still gated by
getArtifact(), so only Grails artifacts receive synthetic members).
Reduces test failures from 238 to 168 (970 total).
---
.../GrailsArtifactNonCodeMemberProcessor.java | 28 +++++++++++++++++-----
.../GormDynamicFinderCompletionProvider.java | 16 ++++++++-----
2 files changed, 32 insertions(+), 12 deletions(-)
diff --git
a/src/org/jetbrains/plugins/grails/references/GrailsArtifactNonCodeMemberProcessor.java
b/src/org/jetbrains/plugins/grails/references/GrailsArtifactNonCodeMemberProcessor.java
index 24028b3..123e3aa 100644
---
a/src/org/jetbrains/plugins/grails/references/GrailsArtifactNonCodeMemberProcessor.java
+++
b/src/org/jetbrains/plugins/grails/references/GrailsArtifactNonCodeMemberProcessor.java
@@ -18,6 +18,7 @@ package org.jetbrains.plugins.grails.references;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiType;
import com.intellij.psi.ResolveState;
import com.intellij.psi.scope.PsiScopeProcessor;
@@ -38,6 +39,8 @@ import
org.jetbrains.plugins.grails.references.urlMappings.UrlMappingMemberProvi
import org.jetbrains.plugins.grails.util.GrailsArtifact;
import org.jetbrains.plugins.grails.util.GrailsPsiUtil;
import org.jetbrains.plugins.grails.util.GrailsUtils;
+import
org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+import
org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersContributor;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
@@ -79,24 +82,37 @@ public final class GrailsArtifactNonCodeMemberProcessor
extends NonCodeMembersCo
@NotNull PsiScopeProcessor processor,
@NotNull PsiElement place,
@NotNull ResolveState state) {
- if (psiClass == null) return;
-
- GrailsArtifact artifact = CachedValuesManager.getCachedValue(psiClass, ()
->
- CachedValueProvider.Result.create(getArtifact(psiClass),
PsiModificationTracker.MODIFICATION_COUNT));
+ // Since 2026.2 a bare class-reference qualifier (e.g.
`Domain.findAllBy...`) is passed
+ // with a null psiClass and an Object qualifier type, so recover the
referenced class
+ // from the static qualifier. getArtifact() below still gates members to
Grails artifacts.
+ final PsiClass targetClass = psiClass != null ? psiClass :
resolveStaticQualifierClass(place);
+ if (targetClass == null) return;
+
+ GrailsArtifact artifact = CachedValuesManager.getCachedValue(targetClass,
() ->
+ CachedValueProvider.Result.create(getArtifact(targetClass),
PsiModificationTracker.MODIFICATION_COUNT));
if (artifact == null) return;
// See org.codehaus.groovy.grails.compiler.logging.LoggingTransformer
- if (!GrailsPsiUtil.processLogVariable(processor, psiClass,
ResolveUtil.getNameHint(processor))) return;
+ if (!GrailsPsiUtil.processLogVariable(processor, targetClass,
ResolveUtil.getNameHint(processor))) return;
MemberProvider[] providers = getMemberProviderMap().get(artifact);
if (providers != null) {
for (MemberProvider provider : providers) {
- provider.processMembers(processor, psiClass, place);
+ provider.processMembers(processor, targetClass, place);
}
}
}
+ private static @Nullable PsiClass resolveStaticQualifierClass(@NotNull
PsiElement place) {
+ if (!(place instanceof GrReferenceExpression)) return null;
+ GrExpression qualifier =
((GrReferenceExpression)place).getQualifierExpression();
+ if (qualifier == null) return null;
+ PsiReference ref = qualifier.getReference();
+ PsiElement resolved = ref == null ? null : ref.resolve();
+ return resolved instanceof PsiClass ? (PsiClass)resolved : null;
+ }
+
private static @Nullable GrailsArtifact getArtifact(@NotNull PsiClass
psiClass) {
GrailsArtifact artifact = GrailsUtils.calculateArtifactType(psiClass);
return artifact != null ? artifact : isTagLibByPackage(psiClass) ?
GrailsArtifact.TAGLIB : null;
diff --git
a/src/org/jetbrains/plugins/grails/references/domain/GormDynamicFinderCompletionProvider.java
b/src/org/jetbrains/plugins/grails/references/domain/GormDynamicFinderCompletionProvider.java
index 6e4a893..1006540 100644
---
a/src/org/jetbrains/plugins/grails/references/domain/GormDynamicFinderCompletionProvider.java
+++
b/src/org/jetbrains/plugins/grails/references/domain/GormDynamicFinderCompletionProvider.java
@@ -29,6 +29,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiClassType;
+import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiType;
import com.intellij.util.ArrayUtilRt;
@@ -64,19 +65,22 @@ public final class GormDynamicFinderCompletionProvider
extends CompletionProvide
final GrReferenceExpression refExpr =
(GrReferenceExpression)parameters.getPosition().getParent();
final GrExpression qualifier = refExpr.getQualifierExpression();
if (qualifier == null) return;
- final PsiType type = GroovyCompletionUtil.getQualifierType(qualifier);
-
- if (!(type instanceof PsiClassType)) return;
PsiClass domainClass;
if (isStaticMemberReference(qualifier)) {
- domainClass = ((PsiClassType)type).resolve();
+ // `Domain.findAllBy...`: the qualifier is a class reference. Since
2026.2 a bare class
+ // reference expression no longer has a PsiClassType, so resolve the
class from the
+ // reference itself rather than from getQualifierType() (which returns
null here).
+ PsiReference ref = qualifier.getReference();
+ PsiElement resolved = ref == null ? null : ref.resolve();
+ if (!(resolved instanceof PsiClass)) return;
+ domainClass = (PsiClass)resolved;
if (!GormUtils.isGormBean(domainClass)) return;
-
- assert domainClass != null;
}
else {
+ final PsiType type = GroovyCompletionUtil.getQualifierType(qualifier);
+ if (!(type instanceof PsiClassType)) return;
domainClass =
DetachedCriteriaUtil.getDomainClassByDetachedCriteriaExpression(type);
if (domainClass == null) return;
}