From 5e1e6c25950813a326dcdc0fc2f4056d07363663 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Fri, 18 Jan 2013 13:50:02 -0800 Subject: [PATCH] Invisible private classes are not auto-imported --- ...otlinLightClassForExplicitDeclaration.java | 5 +++ .../plugin/quickfix/ImportClassAndFunFix.java | 34 +++++++++++++++++-- .../autoImports/packageClass.before.Main.kt | 8 +++++ .../packageClass.before.data.Sample.kt | 4 +++ .../plugin/quickfix/AutoImportFixTest.java | 4 +++ 5 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 idea/testData/quickfix/autoImports/packageClass.before.Main.kt create mode 100644 idea/testData/quickfix/autoImports/packageClass.before.data.Sample.kt diff --git a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinLightClassForExplicitDeclaration.java b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinLightClassForExplicitDeclaration.java index a598e0388b1..6810851a5ed 100644 --- a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinLightClassForExplicitDeclaration.java +++ b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/KotlinLightClassForExplicitDeclaration.java @@ -102,6 +102,11 @@ public class KotlinLightClassForExplicitDeclaration extends AbstractLightClass i this.classOrObject = classOrObject; } + @NotNull + public JetClassOrObject getJetClassOrObject() { + return classOrObject; + } + @NotNull @Override public FqName getFqName() { diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java index 13db0d0aaa4..d6344f75923 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java @@ -39,10 +39,13 @@ import com.intellij.psi.search.PsiShortNamesCache; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.asJava.KotlinLightClassForExplicitDeclaration; +import org.jetbrains.jet.asJava.KotlinLightClassForPackage; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.diagnostics.Diagnostic; +import org.jetbrains.jet.lang.psi.JetClassOrObject; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetPsiUtil; import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; @@ -50,11 +53,13 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.ImportPath; import org.jetbrains.jet.lang.resolve.lazy.ResolveSession; import org.jetbrains.jet.lang.resolve.name.FqName; +import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.plugin.JetBundle; import org.jetbrains.jet.plugin.actions.JetAddImportAction; import org.jetbrains.jet.plugin.caches.JetShortNamesCache; import org.jetbrains.jet.plugin.project.JsModuleDetector; import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade; +import org.jetbrains.jet.util.QualifiedNamesUtil; import java.util.Collection; import java.util.Collections; @@ -173,7 +178,7 @@ public class ImportClassAndFunFix extends JetHintAction return Lists.newArrayList(possibleResolveNames); } - private static Collection getClassesFromCache(@NotNull final String typeName, @NotNull JetFile file) { + private static Collection getClassesFromCache(@NotNull final String typeName, @NotNull final JetFile file) { PsiShortNamesCache cache = getShortNamesCache(file); PsiClass[] classes = cache.getClassesByName(typeName, GlobalSearchScope.allScope(file.getProject())); @@ -182,7 +187,7 @@ public class ImportClassAndFunFix extends JetHintAction @Override public boolean apply(PsiClass psiClass) { assert psiClass != null; - return isAccessible(psiClass); + return isAccessible(psiClass, file); } }); @@ -223,10 +228,33 @@ public class ImportClassAndFunFix extends JetHintAction }); } - private static boolean isAccessible(PsiMember member) { + private static boolean isAccessible(PsiMember member, JetFile fromFile) { + if (member instanceof KotlinLightClassForPackage) { + // Package classes are only available from Java, so they should not be visisble from Kotlin + return false; + } + if (member instanceof KotlinLightClassForExplicitDeclaration) { + KotlinLightClassForExplicitDeclaration lightClass = (KotlinLightClassForExplicitDeclaration) member; + + // It is a Kotlin class already, we need to properly check visibility? + JetClassOrObject classOrObject = lightClass.getJetClassOrObject(); + + if (isTopLevelDeclaration(classOrObject) && classOrObject.hasModifier(JetTokens.PRIVATE_KEYWORD)) { + // The class is declared private in the targetPackage + // It is visible in this package and all of its subpackages + JetFile targetFile = (JetFile) classOrObject.getContainingFile(); + FqName targetPackage = JetPsiUtil.getFQName(targetFile); + FqName fromPackage = JetPsiUtil.getFQName(fromFile); + return QualifiedNamesUtil.isSubpackageOf(fromPackage, targetPackage); + } + } return member.hasModifierProperty(PsiModifier.PUBLIC) || member.hasModifierProperty(PsiModifier.PROTECTED); } + private static boolean isTopLevelDeclaration(JetClassOrObject classOrObject) { + return classOrObject.getContainingFile() == classOrObject.getParent(); + } + @Override public boolean showHint(@NotNull Editor editor) { if (suggestions.isEmpty()) { diff --git a/idea/testData/quickfix/autoImports/packageClass.before.Main.kt b/idea/testData/quickfix/autoImports/packageClass.before.Main.kt new file mode 100644 index 00000000000..fcb6a47c9f8 --- /dev/null +++ b/idea/testData/quickfix/autoImports/packageClass.before.Main.kt @@ -0,0 +1,8 @@ +// "Import" "false" +// ERROR: Unresolved reference: FooPackage + +package packageClass + +fun functionImportTest() { + FooPackage() +} diff --git a/idea/testData/quickfix/autoImports/packageClass.before.data.Sample.kt b/idea/testData/quickfix/autoImports/packageClass.before.data.Sample.kt new file mode 100644 index 00000000000..b81c235e40e --- /dev/null +++ b/idea/testData/quickfix/autoImports/packageClass.before.data.Sample.kt @@ -0,0 +1,4 @@ +package packageClass.foo + +fun someTestFun() { +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/AutoImportFixTest.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/AutoImportFixTest.java index d4bfbe8e31e..8f4122a8f14 100644 --- a/idea/tests/org/jetbrains/jet/plugin/quickfix/AutoImportFixTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/AutoImportFixTest.java @@ -67,6 +67,10 @@ public class AutoImportFixTest extends JetQuickFixMultiFileTest { doTest(); } + public void testPackageClass() throws Exception { + doTest(); + } + @Override protected String getCheckFileName() { return getTestName(true) + ".after.kt";