提交 e5c39df5 编写于 作者: N Nikolay Krasko

KT-658 Show types in IDEA auto assist for kotlin

上级 bf54dc54
...@@ -267,7 +267,7 @@ public class JavaDescriptorResolver { ...@@ -267,7 +267,7 @@ public class JavaDescriptorResolver {
return javaFacade.findClass(qualifiedName, javaSearchScope); return javaFacade.findClass(qualifiedName, javaSearchScope);
} }
private PsiPackage findPackage(String qualifiedName) { /*package*/ PsiPackage findPackage(String qualifiedName) {
return javaFacade.findPackage(qualifiedName); return javaFacade.findPackage(qualifiedName);
} }
......
package org.jetbrains.jet.lang.resolve.java; package org.jetbrains.jet.lang.resolve.java;
import com.google.common.collect.Sets;
import com.intellij.psi.PsiClass; import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.PsiPackage;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.JetScopeImpl; import org.jetbrains.jet.lang.resolve.scopes.JetScopeImpl;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
...@@ -14,11 +21,13 @@ import java.util.Set; ...@@ -14,11 +21,13 @@ import java.util.Set;
public class JavaPackageScope extends JetScopeImpl { public class JavaPackageScope extends JetScopeImpl {
private final JavaSemanticServices semanticServices; private final JavaSemanticServices semanticServices;
private final DeclarationDescriptor containingDescriptor; private final DeclarationDescriptor containingDescriptor;
private final String packagePrefix; private final String packageFQN;
private Collection<DeclarationDescriptor> allDescriptors;
public JavaPackageScope(@NotNull String packageFQN, DeclarationDescriptor containingDescriptor, JavaSemanticServices semanticServices) { public JavaPackageScope(@NotNull String packageFQN, DeclarationDescriptor containingDescriptor, JavaSemanticServices semanticServices) {
this.semanticServices = semanticServices; this.semanticServices = semanticServices;
this.packagePrefix = packageFQN.isEmpty() ? "" : packageFQN + "."; this.packageFQN = packageFQN;
this.containingDescriptor = containingDescriptor; this.containingDescriptor = containingDescriptor;
} }
...@@ -36,7 +45,7 @@ public class JavaPackageScope extends JetScopeImpl { ...@@ -36,7 +45,7 @@ public class JavaPackageScope extends JetScopeImpl {
@Override @Override
public Set<FunctionDescriptor> getFunctions(@NotNull String name) { public Set<FunctionDescriptor> getFunctions(@NotNull String name) {
// TODO: what is GlobalSearchScope // TODO: what is GlobalSearchScope
PsiClass psiClass = semanticServices.getDescriptorResolver().javaFacade.findClass(packagePrefix + "namespace"); PsiClass psiClass = semanticServices.getDescriptorResolver().javaFacade.findClass(getQualifiedName("namespace"));
if (psiClass == null) { if (psiClass == null) {
return Collections.emptySet(); return Collections.emptySet();
} }
...@@ -54,7 +63,35 @@ public class JavaPackageScope extends JetScopeImpl { ...@@ -54,7 +63,35 @@ public class JavaPackageScope extends JetScopeImpl {
return containingDescriptor; return containingDescriptor;
} }
@NotNull
@Override
public Collection<DeclarationDescriptor> getAllDescriptors() {
if (allDescriptors == null) {
allDescriptors = Sets.newHashSet();
final PsiPackage javaPackage = semanticServices.getDescriptorResolver().findPackage(packageFQN);
if (javaPackage != null) {
final JavaDescriptorResolver descriptorResolver = semanticServices.getDescriptorResolver();
for (PsiPackage psiSubPackage : javaPackage.getSubPackages()) {
allDescriptors.add(descriptorResolver.resolveNamespace(psiSubPackage.getQualifiedName()));
}
for (PsiClass psiClass : javaPackage.getClasses()) {
if (psiClass.hasModifierProperty(PsiModifier.PUBLIC)) {
allDescriptors.add(descriptorResolver.resolveClass(psiClass));
}
}
}
}
return allDescriptors;
}
private String getQualifiedName(String name) { private String getQualifiedName(String name) {
return packagePrefix + name; return (packageFQN.isEmpty() ? "" : packageFQN + ".") + name;
} }
} }
...@@ -199,6 +199,10 @@ public class WriteThroughScope extends WritableScopeWithImports { ...@@ -199,6 +199,10 @@ public class WriteThroughScope extends WritableScopeWithImports {
allDescriptors = Lists.newArrayList(); allDescriptors = Lists.newArrayList();
allDescriptors.addAll(writableWorker.getAllDescriptors()); allDescriptors.addAll(writableWorker.getAllDescriptors());
allDescriptors.addAll(getWorkerScope().getAllDescriptors()); allDescriptors.addAll(getWorkerScope().getAllDescriptors());
for (JetScope imported : getImports()) {
allDescriptors.addAll(imported.getAllDescriptors());
}
} }
return allDescriptors; return allDescriptors;
} }
......
...@@ -4,7 +4,7 @@ import com.intellij.ide.IconProvider; ...@@ -4,7 +4,7 @@ import com.intellij.ide.IconProvider;
import com.intellij.openapi.util.Iconable; import com.intellij.openapi.util.Iconable;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Icons; import com.intellij.util.PlatformIcons;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
...@@ -15,21 +15,21 @@ import javax.swing.*; ...@@ -15,21 +15,21 @@ import javax.swing.*;
* @author yole * @author yole
*/ */
public class JetIconProvider extends IconProvider { public class JetIconProvider extends IconProvider {
public static final Icon ICON_FOR_OBJECT = Icons.ANONYMOUS_CLASS_ICON; public static final Icon ICON_FOR_OBJECT = PlatformIcons.ANONYMOUS_CLASS_ICON;
@Override @Override
public Icon getIcon(@NotNull PsiElement psiElement, int flags) { public Icon getIcon(@NotNull PsiElement psiElement, int flags) {
if (psiElement instanceof JetNamespace) { if (psiElement instanceof JetNamespace) {
return (flags & Iconable.ICON_FLAG_OPEN) != 0 ? Icons.PACKAGE_OPEN_ICON : Icons.PACKAGE_ICON; return (flags & Iconable.ICON_FLAG_OPEN) != 0 ? PlatformIcons.PACKAGE_OPEN_ICON : PlatformIcons.PACKAGE_ICON;
} }
if (psiElement instanceof JetNamedFunction) { if (psiElement instanceof JetNamedFunction) {
return PsiTreeUtil.getParentOfType(psiElement, JetNamedDeclaration.class) instanceof JetClass return PsiTreeUtil.getParentOfType(psiElement, JetNamedDeclaration.class) instanceof JetClass
? Icons.METHOD_ICON ? PlatformIcons.METHOD_ICON
: Icons.FUNCTION_ICON; : PlatformIcons.FUNCTION_ICON;
} }
if (psiElement instanceof JetClass) { if (psiElement instanceof JetClass) {
JetClass jetClass = (JetClass) psiElement; JetClass jetClass = (JetClass) psiElement;
Icon icon = jetClass.hasModifier(JetTokens.ENUM_KEYWORD) ? Icons.ENUM_ICON : Icons.CLASS_ICON; Icon icon = jetClass.hasModifier(JetTokens.ENUM_KEYWORD) ? PlatformIcons.ENUM_ICON : PlatformIcons.CLASS_ICON;
if (jetClass instanceof JetEnumEntry) { if (jetClass instanceof JetEnumEntry) {
JetEnumEntry enumEntry = (JetEnumEntry) jetClass; JetEnumEntry enumEntry = (JetEnumEntry) jetClass;
if (enumEntry.getPrimaryConstructorParameterList() == null) { if (enumEntry.getPrimaryConstructorParameterList() == null) {
...@@ -42,13 +42,13 @@ public class JetIconProvider extends IconProvider { ...@@ -42,13 +42,13 @@ public class JetIconProvider extends IconProvider {
if (((JetParameter) psiElement).getValOrVarNode() != null) { if (((JetParameter) psiElement).getValOrVarNode() != null) {
JetParameterList parameterList = PsiTreeUtil.getParentOfType(psiElement, JetParameterList.class); JetParameterList parameterList = PsiTreeUtil.getParentOfType(psiElement, JetParameterList.class);
if (parameterList != null && parameterList.getParent() instanceof JetClass) { if (parameterList != null && parameterList.getParent() instanceof JetClass) {
return Icons.PROPERTY_ICON; return PlatformIcons.PROPERTY_ICON;
} }
} }
return Icons.PARAMETER_ICON; return PlatformIcons.PARAMETER_ICON;
} }
if (psiElement instanceof JetProperty) { if (psiElement instanceof JetProperty) {
return Icons.PROPERTY_ICON; return PlatformIcons.PROPERTY_ICON;
} }
return null; return null;
} }
......
...@@ -24,13 +24,23 @@ import java.util.Set; ...@@ -24,13 +24,23 @@ import java.util.Set;
/** /**
* @author abreslav * @author abreslav
*/ */
public class WholeProjectAnalyzerFacade { public final class WholeProjectAnalyzerFacade {
public static final Function<JetFile, Collection<JetDeclaration>> WHOLE_PROJECT_DECLARATION_PROVIDER = new Function<JetFile, Collection<JetDeclaration>>() {
/** Forbid creating */
private WholeProjectAnalyzerFacade() {}
/**
* Will collect all root-namespaces in all kotlin files in the project.
*/
public static final Function<JetFile, Collection<JetDeclaration>> WHOLE_PROJECT_DECLARATION_PROVIDER =
new Function<JetFile, Collection<JetDeclaration>>() {
@Override @Override
public Collection<JetDeclaration> fun(final JetFile rootFile) { public Collection<JetDeclaration> fun(final JetFile rootFile) {
final Project project = rootFile.getProject(); final Project project = rootFile.getProject();
final Set<JetDeclaration> namespaces = Sets.newLinkedHashSet(); final Set<JetDeclaration> namespaces = Sets.newLinkedHashSet();
ProjectRootManager rootManager = ProjectRootManager.getInstance(project); final ProjectRootManager rootManager = ProjectRootManager.getInstance(project);
if (rootManager != null && !ApplicationManager.getApplication().isUnitTestMode()) { if (rootManager != null && !ApplicationManager.getApplication().isUnitTestMode()) {
VirtualFile[] contentRoots = rootManager.getContentRoots(); VirtualFile[] contentRoots = rootManager.getContentRoots();
...@@ -55,9 +65,9 @@ public class WholeProjectAnalyzerFacade { ...@@ -55,9 +65,9 @@ public class WholeProjectAnalyzerFacade {
} }
}; };
@NotNull @NotNull
public static BindingContext analyzeProjectWithCacheOnAFile(@NotNull JetFile file) { public static BindingContext analyzeProjectWithCacheOnAFile(@NotNull JetFile file) {
return AnalyzerFacade.analyzeFileWithCache(file, WHOLE_PROJECT_DECLARATION_PROVIDER); return AnalyzerFacade.analyzeFileWithCache(file, WHOLE_PROJECT_DECLARATION_PROVIDER);
} }
} }
namespace Tests
import java.util.*
fun hello() {
val a = So<caret>
}
// EXIST: SortedSet, SortedMap
namespace Tests
class A : java.<caret>
// EXIST: lang, util, io
// ABSENT: fun, val, var, namespace
open class MyClass() { open class MyClass() {
} }
class A() : My<caret> { class A() {
public fun test() { public fun test() {
val a : MyC<caret> val a : MyC<caret>
} }
} }
// EXIST: MyClass // EXIST: MyClass
\ No newline at end of file
...@@ -3,4 +3,4 @@ fun foo() { ...@@ -3,4 +3,4 @@ fun foo() {
} }
// TODO: Move all keywords to absent // TODO: Move all keywords to absent
// EXPECT: fun, val, var, namespace // EXIST: fun, val, var, namespace
<caret> <caret>
// EXPECT: namespace, as, type, class, this, super, val, var, fun, for, null, true // EXIST: namespace, as, type, class, this, super, val, var, fun, for, null, true
// EXPECT: false, is, in, throw, return, break, continue, object, if, try, else, while // EXIST: false, is, in, throw, return, break, continue, object, if, try, else, while
// EXPECT: do, when, trait, This // EXIST: do, when, trait, This
// EXPECT: import, where, by, get, set, abstract, enum, open, annotation, override, private // EXIST: import, where, by, get, set, abstract, enum, open, annotation, override, private
// EXPECT: public, internal, protected, catch, out, vararg, inline, finally, final, ref // EXIST: public, internal, protected, catch, out, vararg, inline, finally, final, ref
// ABSENT: ?in, new, extends, implements // ABSENT: ?in, new, extends, implements
\ No newline at end of file
...@@ -23,7 +23,7 @@ public class JetBasicCompletionTest extends JetCompletionTestBase { ...@@ -23,7 +23,7 @@ public class JetBasicCompletionTest extends JetCompletionTestBase {
setName("testCompletionExecute"); setName("testCompletionExecute");
} }
public void testCompletionExecute() { public void testCompletionExecute() throws Exception {
doTest(); doTest();
} }
......
...@@ -2,70 +2,64 @@ package org.jetbrains.jet.completion; ...@@ -2,70 +2,64 @@ package org.jetbrains.jet.completion;
import com.intellij.codeInsight.completion.CodeCompletionHandlerBase; import com.intellij.codeInsight.completion.CodeCompletionHandlerBase;
import com.intellij.codeInsight.completion.CompletionType; import com.intellij.codeInsight.completion.CompletionType;
import com.intellij.codeInsight.completion.LightCompletionTestCase;
import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupEx;
import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.testFramework.LightCodeInsightTestCase; import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.openapi.projectRoots.Sdk;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.plugin.PluginTestCaseBase;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.StringReader; import java.io.StringReader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
/** /**
* @author Nikolay.Krasko * @author Nikolay.Krasko
*/ */
public abstract class JetCompletionTestBase extends LightCodeInsightTestCase { public abstract class JetCompletionTestBase extends LightCompletionTestCase {
protected void doTest() { private CompletionType type;
protected void doTest() throws Exception {
final String testName = getTestName(false); final String testName = getTestName(false);
configureByFile(testName + ".kt");
CompletionType completionType = (testName.startsWith("Smart")) ? CompletionType.SMART : CompletionType.BASIC; type = (testName.startsWith("Smart")) ? CompletionType.SMART : CompletionType.BASIC;
new CodeCompletionHandlerBase(completionType, false, false, true).invokeCompletion(getProject(), getEditor());
LookupEx lookup = LookupManager.getActiveLookup(getEditor()); configureByFile(testName + ".kt");
assert lookup != null;
HashSet<String> items = new HashSet<String>(resolveLookups(lookup.getItems())); assertContainsItems(itemsShouldExist(getFile().getText()));
assertNotContainItems(itemsShouldAbsent(getFile().getText()));
}
List<String> shouldExist = itemsShouldExist(getFile().getText()); @Override
for (String shouldExistItem : shouldExist) { protected Sdk getProjectJDK() {
assertTrue(String.format("Should contain proposal '%s'.", shouldExistItem), return PluginTestCaseBase.jdkFromIdeaHome();
items.contains(shouldExistItem));
}
List<String> shouldAbsent = itemsShouldAbsent(getFile().getText());
for (String shouldAbsentItem : shouldAbsent) {
assertTrue(String.format("Shouldn't contain proposal '%s'.", shouldAbsentItem),
!items.contains(shouldAbsentItem));
}
} }
private static List<String> resolveLookups(List<LookupElement> items) {
ArrayList<String> result = new ArrayList<String>(items.size());
for (LookupElement item : items) {
result.add(item.getLookupString());
}
return result; @Override
protected void complete(final int time) {
new CodeCompletionHandlerBase(type, false, false, true).invokeCompletion(getProject(), getEditor(), time, false);
LookupImpl lookup = (LookupImpl) LookupManager.getActiveLookup(myEditor);
myItems = lookup == null ? null : lookup.getItems().toArray(LookupElement.EMPTY_ARRAY);
myPrefix = lookup == null ? null : lookup.itemPattern(lookup.getItems().get(0));
} }
@NotNull @NotNull
private static List<String> itemsShouldExist(String fileText) { private static String[] itemsShouldExist(String fileText) {
return findListWithPrefix("// EXIST:", fileText); return findListWithPrefix("// EXIST:", fileText);
} }
@NotNull @NotNull
private static List<String> itemsShouldAbsent(String fileText) { private static String[] itemsShouldAbsent(String fileText) {
return findListWithPrefix("// ABSENT:", fileText); return findListWithPrefix("// ABSENT:", fileText);
} }
@NotNull @NotNull
private static List<String> findListWithPrefix(String prefix, String fileText) { private static String[] findListWithPrefix(String prefix, String fileText) {
ArrayList<String> result = new ArrayList<String>(); ArrayList<String> result = new ArrayList<String>();
for (String line : findLinesWithPrefixRemoved(prefix, fileText)) { for (String line : findLinesWithPrefixRemoved(prefix, fileText)) {
...@@ -76,7 +70,7 @@ public abstract class JetCompletionTestBase extends LightCodeInsightTestCase { ...@@ -76,7 +70,7 @@ public abstract class JetCompletionTestBase extends LightCodeInsightTestCase {
} }
} }
return result; return result.toArray(new String[result.size()]);
} }
@NotNull @NotNull
......
package org.jetbrains.jet.completion; package org.jetbrains.jet.completion;
import junit.framework.Test;
import junit.framework.TestSuite; import junit.framework.TestSuite;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBuilder; import org.jetbrains.jet.JetTestCaseBuilder;
...@@ -25,7 +26,7 @@ public class KeywordsCompletionTest extends JetCompletionTestBase { ...@@ -25,7 +26,7 @@ public class KeywordsCompletionTest extends JetCompletionTestBase {
setName("testCompletionExecute"); setName("testCompletionExecute");
} }
public void testCompletionExecute() { public void testCompletionExecute() throws Exception {
doTest(); doTest();
} }
...@@ -49,13 +50,14 @@ public class KeywordsCompletionTest extends JetCompletionTestBase { ...@@ -49,13 +50,14 @@ public class KeywordsCompletionTest extends JetCompletionTestBase {
PluginTestCaseBase.getTestDataPathBase(), "/completion/keywords/", false, PluginTestCaseBase.getTestDataPathBase(), "/completion/keywords/", false,
JetTestCaseBuilder.emptyFilter, new JetTestCaseBuilder.NamedTestFactory() { JetTestCaseBuilder.emptyFilter, new JetTestCaseBuilder.NamedTestFactory() {
@NotNull @NotNull
@Override @Override
public junit.framework.Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) { public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) {
return new KeywordsCompletionTest(dataPath, name); return new KeywordsCompletionTest(dataPath, name);
} }
}, suite); }, suite);
return suite; return suite;
} }
} }
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册