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
This commit is contained in:
@@ -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<CallableDescriptor>() {
|
||||
@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();
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public class ImportsResolver {
|
||||
List<JetImportDirective> importDirectives = file.getImportDirectives();
|
||||
for (JetImportDirective importDirective : importDirectives) {
|
||||
Collection<? extends DeclarationDescriptor> 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<? extends DeclarationDescriptor> 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<? extends DeclarationDescriptor> 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<FunctionDescriptor> resolveCallsByReceiver(
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull JetScope scope,
|
||||
@NotNull final Call call,
|
||||
@NotNull String name) {
|
||||
|
||||
List<ResolutionTask<FunctionDescriptor>> tasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(
|
||||
scope, call, name, trace.getBindingContext(), dataFlowInfo);
|
||||
|
||||
ArrayList<FunctionDescriptor> functionDescriptors = new ArrayList<FunctionDescriptor>();
|
||||
|
||||
for (ResolutionTask<FunctionDescriptor> task : tasks) {
|
||||
Collection<ResolvedCallImpl<FunctionDescriptor>> candidates = task.getCandidates();
|
||||
for (ResolvedCallImpl<FunctionDescriptor> candidate : candidates) {
|
||||
if (checkIsExtensionCallable(call.getExplicitReceiver(), candidate.getCandidateDescriptor())) {
|
||||
functionDescriptors.add(candidate.getCandidateDescriptor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return functionDescriptors;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private OverloadResolutionResults<FunctionDescriptor> 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
-8
@@ -355,14 +355,6 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
return context.replaceBindingTrace(fakeTrace).resolveCallWithGivenName(call, fake, name);
|
||||
}
|
||||
|
||||
public static List<FunctionDescriptor> 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.<ValueArgument>emptyList());
|
||||
return context.replaceBindingTrace(fakeTrace).resolveForReceiverOnly(call, fake, name);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static FunctionDescriptor checkHasNextFunctionSupport(@NotNull JetExpression loopRange, @NotNull JetType iteratorType, ExpressionTypingContext context) {
|
||||
OverloadResolutionResults<FunctionDescriptor> hasNextResolutionResults = context.resolveExactSignature(new TransientReceiver(iteratorType), "hasNext", Collections.<JetType>emptyList());
|
||||
|
||||
-6
@@ -204,12 +204,6 @@ import java.util.Map;
|
||||
// return results == null ? null : results.getResultingDescriptor();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<FunctionDescriptor> 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<FunctionDescriptor> results = getCallResolver().resolveCall(trace, scope, CallMaker.makeCall(receiver, callOperationNode, callExpression), expectedType);
|
||||
|
||||
+58
-37
@@ -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<FunctionDescriptor> canFindSuitableCall(
|
||||
public static List<CallableDescriptor> 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<? extends DeclarationDescriptor> declarationDescriptors = importResolver.processImportReference(
|
||||
importDirective, scope,
|
||||
new Importer.StandardImporter(writableScopeWithImports, false));
|
||||
|
||||
ExpressionTypingContext context = ExpressionTypingContext.newContext(
|
||||
project,
|
||||
JetSemanticServices.createSemanticServices(project),
|
||||
new HashMap<JetPattern, DataFlowInfo>(),
|
||||
new HashMap<JetPattern, List<VariableDescriptor>>(),
|
||||
new LabelResolver(),
|
||||
new BindingTraceContext(),
|
||||
writableScopeWithImports,
|
||||
DataFlowInfo.EMPTY,
|
||||
TypeUtils.NO_EXPECTED_TYPE,
|
||||
TypeUtils.NO_EXPECTED_TYPE,
|
||||
false
|
||||
);
|
||||
List<CallableDescriptor> callableExtensionDescriptors = new ArrayList<CallableDescriptor>();
|
||||
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<FunctionDescriptor> resolvedDescriptors = new ArrayList<FunctionDescriptor>();
|
||||
//
|
||||
// for (ResolvedCall<? extends FunctionDescriptor> resolvedCall : resolutionResult.getResultingCalls()) {
|
||||
// resolvedDescriptors.add(resolvedCall.getCandidateDescriptor());
|
||||
// }
|
||||
//
|
||||
// return resolvedDescriptors;
|
||||
// }
|
||||
//
|
||||
// return new ArrayList<FunctionDescriptor>();
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<String> getPossiblePackageDeclarationsNames(Project project, GlobalSearchScope scope) {
|
||||
final ArrayList<String> result = new ArrayList<String>();
|
||||
Collection<String> result = new ArrayList<String>();
|
||||
|
||||
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<String> extensionNames = new HashSet<String>();
|
||||
Set<String> extensionNames = new HashSet<String>();
|
||||
|
||||
Collection<PsiAnnotation> 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<PsiMethod> getTopExtensionFunctionByName(String name, Project project, GlobalSearchScope scope) {
|
||||
|
||||
HashSet<PsiMethod> selectedMethods = new HashSet<PsiMethod>();
|
||||
Set<PsiMethod> selectedMethods = new HashSet<PsiMethod>();
|
||||
|
||||
Collection<PsiMethod> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
||||
@NotNull
|
||||
@Override
|
||||
public String[] getAllClassNames() {
|
||||
final Collection<String> classNames = JetShortClassNameIndex.getInstance().getAllKeys(project);
|
||||
Collection<String> 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<String> classNames = JetShortClassNameIndex.getInstance().getAllKeys(project);
|
||||
Collection<String> 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<String> 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<String>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable String fqName) {
|
||||
@@ -128,26 +128,24 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
||||
*/
|
||||
@NotNull
|
||||
public Collection<String> getAllTopLevelFunctionNames() {
|
||||
final HashSet<String> functionNames = new HashSet<String>();
|
||||
Set<String> functionNames = new HashSet<String>();
|
||||
functionNames.addAll(JetShortFunctionNameIndex.getInstance().getAllKeys(project));
|
||||
functionNames.addAll(JetFromJavaDescriptorHelper.getPossiblePackageDeclarationsNames(project, GlobalSearchScope.allScope(project)));
|
||||
return functionNames;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<SimpleFunctionDescriptor> getTopLevelFunctionDescriptorsByName(final @NotNull String name,
|
||||
final @NotNull GlobalSearchScope scope) {
|
||||
public Collection<SimpleFunctionDescriptor> getTopLevelFunctionDescriptorsByName(@NotNull String name,
|
||||
@NotNull GlobalSearchScope scope) {
|
||||
|
||||
|
||||
|
||||
final Collection<JetNamedFunction> jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(name, project, scope);
|
||||
Collection<JetNamedFunction> jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(name, project, scope);
|
||||
|
||||
final BindingContext context = getResolutionContext(scope);
|
||||
BindingContext context = getResolutionContext(scope);
|
||||
|
||||
final HashSet<SimpleFunctionDescriptor> result = new HashSet<SimpleFunctionDescriptor>();
|
||||
HashSet<SimpleFunctionDescriptor> result = new HashSet<SimpleFunctionDescriptor>();
|
||||
|
||||
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<JetNamedFunction> getTopLevelFunctionsByName(final @NotNull String name, @NotNull GlobalSearchScope scope) {
|
||||
public Collection<JetNamedFunction> 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<String> getAllJetExtensionFunctionsNames(@NotNull GlobalSearchScope scope) {
|
||||
final Set<String> extensionFunctionNames = new HashSet<String>();
|
||||
Set<String> extensionFunctionNames = new HashSet<String>();
|
||||
|
||||
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<PsiElement> getJetExtensionFunctionsByName(final @NotNull String name, @NotNull GlobalSearchScope scope) {
|
||||
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));
|
||||
@@ -189,29 +187,6 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
||||
return functions;
|
||||
}
|
||||
|
||||
// public Collection<NamedFunctionDescriptor> 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<JetNamedFunction> jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(name, project, scope);
|
||||
//
|
||||
// final BindingContext context = getResolutionContext(scope);
|
||||
//
|
||||
// final HashSet<NamedFunctionDescriptor> result = new HashSet<NamedFunctionDescriptor>();
|
||||
//
|
||||
// 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<JetNamedFunction> getJetFunctionsByName(@NonNls @NotNull String name, @NotNull GlobalSearchScope scope) {
|
||||
return JetShortFunctionNameIndex.getInstance().get(name, project, scope);
|
||||
}
|
||||
|
||||
@@ -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<CompletionParameters>() {
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context,
|
||||
final @NotNull CompletionResultSet result) {
|
||||
@NotNull CompletionResultSet result) {
|
||||
|
||||
final HashSet<LookupPositionObject> positions = new HashSet<LookupPositionObject>();
|
||||
Set<LookupPositionObject> positions = new HashSet<LookupPositionObject>();
|
||||
|
||||
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<String> extensionFunctionsNames = namesCache.getAllJetExtensionFunctionsNames(
|
||||
GlobalSearchScope.allScope(position.getProject()));
|
||||
|
||||
HashSet<String> functionFQNs = new HashSet<String>();
|
||||
Set<String> functionFQNs = new HashSet<String>();
|
||||
|
||||
// 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<FunctionDescriptor> 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<LookupPositionObject> positions) {
|
||||
@NotNull Set<LookupPositionObject> 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<LookupPositionObject> positions) {
|
||||
@NotNull Set<LookupPositionObject> 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<String> functionNames = namesCache.getAllTopLevelFunctionNames();
|
||||
JetShortNamesCache namesCache = JetCacheManager.getInstance(position.getProject()).getNamesCache();
|
||||
GlobalSearchScope scope = GlobalSearchScope.allScope(project);
|
||||
Collection<String> 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<LookupPositionObject> positions) {
|
||||
@NotNull final Set<LookupPositionObject> positions) {
|
||||
|
||||
JetClassCompletionContributor.addClasses(parameters, result, new Consumer<LookupElement>() {
|
||||
@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<LookupPositionObject> positions) {
|
||||
@NotNull Set<LookupPositionObject> 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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user