From c081ced616223620abf98fc68d3c9b7e7c83cebe Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Thu, 8 Nov 2012 14:45:35 +0400 Subject: [PATCH] KT-2499 If Java class is imported, it is visible in completion three times: as Java class, Kotlin class and package - Add java trace into delegation for lazy resolve session #KT-2499 Fixed --- .../resolve/java/AnalyzerFacadeForJVM.java | 2 +- .../jet/lang/resolve/lazy/ResolveSession.java | 27 +++++++++++-- .../jet/lang/types/lang/KotlinBuiltIns.java | 9 ++++- .../lazy/LazyResolveBuiltinClassesTest.java | 10 +++-- .../completion/DescriptorLookupConverter.java | 38 ++++++++++++++++++- .../libraries/DecompiledDataFactory.java | 10 +++-- .../basic/NoImportedJavaClassDuplication.kt | 7 ++++ .../completion/JetBasicCompletionTest.java | 4 ++ 8 files changed, 93 insertions(+), 14 deletions(-) create mode 100644 idea/testData/completion/basic/NoImportedJavaClassDuplication.kt diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java index 2ed7c45cfde..b133e8bf50c 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java @@ -139,7 +139,7 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade { ModuleDescriptor lazyModule = new ModuleDescriptor(Name.special("")); - return new ResolveSession(fileProject, lazyModule, moduleConfiguration, declarationProviderFactory); + return new ResolveSession(fileProject, lazyModule, moduleConfiguration, declarationProviderFactory, javaResolverTrace); } public static AnalyzeExhaust analyzeOneFileWithJavaIntegrationAndCheckForErrors( diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java index ec6e6643227..4722b9dfc60 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java @@ -31,6 +31,7 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTraceContext; +import org.jetbrains.jet.lang.resolve.ObservableBindingTrace; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; import org.jetbrains.jet.lang.resolve.name.Name; @@ -53,7 +54,7 @@ public class ResolveSession { private final ModuleDescriptor module; private final LazyPackageDescriptor rootPackage; - private final BindingTrace trace = new BindingTraceContext(); + private final BindingTrace trace; private final DeclarationProviderFactory declarationProviderFactory; private final Predicate specialClasses; @@ -70,7 +71,25 @@ public class ResolveSession { @NotNull ModuleConfiguration moduleConfiguration, @NotNull DeclarationProviderFactory declarationProviderFactory ) { - this(project, rootDescriptor, moduleConfiguration, declarationProviderFactory, NO_ALIASES, Predicates.alwaysFalse()); + this(project, rootDescriptor, moduleConfiguration, declarationProviderFactory, NO_ALIASES, + Predicates.alwaysFalse(), + new BindingTraceContext()); + } + + public ResolveSession( + @NotNull Project project, + @NotNull ModuleDescriptor rootDescriptor, + @NotNull ModuleConfiguration moduleConfiguration, + @NotNull DeclarationProviderFactory declarationProviderFactory, + @NotNull BindingTrace delegationTrace + ) { + this(project, + rootDescriptor, + moduleConfiguration, + declarationProviderFactory, + NO_ALIASES, + Predicates.alwaysFalse(), + delegationTrace); } @Deprecated // Internal use only @@ -80,10 +99,12 @@ public class ResolveSession { @NotNull ModuleConfiguration moduleConfiguration, @NotNull DeclarationProviderFactory declarationProviderFactory, @NotNull Function classifierAliases, - @NotNull Predicate specialClasses + @NotNull Predicate specialClasses, + @NotNull BindingTrace delegationTrace ) { this.classifierAliases = classifierAliases; this.specialClasses = specialClasses; + this.trace = new ObservableBindingTrace(delegationTrace); this.injector = new InjectorForLazyResolve(project, this, trace, moduleConfiguration); this.module = rootDescriptor; this.moduleConfiguration = moduleConfiguration; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java index 426fc822b4e..371c2e1bb73 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java @@ -17,7 +17,10 @@ package org.jetbrains.jet.lang.types.lang; import com.google.common.base.Predicates; -import com.google.common.collect.*; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; @@ -35,6 +38,7 @@ import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetImportDirective; import org.jetbrains.jet.lang.psi.JetPsiFactory; import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.BindingTraceContext; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.ImportPath; import org.jetbrains.jet.lang.resolve.lazy.FileBasedDeclarationProviderFactory; @@ -230,7 +234,8 @@ public class KotlinBuiltIns { return ALIASES.get(name); } }, - Predicates.in(Sets.newHashSet(new FqNameUnsafe("jet.Any"), new FqNameUnsafe("jet.Nothing")))); + Predicates.in(Sets.newHashSet(new FqNameUnsafe("jet.Any"), new FqNameUnsafe("jet.Nothing"))), + new BindingTraceContext()); } @NotNull diff --git a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveBuiltinClassesTest.java b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveBuiltinClassesTest.java index 818a7e1d0c4..d6bafb6e43d 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveBuiltinClassesTest.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveBuiltinClassesTest.java @@ -25,23 +25,24 @@ import com.intellij.util.Function; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.ConfigurationKind; import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; -import org.jetbrains.jet.lang.PlatformToKotlinClassMap; -import org.jetbrains.jet.lang.resolve.java.JavaToKotlinClassMap; -import org.jetbrains.jet.test.util.NamespaceComparator; import org.jetbrains.jet.lang.DefaultModuleConfiguration; import org.jetbrains.jet.lang.ModuleConfiguration; +import org.jetbrains.jet.lang.PlatformToKotlinClassMap; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetImportDirective; import org.jetbrains.jet.lang.psi.JetPsiFactory; import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.BindingTraceContext; import org.jetbrains.jet.lang.resolve.ImportPath; +import org.jetbrains.jet.lang.resolve.java.JavaToKotlinClassMap; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; +import org.jetbrains.jet.test.util.NamespaceComparator; import org.junit.Test; import java.io.File; @@ -80,7 +81,8 @@ public class LazyResolveBuiltinClassesTest extends KotlinTestWithEnvironment { return aliases.get(name); } }, - Predicates.in(Sets.newHashSet(new FqNameUnsafe("jet.Any"), new FqNameUnsafe("jet.Nothing")))); + Predicates.in(Sets.newHashSet(new FqNameUnsafe("jet.Any"), new FqNameUnsafe("jet.Nothing"))), + new BindingTraceContext()); NamespaceDescriptor jetNamespaceFromJSL = (NamespaceDescriptor) KotlinBuiltIns.getInstance().getInt().getContainingDeclaration(); diff --git a/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.java b/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.java index 3f9f1830456..e3d18ea095a 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.java @@ -17,10 +17,13 @@ package org.jetbrains.jet.plugin.completion; import com.google.common.collect.Lists; +import com.intellij.codeInsight.completion.JavaMethodCallElement; +import com.intellij.codeInsight.completion.JavaPsiClassReferenceElement; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.codeInsight.lookup.VariableLookupItem; import com.intellij.openapi.util.Iconable; -import com.intellij.psi.PsiElement; +import com.intellij.psi.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; @@ -33,6 +36,8 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.plugin.JetDescriptorIconProvider; import org.jetbrains.jet.plugin.completion.handlers.JetClassInsertHandler; import org.jetbrains.jet.plugin.completion.handlers.JetFunctionInsertHandler; +import org.jetbrains.jet.plugin.completion.handlers.JetJavaClassInsertHandler; +import org.jetbrains.jet.plugin.libraries.DecompiledDataFactory; import org.jetbrains.jet.resolve.DescriptorRenderer; import java.util.List; @@ -56,6 +61,12 @@ public final class DescriptorLookupConverter { @NotNull public static LookupElement createLookupElement(@NotNull ResolveSession resolveSession, @NotNull DeclarationDescriptor descriptor, @Nullable PsiElement declaration) { + if (declaration != null) { + LookupElement javaLookupElement = createJavaLookupElementIfPossible(declaration); + if (javaLookupElement != null) { + return javaLookupElement; + } + } LookupElementBuilder element = LookupElementBuilder.create( new JetLookupObject(descriptor, resolveSession, declaration), descriptor.getName().getName()); @@ -113,6 +124,31 @@ public final class DescriptorLookupConverter { return element; } + @Nullable + private static LookupElement createJavaLookupElementIfPossible(@NotNull PsiElement declaration) { + if (declaration instanceof PsiClass) { + PsiClass psiClass = (PsiClass) declaration; + if (!DecompiledDataFactory.isCompiledFromKotlin(psiClass)) { + return new JavaPsiClassReferenceElement(psiClass).setInsertHandler(JetJavaClassInsertHandler.JAVA_CLASS_INSERT_HANDLER); + } + } + + if (declaration instanceof PsiMember) { + PsiClass containingClass = ((PsiMember) declaration).getContainingClass(); + if (containingClass != null && !DecompiledDataFactory.isCompiledFromKotlin(containingClass)) { + if (declaration instanceof PsiMethod) { + return new JavaMethodCallElement((PsiMethod) declaration); + } + + if (declaration instanceof PsiField) { + return new VariableLookupItem((PsiField) declaration); + } + } + } + + return null; + } + @NotNull public static LookupElement createLookupElement( @NotNull ResolveSession resolveSession, diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledDataFactory.java b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledDataFactory.java index e7fc2ea563e..fb9cd4b2809 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledDataFactory.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledDataFactory.java @@ -44,7 +44,7 @@ import java.util.*; * @author Evgeny Gerashchenko * @since 3/11/12 */ -class DecompiledDataFactory { +public class DecompiledDataFactory { private static final String JET_CLASS = JetClass.class.getName(); private static final String JET_METHOD = JetMethod.class.getName(); private static final String DECOMPILED_COMMENT = "/* compiled code */"; @@ -196,11 +196,11 @@ class DecompiledDataFactory { return false; } - static boolean isKotlinClass(PsiClass psiClass) { + public static boolean isKotlinClass(@NotNull PsiClass psiClass) { return hasAnnotation(psiClass, JET_CLASS); } - static boolean isKotlinNamespaceClass(PsiClass psiClass) { + public static boolean isKotlinNamespaceClass(@NotNull PsiClass psiClass) { if (JvmAbi.PACKAGE_CLASS.equals(psiClass.getName()) && !isKotlinClass(psiClass)) { for (PsiMethod method : psiClass.getMethods()) { if (hasAnnotation(method, JET_METHOD)) { @@ -210,4 +210,8 @@ class DecompiledDataFactory { } return false; } + + public static boolean isCompiledFromKotlin(@NotNull PsiClass psiClass) { + return isKotlinClass(psiClass) || isKotlinNamespaceClass(psiClass); + } } diff --git a/idea/testData/completion/basic/NoImportedJavaClassDuplication.kt b/idea/testData/completion/basic/NoImportedJavaClassDuplication.kt new file mode 100644 index 00000000000..05139ad47c7 --- /dev/null +++ b/idea/testData/completion/basic/NoImportedJavaClassDuplication.kt @@ -0,0 +1,7 @@ +import java.io.InputStreamReader + +val x = InputStreamReader + +// TIME: 1 +// EXIST: InputStreamReader +// NUMBER: 1 \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java b/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java index 7c68ae8a7da..3e8e13c2966 100644 --- a/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java +++ b/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java @@ -201,6 +201,10 @@ public class JetBasicCompletionTest extends JetCompletionTestBase { doTest(); } + public void testNoImportedJavaClassDuplication() { + doTest(); + } + public void testNoTopLevelCompletionInQualifiedUserTypes() { doTest(); }