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

KT-658 Show types in IDEA auto assist for kotlin

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