From: Alexey Kudravtsev Date: Mon, 15 Feb 2010 09:57:57 +0000 (+0300) Subject: good code is red (in presence of raw overriding) X-Git-Tag: review-1~21^2^2~3 X-Git-Url: https://repo.or.cz/w/fedora-idea.git/commitdiff_plain/7e472d54f6ce4e9fb6adad595ee8fbe4bf73a22c good code is red (in presence of raw overriding) --- diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index 4775d872a5..8229bc923c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -980,7 +980,7 @@ public class GenericsHighlightUtil { holder.add(highlightInfo); return; } - highlightInfo = HighlightClassUtil.checkClassWithAbstractMethods(enumConstant.getContainingClass(), enumConstant.getNameIdentifier()); + highlightInfo = HighlightClassUtil.checkClassWithAbstractMethods(enumConstant.getContainingClass(), enumConstant.getNameIdentifier().getTextRange()); if (highlightInfo != null) { holder.add(highlightInfo); return; diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java index 2e9dd27a66..1cbbbf85cb 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java @@ -31,13 +31,13 @@ import com.intellij.codeInsight.daemon.impl.quickfix.*; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInsight.intention.QuickFixFactory; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.psi.*; import com.intellij.psi.impl.source.jsp.jspJava.JspClass; import com.intellij.psi.search.GlobalSearchScope; @@ -72,30 +72,43 @@ public class HighlightClassUtil { && parent.getParent() instanceof PsiNewExpression && !PsiUtilBase.hasErrorElementChild(parent.getParent())) { PsiAnonymousClass aClass = (PsiAnonymousClass)parent; - highlightInfo = checkClassWithAbstractMethods(aClass, ref); + highlightInfo = checkClassWithAbstractMethods(aClass, ref.getTextRange()); } return highlightInfo; } - public static HighlightInfo checkClassWithAbstractMethods(PsiClass aClass, PsiElement highlightElement) { - Collection allMethods = aClass.getVisibleSignatures(); - PsiMethod abstractMethod = ClassUtil.getAnyAbstractMethod(aClass, allMethods); + static HighlightInfo checkClassWithAbstractMethods(PsiClass aClass, TextRange textRange) { + PsiMethod abstractMethod = ClassUtil.getAnyAbstractMethod(aClass); - if (abstractMethod != null && abstractMethod.getContainingClass() != null) { - String baseClassName = HighlightUtil.formatClass(aClass, false); - String methodName = HighlightUtil.formatMethod(abstractMethod); - String message = JavaErrorMessages.message("class.must.be.abstract", - baseClassName, - methodName, - HighlightUtil.formatClass(abstractMethod.getContainingClass(), false)); + if (abstractMethod == null || abstractMethod.getContainingClass() == null) { + return null; + } + String baseClassName = HighlightUtil.formatClass(aClass, false); + String methodName = HighlightUtil.formatMethod(abstractMethod); + String message = JavaErrorMessages.message("class.must.be.abstract", + baseClassName, + methodName, + HighlightUtil.formatClass(abstractMethod.getContainingClass(), false)); - HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, highlightElement, message); - if (ClassUtil.getAnyMethodToImplement(aClass, allMethods) != null) { - QuickFixAction.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createImplementMethodsFix(aClass)); - } - return highlightInfo; + HighlightInfo errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, message); + if (ClassUtil.getAnyMethodToImplement(aClass) != null) { + QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createImplementMethodsFix(aClass)); } - return null; + if (!(aClass instanceof PsiAnonymousClass) + && HighlightUtil.getIncompatibleModifier(PsiModifier.ABSTRACT, aClass.getModifierList()) == null) { + IntentionAction fix = QUICK_FIX_FACTORY.createModifierListFix(aClass, PsiModifier.ABSTRACT, true, false); + QuickFixAction.registerQuickFixAction(errorResult, fix); + } + return errorResult; + } + + static HighlightInfo checkClassMustBeAbstract(final PsiClass aClass, final TextRange textRange) { + if (aClass.hasModifierProperty(PsiModifier.ABSTRACT) || aClass.getRBrace() == null + || aClass.isEnum() && hasEnumConstants(aClass) + ) { + return null; + } + return checkClassWithAbstractMethods(aClass, textRange); } @@ -105,7 +118,7 @@ public class HighlightClassUtil { String baseClassName = aClass.getName(); String message = JavaErrorMessages.message("abstract.cannot.be.instantiated", baseClassName); errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, highlighElement, message); - if (!aClass.isInterface() && ClassUtil.getAnyAbstractMethod(aClass, aClass.getVisibleSignatures()) == null) { + if (!aClass.isInterface() && ClassUtil.getAnyAbstractMethod(aClass) == null) { // suggest to make not abstract only if possible IntentionAction fix = QUICK_FIX_FACTORY.createModifierListFix(aClass, PsiModifier.ABSTRACT, false, false); QuickFixAction.registerQuickFixAction(errorResult, fix); @@ -114,36 +127,6 @@ public class HighlightClassUtil { return errorResult; } - - static HighlightInfo checkClassMustBeAbstract(PsiClass aClass) { - if (aClass.hasModifierProperty(PsiModifier.ABSTRACT) || aClass.getRBrace() == null || - aClass.isEnum() && hasEnumConstants(aClass) - ) { - return null; - } - HighlightInfo errorResult = null; - Collection allMethods = aClass.getVisibleSignatures(); - PsiMethod abstractMethod = ClassUtil.getAnyAbstractMethod(aClass, allMethods); - if (abstractMethod != null) { - String message = JavaErrorMessages.message("class.must.be.abstract", - HighlightUtil.formatClass(aClass, false), - HighlightUtil.formatMethod(abstractMethod), - HighlightUtil.formatClass(abstractMethod.getContainingClass())); - - TextRange textRange = HighlightNamesUtil.getClassDeclarationTextRange(aClass); - errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, message); - if (ClassUtil.getAnyMethodToImplement(aClass, allMethods) != null) { - QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createImplementMethodsFix(aClass)); - } - if (!(aClass instanceof PsiAnonymousClass) - && HighlightUtil.getIncompatibleModifier(PsiModifier.ABSTRACT, aClass.getModifierList()) == null) { - IntentionAction fix = QUICK_FIX_FACTORY.createModifierListFix(aClass, PsiModifier.ABSTRACT, true, false); - QuickFixAction.registerQuickFixAction(errorResult, fix); - } - } - return errorResult; - } - private static boolean hasEnumConstants(PsiClass aClass) { PsiField[] fields = aClass.getFields(); for (PsiField field : fields) { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index 393f3f2046..2f50f7adb3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -328,7 +328,10 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh @Override public void visitEnumConstantInitializer(PsiEnumConstantInitializer enumConstantInitializer) { super.visitEnumConstantInitializer(enumConstantInitializer); - if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkClassMustBeAbstract(enumConstantInitializer)); + if (!myHolder.hasErrorResults()) { + TextRange textRange = HighlightNamesUtil.getClassDeclarationTextRange(enumConstantInitializer); + myHolder.add(HighlightClassUtil.checkClassMustBeAbstract(enumConstantInitializer, textRange)); + } } @Override public void visitExpression(PsiExpression expression) { @@ -599,7 +602,10 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh else if (parent instanceof PsiClass) { PsiClass aClass = (PsiClass)parent; if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkDuplicateNestedClass(aClass)); - if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkClassMustBeAbstract(aClass)); + if (!myHolder.hasErrorResults()) { + TextRange textRange = HighlightNamesUtil.getClassDeclarationTextRange(aClass); + myHolder.add(HighlightClassUtil.checkClassMustBeAbstract(aClass, textRange)); + } if (!myHolder.hasErrorResults()) { myHolder.add(HighlightClassUtil.checkClassDoesNotCallSuperConstructorOrHandleExceptions(aClass, myRefCountHolder, myResolveHelper)); } diff --git a/java/java-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java b/java/java-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java index ac7768ffdb..797385f2f5 100644 --- a/java/java-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java +++ b/java/java-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java @@ -149,7 +149,7 @@ public class PsiSuperMethodImplUtil { if (superClass == null) continue; if (!visited.add(superClass)) continue; // cyclic inheritance final PsiSubstitutor superSubstitutor = superTypeResolveResult.getSubstitutor(); - PsiSubstitutor finalSubstitutor = obtainFinalSubstitutor(superClass, superSubstitutor, substitutor); + PsiSubstitutor finalSubstitutor = obtainFinalSubstitutor(superClass, superSubstitutor, substitutor, isInRawContext); final boolean isInRawContextSuper = (isInRawContext || PsiUtil.isRawSubstitutor(superClass, superSubstitutor)) && superClass.getTypeParameters().length != 0; Map superResult = buildMethodHierarchy(superClass, finalSubstitutor, false, visited, isInRawContextSuper); @@ -263,7 +263,10 @@ public class PsiSuperMethodImplUtil { private static PsiSubstitutor obtainFinalSubstitutor(PsiClass superClass, PsiSubstitutor superSubstitutor, - PsiSubstitutor derivedSubstitutor) { + PsiSubstitutor derivedSubstitutor, boolean inRawContext) { + if (inRawContext) { + superSubstitutor = JavaPsiFacadeEx.getElementFactory(superClass.getProject()).createRawSubstitutor(derivedSubstitutor, superSubstitutor.getSubstitutionMap().keySet().toArray(PsiTypeParameter.EMPTY_ARRAY)); + } Map map = null; for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(superClass)) { PsiType type = superSubstitutor.substitute(typeParameter); diff --git a/java/openapi/src/com/intellij/codeInsight/ClassUtil.java b/java/openapi/src/com/intellij/codeInsight/ClassUtil.java dissimilarity index 76% index c06d03d818..e7b0fbf684 100644 --- a/java/openapi/src/com/intellij/codeInsight/ClassUtil.java +++ b/java/openapi/src/com/intellij/codeInsight/ClassUtil.java @@ -1,154 +1,98 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @author Alexey - */ -package com.intellij.codeInsight; - -import com.intellij.psi.*; -import gnu.trove.THashSet; -import org.jetbrains.annotations.NotNull; - -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Set; - -public class ClassUtil { - public static PsiMethod getAnyAbstractMethod(PsiClass aClass, Collection allMethodsCollection) { - PsiMethod methodToImplement = getAnyMethodToImplement(aClass, allMethodsCollection); - if (methodToImplement != null) { - return methodToImplement; - } - PsiMethod[] methods = aClass.getMethods(); - for (PsiMethod method : methods) { - if (method.hasModifierProperty(PsiModifier.ABSTRACT)) return method; - } - - return abstractPackageLocalMethod(aClass, allMethodsCollection); -/* - // the only remaining possiblity for class to have abstract method here is - // from package local abstract method defined in inherited class from other package - PsiManager manager = aClass.getManager(); - for (List sameSignatureMethods : allMethodsCollection.values()) { - // look for abstract package locals - for (int i = sameSignatureMethods.size() - 1; i >= 0; i--) { - MethodSignatureBackedByPsiMethod methodSignature1 = sameSignatureMethods.get(i); - PsiMethod method1 = methodSignature1.getMethod(); - PsiClass class1 = method1.getContainingClass(); - if (class1 == null) { - sameSignatureMethods.remove(i); - continue; - } - if (!method1.hasModifierProperty(PsiModifier.ABSTRACT) - || !method1.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) - || manager.arePackagesTheSame(class1, aClass)) { - continue; - } - // check if abstract package local method gets overriden by not abstract - // i.e. there is direct subclass in the same package which overrides this method - for (int j = sameSignatureMethods.size() - 1; j >= 0; j--) { - MethodSignatureBackedByPsiMethod methodSignature2 = sameSignatureMethods.get(j); - PsiMethod method2 = methodSignature2.getMethod(); - PsiClass class2 = method2.getContainingClass(); - if (i == j || class2 == null) continue; - if (class2.isInheritor(class1, true) - // NB! overriding method may be abstract -// && !method2.hasModifierProperty(PsiModifier.ABSTRACT) -&& manager.arePackagesTheSame(class1, class2)) { - sameSignatureMethods.remove(i); - break; - } - } - } - for (int i = sameSignatureMethods.size() - 1; i >= 0; i--) { - MethodSignatureBackedByPsiMethod methodSignature = sameSignatureMethods.get(i); - PsiMethod method = methodSignature.getMethod(); - PsiClass class1 = method.getContainingClass(); - if (class1 == null - || !method.hasModifierProperty(PsiModifier.ABSTRACT) - || !method.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) - || manager.arePackagesTheSame(class1, aClass)) { - continue; - } - return method; - } - } - return null; -*/ - } - - private static PsiMethod abstractPackageLocalMethod(PsiClass aClass, Collection allMethodsCollection) { - Set allMethods = new THashSet(Arrays.asList(aClass.getAllMethods())); - Set suspects = new THashSet(); - // check all methods collection first for sibling overrides - for (HierarchicalMethodSignature signature : allMethodsCollection) { - removeSupers(signature, allMethods, suspects); - PsiMethod method = signature.getMethod(); - if (method.hasModifierProperty(PsiModifier.ABSTRACT)) { - suspects.add(method); - } - allMethods.remove(method); - } - while (!allMethods.isEmpty()) { - PsiMethod method = allMethods.iterator().next(); - removeSupers(method.getHierarchicalMethodSignature(), allMethods, suspects); - if (method.hasModifierProperty(PsiModifier.ABSTRACT)) { - suspects.add(method); - } - allMethods.remove(method); - } - return suspects.isEmpty() ? null : suspects.iterator().next(); - } - - private static void removeSupers(@NotNull HierarchicalMethodSignature hierarchicalMethodSignature, Set allMethods, Set suspects) { - for (HierarchicalMethodSignature superS : hierarchicalMethodSignature.getSuperSignatures()) { - PsiMethod superMethod = superS.getMethod(); - allMethods.remove(superMethod); - suspects.remove(superMethod); - assert superS != hierarchicalMethodSignature; - removeSupers(superS, allMethods, suspects); - } - } - - public static PsiMethod getAnyMethodToImplement(PsiClass aClass, Collection allMethodsCollection) { - for (HierarchicalMethodSignature signatureHierarchical : allMethodsCollection) { - final PsiMethod method = signatureHierarchical.getMethod(); - PsiClass containingClass = method.getContainingClass(); - if (containingClass == null) { - continue; - } - if (!aClass.equals(containingClass) && - method.hasModifierProperty(PsiModifier.ABSTRACT) - && !method.hasModifierProperty(PsiModifier.STATIC) - && !method.hasModifierProperty(PsiModifier.PRIVATE)) { - return method; - } - else { - final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(aClass.getProject()).getResolveHelper(); - final List superSignatures = signatureHierarchical.getSuperSignatures(); - for (HierarchicalMethodSignature superSignatureHierarchical : superSignatures) { - final PsiMethod superMethod = superSignatureHierarchical.getMethod(); - if (superMethod.hasModifierProperty(PsiModifier.ABSTRACT) && !resolveHelper.isAccessible(superMethod, method, null)) return superMethod; - } - } - } - - return null; - } - -} \ No newline at end of file +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @author Alexey + */ +package com.intellij.codeInsight; + +import com.intellij.psi.*; +import gnu.trove.THashSet; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Set; + +public class ClassUtil { + public static PsiMethod getAnyAbstractMethod(@NotNull PsiClass aClass) { + PsiMethod methodToImplement = getAnyMethodToImplement(aClass); + if (methodToImplement != null) { + return methodToImplement; + } + PsiMethod[] methods = aClass.getMethods(); + for (PsiMethod method : methods) { + if (method.hasModifierProperty(PsiModifier.ABSTRACT)) return method; + } + + return null; + } + + public static PsiMethod getAnyMethodToImplement(PsiClass aClass) { + Set alreadyImplemented = new THashSet(); + for (HierarchicalMethodSignature signatureHierarchical : aClass.getVisibleSignatures()) { + for (PsiMethod superS : signatureHierarchical.getMethod().findSuperMethods()) { + add(superS, alreadyImplemented); + } + } + PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(aClass.getProject()).getResolveHelper(); + for (HierarchicalMethodSignature signatureHierarchical : aClass.getVisibleSignatures()) { + PsiMethod method = signatureHierarchical.getMethod(); + PsiClass containingClass = method.getContainingClass(); + if (containingClass == null) { + continue; + } + if (!aClass.equals(containingClass) + && method.hasModifierProperty(PsiModifier.ABSTRACT) + && !method.hasModifierProperty(PsiModifier.STATIC) + && !method.hasModifierProperty(PsiModifier.PRIVATE) + && !alreadyImplemented.contains(method)) { + return method; + } + final List superSignatures = signatureHierarchical.getSuperSignatures(); + for (HierarchicalMethodSignature superSignatureHierarchical : superSignatures) { + final PsiMethod superMethod = superSignatureHierarchical.getMethod(); + if (superMethod.hasModifierProperty(PsiModifier.ABSTRACT) && !resolveHelper.isAccessible(superMethod, method, null)) { + return superMethod; + } + } + } + + return checkPackageLocalInSuperClass(aClass); + } + + private static PsiMethod checkPackageLocalInSuperClass(PsiClass aClass) { + // super class can have package local sbstract methods not accessible for overriding + PsiClass superClass = aClass.getSuperClass(); + if (superClass == null) return null; + if ("java.lang.Object".equals(aClass.getQualifiedName())) return null; + if (JavaPsiFacade.getInstance(aClass.getProject()).arePackagesTheSame(aClass, superClass)) return null; + + for (HierarchicalMethodSignature methodSignature : superClass.getVisibleSignatures()) { + PsiMethod method = methodSignature.getMethod(); + if (method.hasModifierProperty(PsiModifier.ABSTRACT) && method.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) return method; + } + return null; + } + + private static boolean add(PsiMethod method, Set alreadyImplemented) { + boolean already = alreadyImplemented.add(method); + + for (PsiMethod superSig : method.findSuperMethods()) { + already &= add(superSig, alreadyImplemented); + } + return already; + } +} \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java index 35707bf19c..f04ee3a793 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -26,8 +26,8 @@ import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; -import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.ClassUtil; import com.intellij.psi.util.PsiTreeUtil; import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; @@ -76,10 +76,12 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; import org.jetbrains.plugins.groovy.lang.resolve.processors.PropertyResolverProcessor; -import org.jetbrains.plugins.groovy.overrideImplement.GroovyOverrideImplementUtil; import org.jetbrains.plugins.groovy.overrideImplement.quickFix.ImplementMethodsQuickFix; -import java.util.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; /** * @author ven @@ -645,12 +647,11 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { if (typeDefinition.isEnum() || typeDefinition.isAnnotationType()) return; if (typeDefinition instanceof GrTypeParameter) return; - Collection collection = GroovyOverrideImplementUtil.getMethodsToImplement(typeDefinition); - if (collection.isEmpty()) return; + PsiMethod abstractMethod = ClassUtil.getAnyAbstractMethod(typeDefinition); - final PsiElement element = collection.iterator().next().getElement(); - assert element instanceof PsiNamedElement; - String notImplementedMethodName = ((PsiNamedElement)element).getName(); + if (abstractMethod == null) return; + + String notImplementedMethodName = abstractMethod.getName(); final int startOffset = typeDefinition.getTextOffset(); int endOffset = typeDefinition.getNameIdentifierGroovy().getTextRange().getEndOffset();