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

Completion for top-level functions from class and jar files.

上级 ef6461c4
......@@ -24,18 +24,8 @@ import com.google.inject.Inject;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.Configuration;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetImportDirective;
import org.jetbrains.jet.lang.psi.JetQualifiedExpression;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.types.JetType;
......@@ -45,13 +35,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.jetbrains.jet.lang.diagnostics.Errors.CANNOT_BE_IMPORTED;
import static org.jetbrains.jet.lang.diagnostics.Errors.CANNOT_IMPORT_FROM_ELEMENT;
import static org.jetbrains.jet.lang.diagnostics.Errors.NO_CLASS_OBJECT;
import static org.jetbrains.jet.lang.diagnostics.Errors.UNRESOLVED_REFERENCE;
import static org.jetbrains.jet.lang.diagnostics.Errors.UNSUPPORTED;
import static org.jetbrains.jet.lang.diagnostics.Errors.USELESS_HIDDEN_IMPORT;
import static org.jetbrains.jet.lang.diagnostics.Errors.USELESS_SIMPLE_IMPORT;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
/**
* @author abreslav
......@@ -166,7 +150,10 @@ public class ImportsResolver {
}
}
public static Collection<? extends DeclarationDescriptor> analyseImportReference(@NotNull JetImportDirective importDirective, @NotNull JetScope scope, @NotNull BindingTrace trace) {
public static Collection<? extends DeclarationDescriptor> analyseImportReference(
@NotNull JetImportDirective importDirective,
@NotNull JetScope scope, @NotNull BindingTrace trace
) {
ImportsResolver.SingleImportResolver importResolver = new ImportsResolver.SingleImportResolver(trace, false);
return importResolver.processImportReference(importDirective, scope, Importer.DO_NOTHING);
}
......
......@@ -16,6 +16,7 @@
package org.jetbrains.jet.plugin.caches;
import com.google.common.base.Predicate;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.impl.java.stubs.index.JavaAnnotationIndex;
......@@ -24,8 +25,11 @@ import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.psi.util.PsiTreeUtil;
import jet.runtime.typeinfo.JetValueParameter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.kt.JetValueParameterAnnotation;
import org.jetbrains.jet.util.QualifiedNamesUtil;
import java.util.ArrayList;
import java.util.Collection;
......@@ -33,8 +37,7 @@ import java.util.HashSet;
import java.util.Set;
/**
* Get jet declarations from java that could be used in completion. Unlike the real jet resolver this helper is allowed
* to return partially unresolved descriptors in exchange of execution speed.
* Number of helper methods for searching jet element prototypes in java. Methods use java indices for search.
*
* @author Nikolay Krasko
*/
......@@ -47,6 +50,9 @@ class JetFromJavaDescriptorHelper {
* Get java equivalents for jet top level classes.
*/
static PsiClass[] getClassesForJetNamespaces(Project project, GlobalSearchScope scope) {
/* Will iterate through short name caches
Kotlin namespaces from jar a class files will be collected from java cache
Kotlin namespaces classes from sources will be collected with JetShortNamesCache.getClassesByName */
return PsiShortNamesCache.getInstance(project).getClassesByName(JvmAbi.PACKAGE_CLASS, scope);
}
......@@ -96,8 +102,51 @@ class JetFromJavaDescriptorHelper {
return extensionNames;
}
static Collection<PsiMethod> getTopExtensionFunctionByName(String name, Project project, GlobalSearchScope scope) {
static Collection<PsiMethod> getTopExtensionFunctionPrototypesByName(String name, Project project, GlobalSearchScope scope) {
return filterJetJavaPrototypesByName(
name, project, scope,
new Predicate<JetValueParameterAnnotation>() {
@Override
public boolean apply(@Nullable JetValueParameterAnnotation jetValueParameterAnnotation) {
assert jetValueParameterAnnotation != null;
return jetValueParameterAnnotation.receiver();
}
});
}
static Collection<PsiMethod> getTopLevelFunctionPrototypesByName(String name, Project project, GlobalSearchScope scope) {
return filterJetJavaPrototypesByName(
name, project, scope,
new Predicate<JetValueParameterAnnotation>() {
@Override
public boolean apply(@Nullable JetValueParameterAnnotation jetValueParameterAnnotation) {
assert jetValueParameterAnnotation != null;
return !jetValueParameterAnnotation.receiver();
}
});
}
@Nullable
static String getJetTopLevelDeclarationFQN(@NotNull PsiMethod method) {
PsiClass containingClass = method.getContainingClass();
if (containingClass != null) {
String classFQN = containingClass.getQualifiedName();
if (classFQN != null) {
if (QualifiedNamesUtil.fqnToShortName(classFQN).equals(JvmAbi.PACKAGE_CLASS)) {
String classParentFQN = QualifiedNamesUtil.withoutLastSegment(classFQN);
return QualifiedNamesUtil.combine(classParentFQN, method.getName());
}
}
}
return null;
}
private static Collection<PsiMethod> filterJetJavaPrototypesByName(
String name, Project project, GlobalSearchScope scope,
Predicate<JetValueParameterAnnotation> filterPredicate) {
Set<PsiMethod> selectedMethods = new HashSet<PsiMethod>();
Collection<PsiMethod> psiMethods = JavaMethodNameIndex.getInstance().get(name, project, scope);
......@@ -121,7 +170,7 @@ class JetFromJavaDescriptorHelper {
continue;
}
if (new JetValueParameterAnnotation(psiAnnotation).receiver()) {
if (filterPredicate.apply(new JetValueParameterAnnotation(psiAnnotation))) {
selectedMethods.add(psiMethod);
}
}
......
......@@ -34,12 +34,11 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.asJava.JavaElementFinder;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import org.jetbrains.jet.lang.resolve.ImportsResolver;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
......@@ -157,15 +156,36 @@ public class JetShortNamesCache extends PsiShortNamesCache {
}
@NotNull
public Collection<SimpleFunctionDescriptor> getTopLevelFunctionDescriptorsByName(@NotNull String name,
@NotNull GlobalSearchScope scope) {
public Collection<FunctionDescriptor> getTopLevelFunctionDescriptorsByName(
@NotNull String name,
@NotNull JetSimpleNameExpression expression,
@NotNull GlobalSearchScope scope
) {
HashSet<FunctionDescriptor> result = new HashSet<FunctionDescriptor>();
Collection<JetNamedFunction> jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(name, project, scope);
BindingContext context = getResolutionContext(scope);
JetFile jetFile = (JetFile) expression.getContainingFile();
BindingContext context = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(jetFile);
JetScope jetScope = context.get(BindingContext.RESOLUTION_SCOPE, expression);
HashSet<SimpleFunctionDescriptor> result = new HashSet<SimpleFunctionDescriptor>();
if (jetScope == null) {
return result;
}
Collection<PsiMethod> topLevelFunctionPrototypes = JetFromJavaDescriptorHelper.getTopLevelFunctionPrototypesByName(name, project, scope);
for (PsiMethod method : topLevelFunctionPrototypes) {
String functionFQN = JetFromJavaDescriptorHelper.getJetTopLevelDeclarationFQN(method);
if (functionFQN != null) {
JetImportDirective importDirective = JetPsiFactory.createImportDirective(project, functionFQN);
Collection<? extends DeclarationDescriptor> declarationDescriptors = ImportsResolver.analyseImportReference(importDirective, jetScope, new BindingTraceContext());
for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) {
if (declarationDescriptor instanceof FunctionDescriptor) {
result.add((FunctionDescriptor) declarationDescriptor);
}
}
}
}
Collection<JetNamedFunction> jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(name, project, scope);
for (JetNamedFunction jetNamedFunction : jetNamedFunctions) {
SimpleFunctionDescriptor functionDescriptor = context.get(BindingContext.FUNCTION, jetNamedFunction);
if (functionDescriptor != null) {
......@@ -204,7 +224,7 @@ public class JetShortNamesCache extends PsiShortNamesCache {
public Collection<PsiElement> getJetExtensionFunctionsByName(@NotNull String name, @NotNull GlobalSearchScope scope) {
HashSet<PsiElement> functions = new HashSet<PsiElement>();
functions.addAll(JetExtensionFunctionNameIndex.getInstance().get(name, project, scope));
functions.addAll(JetFromJavaDescriptorHelper.getTopExtensionFunctionByName(name, project, scope));
functions.addAll(JetFromJavaDescriptorHelper.getTopExtensionFunctionPrototypesByName(name, project, scope));
return functions;
}
......@@ -217,10 +237,6 @@ public class JetShortNamesCache extends PsiShortNamesCache {
) {
Collection<DeclarationDescriptor> resultDescriptors = new ArrayList<DeclarationDescriptor>();
if (!(expression.getContainingFile() instanceof JetFile)) {
return resultDescriptors;
}
JetFile jetFile = (JetFile) expression.getContainingFile();
BindingContext context = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(jetFile);
......@@ -245,16 +261,9 @@ public class JetShortNamesCache extends PsiShortNamesCache {
functionFQNs.add(JetPsiUtil.getFQName((JetNamedFunction) extensionFunction));
}
else if (extensionFunction instanceof PsiMethod) {
PsiMethod function = (PsiMethod) extensionFunction;
PsiClass containingClass = function.getContainingClass();
if (containingClass != null) {
String classFQN = containingClass.getQualifiedName();
if (classFQN != null) {
String classParentFQN = QualifiedNamesUtil.withoutLastSegment(classFQN);
functionFQNs.add(QualifiedNamesUtil.combine(classParentFQN, function.getName()));
}
String functionFQN = JetFromJavaDescriptorHelper.getJetTopLevelDeclarationFQN((PsiMethod) extensionFunction);
if (functionFQN != null) {
functionFQNs.add(functionFQN);
}
}
}
......@@ -279,7 +288,7 @@ public class JetShortNamesCache extends PsiShortNamesCache {
return JetShortFunctionNameIndex.getInstance().get(name, project, scope);
}
public Collection<String> getAllJetFunctionsNames() {
public Collection<String> getAllJetOnlyTopFunctionsNames() {
return JetShortFunctionNameIndex.getInstance().getAllKeys(project);
}
......
......@@ -51,6 +51,7 @@ import java.util.Set;
* @author Nikolay Krasko
*/
public class JetCompletionContributor extends CompletionContributor {
public JetCompletionContributor() {
extend(CompletionType.BASIC, PlatformPatterns.psiElement(),
new CompletionProvider<CompletionParameters>() {
......@@ -86,7 +87,7 @@ public class JetCompletionContributor extends CompletionContributor {
if (shouldRunTopLevelCompletion(parameters, prefix)) {
addClasses(parameters, result);
addJetTopLevelFunctions(result, position, positions);
addJetTopLevelFunctions(jetReference.getExpression(), result, position, positions);
}
if (shouldRunExtensionsCompletion(parameters, prefix)) {
......@@ -132,7 +133,7 @@ public class JetCompletionContributor extends CompletionContributor {
}
}
private static void addJetTopLevelFunctions(@NotNull CompletionResultSet result, @NotNull PsiElement position,
private static void addJetTopLevelFunctions(JetSimpleNameExpression expression, @NotNull CompletionResultSet result, @NotNull PsiElement position,
@NotNull Set<LookupPositionObject> positions) {
String actualPrefix = result.getPrefixMatcher().getPrefix();
......@@ -147,7 +148,7 @@ public class JetCompletionContributor extends CompletionContributor {
for (String name : functionNames) {
if (name.contains(actualPrefix)) {
for (FunctionDescriptor function : namesCache.getTopLevelFunctionDescriptorsByName(name, scope)) {
for (FunctionDescriptor function : namesCache.getTopLevelFunctionDescriptorsByName(name, expression, scope)) {
addCompletionToResult(result, DescriptorLookupConverter.createLookupElement(resolutionContext, function), positions);
}
}
......
package testing
fun someFun() {
measureTime<caret>
}
// Important: This test checks that completion will find top level functions from jars.
// If you going to update it make sure that methods are not auto-imported
// RUNTIME: 1
// EXIST: measureTimeNano, measureTimeMillis
\ No newline at end of file
......@@ -105,6 +105,10 @@ public class JetBasicCompletionTest extends JetCompletionTestBase {
doTest();
}
public void testTopLevelFromStandardLibrary() {
doTest();
}
public void testVariableClassName() {
doTest();
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册