From b6be69e4a910dcab4898a3df1145e4a0aea1f6d6 Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Thu, 24 Mar 2016 18:12:10 +0300 Subject: [PATCH] [groovy] unify handling of class literals --- .../annotator/intentions/QuickfixUtil.java | 10 +++- .../GrReferenceExpressionImpl.java | 11 ++-- .../expressions/GrReferenceResolveRunner.java | 54 +++---------------- .../groovy/lang/psi/util/GrStaticChecker.java | 5 +- .../plugins/groovy/lang/psi/util/PsiUtil.java | 16 +++++- .../groovy/lang/resolve/ResolveUtil.java | 25 ++++++++- .../CompleteReferenceExpression.java | 12 +++-- .../completion/GrMainCompletionProvider.java | 17 +++++- .../convertToJava/ExpressionGenerator.java | 14 +++-- .../convertToJava/GenerationUtil.java | 18 +++++-- .../CreateFieldFromUsageTest.groovy | 14 ++++- .../lang/resolve/ResolveMethodTest.groovy | 27 +++++++++- .../CodeBlockGenerationTest.groovy | 6 ++- .../codeBlock/classMethod.groovy | 11 ++++ .../codeBlock/classMethod.java | 6 +++ 15 files changed, 164 insertions(+), 82 deletions(-) create mode 100644 plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/classMethod.groovy create mode 100644 plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/classMethod.java diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/intentions/QuickfixUtil.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/intentions/QuickfixUtil.java index 6d32b15779b8..e27961c88798 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/intentions/QuickfixUtil.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/intentions/QuickfixUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 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. @@ -54,6 +54,14 @@ public class QuickfixUtil { if (type == null && compileStatic) { return GroovyPsiManager.getInstance(refExpr.getProject()).findClassWithCache(CommonClassNames.JAVA_LANG_OBJECT, refExpr.getResolveScope()); } + + if (ResolveUtil.resolvesToClass(refExpr.getQualifierExpression())) { + PsiType classType = ResolveUtil.unwrapClassType(type); + if (classType != null) { + type = classType; + } + } + if (!(type instanceof PsiClassType)) return null; return ((PsiClassType)type).resolve(); } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java index abcfbbc23ae4..08671ebd47be 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.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. @@ -274,12 +274,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl staticMembers = ContainerUtil.newHashMap(); final PsiElement qualifier = reference.getQualifier(); - final PsiType qualifierType = qualifier instanceof GrExpression ? ((GrExpression)qualifier).getType() : null; + final PsiType qualifierType = getQualifierType(qualifier); if (reference instanceof GrReferenceExpression && (qualifier instanceof GrExpression || qualifier == null)) { for (String string : CompleteReferencesWithSameQualifier.getVariantsWithSameQualifier((GrReferenceExpression)reference, matcher, (GrExpression)qualifier)) { @@ -284,6 +285,18 @@ public class GrMainCompletionProvider extends CompletionProvider.class - if (resolved instanceof PsiClass && PsiUtil.isExpressionUsed(referenceExpression)) { + if (resolved instanceof PsiClass) { builder.append(((PsiClass)resolved).getQualifiedName()); - builder.append(".class"); + if (PsiUtil.isExpressionUsed(referenceExpression)) { + builder.append(".class"); + } return; } @@ -1036,9 +1037,6 @@ public class ExpressionGenerator extends Generator { builder.append(".get()"); } } - else if (resolved instanceof PsiClass) { - TypeWriter.writeType(builder, referenceExpression.getType(), referenceExpression); - } else { builder.append(refName); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java index ac12418ca3c4..a58e0f7cf853 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.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. @@ -517,12 +517,24 @@ public class GenerationUtil { if (declared == null) return false; final CheckProcessElement checker = new CheckProcessElement(member); - ResolveUtil.processAllDeclarationsSeparately(declared, checker, new BaseScopeProcessor() { + final BaseScopeProcessor processor = new BaseScopeProcessor() { @Override public boolean execute(@NotNull PsiElement element, @NotNull ResolveState state) { return false; } - }, ResolveState.initial(), qualifier); + }; + + if (ResolveUtil.resolvesToClass(qualifier)) { + PsiType type = ResolveUtil.unwrapClassType(declared); + if (type != null) { + ResolveUtil.processAllDeclarationsSeparately(type, checker, processor, ResolveState.initial(), qualifier); + if (checker.isFound()) { + return false; + } + } + } + + ResolveUtil.processAllDeclarationsSeparately(declared, checker, processor, ResolveState.initial(), qualifier); return !checker.isFound(); } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/CreateFieldFromUsageTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/CreateFieldFromUsageTest.groovy index f7dfa8232cb4..3c3280060253 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/CreateFieldFromUsageTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/CreateFieldFromUsageTest.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 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. @@ -125,5 +125,17 @@ print A.object ''') } + void testClassRef() { + doTextTest '''\ +class A { +} +print A.class.object +''', '''\ +class A { + static def object +} +print A.class.object +''' + } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy index a7dfabcc7411..40dd33685159 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy @@ -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. @@ -2245,4 +2245,29 @@ SourceConcrete.someOtherStaticMethod() assert !computer.computed } } + + void 'test resolve method with class qualifier'() { + myFixture.addClass '''\ +package foo.bar; + +public class A { + public static void foo() {} + public static String getCanonicalName() {return "";} +} +''' + def data = [ + 'A.foo()' : 'foo.bar.A', + 'A.class.foo()' : 'foo.bar.A', + 'A.simpleName' : 'java.lang.Class', + 'A.class.simpleName' : 'java.lang.Class', + 'A.canonicalName' : 'foo.bar.A', + 'A.class.canonicalName': 'foo.bar.A' + ] + data.each { expression, expectedClass -> + def ref = configureByText "import foo.bar.A; $expression" + def element = ref.resolve() + assert element instanceof PsiMember : "$expression -> $expectedClass" + assert element.containingClass.qualifiedName == expectedClass + } + } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerationTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerationTest.groovy index 07dddce977a7..2af2c6b83415 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerationTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerationTest.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 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. @@ -45,7 +45,7 @@ public class CodeBlockGenerationTest extends LightGroovyTestCase { PostprocessReformattingAspect.getInstance(project).doPostponedFormatting() final String text = result.text final String expected = psiManager.findFile(myFixture.copyFileToProject(testName + '.java')).text - assertEquals expected, text + assertEquals expected.trim(), text.trim() } private addFile(String text) { @@ -190,6 +190,8 @@ public final class Matcher { void testClassReference() { doTest() } + void testClassMethod() { doTest() } + void testEquals() { doTest() } void testSelfNavigatingOperator() { doTest() } diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/classMethod.groovy b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/classMethod.groovy new file mode 100644 index 000000000000..ac2a2f31b9a2 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/classMethod.groovy @@ -0,0 +1,11 @@ +class A { + static foo() {} + static getCanonicalName() { "" } +} + +print A.foo() +print A.class.foo() +print A.simpleName +print A.class.simpleName +print A.canonicalName +print A.class.canonicalName diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/classMethod.java b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/classMethod.java new file mode 100644 index 000000000000..0da4f7f905d7 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/classMethod.java @@ -0,0 +1,6 @@ +print(A.foo()); +print(A.foo()); +print(A.class.getSimpleName()); +print(A.class.getSimpleName()); +print(A.getCanonicalName()); +print(A.getCanonicalName()); \ No newline at end of file