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;
     }

Reply via email to