void (final GrReferenceExpression ref, AnnotationHolder holder) { PsiElement nameElement = ref.getReferenceNameElement(); if (nameElement == null) return; IElementType elementType = nameElement.getNode().getElementType(); if (!(elementType == GroovyTokenTypes.kSUPER || elementType == GroovyTokenTypes.kTHIS)) return; final GrExpression qualifier = ref.getQualifier(); if (qualifier instanceof GrReferenceExpression) { final PsiElement resolved = ((GrReferenceExpression)qualifier).resolve(); if (resolved instanceof PsiClass) { GrTypeDefinition containingClass = PsiTreeUtil.getParentOfType(ref, GrTypeDefinition.class, true, GroovyFile.class); if (elementType == GroovyTokenTypes.kSUPER && containingClass != null && GrTraitUtil.isTrait((PsiClass)resolved)) { PsiClassType[] superTypes = containingClass.getSuperTypes(); if (ContainerUtil.find(superTypes, type -> ref.getManager().areElementsEquivalent(type.resolve(), resolved)) != null) { holder.newSilentAnnotation(HighlightSeverity.INFORMATION).range(nameElement).textAttributes(GroovySyntaxHighlighter.KEYWORD).create(); return; // reference to trait method } } if (containingClass == null || containingClass.getContainingClass() == null && !containingClass.isAnonymous()) { holder.newAnnotation(HighlightSeverity.ERROR, GroovyBundle.message("qualified.0.is.allowed.only.in.nested.or.inner.classes", nameElement.getText())).create(); return; } if (!PsiTreeUtil.isAncestor(resolved, ref, true)) { String qname = ((PsiClass)resolved).getQualifiedName(); assert qname != null; holder.newAnnotation(HighlightSeverity.ERROR, GroovyBundle.message("is.not.enclosing.class", qname)).create(); } } } else if (qualifier == null) { if (elementType == GroovyTokenTypes.kSUPER) { final GrMember container = PsiTreeUtil.getParentOfType(ref, GrMethod.class, GrClassInitializer.class); if (container != null && container.hasModifierProperty(PsiModifier.STATIC)) { holder.newAnnotation(HighlightSeverity.ERROR, GroovyBundle.message("super.cannot.be.used.in.static.context")).create(); } } } }