From 8d1c3dc759e9f44bfc9ca10b8ebb761c37fe1e41 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Wed, 29 Feb 2012 15:43:56 +0400 Subject: [PATCH] KT-1151 Code completion for not imported extension functions - refactorings: - Don't touch call resolver - Check only newly imported descriptors - Use Stepa's wrapper for getting boolean attribute from annotation --- .../jetbrains/jet/compiler/TipsManager.java | 47 +-------- .../jet/lang/resolve/ImportsResolver.java | 19 ++-- .../jet/lang/resolve/calls/CallResolver.java | 73 -------------- .../lang/resolve/scopes/JetScopeUtils.java | 2 +- .../ControlStructureTypingVisitor.java | 8 -- .../expressions/ExpressionTypingContext.java | 6 -- .../expressions/ExpressionTypingUtils.java | 95 +++++++++++-------- .../caches/JetFromJavaDescriptorHelper.java | 28 ++---- .../jet/plugin/caches/JetShortNamesCache.java | 57 ++++------- .../completion/JetCompletionContributor.java | 75 +++++++-------- 10 files changed, 132 insertions(+), 278 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/compiler/TipsManager.java b/compiler/backend/src/org/jetbrains/jet/compiler/TipsManager.java index 9a00911b087..81d7de736da 100644 --- a/compiler/backend/src/org/jetbrains/jet/compiler/TipsManager.java +++ b/compiler/backend/src/org/jetbrains/jet/compiler/TipsManager.java @@ -30,13 +30,13 @@ import org.jetbrains.jet.lang.psi.JetImportDirective; import org.jetbrains.jet.lang.psi.JetNamespaceHeader; import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.calls.CallResolver; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScopeUtils; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.NamespaceType; +import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils; import java.util.*; @@ -138,7 +138,7 @@ public final class TipsManager { return false; } for (ReceiverDescriptor receiverDescriptor : result) { - if (CallResolver.checkIsExtensionCallable(receiverDescriptor, callableDescriptor)) { + if (ExpressionTypingUtils.checkIsExtensionCallable(receiverDescriptor, callableDescriptor)) { return false; } } @@ -177,51 +177,10 @@ public final class TipsManager { new Predicate() { @Override public boolean apply(CallableDescriptor callableDescriptor) { - return CallResolver.checkIsExtensionCallable(receiverDescriptor, callableDescriptor); + return ExpressionTypingUtils.checkIsExtensionCallable(receiverDescriptor, callableDescriptor); } })); return descriptorsSet; } - -// /* -// * Checks if receiver declaration could be resolved to call expected receiver. -// */ -// private static boolean checkReceiverResolution ( -// @NotNull ReceiverDescriptor expectedReceiver, -// @NotNull CallableDescriptor receiverArgument -// ) { -// JetType type = expectedReceiver.getType(); -// if (checkReceiverResolution(expectedReceiver, type, receiverArgument)) return true; -// if (type.isNullable()) { -// JetType notNullableType = TypeUtils.makeNotNullable(type); -// if (checkReceiverResolution(expectedReceiver, notNullableType, receiverArgument)) return true; -// } -// return false; -// } -// -// private static boolean checkReceiverResolution ( -// @NotNull ReceiverDescriptor expectedReceiver, -// @NotNull JetType receiverType, -// @NotNull CallableDescriptor receiverArgument -// ) { -// ConstraintSystem constraintSystem = new ConstraintSystemImpl(ConstraintResolutionListener.DO_NOTHING); -// for (TypeParameterDescriptor typeParameterDescriptor : receiverArgument.getTypeParameters()) { -// constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); -// } -// -// ReceiverDescriptor receiverParameter = receiverArgument.getReceiverParameter(); -// if (expectedReceiver.exists() && receiverParameter.exists()) { -// constraintSystem.addSubtypingConstraint( -// RECEIVER.assertSubtyping(receiverType, receiverParameter.getType())); -// } -// else if (expectedReceiver.exists() || receiverParameter.exists()) { -// // Only one of receivers exist -// return false; -// } -// -// ConstraintSystemSolution solution = constraintSystem.solve(); -// return solution.getStatus().isSuccessful(); -// } - } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java index 7d95fd82c2d..3916d795dd1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java @@ -68,7 +68,7 @@ public class ImportsResolver { List importDirectives = file.getImportDirectives(); for (JetImportDirective importDirective : importDirectives) { Collection descriptors = importResolver.processImportReference(importDirective, namespaceScope, delayedImporter); - if (descriptors != null && descriptors.size() == 1) { + if (descriptors.size() == 1) { resolvedDirectives.put(importDirective, descriptors.iterator().next()); } } @@ -144,14 +144,15 @@ public class ImportsResolver { this.firstPhase = firstPhase; } - @Nullable + @NotNull public Collection processImportReference(@NotNull JetImportDirective importDirective, @NotNull JetScope scope, @NotNull Importer importer) { if (importDirective.isAbsoluteInRootNamespace()) { trace.report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO - return null; + return Collections.emptyList(); } JetExpression importedReference = importDirective.getImportedReference(); - if (importedReference == null) return null; + if (importedReference == null) return Collections.emptyList(); + Collection descriptors; if (importedReference instanceof JetQualifiedExpression) { descriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression) importedReference, scope); @@ -163,19 +164,23 @@ public class ImportsResolver { JetSimpleNameExpression referenceExpression = getLastReference(importedReference); if (importDirective.isAllUnder()) { - if (referenceExpression == null || !canImportMembersFrom(descriptors, referenceExpression)) return null; + if (referenceExpression == null || !canImportMembersFrom(descriptors, referenceExpression)) { + return Collections.emptyList(); + } + for (DeclarationDescriptor descriptor : descriptors) { importer.addAllUnderImport(descriptor); } - return null; + return Collections.emptyList(); } String aliasName = getAliasName(importDirective); - if (aliasName == null) return null; + if (aliasName == null) return Collections.emptyList(); for (DeclarationDescriptor descriptor : descriptors) { importer.addAliasImport(descriptor, aliasName); } + return descriptors; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index a2ccc1b7e10..3d2fccd1e3c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -113,39 +113,6 @@ public class CallResolver { return doResolveCall(trace, scope, call, expectedType, tasks, functionReference); } - /** - * Get all function from the given scope with the given name and check is they could be satisfied for call on given - * receiver. - * - * @param trace - * @param scope - * @param call - * @param name - * @return - */ - public List resolveCallsByReceiver( - @NotNull BindingTrace trace, - @NotNull JetScope scope, - @NotNull final Call call, - @NotNull String name) { - - List> tasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks( - scope, call, name, trace.getBindingContext(), dataFlowInfo); - - ArrayList functionDescriptors = new ArrayList(); - - for (ResolutionTask task : tasks) { - Collection> candidates = task.getCandidates(); - for (ResolvedCallImpl candidate : candidates) { - if (checkIsExtensionCallable(call.getExplicitReceiver(), candidate.getCandidateDescriptor())) { - functionDescriptors.add(candidate.getCandidateDescriptor()); - } - } - } - - return functionDescriptors; - } - @NotNull private OverloadResolutionResults resolveSimpleCallToFunctionDescriptor( @NotNull BindingTrace trace, @@ -1053,44 +1020,4 @@ public class CallResolver { } return true; } - - /* - * Checks if receiver declaration could be resolved to call expected receiver. - */ - public static boolean checkIsExtensionCallable ( - @NotNull ReceiverDescriptor expectedReceiver, - @NotNull CallableDescriptor receiverArgument - ) { - JetType type = expectedReceiver.getType(); - if (checkReceiverResolution(expectedReceiver, type, receiverArgument)) return true; - if (type.isNullable()) { - JetType notNullableType = TypeUtils.makeNotNullable(type); - if (checkReceiverResolution(expectedReceiver, notNullableType, receiverArgument)) return true; - } - return false; - } - - private static boolean checkReceiverResolution ( - @NotNull ReceiverDescriptor expectedReceiver, - @NotNull JetType receiverType, - @NotNull CallableDescriptor receiverArgument - ) { - ConstraintSystem constraintSystem = new ConstraintSystemImpl(ConstraintResolutionListener.DO_NOTHING); - for (TypeParameterDescriptor typeParameterDescriptor : receiverArgument.getTypeParameters()) { - constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); - } - - ReceiverDescriptor receiverParameter = receiverArgument.getReceiverParameter(); - if (expectedReceiver.exists() && receiverParameter.exists()) { - constraintSystem.addSubtypingConstraint( - RECEIVER.assertSubtyping(receiverType, receiverParameter.getType())); - } - else if (expectedReceiver.exists() || receiverParameter.exists()) { - // Only one of receivers exist - return false; - } - - ConstraintSystemSolution solution = constraintSystem.solve(); - return solution.getStatus().isSuccessful(); - } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeUtils.java index d2ae4d7f0c1..e62052e741f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeUtils.java @@ -35,7 +35,7 @@ public final class JetScopeUtils { /** * Get receivers in order of locality, so that the closest (the most local) receiver goes first - * A wrapper for {@link JetScope#getImplicitReceiversHierarchy(java.util.List)} + * A wrapper for {@link JetScope#getImplicitReceiversHierarchy(List)} * * @param scope Scope for getting receivers hierarchy. * @return receivers hierarchy. diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java index 4ceeec0995a..9fcaa801c48 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java @@ -355,14 +355,6 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { return context.replaceBindingTrace(fakeTrace).resolveCallWithGivenName(call, fake, name); } - public static List resolveFakeCallWithReceiverOnly(ExpressionReceiver receiver, - ExpressionTypingContext context, String name) { - JetReferenceExpression fake = JetPsiFactory.createSimpleName(context.getProject(), "fake"); - BindingTrace fakeTrace = new BindingTraceContext(); - Call call = CallMaker.makeCall(fake, receiver, null, fake, Collections.emptyList()); - return context.replaceBindingTrace(fakeTrace).resolveForReceiverOnly(call, fake, name); - } - @Nullable private static FunctionDescriptor checkHasNextFunctionSupport(@NotNull JetExpression loopRange, @NotNull JetType iteratorType, ExpressionTypingContext context) { OverloadResolutionResults hasNextResolutionResults = context.resolveExactSignature(new TransientReceiver(iteratorType), "hasNext", Collections.emptyList()); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java index f6931c4ff38..fffff07eea3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java @@ -204,12 +204,6 @@ import java.util.Map; // return results == null ? null : results.getResultingDescriptor(); } - @NotNull - public List resolveForReceiverOnly(@NotNull Call call, @NotNull JetReferenceExpression functionReference, @NotNull String name) { - return getCallResolver().resolveCallsByReceiver(trace, scope, call, name); - } - - @Nullable public FunctionDescriptor resolveCall(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetCallExpression callExpression) { OverloadResolutionResults results = getCallResolver().resolveCall(trace, scope, CallMaker.makeCall(receiver, callOperationNode, callExpression), expectedType); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java index 90fa9e854d8..8d854b63269 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java @@ -25,18 +25,22 @@ import org.jetbrains.jet.JetNodeTypes; import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; +import org.jetbrains.jet.lang.resolve.calls.inference.*; import org.jetbrains.jet.lang.resolve.scopes.*; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeUtils; -import org.jetbrains.jet.util.QualifiedNamesUtil; +import org.jetbrains.jet.lang.types.Variance; +import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -164,14 +168,14 @@ public class ExpressionTypingUtils { } /** - * Check that function or property with the given qualified name can be resolved in given scope for given receiver + * Check that function or property with the given qualified name can be resolved in given scope and called on given receiver * * @param callableFQN * @param project * @param scope * @return */ - public static List canFindSuitableCall( + public static List canFindSuitableCall( @NotNull String callableFQN, @NotNull Project project, @NotNull JetExpression receiverExpression, @@ -183,46 +187,63 @@ public class ExpressionTypingUtils { JetImportDirective importDirective = JetPsiFactory.createImportDirective(project, callableFQN); - ExpressionReceiver expressionReceiver = new ExpressionReceiver(receiverExpression, receiverType); - ImportsResolver.ImportResolver importResolver = new ImportsResolver.ImportResolver(new BindingTraceContext(), false); - importResolver.processImportReference( + Collection declarationDescriptors = importResolver.processImportReference( importDirective, scope, new Importer.StandardImporter(writableScopeWithImports, false)); - ExpressionTypingContext context = ExpressionTypingContext.newContext( - project, - JetSemanticServices.createSemanticServices(project), - new HashMap(), - new HashMap>(), - new LabelResolver(), - new BindingTraceContext(), - writableScopeWithImports, - DataFlowInfo.EMPTY, - TypeUtils.NO_EXPECTED_TYPE, - TypeUtils.NO_EXPECTED_TYPE, - false - ); + List callableExtensionDescriptors = new ArrayList(); + ReceiverDescriptor receiverDescriptor = new ExpressionReceiver(receiverExpression, receiverType); - writableScopeWithImports.changeLockLevel(WritableScope.LockLevel.READING); + for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) { + if (declarationDescriptor instanceof CallableDescriptor) { + CallableDescriptor callableDescriptor = (CallableDescriptor) declarationDescriptor; - return ControlStructureTypingVisitor.resolveFakeCallWithReceiverOnly(expressionReceiver, context, QualifiedNamesUtil.fqnToShortName(callableFQN)); + if (checkIsExtensionCallable(receiverDescriptor, callableDescriptor)) { + callableExtensionDescriptors.add(callableDescriptor); + } + } + } + return callableExtensionDescriptors; + } -// OverloadResolutionResults.Code resultCode = resolutionResult.getResultCode(); -// if (resultCode == OverloadResolutionResults.Code.SUCCESS || -// resultCode == OverloadResolutionResults.Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH || -// resultCode == OverloadResolutionResults.Code.MANY_FAILED_CANDIDATES) { -// -// ArrayList resolvedDescriptors = new ArrayList(); -// -// for (ResolvedCall resolvedCall : resolutionResult.getResultingCalls()) { -// resolvedDescriptors.add(resolvedCall.getCandidateDescriptor()); -// } -// -// return resolvedDescriptors; -// } -// -// return new ArrayList(); + /* + * Checks if receiver declaration could be resolved to call expected receiver. + */ + public static boolean checkIsExtensionCallable ( + @NotNull ReceiverDescriptor expectedReceiver, + @NotNull CallableDescriptor receiverArgument + ) { + JetType type = expectedReceiver.getType(); + if (checkReceiverResolution(expectedReceiver, type, receiverArgument)) return true; + if (type.isNullable()) { + JetType notNullableType = TypeUtils.makeNotNullable(type); + if (checkReceiverResolution(expectedReceiver, notNullableType, receiverArgument)) return true; + } + return false; + } + + private static boolean checkReceiverResolution ( + @NotNull ReceiverDescriptor expectedReceiver, + @NotNull JetType receiverType, + @NotNull CallableDescriptor receiverArgument + ) { + ConstraintSystem constraintSystem = new ConstraintSystemImpl(ConstraintResolutionListener.DO_NOTHING); + for (TypeParameterDescriptor typeParameterDescriptor : receiverArgument.getTypeParameters()) { + constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); + } + + ReceiverDescriptor receiverParameter = receiverArgument.getReceiverParameter(); + if (expectedReceiver.exists() && receiverParameter.exists()) { + constraintSystem.addSubtypingConstraint(ConstraintType.RECEIVER.assertSubtyping(receiverType, receiverParameter.getType())); + } + else if (expectedReceiver.exists() || receiverParameter.exists()) { + // Only one of receivers exist + return false; + } + + ConstraintSystemSolution solution = constraintSystem.solve(); + return solution.getStatus().isSuccessful(); } } diff --git a/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java b/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java index 4b67c06c968..50f95fb2150 100644 --- a/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java +++ b/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java @@ -25,10 +25,12 @@ import com.intellij.psi.search.PsiShortNamesCache; import com.intellij.psi.util.PsiTreeUtil; import jet.runtime.typeinfo.JetValueParameter; import org.jetbrains.jet.lang.resolve.java.JvmAbi; +import org.jetbrains.jet.lang.resolve.java.kt.JetValueParameterAnnotation; import java.util.ArrayList; import java.util.Collection; 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 @@ -52,7 +54,7 @@ class JetFromJavaDescriptorHelper { * Get names that could have jet descriptor equivalents. It could be inaccurate and return more results than necessary. */ static Collection getPossiblePackageDeclarationsNames(Project project, GlobalSearchScope scope) { - final ArrayList result = new ArrayList(); + Collection result = new ArrayList(); for (PsiClass jetNamespaceClass : getClassesForJetNamespaces(project, scope)) { for (PsiMethod psiMethod : jetNamespaceClass.getMethods()) { @@ -69,7 +71,7 @@ class JetFromJavaDescriptorHelper { // Extension function should have an parameter of type JetValueParameter with explicit receiver parameter. - HashSet extensionNames = new HashSet(); + Set extensionNames = new HashSet(); Collection valueParametersAnnotations = JavaAnnotationIndex.getInstance().get( JetValueParameter.class.getSimpleName(), project, scope); @@ -81,7 +83,7 @@ class JetFromJavaDescriptorHelper { continue; } - if (!getAnnotationAttribute(parameterAnnotation, "receiver", false)) { + if (!new JetValueParameterAnnotation(parameterAnnotation).receiver()) { continue; } @@ -96,7 +98,7 @@ class JetFromJavaDescriptorHelper { static Collection getTopExtensionFunctionByName(String name, Project project, GlobalSearchScope scope) { - HashSet selectedMethods = new HashSet(); + Set selectedMethods = new HashSet(); Collection psiMethods = JavaMethodNameIndex.getInstance().get(name, project, scope); for (PsiMethod psiMethod : psiMethods) { @@ -119,7 +121,7 @@ class JetFromJavaDescriptorHelper { continue; } - if (getAnnotationAttribute(psiAnnotation, "receiver", false)) { + if (new JetValueParameterAnnotation(psiAnnotation).receiver()) { selectedMethods.add(psiMethod); } } @@ -129,20 +131,4 @@ class JetFromJavaDescriptorHelper { return selectedMethods; } - - private static boolean getAnnotationAttribute(PsiAnnotation annotation, String attributeName, boolean defaultValue) { - // Check that parameter is receiver - PsiAnnotationMemberValue attributeValue = annotation.findAttributeValue(attributeName); - if (!(attributeValue instanceof PsiLiteralExpression)) { - return defaultValue; - } - - // Every extension function will have parameter marked with attribute where receiver == true - Object value = ((PsiLiteralExpression) attributeValue).getValue(); - if (value == null) { - return defaultValue; - } - - return (Boolean) value; - } } diff --git a/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java b/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java index 27485e94733..7daa7a2db95 100644 --- a/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java +++ b/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java @@ -68,7 +68,7 @@ public class JetShortNamesCache extends PsiShortNamesCache { @NotNull @Override public String[] getAllClassNames() { - final Collection classNames = JetShortClassNameIndex.getInstance().getAllKeys(project); + Collection classNames = JetShortClassNameIndex.getInstance().getAllKeys(project); return ArrayUtil.toStringArray(classNames); } @@ -77,10 +77,10 @@ public class JetShortNamesCache extends PsiShortNamesCache { */ @NotNull @Override - public PsiClass[] getClassesByName(@NotNull @NonNls final String name, @NotNull GlobalSearchScope scope) { + public PsiClass[] getClassesByName(@NotNull @NonNls String name, @NotNull GlobalSearchScope scope) { // Quick check for classes from getAllClassNames() - final Collection classNames = JetShortClassNameIndex.getInstance().getAllKeys(project); + Collection classNames = JetShortClassNameIndex.getInstance().getAllKeys(project); if (!classNames.contains(name)) { return new PsiClass[0]; } @@ -89,7 +89,7 @@ public class JetShortNamesCache extends PsiShortNamesCache { for (String fqName : JetFullClassNameIndex.getInstance().getAllKeys(project)) { if (QualifiedNamesUtil.fqnToShortName(fqName).equals(name)) { - final PsiClass psiClass = javaElementFinder.findClass(fqName, scope); + PsiClass psiClass = javaElementFinder.findClass(fqName, scope); if (psiClass != null) { result.add(psiClass); } @@ -111,7 +111,7 @@ public class JetShortNamesCache extends PsiShortNamesCache { @NotNull public Collection getFQNamesByName(@NotNull final String name, @NotNull GlobalSearchScope scope) { - final BindingContext context = getResolutionContext(scope); + BindingContext context = getResolutionContext(scope); return Collections2.filter(context.getKeys(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR), new Predicate() { @Override public boolean apply(@Nullable String fqName) { @@ -128,26 +128,24 @@ public class JetShortNamesCache extends PsiShortNamesCache { */ @NotNull public Collection getAllTopLevelFunctionNames() { - final HashSet functionNames = new HashSet(); + Set functionNames = new HashSet(); functionNames.addAll(JetShortFunctionNameIndex.getInstance().getAllKeys(project)); functionNames.addAll(JetFromJavaDescriptorHelper.getPossiblePackageDeclarationsNames(project, GlobalSearchScope.allScope(project))); return functionNames; } @NotNull - public Collection getTopLevelFunctionDescriptorsByName(final @NotNull String name, - final @NotNull GlobalSearchScope scope) { + public Collection getTopLevelFunctionDescriptorsByName(@NotNull String name, + @NotNull GlobalSearchScope scope) { - - - final Collection jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(name, project, scope); + Collection jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(name, project, scope); - final BindingContext context = getResolutionContext(scope); + BindingContext context = getResolutionContext(scope); - final HashSet result = new HashSet(); + HashSet result = new HashSet(); for (JetNamedFunction jetNamedFunction : jetNamedFunctions) { - final SimpleFunctionDescriptor functionDescriptor = context.get(BindingContext.FUNCTION, jetNamedFunction); + SimpleFunctionDescriptor functionDescriptor = context.get(BindingContext.FUNCTION, jetNamedFunction); if (functionDescriptor != null) { result.add(functionDescriptor); } @@ -157,11 +155,11 @@ public class JetShortNamesCache extends PsiShortNamesCache { } @NotNull - public BindingContext getResolutionContext(final @NotNull GlobalSearchScope scope) { + public BindingContext getResolutionContext(@NotNull GlobalSearchScope scope) { return WholeProjectAnalyzerFacade.analyzeProjectWithCache(project, scope); } - public Collection getTopLevelFunctionsByName(final @NotNull String name, @NotNull GlobalSearchScope scope) { + public Collection getTopLevelFunctionsByName(@NotNull String name, @NotNull GlobalSearchScope scope) { return JetShortFunctionNameIndex.getInstance().get(name, project, scope); } @@ -173,7 +171,7 @@ public class JetShortNamesCache extends PsiShortNamesCache { */ @NotNull public Collection getAllJetExtensionFunctionsNames(@NotNull GlobalSearchScope scope) { - final Set extensionFunctionNames = new HashSet(); + Set extensionFunctionNames = new HashSet(); extensionFunctionNames.addAll(JetExtensionFunctionNameIndex.getInstance().getAllKeys(project)); extensionFunctionNames.addAll(JetFromJavaDescriptorHelper.getTopExtensionFunctionNames(project, scope)); @@ -181,7 +179,7 @@ public class JetShortNamesCache extends PsiShortNamesCache { return extensionFunctionNames; } - public Collection getJetExtensionFunctionsByName(final @NotNull String name, @NotNull GlobalSearchScope scope) { + public Collection getJetExtensionFunctionsByName(@NotNull String name, @NotNull GlobalSearchScope scope) { HashSet functions = new HashSet(); functions.addAll(JetExtensionFunctionNameIndex.getInstance().get(name, project, scope)); functions.addAll(JetFromJavaDescriptorHelper.getTopExtensionFunctionByName(name, project, scope)); @@ -189,29 +187,6 @@ public class JetShortNamesCache extends PsiShortNamesCache { return functions; } -// public Collection getAllJetExtensionFunctionsByName(@NotNull String name, @NotNull GlobalSearchScope scope) { -// // TODO: Add jet extension functions in jar-dependencies (those functions are missing in BindingContext and stubs) -// -// final Collection jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(name, project, scope); -// -// final BindingContext context = getResolutionContext(scope); -// -// final HashSet result = new HashSet(); -// -// for (JetNamedFunction jetNamedFunction : jetNamedFunctions) { -// final NamedFunctionDescriptor functionDescriptor = context.get(BindingContext.FUNCTION, jetNamedFunction); -// if (functionDescriptor != null) { -// if (functionDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor) { -// if (functionDescriptor.getExpectedThisObject() != ReceiverDescriptor.NO_RECEIVER) { -// result.add(functionDescriptor); -// } -// } -// } -// } -// -// return result; -// } - public Collection getJetFunctionsByName(@NonNls @NotNull String name, @NotNull GlobalSearchScope scope) { return JetShortFunctionNameIndex.getInstance().get(name, project, scope); } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java b/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java index 5e3826fd504..e0417995695 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java @@ -31,6 +31,7 @@ import com.intellij.util.Consumer; import com.intellij.util.ProcessingContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; @@ -46,7 +47,7 @@ import org.jetbrains.jet.util.QualifiedNamesUtil; import java.util.Collection; import java.util.HashSet; -import java.util.List; +import java.util.Set; /** * @author Nikolay Krasko @@ -57,20 +58,20 @@ public class JetCompletionContributor extends CompletionContributor { new CompletionProvider() { @Override protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, - final @NotNull CompletionResultSet result) { + @NotNull CompletionResultSet result) { - final HashSet positions = new HashSet(); + Set positions = new HashSet(); if (result.getPrefixMatcher().getPrefix().isEmpty()) { return; } - final PsiElement position = parameters.getPosition(); + PsiElement position = parameters.getPosition(); if (!(position.getContainingFile() instanceof JetFile)) { return; } - final JetSimpleNameReference jetReference = getJetReference(parameters); + JetSimpleNameReference jetReference = getJetReference(parameters); if (jetReference != null) { for (Object variant : jetReference.getVariants()) { addReferenceVariant(result, variant, positions); @@ -88,6 +89,7 @@ public class JetCompletionContributor extends CompletionContributor { }); } + // TODO: Make it work for properties private static void addJetExtensionFunctions(JetSimpleNameExpression expression, CompletionResultSet result, PsiElement position) { BindingContext context = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) position.getContainingFile()); @@ -95,15 +97,15 @@ public class JetCompletionContributor extends CompletionContributor { if (receiverExpression != null) { - final JetType expressionType = context.get(BindingContext.EXPRESSION_TYPE, receiverExpression); - final JetScope scope = context.get(BindingContext.RESOLUTION_SCOPE, receiverExpression); + JetType expressionType = context.get(BindingContext.EXPRESSION_TYPE, receiverExpression); + JetScope scope = context.get(BindingContext.RESOLUTION_SCOPE, receiverExpression); if (expressionType != null && scope != null) { JetShortNamesCache namesCache = JetCacheManager.getInstance(position.getProject()).getNamesCache(); Collection extensionFunctionsNames = namesCache.getAllJetExtensionFunctionsNames( GlobalSearchScope.allScope(position.getProject())); - HashSet functionFQNs = new HashSet(); + Set functionFQNs = new HashSet(); // Collect all possible extension function qualified names for (String name : extensionFunctionsNames) { @@ -114,15 +116,16 @@ public class JetCompletionContributor extends CompletionContributor { for (PsiElement extensionFunction : extensionFunctions) { if (extensionFunction instanceof JetNamedFunction) { functionFQNs.add(JetPsiUtil.getFQName((JetNamedFunction) extensionFunction)); - } else if (extensionFunction instanceof PsiMethod) { - final PsiMethod function = (PsiMethod) extensionFunction; - final PsiClass containingClass = function.getContainingClass(); + } + else if (extensionFunction instanceof PsiMethod) { + PsiMethod function = (PsiMethod) extensionFunction; + PsiClass containingClass = function.getContainingClass(); if (containingClass != null) { - final String classFQN = containingClass.getQualifiedName(); + String classFQN = containingClass.getQualifiedName(); if (classFQN != null) { - final String classParentFQN = QualifiedNamesUtil.withoutLastSegment(classFQN); + String classParentFQN = QualifiedNamesUtil.withoutLastSegment(classFQN); functionFQNs.add(QualifiedNamesUtil.combine(classParentFQN, function.getName())); } } @@ -133,17 +136,9 @@ public class JetCompletionContributor extends CompletionContributor { // Iterate through the function with attempt to resolve found functions for (String functionFQN : functionFQNs) { - // System.out.println(functionFQN); - - List functionDescriptors = ExpressionTypingUtils.canFindSuitableCall( - functionFQN, position.getProject(), receiverExpression, expressionType, scope); - - // System.out.println(!functionDescriptors.isEmpty()); - - if (!functionDescriptors.isEmpty()) { - for (FunctionDescriptor functionDescriptor : functionDescriptors) { - result.addElement(DescriptorLookupConverter.createLookupElement(context, functionDescriptor)); - } + for (CallableDescriptor functionDescriptor : ExpressionTypingUtils.canFindSuitableCall( + functionFQN, position.getProject(), receiverExpression, expressionType, scope)) { + result.addElement(DescriptorLookupConverter.createLookupElement(context, functionDescriptor)); } } } @@ -153,7 +148,7 @@ public class JetCompletionContributor extends CompletionContributor { private static void addReferenceVariant( @NotNull CompletionResultSet result, @NotNull Object variant, - @NotNull final HashSet positions) { + @NotNull Set positions) { if (variant instanceof LookupElement) { addCompletionToResult(result, (LookupElement) variant, positions); @@ -164,15 +159,15 @@ public class JetCompletionContributor extends CompletionContributor { } private static void addJetTopLevelFunctions(@NotNull CompletionResultSet result, @NotNull PsiElement position, - @NotNull final HashSet positions) { + @NotNull Set positions) { String actualPrefix = result.getPrefixMatcher().getPrefix(); - final Project project = position.getProject(); + Project project = position.getProject(); - final JetShortNamesCache namesCache = JetCacheManager.getInstance(position.getProject()).getNamesCache(); - final GlobalSearchScope scope = GlobalSearchScope.allScope(project); - final Collection functionNames = namesCache.getAllTopLevelFunctionNames(); + JetShortNamesCache namesCache = JetCacheManager.getInstance(position.getProject()).getNamesCache(); + GlobalSearchScope scope = GlobalSearchScope.allScope(project); + Collection functionNames = namesCache.getAllTopLevelFunctionNames(); BindingContext resolutionContext = namesCache.getResolutionContext(scope); @@ -189,9 +184,9 @@ public class JetCompletionContributor extends CompletionContributor { * Jet classes will be added as java completions for unification */ private static void addClasses( - @NotNull final CompletionParameters parameters, + @NotNull CompletionParameters parameters, @NotNull final CompletionResultSet result, - @NotNull final HashSet positions) { + @NotNull final Set positions) { JetClassCompletionContributor.addClasses(parameters, result, new Consumer() { @Override @@ -202,7 +197,7 @@ public class JetCompletionContributor extends CompletionContributor { } private static boolean shouldRunTopLevelCompletion(@NotNull CompletionParameters parameters) { - final PsiElement element = parameters.getPosition(); + PsiElement element = parameters.getPosition(); if (parameters.getInvocationCount() > 1) { return true; @@ -226,9 +221,9 @@ public class JetCompletionContributor extends CompletionContributor { @Nullable private static JetSimpleNameReference getJetReference(@NotNull CompletionParameters parameters) { - final PsiElement element = parameters.getPosition(); + PsiElement element = parameters.getPosition(); if (element.getParent() != null) { - final PsiElement parent = element.getParent(); + PsiElement parent = element.getParent(); PsiReference[] references = parent.getReferences(); if (references.length != 0) { @@ -244,11 +239,11 @@ public class JetCompletionContributor extends CompletionContributor { } private static void addCompletionToResult( - @NotNull final CompletionResultSet result, + @NotNull CompletionResultSet result, @NotNull LookupElement element, - @NotNull HashSet positions) { + @NotNull Set positions) { - final LookupPositionObject lookupPosition = getLookupPosition(element); + LookupPositionObject lookupPosition = getLookupPosition(element); if (lookupPosition != null) { if (!positions.contains(lookupPosition)) { positions.add(lookupPosition); @@ -263,14 +258,14 @@ public class JetCompletionContributor extends CompletionContributor { } private static LookupPositionObject getLookupPosition(LookupElement element) { - final Object lookupObject = element.getObject(); + Object lookupObject = element.getObject(); if (lookupObject instanceof PsiElement) { // PsiElement psiElement = (PsiElement) lookupObject; return new LookupPositionObject((PsiElement) lookupObject); } else if (lookupObject instanceof JetLookupObject) { // JetLookupObject jetLookupObject = (JetLookupObject) lookupObject; - final PsiElement psiElement = ((JetLookupObject) lookupObject).getPsiElement(); + PsiElement psiElement = ((JetLookupObject) lookupObject).getPsiElement(); if (psiElement != null) { return new LookupPositionObject(psiElement); }