diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java index 36ea0524671f..e539b02ea6a2 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -38,7 +38,6 @@ import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.impl.ExpressionConverter; -import com.intellij.psi.impl.light.LightElement; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.searches.SuperMethodsSearch; import com.intellij.psi.tree.IElementType; @@ -97,12 +96,9 @@ import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper; import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.modifiers.GrAnnotationCollector; -import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass; -import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil; -import org.jetbrains.plugins.groovy.lang.psi.util.GrTraitUtil; -import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; +import org.jetbrains.plugins.groovy.lang.psi.util.*; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; import org.jetbrains.plugins.groovy.lang.resolve.ast.GrInheritConstructorContributor; @@ -430,7 +426,6 @@ public class GroovyAnnotator extends GroovyElementVisitor { } checkTypeDefinition(myHolder, typeDefinition); - checkDuplicateMethod(typeDefinition, myHolder); checkImplementedMethodsOfClass(myHolder, typeDefinition); checkConstructors(myHolder, typeDefinition); @@ -610,6 +605,7 @@ public class GroovyAnnotator extends GroovyElementVisitor { @Override public void visitMethod(GrMethod method) { + checkDuplicateMethod(method); checkMethodWithTypeParamsShouldHaveReturnType(myHolder, method); checkInnerMethod(myHolder, method); checkOptionalParametersInAbstractMethod(myHolder, method); @@ -1484,7 +1480,6 @@ public class GroovyAnnotator extends GroovyElementVisitor { public void visitFile(GroovyFileBase file) { final PsiClass scriptClass = file.getScriptClass(); if (scriptClass != null) { - checkDuplicateMethod(scriptClass, myHolder); checkSameNameMethodsWithDifferentAccessModifiers(myHolder, file.getCodeMethods()); } } @@ -1992,31 +1987,31 @@ public class GroovyAnnotator extends GroovyElementVisitor { } } - private static void checkDuplicateMethod(PsiClass clazz, AnnotationHolder holder) { - MultiMap map = GrClosureSignatureUtil.findRawMethodSignatures(clazz.getMethods(), clazz); - processMethodDuplicates(map, holder); - } - - protected static void processMethodDuplicates(MultiMap map, AnnotationHolder holder) { - for (MethodSignature signature : map.keySet()) { - Collection methods = map.get(signature); - if (methods.size() > 1) { - for (Iterator iterator = methods.iterator(); iterator.hasNext(); ) { - PsiMethod method = iterator.next(); - if (method instanceof LightElement) iterator.remove(); - } - - if (methods.size() < 2) continue; - String signaturePresentation = GroovyPresentationUtil.getSignaturePresentation(signature); - for (PsiMethod method : methods) { - //noinspection ConstantConditions - holder.createErrorAnnotation(GrHighlightUtil.getMethodHeaderTextRange(method), GroovyBundle - .message("method.duplicate", signaturePresentation, method.getContainingClass().getName())); - } + private void checkDuplicateMethod(@NotNull GrMethod method) { + PsiClass clazz = method.getContainingClass(); + if (clazz == null) return; + GrReflectedMethod[] reflectedMethods = method.getReflectedMethods(); + if (reflectedMethods.length == 0) { + doCheckDuplicateMethod(method, clazz); + } + else { + for (GrReflectedMethod reflectedMethod : reflectedMethods) { + doCheckDuplicateMethod(reflectedMethod, clazz); } } } + private void doCheckDuplicateMethod(@NotNull GrMethod method, @NotNull PsiClass clazz) { + MethodSignature signature = GrClassImplUtil.getDuplicatedMethods(clazz).get(method); + if (signature == null) return; + String signaturePresentation = GroovyPresentationUtil.getSignaturePresentation(signature); + GrMethod original = method instanceof GrReflectedMethod ? ((GrReflectedMethod)method).getBaseMethod() : method; + myHolder.createErrorAnnotation( + GrHighlightUtil.getMethodHeaderTextRange(original), + GroovyBundle.message("method.duplicate", signaturePresentation, clazz.getName()) + ); + } + private static void checkTypeDefinition(AnnotationHolder holder, GrTypeDefinition typeDefinition) { final GroovyConfigUtils configUtils = GroovyConfigUtils.getInstance(); if (typeDefinition.isAnonymous()) { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/util/GrClassImplUtil.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/util/GrClassImplUtil.java index e347ce2fb1f4..cb20e0bf2a87 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/util/GrClassImplUtil.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/util/GrClassImplUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -33,6 +33,7 @@ import com.intellij.psi.util.PsiUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.MostlySingularMultiMap; import com.intellij.util.containers.hash.HashSet; import gnu.trove.TObjectIntHashMap; import org.jetbrains.annotations.NonNls; @@ -636,4 +637,29 @@ public class GrClassImplUtil { } }); } + + @NotNull + public static Map getDuplicatedMethods(@NotNull PsiClass clazz) { + return CachedValuesManager.getCachedValue(clazz, () -> { + PsiElementFactory factory = JavaPsiFacade.getInstance(clazz.getProject()).getElementFactory(); + + MostlySingularMultiMap signatures = MostlySingularMultiMap.newMap(); + for (PsiMethod method : clazz.getMethods()) { + MethodSignature signature = method.getSignature(factory.createRawSubstitutor(method)); + signatures.add(signature, method); + } + + Map result = ContainerUtil.newHashMap(); + for (MethodSignature signature : signatures.keySet()) { + if (signatures.valuesForKey(signature) > 1) { + signatures.processForKey(signature, m -> { + result.put(m, signature); + return true; + }); + } + } + + return CachedValueProvider.Result.create(result, clazz); + }); + } }