KT-1808 Auto import offers private static Java classes

#KT-1808 fixed
This commit is contained in:
Nikolay Krasko
2012-06-01 17:09:09 +04:00
parent a5801198d5
commit c00c4d3881
6 changed files with 68 additions and 29 deletions
@@ -17,7 +17,6 @@
package org.jetbrains.jet.plugin.caches;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
@@ -36,7 +35,10 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.asJava.JavaElementFinder;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import org.jetbrains.jet.lang.resolve.ImportPath;
import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetType;
@@ -48,7 +50,6 @@ import org.jetbrains.jet.plugin.stubindex.JetExtensionFunctionNameIndex;
import org.jetbrains.jet.plugin.stubindex.JetFullClassNameIndex;
import org.jetbrains.jet.plugin.stubindex.JetShortClassNameIndex;
import org.jetbrains.jet.plugin.stubindex.JetShortFunctionNameIndex;
import org.jetbrains.jet.util.QualifiedNamesUtil;
import java.util.*;
@@ -93,7 +94,7 @@ public class JetShortNamesCache extends PsiShortNamesCache {
List<PsiClass> result = new ArrayList<PsiClass>();
for (String fqName : JetFullClassNameIndex.getInstance().getAllKeys(project)) {
if (QualifiedNamesUtil.fqnToShortName(new FqName(fqName)).getName().equals(name)) {
if ((new FqName(fqName)).shortName().getName().equals(name)) {
PsiClass psiClass = javaElementFinder.findClass(fqName, scope);
if (psiClass != null) {
result.add(psiClass);
@@ -129,17 +130,6 @@ public class JetShortNamesCache extends PsiShortNamesCache {
return standardTypes;
}
@NotNull
public Collection<FqName> getFQNamesByName(@NotNull final String name, JetFile file, @NotNull GlobalSearchScope scope) {
BindingContext context = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file).getBindingContext();
return Collections2.filter(context.getKeys(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR), new Predicate<FqName>() {
@Override
public boolean apply(@Nullable FqName fqName) {
return fqName != null && QualifiedNamesUtil.isShortNameForFQN(name, fqName);
}
});
}
/**
* Get jet non-extension top-level function names. Method is allowed to give invalid names - all result should be
* checked with getTopLevelFunctionDescriptorsByName().
@@ -30,28 +30,32 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiFile;
import com.intellij.psi.search.DelegatingGlobalSearchScope;
import com.intellij.psi.PsiMember;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.search.GlobalSearchScope;
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.JetLightClass;
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.descriptors.Visibilities;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.ImportPath;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.plugin.JetBundle;
import org.jetbrains.jet.plugin.JetFileType;
import org.jetbrains.jet.plugin.actions.JetAddImportAction;
import org.jetbrains.jet.plugin.caches.JetCacheManager;
import org.jetbrains.jet.plugin.caches.JetShortNamesCache;
import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade;
import java.util.Collection;
import java.util.Collections;
@@ -100,8 +104,10 @@ public class ImportClassAndFunFix extends JetHintAction<JetSimpleNameExpression>
}
});
}
private static Collection<FqName> getJetTopLevelFunctions(@NotNull String referenceName, JetSimpleNameExpression expression, @NotNull Project project) {
private static Collection<FqName> getJetTopLevelFunctions(@NotNull String referenceName,
JetSimpleNameExpression expression,
@NotNull Project project) {
JetShortNamesCache namesCache = JetCacheManager.getInstance(project).getNamesCache();
Collection<FunctionDescriptor> topLevelFunctions = namesCache.getTopLevelFunctionDescriptorsByName(
referenceName,
@@ -148,33 +154,58 @@ public class ImportClassAndFunFix extends JetHintAction<JetSimpleNameExpression>
public static Collection<FqName> getClassNames(@NotNull String referenceName, @NotNull JetFile file) {
final GlobalSearchScope scope = GlobalSearchScope.allScope(file.getProject());
Set<FqName> possibleResolveNames = Sets.newHashSet();
possibleResolveNames.addAll(JetCacheManager.getInstance(file.getProject()).getNamesCache().getFQNamesByName(referenceName, file, scope));
possibleResolveNames.addAll(getJavaClasses(referenceName, file.getProject(), scope));
// TODO: Do appropriate sorting
return Lists.newArrayList(possibleResolveNames);
}
private static Collection<FqName> getJavaClasses(@NotNull final String typeName, @NotNull Project project, final GlobalSearchScope scope) {
private static Collection<FqName> getJavaClasses(@NotNull final String typeName,
@NotNull Project project,
final GlobalSearchScope scope) {
PsiShortNamesCache cache = PsiShortNamesCache.getInstance(project);
PsiClass[] classes = cache.getClassesByName(typeName, new DelegatingGlobalSearchScope(scope) {
PsiClass[] classes = cache.getClassesByName(typeName, scope);
Collection<PsiClass> accessibleClasses = Collections2.filter(Lists.newArrayList(classes), new Predicate<PsiClass>() {
@Override
public boolean contains(@NotNull VirtualFile file) {
return myBaseScope.contains(file) && file.getFileType() != JetFileType.INSTANCE;
public boolean apply(PsiClass psiClass) {
assert psiClass != null;
return isAccessible(psiClass);
}
});
return Collections2.transform(Lists.newArrayList(classes), new Function<PsiClass, FqName>() {
return Collections2.transform(accessibleClasses, new Function<PsiClass, FqName>() {
@Nullable
@Override
public FqName apply(@Nullable PsiClass javaClass) {
assert javaClass != null;
return new FqName(javaClass.getQualifiedName());
String qualifiedName = javaClass.getQualifiedName();
assert qualifiedName != null;
return new FqName(qualifiedName);
}
});
}
private static boolean isAccessible(PsiMember member) {
if (member instanceof JetLightClass) {
// TODO: Now light class can't losing accessibility information
JetLightClass lightClass = (JetLightClass) member;
BindingContext context = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) lightClass.getContainingFile()).getBindingContext();
ClassDescriptor descriptor = context.get(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, lightClass.getFqName());
if (descriptor != null) {
return descriptor.getVisibility() == Visibilities.PUBLIC || descriptor.getVisibility() == Visibilities.INTERNAL;
}
else {
assert false : "Descriptor of the class isn't found in the binding context";
}
}
return member.hasModifierProperty(PsiModifier.PUBLIC) || member.hasModifierProperty(PsiModifier.PROTECTED);
}
@Override
public boolean showHint(@NotNull Editor editor) {
if (suggestions.isEmpty()) {
@@ -220,7 +251,8 @@ public class ImportClassAndFunFix extends JetHintAction<JetSimpleNameExpression>
}
@Override
public void invoke(@NotNull final Project project, @NotNull final Editor editor, final PsiFile file) throws IncorrectOperationException {
public void invoke(@NotNull final Project project, @NotNull final Editor editor, final PsiFile file)
throws IncorrectOperationException {
CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
@Override
public void run() {
@@ -0,0 +1,5 @@
// "Import Class" "false"
fun test() {
PrivateClass
}
@@ -0,0 +1,5 @@
// "Import" "false"
fun test() {
<caret>PrivateClass
}
@@ -0,0 +1,3 @@
package sometest
private class PrivateClass
@@ -38,6 +38,10 @@ public class AutoImportFixTest extends JetQuickFixMultiFileTest {
doTest();
}
public void testNoImportForPrivateClass() throws Exception {
doTest();
}
@Override
protected String getCheckFileName() {
return getTestName(true) + ".after.kt";