From 9e21bde7439adc40d53d0dbb26bb08682c82e1d3 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Tue, 23 Apr 2013 15:41:13 +0400 Subject: [PATCH] IDEA-99520 Groovy: check overloading methods have the same raw signatures --- .../groovy/annotator/GroovyAnnotator.java | 8 ++-- .../signatures/GrClosureSignatureUtil.java | 40 ++++++++++++++++--- .../changeSignature/GrMethodConflictUtil.java | 4 +- .../GroovyHighlightingTest.groovy | 24 +++++++++++ 4 files changed, 64 insertions(+), 12 deletions(-) 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 e0960550380b..7cb03049ed19 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -336,7 +336,7 @@ public class GroovyAnnotator extends GroovyElementVisitor { } checkTypeDefinition(myHolder, typeDefinition); - checkDuplicateMethod(typeDefinition.getMethods(), myHolder); + checkDuplicateMethod(typeDefinition, myHolder); checkImplementedMethodsOfClass(myHolder, typeDefinition); checkConstructors(myHolder, typeDefinition); @@ -1279,7 +1279,7 @@ public class GroovyAnnotator extends GroovyElementVisitor { public void visitFile(GroovyFileBase file) { final PsiClass scriptClass = file.getScriptClass(); if (scriptClass != null) { - checkDuplicateMethod(scriptClass.getMethods(), myHolder); + checkDuplicateMethod(scriptClass, myHolder); } } @@ -1758,8 +1758,8 @@ public class GroovyAnnotator extends GroovyElementVisitor { } } - private static void checkDuplicateMethod(PsiMethod[] methods, AnnotationHolder holder) { - MultiMap map = GrClosureSignatureUtil.findMethodSignatures(methods); + private static void checkDuplicateMethod(PsiClass clazz, AnnotationHolder holder) { + MultiMap map = GrClosureSignatureUtil.findRawMethodSignatures(clazz.getMethods(), clazz); processMethodDuplicates(map, holder); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/signatures/GrClosureSignatureUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/signatures/GrClosureSignatureUtil.java index c3a7026f105d..69b5f2aca795 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/signatures/GrClosureSignatureUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/signatures/GrClosureSignatureUtil.java @@ -18,6 +18,7 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.signatures; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Trinity; import com.intellij.psi.*; +import com.intellij.psi.impl.PsiSubstitutorImpl; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.MethodSignature; @@ -770,14 +771,41 @@ public class GrClosureSignatureUtil { return result; } - public static MultiMap findMethodSignatures(PsiMethod[] methods) { - MultiMap map = new MultiMap(); - for (PsiMethod method : methods) { - final PsiMethod actual = method instanceof GrReflectedMethod ? ((GrReflectedMethod)method).getBaseMethod() : method; - map.putValue(method.getSignature(PsiSubstitutor.EMPTY), actual); + @NotNull + public static MultiMap findRawMethodSignatures(@NotNull PsiMethod[] methods, @NotNull PsiClass clazz) { + Map initialMap = ContainerUtil.newHashMap(); + + for (PsiTypeParameter parameter : clazz.getTypeParameters()) { + initialMap.put(parameter, null); } - return map; + final PsiSubstitutor initialSubstitutor = PsiSubstitutorImpl.createSubstitutor(initialMap); + + MultiMap result = new MultiMap(); + for (PsiMethod method : methods) { + final PsiMethod actual = method instanceof GrReflectedMethod ? ((GrReflectedMethod)method).getBaseMethod() : method; + + PsiSubstitutor substitutor = calcRawSubstitutor(initialMap, initialSubstitutor, actual); + result.putValue(method.getSignature(substitutor), actual); + } + + return result; + } + + @NotNull + private static PsiSubstitutor calcRawSubstitutor(@NotNull Map initialMap, + @NotNull PsiSubstitutor initialSubstitutor, + @NotNull PsiMethod actual) { + if (actual.hasTypeParameters()) { + final HashMap map1 = ContainerUtil.newHashMap(initialMap); + for (PsiTypeParameter parameter : actual.getTypeParameters()) { + map1.put(parameter, null); + } + return PsiSubstitutorImpl.createSubstitutor(map1); + } + else { + return initialSubstitutor; + } } private static MethodSignature generateSignature(String name, diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodConflictUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodConflictUtil.java index 761c37dd2fc3..49a5c8a39789 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodConflictUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodConflictUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -109,7 +109,7 @@ public class GrMethodConflictUtil { String newName = prototype.getName(); PsiMethod[] methods = clazz.findMethodsByName(newName, false); - MultiMap signatures = GrClosureSignatureUtil.findMethodSignatures(methods); + MultiMap signatures = GrClosureSignatureUtil.findRawMethodSignatures(methods, clazz); for (MethodSignature prototypeSignature : prototypeSignatures) { for (PsiMethod method : signatures.get(prototypeSignature)) { if (method != refactoredMethod) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy index 8dd6422013b3..dcdf59c935ea 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy @@ -1238,4 +1238,28 @@ def e def f ''') } + + void testDuplicateMethodsWithGenerics() { + testHighlighting('''\ +class A { + def foo(T t) {} + def foo(E e) {} +} + +class B { + def void foo(T t) {} + def void foo(E e) {} +} + +class C { + def foo(T t, T t2 = null) {} + def foo(E e) {} +} + +class D { + def foo(T t, E e) {} + def foo(E t, T e) {} + def foo(E t) {} +}''') + } } \ No newline at end of file