Enable completion for top level functions from kotlin in kotlin mode
This commit is contained in:
@@ -13,7 +13,7 @@ import org.jetbrains.annotations.NonNls;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.asJava.JavaElementFinder;
|
import org.jetbrains.jet.asJava.JavaElementFinder;
|
||||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
import org.jetbrains.jet.lang.descriptors.NamedFunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.JetNamedFunction;
|
import org.jetbrains.jet.lang.psi.JetNamedFunction;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
|
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
|
||||||
@@ -53,7 +53,7 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return fake java names form jet project sources which should be visible from java.
|
* Return class names form jet sources in given scope which should be visible as java classes.
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
@@ -137,7 +137,13 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get jet non-extension top-level function names. Method is allowed to give invalid names - all result should be
|
||||||
|
* checked with getTopLevelFunctionDescriptorsByName().
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
public Collection<String> getAllTopLevelFunctionNames() {
|
public Collection<String> getAllTopLevelFunctionNames() {
|
||||||
final HashSet<String> functionNames = new HashSet<String>();
|
final HashSet<String> functionNames = new HashSet<String>();
|
||||||
@@ -145,9 +151,27 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
|||||||
functionNames.addAll(JetFromJavaDescriptorHelper.getPossiblePackageDeclarationsNames(project, GlobalSearchScope.allScope(project)));
|
functionNames.addAll(JetFromJavaDescriptorHelper.getPossiblePackageDeclarationsNames(project, GlobalSearchScope.allScope(project)));
|
||||||
return functionNames;
|
return functionNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<FunctionDescriptor> getTopLevelFunctionDescriptorsByName(final @NotNull String name, @NotNull GlobalSearchScope scope) {
|
@NotNull
|
||||||
return new ArrayList<FunctionDescriptor>();
|
public Collection<NamedFunctionDescriptor> getTopLevelFunctionDescriptorsByName(final @NotNull String name,
|
||||||
|
final @NotNull GlobalSearchScope scope) {
|
||||||
|
|
||||||
|
// TODO: Add jet function in jar-dependencies (those functions are missing in BindingContext and stubs)
|
||||||
|
|
||||||
|
final Collection<JetNamedFunction> jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(name, project, scope);
|
||||||
|
|
||||||
|
final BindingContext context = WholeProjectAnalyzerFacade.analyzeProjectWithCache(project, scope);
|
||||||
|
|
||||||
|
final HashSet<NamedFunctionDescriptor> result = new HashSet<NamedFunctionDescriptor>();
|
||||||
|
|
||||||
|
for (JetNamedFunction jetNamedFunction : jetNamedFunctions) {
|
||||||
|
final NamedFunctionDescriptor functionDescriptor = context.get(BindingContext.FUNCTION, jetNamedFunction);
|
||||||
|
if (functionDescriptor != null) {
|
||||||
|
result.add(functionDescriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<JetNamedFunction> getTopLevelFunctionsByName(final @NotNull String name, @NotNull GlobalSearchScope scope) {
|
public Collection<JetNamedFunction> getTopLevelFunctionsByName(final @NotNull String name, @NotNull GlobalSearchScope scope) {
|
||||||
@@ -156,6 +180,9 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Collection<String> getAllJetExtensionFunctionsNames(@NotNull GlobalSearchScope scope) {
|
public Collection<String> getAllJetExtensionFunctionsNames(@NotNull GlobalSearchScope scope) {
|
||||||
|
|
||||||
|
|
||||||
|
JetExtensionFunctionNameIndex.getInstance().getKey();
|
||||||
return JetFromJavaDescriptorHelper.getTopExtensionFunctionNames(null, project, scope);
|
return JetFromJavaDescriptorHelper.getTopExtensionFunctionNames(null, project, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,9 +31,6 @@ import java.util.HashSet;
|
|||||||
* @author Nikolay Krasko
|
* @author Nikolay Krasko
|
||||||
*/
|
*/
|
||||||
public class JetCompletionContributor extends CompletionContributor {
|
public class JetCompletionContributor extends CompletionContributor {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public JetCompletionContributor() {
|
public JetCompletionContributor() {
|
||||||
extend(CompletionType.BASIC, PlatformPatterns.psiElement(),
|
extend(CompletionType.BASIC, PlatformPatterns.psiElement(),
|
||||||
new CompletionProvider<CompletionParameters>() {
|
new CompletionProvider<CompletionParameters>() {
|
||||||
@@ -82,45 +79,24 @@ public class JetCompletionContributor extends CompletionContributor {
|
|||||||
|
|
||||||
private static void addJetTopLevelFunctions(@NotNull CompletionResultSet result, @NotNull PsiElement position,
|
private static void addJetTopLevelFunctions(@NotNull CompletionResultSet result, @NotNull PsiElement position,
|
||||||
@NotNull final HashSet<LookupPositionObject> positions) {
|
@NotNull final HashSet<LookupPositionObject> positions) {
|
||||||
String actualPrefix = getActualCompletionPrefix(position);
|
|
||||||
if (actualPrefix != null) {
|
String actualPrefix = result.getPrefixMatcher().getPrefix();
|
||||||
final Project project = position.getProject();
|
|
||||||
|
|
||||||
final JetShortNamesCache namesCache = JetCacheManager.getInstance(position.getProject()).getNamesCache();
|
final Project project = position.getProject();
|
||||||
final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
|
|
||||||
final Collection<String> functionNames = namesCache.getAllTopLevelFunctionNames();
|
|
||||||
|
|
||||||
for (String name : functionNames) {
|
final JetShortNamesCache namesCache = JetCacheManager.getInstance(position.getProject()).getNamesCache();
|
||||||
if (name.contains(actualPrefix)) {
|
final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
|
||||||
for (FunctionDescriptor function : namesCache.getTopLevelFunctionDescriptorsByName(name, scope)) {
|
final Collection<String> functionNames = namesCache.getAllTopLevelFunctionNames();
|
||||||
addCompletionToResult(result, DescriptorLookupConverter.createLookupElement(null, function, null), positions);
|
|
||||||
}
|
for (String name : functionNames) {
|
||||||
|
if (name.contains(actualPrefix)) {
|
||||||
|
for (FunctionDescriptor function : namesCache.getTopLevelFunctionDescriptorsByName(name, scope)) {
|
||||||
|
addCompletionToResult(result, DescriptorLookupConverter.createLookupElement(null, function, null), positions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private static String getActualCompletionPrefix(@NotNull PsiElement position) {
|
|
||||||
if (position.getParent() instanceof JetSimpleNameExpression) {
|
|
||||||
final JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) position.getParent();
|
|
||||||
|
|
||||||
// Should be checked before call completion as pre-condition
|
|
||||||
assert (PsiTreeUtil.getParentOfType(nameExpression, JetQualifiedExpression.class) == null);
|
|
||||||
|
|
||||||
final String referencedName = nameExpression.getReferencedName();
|
|
||||||
|
|
||||||
if (referencedName != null && referencedName.endsWith(CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED)) {
|
|
||||||
int lastPrefixIndex = referencedName.length() -
|
|
||||||
CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED.length();
|
|
||||||
|
|
||||||
return referencedName.substring(0, lastPrefixIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addClasses(@NotNull CompletionParameters parameters, @NotNull final CompletionResultSet result, final HashSet<LookupPositionObject> positions) {
|
private static void addClasses(@NotNull CompletionParameters parameters, @NotNull final CompletionResultSet result, final HashSet<LookupPositionObject> positions) {
|
||||||
CompletionResultSet tempResult = result.withPrefixMatcher(CompletionUtil.findReferenceOrAlphanumericPrefix(parameters));
|
CompletionResultSet tempResult = result.withPrefixMatcher(CompletionUtil.findReferenceOrAlphanumericPrefix(parameters));
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ import org.jetbrains.jet.plugin.PluginTestCaseBase;
|
|||||||
*/
|
*/
|
||||||
public class JetMultifileBasicCompletionTest extends JetCompletionMultiTestBase {
|
public class JetMultifileBasicCompletionTest extends JetCompletionMultiTestBase {
|
||||||
|
|
||||||
// TODO: fix and uncomment
|
public void testTopLevelFunction() throws Exception {
|
||||||
public void skiptestTopLevelFunction() throws Exception {
|
|
||||||
doFileTest();
|
doFileTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,7 +18,7 @@ public class JetMultifileBasicCompletionTest extends JetCompletionMultiTestBase
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getTestDataPath() {
|
protected String getTestDataPath() {
|
||||||
return PluginTestCaseBase.getTestDataPathBase() + "/completion/basic/multifile";
|
return PluginTestCaseBase.getTestDataPathBase() + "/completion/basic/multifile/";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user