KT-4893 Code completion should not show multiple functions with the same signature
#KT-4893 Fixed
This commit is contained in:
@@ -18,16 +18,23 @@ package org.jetbrains.kotlin.psi;
|
|||||||
|
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.kotlin.JetNodeTypes;
|
import org.jetbrains.kotlin.JetNodeTypes;
|
||||||
|
import org.jetbrains.kotlin.name.Name;
|
||||||
|
|
||||||
public class JetValueArgumentName extends JetElementImpl {
|
public class JetValueArgumentName extends JetElementImpl implements ValueArgumentName {
|
||||||
public JetValueArgumentName(@NotNull ASTNode node) {
|
public JetValueArgumentName(@NotNull ASTNode node) {
|
||||||
super(node);
|
super(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable @IfNotParsed
|
@Override
|
||||||
|
@NotNull
|
||||||
public JetSimpleNameExpression getReferenceExpression() {
|
public JetSimpleNameExpression getReferenceExpression() {
|
||||||
return (JetSimpleNameExpression) findChildByType(JetNodeTypes.REFERENCE_EXPRESSION);
|
return (JetSimpleNameExpression) findChildByType(JetNodeTypes.REFERENCE_EXPRESSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Name getAsName() {
|
||||||
|
return getReferenceExpression().getReferencedNameAsName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,12 +17,13 @@
|
|||||||
package org.jetbrains.kotlin.psi
|
package org.jetbrains.kotlin.psi
|
||||||
|
|
||||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
public trait ValueArgument {
|
public trait ValueArgument {
|
||||||
IfNotParsed
|
IfNotParsed
|
||||||
public fun getArgumentExpression(): JetExpression?
|
public fun getArgumentExpression(): JetExpression?
|
||||||
|
|
||||||
public fun getArgumentName(): JetValueArgumentName?
|
public fun getArgumentName(): ValueArgumentName?
|
||||||
|
|
||||||
public fun isNamed(): Boolean
|
public fun isNamed(): Boolean
|
||||||
|
|
||||||
@@ -40,3 +41,8 @@ public trait FunctionLiteralArgument : ValueArgument {
|
|||||||
|
|
||||||
override fun getArgumentExpression(): JetExpression
|
override fun getArgumentExpression(): JetExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface ValueArgumentName {
|
||||||
|
public val asName: Name
|
||||||
|
public val referenceExpression: JetSimpleNameExpression?
|
||||||
|
}
|
||||||
|
|||||||
+14
-6
@@ -155,9 +155,11 @@ public class ValueArgumentsToParametersMapper {
|
|||||||
|
|
||||||
D candidate = candidateCall.getCandidateDescriptor();
|
D candidate = candidateCall.getCandidateDescriptor();
|
||||||
|
|
||||||
JetSimpleNameExpression nameReference = argument.getArgumentName().getReferenceExpression();
|
ValueArgumentName argumentName = argument.getArgumentName();
|
||||||
ValueParameterDescriptor valueParameterDescriptor = parameterByName.get(nameReference.getReferencedNameAsName());
|
assert argumentName != null;
|
||||||
if (!candidate.hasStableParameterNames()) {
|
ValueParameterDescriptor valueParameterDescriptor = parameterByName.get(argumentName.getAsName());
|
||||||
|
JetReferenceExpression nameReference = argumentName.getReferenceExpression();
|
||||||
|
if (!candidate.hasStableParameterNames() && nameReference != null) {
|
||||||
report(NAMED_ARGUMENTS_NOT_ALLOWED.on(
|
report(NAMED_ARGUMENTS_NOT_ALLOWED.on(
|
||||||
nameReference,
|
nameReference,
|
||||||
candidate instanceof FunctionInvokeDescriptor ? INVOKE_ON_FUNCTION_TYPE : NON_KOTLIN_FUNCTION
|
candidate instanceof FunctionInvokeDescriptor ? INVOKE_ON_FUNCTION_TYPE : NON_KOTLIN_FUNCTION
|
||||||
@@ -165,14 +167,20 @@ public class ValueArgumentsToParametersMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (valueParameterDescriptor == null) {
|
if (valueParameterDescriptor == null) {
|
||||||
report(NAMED_PARAMETER_NOT_FOUND.on(nameReference, nameReference));
|
if (nameReference != null) {
|
||||||
|
report(NAMED_PARAMETER_NOT_FOUND.on(nameReference, nameReference));
|
||||||
|
}
|
||||||
unmappedArguments.add(argument);
|
unmappedArguments.add(argument);
|
||||||
setStatus(WEAK_ERROR);
|
setStatus(WEAK_ERROR);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
candidateCall.getTrace().record(REFERENCE_TARGET, nameReference, valueParameterDescriptor);
|
if (nameReference != null) {
|
||||||
|
candidateCall.getTrace().record(REFERENCE_TARGET, nameReference, valueParameterDescriptor);
|
||||||
|
}
|
||||||
if (!usedParameters.add(valueParameterDescriptor)) {
|
if (!usedParameters.add(valueParameterDescriptor)) {
|
||||||
report(ARGUMENT_PASSED_TWICE.on(nameReference));
|
if (nameReference != null) {
|
||||||
|
report(ARGUMENT_PASSED_TWICE.on(nameReference));
|
||||||
|
}
|
||||||
unmappedArguments.add(argument);
|
unmappedArguments.add(argument);
|
||||||
setStatus(WEAK_ERROR);
|
setStatus(WEAK_ERROR);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ object DynamicCallableDescriptors {
|
|||||||
null,
|
null,
|
||||||
index,
|
index,
|
||||||
Annotations.EMPTY,
|
Annotations.EMPTY,
|
||||||
arg.getArgumentName()?.getReferenceExpression()?.getReferencedNameAsName() ?: Name.identifier("p$index"),
|
arg.getArgumentName()?.asName ?: Name.identifier("p$index"),
|
||||||
outType,
|
outType,
|
||||||
false,
|
false,
|
||||||
varargElementType,
|
varargElementType,
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ public class CallMaker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetValueArgumentName getArgumentName() {
|
public ValueArgumentName getArgumentName() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.resolve.scopes
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.utils.Printer
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
|
|
||||||
|
public class ExplicitImportsScope(private val descriptors: Collection<DeclarationDescriptor>) : JetScope {
|
||||||
|
override fun getClassifier(name: Name) = descriptors.filter { it.getName() == name }.firstIsInstanceOrNull<ClassifierDescriptor>()
|
||||||
|
|
||||||
|
override fun getPackage(name: Name)= descriptors.filter { it.getName() == name }.firstIsInstanceOrNull<PackageViewDescriptor>()
|
||||||
|
|
||||||
|
override fun getProperties(name: Name) = descriptors.filter { it.getName() == name }.filterIsInstance<VariableDescriptor>()
|
||||||
|
|
||||||
|
override fun getLocalVariable(name: Name): VariableDescriptor? = null
|
||||||
|
|
||||||
|
override fun getFunctions(name: Name) = descriptors.filter { it.getName() == name }.filterIsInstance<FunctionDescriptor>()
|
||||||
|
|
||||||
|
override fun getContainingDeclaration() = throw UnsupportedOperationException()
|
||||||
|
|
||||||
|
override fun getDeclarationsByLabel(labelName: Name) = emptyList<DeclarationDescriptor>()
|
||||||
|
|
||||||
|
override fun getDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean) = descriptors
|
||||||
|
|
||||||
|
override fun getImplicitReceiversHierarchy() = emptyList<ReceiverParameterDescriptor>()
|
||||||
|
|
||||||
|
override fun getOwnDeclaredDescriptors() = emptyList<DeclarationDescriptor>()
|
||||||
|
|
||||||
|
override fun printScopeStructure(p: Printer) {
|
||||||
|
p.println(javaClass.getName())
|
||||||
|
}
|
||||||
|
}
|
||||||
+34
-32
@@ -1,4 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
|
||||||
* Copyright 2010-2015 JetBrains s.r.o.
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@@ -16,34 +17,37 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.codeInsight
|
package org.jetbrains.kotlin.idea.codeInsight
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import com.intellij.openapi.project.Project
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastUtils
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
import org.jetbrains.kotlin.idea.util.*
|
||||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
import org.jetbrains.kotlin.lexer.JetTokens
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
|
||||||
import java.util.*
|
|
||||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastUtils
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||||
import org.jetbrains.kotlin.types.JetType
|
import org.jetbrains.kotlin.types.JetType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
||||||
import org.jetbrains.kotlin.lexer.JetTokens
|
import java.util.*
|
||||||
import org.jetbrains.kotlin.idea.util.CallType
|
|
||||||
import org.jetbrains.kotlin.idea.util.substituteExtensionIfCallable
|
|
||||||
import org.jetbrains.kotlin.idea.util.getImplicitReceiversWithInstance
|
|
||||||
|
|
||||||
public class ReferenceVariantsHelper(
|
public class ReferenceVariantsHelper(
|
||||||
private val context: BindingContext,
|
private val context: BindingContext,
|
||||||
|
private val moduleDescriptor: ModuleDescriptor,
|
||||||
|
private val project: Project,
|
||||||
private val visibilityFilter: (DeclarationDescriptor) -> Boolean
|
private val visibilityFilter: (DeclarationDescriptor) -> Boolean
|
||||||
) {
|
) {
|
||||||
|
|
||||||
public data class ReceiversData(
|
public data class ReceiversData(
|
||||||
public val receivers: Collection<ReceiverValue>,
|
public val receivers: Collection<ReceiverValue>,
|
||||||
public val callType: CallType
|
public val callType: CallType
|
||||||
@@ -59,7 +63,10 @@ public class ReferenceVariantsHelper(
|
|||||||
useRuntimeReceiverType: Boolean,
|
useRuntimeReceiverType: Boolean,
|
||||||
nameFilter: (Name) -> Boolean
|
nameFilter: (Name) -> Boolean
|
||||||
): Collection<DeclarationDescriptor> {
|
): Collection<DeclarationDescriptor> {
|
||||||
return getReferenceVariantsNoVisibilityFilter(expression, kindFilter, useRuntimeReceiverType, nameFilter).filter(visibilityFilter)
|
val variants = getReferenceVariantsNoVisibilityFilter(expression, kindFilter, useRuntimeReceiverType, nameFilter)
|
||||||
|
.filter(visibilityFilter)
|
||||||
|
return ShadowedDeclarationsFilter(context, moduleDescriptor, project).filter(variants, expression)
|
||||||
|
//TODO: if visibility filter is empty, filter out shadowed can work incorrectly!
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getReferenceVariantsNoVisibilityFilter(
|
private fun getReferenceVariantsNoVisibilityFilter(
|
||||||
@@ -69,7 +76,7 @@ public class ReferenceVariantsHelper(
|
|||||||
nameFilter: (Name) -> Boolean
|
nameFilter: (Name) -> Boolean
|
||||||
): Collection<DeclarationDescriptor> {
|
): Collection<DeclarationDescriptor> {
|
||||||
val parent = expression.getParent()
|
val parent = expression.getParent()
|
||||||
val resolutionScope = context[BindingContext.RESOLUTION_SCOPE, expression] ?: return listOf()
|
val resolutionScope = context.correctedResolutionScope(expression) ?: return listOf()
|
||||||
val containingDeclaration = resolutionScope.getContainingDeclaration()
|
val containingDeclaration = resolutionScope.getContainingDeclaration()
|
||||||
|
|
||||||
if (parent is JetImportDirective || parent is JetPackageDirective) {
|
if (parent is JetImportDirective || parent is JetPackageDirective) {
|
||||||
@@ -80,13 +87,12 @@ public class ReferenceVariantsHelper(
|
|||||||
return resolutionScope.getDescriptorsFiltered(kindFilter.restrictedToKinds(DescriptorKindFilter.CLASSIFIERS_MASK or DescriptorKindFilter.PACKAGES_MASK), nameFilter)
|
return resolutionScope.getDescriptorsFiltered(kindFilter.restrictedToKinds(DescriptorKindFilter.CLASSIFIERS_MASK or DescriptorKindFilter.PACKAGES_MASK), nameFilter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val descriptors = LinkedHashSet<DeclarationDescriptor>()
|
||||||
|
|
||||||
val pair = getExplicitReceiverData(expression)
|
val pair = getExplicitReceiverData(expression)
|
||||||
if (pair != null) {
|
if (pair != null) {
|
||||||
val (receiverExpression, callType) = pair
|
val (receiverExpression, callType) = pair
|
||||||
|
|
||||||
// Process as call expression
|
|
||||||
val descriptors = HashSet<DeclarationDescriptor>()
|
|
||||||
|
|
||||||
val qualifier = context[BindingContext.QUALIFIER, receiverExpression]
|
val qualifier = context[BindingContext.QUALIFIER, receiverExpression]
|
||||||
if (qualifier != null) {
|
if (qualifier != null) {
|
||||||
// It's impossible to add extension function for package or class (if it's companion object, expression type is not null)
|
// It's impossible to add extension function for package or class (if it's companion object, expression type is not null)
|
||||||
@@ -107,20 +113,16 @@ public class ReferenceVariantsHelper(
|
|||||||
|
|
||||||
descriptors.addCallableExtensions(resolutionScope, receiverValue, dataFlowInfo, callType, kindFilter, nameFilter)
|
descriptors.addCallableExtensions(resolutionScope, receiverValue, dataFlowInfo, callType, kindFilter, nameFilter)
|
||||||
}
|
}
|
||||||
|
|
||||||
return descriptors
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val dataFlowInfo = context.getDataFlowInfo(expression)
|
val dataFlowInfo = context.getDataFlowInfo(expression)
|
||||||
|
|
||||||
val descriptorsSet = HashSet<DeclarationDescriptor>()
|
|
||||||
|
|
||||||
// process instance members that can be called via implicit receiver's instances
|
// process instance members that can be called via implicit receiver's instances
|
||||||
val receivers = resolutionScope.getImplicitReceiversWithInstance()
|
val receivers = resolutionScope.getImplicitReceiversWithInstance()
|
||||||
val receiverValues = receivers.map { it.getValue() }
|
val receiverValues = receivers.map { it.getValue() }
|
||||||
for (receiverValue in receiverValues) {
|
for (receiverValue in receiverValues) {
|
||||||
for (variant in SmartCastUtils.getSmartCastVariantsWithLessSpecificExcluded(receiverValue, context, containingDeclaration, dataFlowInfo)) {
|
for (variant in SmartCastUtils.getSmartCastVariantsWithLessSpecificExcluded(receiverValue, context, containingDeclaration, dataFlowInfo)) {
|
||||||
descriptorsSet.addMembersFromReceiver(variant, CallType.NORMAL, kindFilter, nameFilter)
|
descriptors.addMembersFromReceiver(variant, CallType.NORMAL, kindFilter, nameFilter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,17 +131,17 @@ public class ReferenceVariantsHelper(
|
|||||||
if (descriptor is CallableDescriptor && descriptor.getExtensionReceiverParameter() != null) {
|
if (descriptor is CallableDescriptor && descriptor.getExtensionReceiverParameter() != null) {
|
||||||
val dispatchReceiver = descriptor.getDispatchReceiverParameter()
|
val dispatchReceiver = descriptor.getDispatchReceiverParameter()
|
||||||
if (dispatchReceiver == null || dispatchReceiver in receivers) {
|
if (dispatchReceiver == null || dispatchReceiver in receivers) {
|
||||||
descriptorsSet.addAll(descriptor.substituteExtensionIfCallable(receiverValues, context, dataFlowInfo, CallType.NORMAL, containingDeclaration))
|
descriptors.addAll(descriptor.substituteExtensionIfCallable(receiverValues, context, dataFlowInfo, CallType.NORMAL, containingDeclaration))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (descriptor is CallableDescriptor && descriptor.getDispatchReceiverParameter() != null) continue // should already be processed via implicit receivers
|
if (descriptor is CallableDescriptor && descriptor.getDispatchReceiverParameter() != null) continue // should already be processed via implicit receivers
|
||||||
descriptorsSet.add(descriptor)
|
descriptors.add(descriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return descriptorsSet
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return descriptors
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MutableCollection<DeclarationDescriptor>.addMembersFromReceiver(
|
private fun MutableCollection<DeclarationDescriptor>.addMembersFromReceiver(
|
||||||
|
|||||||
@@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.util
|
||||||
|
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.di.InjectorForMacros
|
||||||
|
import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.DelegatingBindingTrace
|
||||||
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.checkers.AdditionalTypeChecker
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.checkers.CompositeChecker
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.context.CheckValueArgumentsMode
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.util.DelegatingCall
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.ChainedScope
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.ExplicitImportsScope
|
||||||
|
import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator
|
||||||
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
public class ShadowedDeclarationsFilter(
|
||||||
|
private val bindingContext: BindingContext,
|
||||||
|
private val moduleDescriptor: ModuleDescriptor,
|
||||||
|
private val project: Project,
|
||||||
|
private val importDeclarations: Boolean = false
|
||||||
|
) {
|
||||||
|
private val psiFactory = JetPsiFactory(project)
|
||||||
|
private val dummyExpressionFactory = DummyExpressionFactory(psiFactory)
|
||||||
|
|
||||||
|
public fun <TDescriptor : DeclarationDescriptor> filter(declarations: Collection<TDescriptor>, expression: JetSimpleNameExpression): Collection<TDescriptor> {
|
||||||
|
val call = expression.getCall(bindingContext) ?: return declarations
|
||||||
|
|
||||||
|
return declarations
|
||||||
|
.groupBy { signature(it) }
|
||||||
|
.flatMap { filterEqualSignatureGroup(it.value, call) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun signature(descriptor: DeclarationDescriptor): Any {
|
||||||
|
return when (descriptor) {
|
||||||
|
is SimpleFunctionDescriptor -> FunctionSignature(descriptor)
|
||||||
|
is VariableDescriptor -> descriptor.getName()
|
||||||
|
else -> descriptor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <TDescriptor : DeclarationDescriptor> filterEqualSignatureGroup(descriptors: Collection<TDescriptor>, call: Call): Collection<TDescriptor> {
|
||||||
|
if (descriptors.size() == 1) return descriptors
|
||||||
|
|
||||||
|
val first = descriptors.first()
|
||||||
|
val isFunction = first is FunctionDescriptor
|
||||||
|
val name = first.getName()
|
||||||
|
val parameters = (first as CallableDescriptor).getValueParameters()
|
||||||
|
|
||||||
|
val dummyArgumentExpressions = dummyExpressionFactory.createDummyExpressions(parameters.size())
|
||||||
|
|
||||||
|
val bindingTrace = DelegatingBindingTrace(bindingContext, "Temporary trace for filtering shadowed declarations")
|
||||||
|
for ((expression, parameter) in dummyArgumentExpressions.zip(parameters)) {
|
||||||
|
bindingTrace.recordType(expression, parameter.getVarargElementType() ?: parameter.getType())
|
||||||
|
bindingTrace.record(BindingContext.PROCESSED, expression, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
val firstVarargIndex = parameters.withIndex().firstOrNull { it.value.getVarargElementType() != null }?.index
|
||||||
|
val useNamedFromIndex = if (firstVarargIndex != null && firstVarargIndex != parameters.lastIndex) firstVarargIndex else parameters.size()
|
||||||
|
|
||||||
|
class DummyArgument(val index: Int) : ValueArgument {
|
||||||
|
private val expression = dummyArgumentExpressions[index]
|
||||||
|
|
||||||
|
private val argumentName: ValueArgumentName? = if (isNamed()) {
|
||||||
|
object : ValueArgumentName {
|
||||||
|
override val asName = parameters[index].getName()
|
||||||
|
override val referenceExpression = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getArgumentExpression() = expression
|
||||||
|
override fun isNamed() = index >= useNamedFromIndex
|
||||||
|
override fun getArgumentName() = argumentName
|
||||||
|
override fun asElement() = expression
|
||||||
|
override fun getSpreadElement() = null
|
||||||
|
override fun isExternal() = false
|
||||||
|
}
|
||||||
|
|
||||||
|
val arguments = ArrayList<DummyArgument>()
|
||||||
|
for (i in parameters.indices) {
|
||||||
|
arguments.add(DummyArgument(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
val newCall = object : DelegatingCall(call) {
|
||||||
|
//TODO: compiler crash (KT-8011)
|
||||||
|
//val arguments = parameters.indices.map { DummyArgument(it) }
|
||||||
|
val callee = psiFactory.createExpressionByPattern("$0", name)
|
||||||
|
|
||||||
|
override fun getCalleeExpression() = callee
|
||||||
|
|
||||||
|
override fun getValueArgumentList() = null
|
||||||
|
|
||||||
|
override fun getValueArguments() = arguments
|
||||||
|
|
||||||
|
override fun getFunctionLiteralArguments() = emptyList<FunctionLiteralArgument>()
|
||||||
|
|
||||||
|
override fun getTypeArguments() = emptyList<JetTypeProjection>()
|
||||||
|
|
||||||
|
override fun getTypeArgumentList() = null
|
||||||
|
}
|
||||||
|
|
||||||
|
val calleeExpression = call.getCalleeExpression() ?: return descriptors
|
||||||
|
var resolutionScope = bindingContext.correctedResolutionScope(calleeExpression) ?: return descriptors
|
||||||
|
|
||||||
|
if (importDeclarations) {
|
||||||
|
val importableDescriptors = descriptors.filter { it.canBeReferencedViaImport() }
|
||||||
|
resolutionScope = ChainedScope(resolutionScope.getContainingDeclaration(), "Scope with explicitly imported descriptors",
|
||||||
|
ExplicitImportsScope(importableDescriptors), resolutionScope)
|
||||||
|
}
|
||||||
|
|
||||||
|
val dataFlowInfo = bindingContext.getDataFlowInfo(calleeExpression)
|
||||||
|
val context = BasicCallResolutionContext.create(bindingTrace, resolutionScope, newCall, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo,
|
||||||
|
ContextDependency.INDEPENDENT, CheckValueArgumentsMode.ENABLED,
|
||||||
|
CompositeChecker(listOf()), SymbolUsageValidator.Empty, AdditionalTypeChecker.Composite(listOf()), false)
|
||||||
|
val callResolver = InjectorForMacros(project, moduleDescriptor).getCallResolver()
|
||||||
|
val results = if (isFunction) callResolver.resolveFunctionCall(context) else callResolver.resolveSimpleProperty(context)
|
||||||
|
val resultingDescriptors = results.getResultingCalls().map { it.getResultingDescriptor() }.toSet()
|
||||||
|
val filtered = descriptors.filter { it in resultingDescriptors }
|
||||||
|
return if (filtered.isNotEmpty()) filtered else descriptors /* something went wrong, none of our declarations among resolve candidates, let's not filter anything */
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DummyExpressionFactory(val factory: JetPsiFactory) {
|
||||||
|
private val expressions = ArrayList<JetExpression>()
|
||||||
|
|
||||||
|
fun createDummyExpressions(count: Int): List<JetExpression> {
|
||||||
|
while (expressions.size() < count) {
|
||||||
|
expressions.add(factory.createExpression("dummy"))
|
||||||
|
}
|
||||||
|
return expressions.take(count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FunctionSignature(val function: FunctionDescriptor) {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (other === this) return true
|
||||||
|
if (other !is FunctionSignature) return false
|
||||||
|
if (function.getName() != other.function.getName()) return false
|
||||||
|
val parameters1 = function.getValueParameters()
|
||||||
|
val parameters2 = other.function.getValueParameters()
|
||||||
|
if (parameters1.size() != parameters2.size()) return false
|
||||||
|
for (i in parameters1.indices) {
|
||||||
|
val p1 = parameters1[i]
|
||||||
|
val p2 = parameters2[i]
|
||||||
|
if (p1.getVarargElementType() != p2.getVarargElementType()) return false // both should be vararg or or both not
|
||||||
|
if (p1.getType() != p2.getType()) return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode() = function.getName().hashCode() * 17 + function.getValueParameters().size()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,8 +16,15 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.util
|
package org.jetbrains.kotlin.idea.util
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||||
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
|
||||||
public fun JetFunctionLiteral.findLabelAndCall(): Pair<Name?, JetCallExpression?> {
|
public fun JetFunctionLiteral.findLabelAndCall(): Pair<Name?, JetCallExpression?> {
|
||||||
val literalParent = (this.getParent() as JetFunctionLiteralExpression).getParent()
|
val literalParent = (this.getParent() as JetFunctionLiteralExpression).getParent()
|
||||||
@@ -44,3 +51,34 @@ public fun JetFunctionLiteral.findLabelAndCall(): Pair<Name?, JetCallExpression?
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns corrected resolution scope excluding variable inside its own initializer
|
||||||
|
// will not be needed after correcting JetScope stored BindingContext (see KT-4822 Wrong scope is used for local variable name completion)
|
||||||
|
public fun BindingContext.correctedResolutionScope(expression: JetExpression): JetScope? {
|
||||||
|
val scope = get(BindingContext.RESOLUTION_SCOPE, expression) ?: return null
|
||||||
|
|
||||||
|
val variablesToExclude = hashSetOf<VariableDescriptor>()
|
||||||
|
for (element in expression.parentsWithSelf) {
|
||||||
|
if (element is JetExpression) {
|
||||||
|
val declaration = element.getParent() as? JetVariableDeclaration ?: continue
|
||||||
|
if (element == declaration.getInitializer()) {
|
||||||
|
variablesToExclude.addIfNotNull(get(BindingContext.VARIABLE, declaration))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (variablesToExclude.isEmpty()) return scope
|
||||||
|
|
||||||
|
return object : JetScope by scope {
|
||||||
|
override fun getDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean)
|
||||||
|
= scope.getDescriptors(kindFilter, nameFilter).filter { it !in variablesToExclude }
|
||||||
|
|
||||||
|
//TODO: it's not correct!
|
||||||
|
override fun getLocalVariable(name: Name): VariableDescriptor? {
|
||||||
|
val variable = scope.getLocalVariable(name) ?: return null
|
||||||
|
return if (variable in variablesToExclude) null else variable
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getProperties(name: Name) = scope.getProperties(name).filter { it !in variablesToExclude }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.idea.core.comparePossiblyOverridingDescriptors
|
|||||||
import org.jetbrains.kotlin.idea.core.isVisible
|
import org.jetbrains.kotlin.idea.core.isVisible
|
||||||
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
||||||
import org.jetbrains.kotlin.idea.util.CallType
|
import org.jetbrains.kotlin.idea.util.CallType
|
||||||
|
import org.jetbrains.kotlin.idea.util.ShadowedDeclarationsFilter
|
||||||
import org.jetbrains.kotlin.idea.util.makeNotNullable
|
import org.jetbrains.kotlin.idea.util.makeNotNullable
|
||||||
import org.jetbrains.kotlin.lexer.JetTokens
|
import org.jetbrains.kotlin.lexer.JetTokens
|
||||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptorKindExclude
|
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptorKindExclude
|
||||||
@@ -74,6 +75,7 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess
|
|||||||
private val file = position.getContainingFile() as JetFile
|
private val file = position.getContainingFile() as JetFile
|
||||||
protected val resolutionFacade: ResolutionFacade = file.getResolutionFacade()
|
protected val resolutionFacade: ResolutionFacade = file.getResolutionFacade()
|
||||||
protected val moduleDescriptor: ModuleDescriptor = resolutionFacade.findModuleDescriptor(file)
|
protected val moduleDescriptor: ModuleDescriptor = resolutionFacade.findModuleDescriptor(file)
|
||||||
|
protected val project: Project = position.getProject()
|
||||||
|
|
||||||
protected val reference: JetSimpleNameReference?
|
protected val reference: JetSimpleNameReference?
|
||||||
protected val expression: JetExpression?
|
protected val expression: JetExpression?
|
||||||
@@ -126,7 +128,7 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess
|
|||||||
|
|
||||||
protected val prefixMatcher: PrefixMatcher = this.resultSet.getPrefixMatcher()
|
protected val prefixMatcher: PrefixMatcher = this.resultSet.getPrefixMatcher()
|
||||||
|
|
||||||
protected val referenceVariantsHelper: ReferenceVariantsHelper = ReferenceVariantsHelper(bindingContext) { isVisibleDescriptor(it) }
|
protected val referenceVariantsHelper: ReferenceVariantsHelper = ReferenceVariantsHelper(bindingContext, moduleDescriptor, project) { isVisibleDescriptor(it) }
|
||||||
|
|
||||||
protected val receiversData: ReferenceVariantsHelper.ReceiversData? = reference?.let { referenceVariantsHelper.getReferenceVariantsReceivers(it.expression) }
|
protected val receiversData: ReferenceVariantsHelper.ReceiversData? = reference?.let { referenceVariantsHelper.getReferenceVariantsReceivers(it.expression) }
|
||||||
|
|
||||||
@@ -158,8 +160,6 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess
|
|||||||
|
|
||||||
protected val collector: LookupElementsCollector = LookupElementsCollector(prefixMatcher, parameters, resolutionFacade, lookupElementFactory, inDescriptor, collectorContext)
|
protected val collector: LookupElementsCollector = LookupElementsCollector(prefixMatcher, parameters, resolutionFacade, lookupElementFactory, inDescriptor, collectorContext)
|
||||||
|
|
||||||
protected val project: Project = position.getProject()
|
|
||||||
|
|
||||||
protected val originalSearchScope: GlobalSearchScope = ResolutionFacade.getResolveScope(parameters.getOriginalFile() as JetFile)
|
protected val originalSearchScope: GlobalSearchScope = ResolutionFacade.getResolveScope(parameters.getOriginalFile() as JetFile)
|
||||||
|
|
||||||
// we need to exclude the original file from scope because our resolve session is built with this file replaced by synthetic one
|
// we need to exclude the original file from scope because our resolve session is built with this file replaced by synthetic one
|
||||||
@@ -224,8 +224,12 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess
|
|||||||
protected fun getTopLevelCallables(): Collection<DeclarationDescriptor>
|
protected fun getTopLevelCallables(): Collection<DeclarationDescriptor>
|
||||||
= indicesHelper.getTopLevelCallables({ prefixMatcher.prefixMatches(it) })
|
= indicesHelper.getTopLevelCallables({ prefixMatcher.prefixMatches(it) })
|
||||||
|
|
||||||
protected fun getTopLevelExtensions(): Collection<CallableDescriptor>
|
protected fun getTopLevelExtensions(): Collection<CallableDescriptor> {
|
||||||
= indicesHelper.getCallableTopLevelExtensions({ prefixMatcher.prefixMatches(it) }, reference!!.expression)
|
val extensions = indicesHelper.getCallableTopLevelExtensions({ prefixMatcher.prefixMatches(it) }, reference!!.expression)
|
||||||
|
//TODO: it filters out too much
|
||||||
|
//TODO: not filtered out dominated by members
|
||||||
|
return ShadowedDeclarationsFilter(bindingContext, moduleDescriptor, project, importDeclarations = true).filter(extensions, reference.expression)
|
||||||
|
}
|
||||||
|
|
||||||
protected fun addAllClasses(kindFilter: (ClassKind) -> Boolean) {
|
protected fun addAllClasses(kindFilter: (ClassKind) -> Boolean) {
|
||||||
AllClassesCompletion(
|
AllClassesCompletion(
|
||||||
@@ -451,7 +455,7 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para
|
|||||||
val dummyArgument = object : FunctionLiteralArgument {
|
val dummyArgument = object : FunctionLiteralArgument {
|
||||||
override fun getFunctionLiteral() = throw UnsupportedOperationException()
|
override fun getFunctionLiteral() = throw UnsupportedOperationException()
|
||||||
override fun getArgumentExpression() = throw UnsupportedOperationException()
|
override fun getArgumentExpression() = throw UnsupportedOperationException()
|
||||||
override fun getArgumentName(): JetValueArgumentName? = null
|
override fun getArgumentName(): ValueArgumentName? = null
|
||||||
override fun isNamed() = false
|
override fun isNamed() = false
|
||||||
override fun asElement() = throw UnsupportedOperationException()
|
override fun asElement() = throw UnsupportedOperationException()
|
||||||
override fun getSpreadElement(): LeafPsiElement? = null
|
override fun getSpreadElement(): LeafPsiElement? = null
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.idea.completion.smart.toList
|
|||||||
import org.jetbrains.kotlin.idea.core.mapArgumentsToParameters
|
import org.jetbrains.kotlin.idea.core.mapArgumentsToParameters
|
||||||
import org.jetbrains.kotlin.idea.util.makeNotNullable
|
import org.jetbrains.kotlin.idea.util.makeNotNullable
|
||||||
import org.jetbrains.kotlin.lexer.JetTokens
|
import org.jetbrains.kotlin.lexer.JetTokens
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DelegatingBindingTrace
|
import org.jetbrains.kotlin.resolve.DelegatingBindingTrace
|
||||||
@@ -63,9 +64,9 @@ data class ItemOptions(val starPrefix: Boolean) {
|
|||||||
|
|
||||||
open data class ExpectedInfo(val type: JetType, val expectedName: String?, val tail: Tail?, val itemOptions: ItemOptions = ItemOptions.DEFAULT)
|
open data class ExpectedInfo(val type: JetType, val expectedName: String?, val tail: Tail?, val itemOptions: ItemOptions = ItemOptions.DEFAULT)
|
||||||
|
|
||||||
data class ArgumentPosition(val argumentIndex: Int, val argumentName: String?, val isFunctionLiteralArgument: Boolean) {
|
data class ArgumentPosition(val argumentIndex: Int, val argumentName: Name?, val isFunctionLiteralArgument: Boolean) {
|
||||||
constructor(argumentIndex: Int, isFunctionLiteralArgument: Boolean = false) : this(argumentIndex, null, isFunctionLiteralArgument)
|
constructor(argumentIndex: Int, isFunctionLiteralArgument: Boolean = false) : this(argumentIndex, null, isFunctionLiteralArgument)
|
||||||
constructor(argumentIndex: Int, argumentName: String?) : this(argumentIndex, argumentName, false)
|
constructor(argumentIndex: Int, argumentName: Name?) : this(argumentIndex, argumentName, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ArgumentExpectedInfo(type: JetType, name: String?, tail: Tail?, val function: FunctionDescriptor, val position: ArgumentPosition, itemOptions: ItemOptions = ItemOptions.DEFAULT)
|
class ArgumentExpectedInfo(type: JetType, name: String?, tail: Tail?, val function: FunctionDescriptor, val position: ArgumentPosition, itemOptions: ItemOptions = ItemOptions.DEFAULT)
|
||||||
@@ -133,7 +134,7 @@ class ExpectedInfos(
|
|||||||
assert(argumentIndex >= 0) {
|
assert(argumentIndex >= 0) {
|
||||||
"Could not find argument '$argument' among arguments of call: $call"
|
"Could not find argument '$argument' among arguments of call: $call"
|
||||||
}
|
}
|
||||||
val argumentName = argument.getArgumentName()?.getReferenceExpression()?.getReferencedName()
|
val argumentName = argument.getArgumentName()?.asName
|
||||||
val isFunctionLiteralArgument = argument is FunctionLiteralArgument
|
val isFunctionLiteralArgument = argument is FunctionLiteralArgument
|
||||||
val argumentPosition = ArgumentPosition(argumentIndex, argumentName, isFunctionLiteralArgument)
|
val argumentPosition = ArgumentPosition(argumentIndex, argumentName, isFunctionLiteralArgument)
|
||||||
|
|
||||||
@@ -243,9 +244,9 @@ class ExpectedInfos(
|
|||||||
return expectedInfos
|
return expectedInfos
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun namedArgumentTail(argumentToParameter: Map<ValueArgument, ValueParameterDescriptor>, argumentName: String, descriptor: FunctionDescriptor): Tail? {
|
private fun namedArgumentTail(argumentToParameter: Map<ValueArgument, ValueParameterDescriptor>, argumentName: Name, descriptor: FunctionDescriptor): Tail? {
|
||||||
val usedParameterNames = (argumentToParameter.values().map { it.getName().asString() } + listOf(argumentName)).toSet()
|
val usedParameterNames = (argumentToParameter.values().map { it.getName() } + listOf(argumentName)).toSet()
|
||||||
val notUsedParameters = descriptor.getValueParameters().filter { it.getName().asString() !in usedParameterNames }
|
val notUsedParameters = descriptor.getValueParameters().filter { it.getName() !in usedParameterNames }
|
||||||
return if (notUsedParameters.isEmpty())
|
return if (notUsedParameters.isEmpty())
|
||||||
Tail.RPARENTH
|
Tail.RPARENTH
|
||||||
else if (notUsedParameters.all { it.hasDefaultValue() })
|
else if (notUsedParameters.all { it.hasDefaultValue() })
|
||||||
|
|||||||
+2
-1
@@ -51,8 +51,9 @@ object PackageDirectiveCompletion {
|
|||||||
|
|
||||||
val resolutionFacade = ref.expression.getResolutionFacade()
|
val resolutionFacade = ref.expression.getResolutionFacade()
|
||||||
val bindingContext = resolutionFacade.analyze(ref.expression)
|
val bindingContext = resolutionFacade.analyze(ref.expression)
|
||||||
|
val moduleDescriptor = resolutionFacade.findModuleDescriptor(file)
|
||||||
|
|
||||||
val variants = ReferenceVariantsHelper(bindingContext, { true }).getPackageReferenceVariants(ref.expression, prefixMatcher.asNameFilter())
|
val variants = ReferenceVariantsHelper(bindingContext, moduleDescriptor, file.getProject(), { true }).getPackageReferenceVariants(ref.expression, prefixMatcher.asNameFilter())
|
||||||
for (variant in variants) {
|
for (variant in variants) {
|
||||||
val lookupElement = LookupElementFactory(resolutionFacade, listOf()).createLookupElement(variant, false)
|
val lookupElement = LookupElementFactory(resolutionFacade, listOf()).createLookupElement(variant, false)
|
||||||
if (!lookupElement.getLookupString().contains(DUMMY_IDENTIFIER)) {
|
if (!lookupElement.getLookupString().contains(DUMMY_IDENTIFIER)) {
|
||||||
|
|||||||
+2
-1
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
|||||||
import org.jetbrains.kotlin.idea.JetDescriptorIconProvider
|
import org.jetbrains.kotlin.idea.JetDescriptorIconProvider
|
||||||
import org.jetbrains.kotlin.idea.completion.*
|
import org.jetbrains.kotlin.idea.completion.*
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
|
import org.jetbrains.kotlin.idea.util.correctedResolutionScope
|
||||||
import org.jetbrains.kotlin.psi.JetExpression
|
import org.jetbrains.kotlin.psi.JetExpression
|
||||||
import org.jetbrains.kotlin.renderer.render
|
import org.jetbrains.kotlin.renderer.render
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
@@ -40,7 +41,7 @@ class MultipleArgumentsItemProvider(val bindingContext: BindingContext,
|
|||||||
public fun addToCollection(collection: MutableCollection<LookupElement>,
|
public fun addToCollection(collection: MutableCollection<LookupElement>,
|
||||||
expectedInfos: Collection<ExpectedInfo>,
|
expectedInfos: Collection<ExpectedInfo>,
|
||||||
context: JetExpression) {
|
context: JetExpression) {
|
||||||
val resolutionScope = bindingContext[BindingContext.RESOLUTION_SCOPE, context] ?: return
|
val resolutionScope = bindingContext.correctedResolutionScope(context) ?: return
|
||||||
|
|
||||||
val added = HashSet<String>()
|
val added = HashSet<String>()
|
||||||
for (expectedInfo in expectedInfos) {
|
for (expectedInfo in expectedInfos) {
|
||||||
|
|||||||
@@ -264,13 +264,6 @@ class SmartCompletion(
|
|||||||
private fun calcItemsToSkip(expression: JetExpression): Set<DeclarationDescriptor> {
|
private fun calcItemsToSkip(expression: JetExpression): Set<DeclarationDescriptor> {
|
||||||
val parent = expression.getParent()
|
val parent = expression.getParent()
|
||||||
when(parent) {
|
when(parent) {
|
||||||
is JetProperty -> {
|
|
||||||
//TODO: this can be filtered out by ordinary completion
|
|
||||||
if (expression == parent.getInitializer()) {
|
|
||||||
return bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, parent].toSet()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
is JetBinaryExpression -> {
|
is JetBinaryExpression -> {
|
||||||
if (parent.getRight() == expression) {
|
if (parent.getRight() == expression) {
|
||||||
val operationToken = parent.getOperationToken()
|
val operationToken = parent.getOperationToken()
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
fun foo(xxx: String) {
|
||||||
|
var xxx = xx<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "xxx", itemText: "xxx", typeText: "String" }
|
||||||
|
// NOTHING_ELSE
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
fun foo() {
|
||||||
|
var xxx = <caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// ABSENT: xxx
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fun foo(xxx: Int) {
|
||||||
|
val xxx: Any = run {
|
||||||
|
xx<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "xxx", itemText: "xxx", typeText: "Int" }
|
||||||
|
// NOTHING_ELSE
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
class C {
|
||||||
|
val xxx = 1
|
||||||
|
|
||||||
|
fun foo(xxx: String) {
|
||||||
|
val xxx = 'x'
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
val xxx = true
|
||||||
|
xx<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "xxx", itemText: "xxx", typeText: "Boolean" }
|
||||||
|
// NOTHING_ELSE
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
class C {
|
||||||
|
val xxx = 1
|
||||||
|
|
||||||
|
fun foo(xxx: String) {
|
||||||
|
xx<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "xxx", itemText: "xxx", typeText: "String" }
|
||||||
|
// NOTHING_ELSE
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package ppp
|
||||||
|
|
||||||
|
class C {
|
||||||
|
fun xxx(p: Int) = ""
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
xx<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun C.xxx(p: Int) = 1
|
||||||
|
fun Any.xxx(c: Char) = 1
|
||||||
|
fun C.xxx(c: Char) = 1
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "xxx", itemText: "xxx", tailText: "(p: Int)", typeText: "String" }
|
||||||
|
// EXIST: { lookupString: "xxx", itemText: "xxx", tailText: "(c: Char) for C in ppp", typeText: "Int" }
|
||||||
|
// NOTHING_ELSE
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package ppp
|
||||||
|
|
||||||
|
class C {
|
||||||
|
fun xxx(vararg s: String, p: Int) = ""
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
xx<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun C.xxx(vararg s: String, p: Int) = 1
|
||||||
|
fun Any.xxx(vararg s: String, c: Char) = 1
|
||||||
|
fun C.xxx(vararg s: String, c: Char) = 1
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "xxx", itemText: "xxx", tailText: "(vararg s: String, p: Int)", typeText: "String" }
|
||||||
|
// EXIST: { lookupString: "xxx", itemText: "xxx", tailText: "(vararg s: String, c: Char) for C in ppp", typeText: "Int" }
|
||||||
|
// NOTHING_ELSE
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
class C {
|
||||||
|
inner class Inner {
|
||||||
|
fun foo() {
|
||||||
|
xx<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
val xxx: String get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
val xxx: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "xxx", itemText: "xxx", typeText: "String" }
|
||||||
|
// NOTHING_ELSE
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
interface I
|
||||||
|
|
||||||
|
class C : I {
|
||||||
|
inner class Inner {
|
||||||
|
fun foo() {
|
||||||
|
xx<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
val Any.xxx: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
val I.xxx: Int get() = 1
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
val C.xxx: Int get() = 1
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "xxx", itemText: "xxx", tailText: " for Any in C.Inner", typeText: "Int" }
|
||||||
|
// NOTHING_ELSE
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
package ppp
|
||||||
|
|
||||||
|
class C {
|
||||||
|
val xxx = ""
|
||||||
|
fun xxx() = ""
|
||||||
|
fun xxx(p: Int) = ""
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
xx<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val C.xxx: Int
|
||||||
|
get() = 1
|
||||||
|
|
||||||
|
fun C.xxx() = 1
|
||||||
|
fun C.xxx(p: Int) = 1
|
||||||
|
fun C.xxx(p: String) = 1
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "xxx", itemText: "xxx", tailText: null, typeText: "String" }
|
||||||
|
// EXIST: { lookupString: "xxx", itemText: "xxx", tailText: "()", typeText: "String" }
|
||||||
|
// EXIST: { lookupString: "xxx", itemText: "xxx", tailText: "(p: Int)", typeText: "String" }
|
||||||
|
// EXIST: { lookupString: "xxx", itemText: "xxx", tailText: "(p: String) for C in ppp", typeText: "Int" }
|
||||||
|
// NOTHING_ELSE
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
val xxx: Int get() = 1
|
||||||
|
|
||||||
|
class C {
|
||||||
|
fun foo() {
|
||||||
|
xx<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
val xxx: String get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "xxx", itemText: "xxx", typeText: "String" }
|
||||||
|
// NOTHING_ELSE
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
package ppp
|
||||||
|
|
||||||
|
interface I
|
||||||
|
|
||||||
|
class C : I {
|
||||||
|
fun foo() {
|
||||||
|
xx<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val Any.xxx: Int get() = 1
|
||||||
|
val I.xxx: Int get() = 1
|
||||||
|
|
||||||
|
fun Any.xxx() = 1
|
||||||
|
fun C.xxx() = 1
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "xxx", itemText: "xxx", tailText: " for I in ppp", typeText: "Int" }
|
||||||
|
// EXIST: { lookupString: "xxx", itemText: "xxx", tailText: "() for C in ppp", typeText: "Int" }
|
||||||
|
// NOTHING_ELSE
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
package dependency
|
||||||
|
|
||||||
|
fun Any.xxx(): Int = 1
|
||||||
|
fun ppp.C.xxx(): Int = 1
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
package ppp
|
||||||
|
|
||||||
|
import dependency.*
|
||||||
|
|
||||||
|
class C {
|
||||||
|
fun foo() {
|
||||||
|
xx<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "xxx", itemText: "xxx", tailText: "() for C in dependency", typeText: "Int" }
|
||||||
|
// NOTHING_ELSE
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
package dependency
|
||||||
|
|
||||||
|
fun Any.xxx(): Int = 1
|
||||||
|
fun ppp.C.xxx(): Int = 1
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package ppp
|
||||||
|
|
||||||
|
class C {
|
||||||
|
fun foo() {
|
||||||
|
xx<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "xxx", itemText: "xxx", tailText: "() for C in dependency", typeText: "Int" }
|
||||||
|
// NOTHING_ELSE
|
||||||
+81
@@ -1396,6 +1396,87 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("idea/idea-completion/testData/basic/common/shadowing")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Shadowing extends AbstractJSBasicCompletionTest {
|
||||||
|
public void testAllFilesPresentInShadowing() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/basic/common/shadowing"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("InInitializer1.kt")
|
||||||
|
public void testInInitializer1() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/InInitializer1.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("InInitializer2.kt")
|
||||||
|
public void testInInitializer2() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/InInitializer2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("InInitializer3.kt")
|
||||||
|
public void testInInitializer3() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/InInitializer3.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Locals1.kt")
|
||||||
|
public void testLocals1() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/Locals1.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Locals2.kt")
|
||||||
|
public void testLocals2() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/Locals2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Overloads.kt")
|
||||||
|
public void testOverloads() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/Overloads.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("OverloadsAndVararg.kt")
|
||||||
|
public void testOverloadsAndVararg() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/OverloadsAndVararg.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("PreferCloserMember.kt")
|
||||||
|
public void testPreferCloserMember() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/PreferCloserMember.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("PreferMemberExtension.kt")
|
||||||
|
public void testPreferMemberExtension() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/PreferMemberExtension.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("PreferMemberToExtension.kt")
|
||||||
|
public void testPreferMemberToExtension() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/PreferMemberToExtension.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("PreferMemberToGlobal.kt")
|
||||||
|
public void testPreferMemberToGlobal() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/PreferMemberToGlobal.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("PreferMoreSpecificExtension.kt")
|
||||||
|
public void testPreferMoreSpecificExtension() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/PreferMoreSpecificExtension.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/idea-completion/testData/basic/common/typeArgsOrNot")
|
@TestMetadata("idea/idea-completion/testData/basic/common/typeArgsOrNot")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+81
@@ -1396,6 +1396,87 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("idea/idea-completion/testData/basic/common/shadowing")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Shadowing extends AbstractJvmBasicCompletionTest {
|
||||||
|
public void testAllFilesPresentInShadowing() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/basic/common/shadowing"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("InInitializer1.kt")
|
||||||
|
public void testInInitializer1() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/InInitializer1.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("InInitializer2.kt")
|
||||||
|
public void testInInitializer2() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/InInitializer2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("InInitializer3.kt")
|
||||||
|
public void testInInitializer3() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/InInitializer3.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Locals1.kt")
|
||||||
|
public void testLocals1() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/Locals1.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Locals2.kt")
|
||||||
|
public void testLocals2() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/Locals2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Overloads.kt")
|
||||||
|
public void testOverloads() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/Overloads.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("OverloadsAndVararg.kt")
|
||||||
|
public void testOverloadsAndVararg() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/OverloadsAndVararg.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("PreferCloserMember.kt")
|
||||||
|
public void testPreferCloserMember() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/PreferCloserMember.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("PreferMemberExtension.kt")
|
||||||
|
public void testPreferMemberExtension() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/PreferMemberExtension.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("PreferMemberToExtension.kt")
|
||||||
|
public void testPreferMemberToExtension() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/PreferMemberToExtension.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("PreferMemberToGlobal.kt")
|
||||||
|
public void testPreferMemberToGlobal() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/PreferMemberToGlobal.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("PreferMoreSpecificExtension.kt")
|
||||||
|
public void testPreferMoreSpecificExtension() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/shadowing/PreferMoreSpecificExtension.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/idea-completion/testData/basic/common/typeArgsOrNot")
|
@TestMetadata("idea/idea-completion/testData/basic/common/typeArgsOrNot")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+12
@@ -209,6 +209,18 @@ public class MultiFileJvmBasicCompletionTestGenerated extends AbstractMultiFileJ
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("PreferMoreSpecificExtension1")
|
||||||
|
public void testPreferMoreSpecificExtension1() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/multifile/PreferMoreSpecificExtension1/");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("PreferMoreSpecificExtension2")
|
||||||
|
public void testPreferMoreSpecificExtension2() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/multifile/PreferMoreSpecificExtension2/");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("TopLevelFunction")
|
@TestMetadata("TopLevelFunction")
|
||||||
public void testTopLevelFunction() throws Exception {
|
public void testTopLevelFunction() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/multifile/TopLevelFunction/");
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/multifile/TopLevelFunction/");
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public fun Call.mapArgumentsToParameters(targetDescriptor: CallableDescriptor):
|
|||||||
if (parameters.isEmpty()) return emptyMap()
|
if (parameters.isEmpty()) return emptyMap()
|
||||||
|
|
||||||
val map = HashMap<ValueArgument, ValueParameterDescriptor>()
|
val map = HashMap<ValueArgument, ValueParameterDescriptor>()
|
||||||
val parametersByName = parameters.toMap { it.getName().asString() }
|
val parametersByName = parameters.toMap { it.getName() }
|
||||||
|
|
||||||
var positionalArgumentIndex: Int? = 0
|
var positionalArgumentIndex: Int? = 0
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ public fun Call.mapArgumentsToParameters(targetDescriptor: CallableDescriptor):
|
|||||||
map[argument] = parameters.last()
|
map[argument] = parameters.last()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val argumentName = argument.getArgumentName()?.getReferenceExpression()?.getReferencedName()
|
val argumentName = argument.getArgumentName()?.asName
|
||||||
|
|
||||||
if (argumentName != null) {
|
if (argumentName != null) {
|
||||||
if (targetDescriptor.hasStableParameterNames()) {
|
if (targetDescriptor.hasStableParameterNames()) {
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ public fun JetFunctionLiteralArgument.moveInsideParenthesesAndReplaceWith(
|
|||||||
val newCallExpression = oldCallExpression.copy() as JetCallExpression
|
val newCallExpression = oldCallExpression.copy() as JetCallExpression
|
||||||
|
|
||||||
val psiFactory = JetPsiFactory(getProject())
|
val psiFactory = JetPsiFactory(getProject())
|
||||||
val argument = if (newCallExpression.getValueArgumentsInParentheses().any { it.getArgumentName() != null }) {
|
val argument = if (newCallExpression.getValueArgumentsInParentheses().any { it.isNamed() }) {
|
||||||
psiFactory.createArgument(replacement, functionLiteralArgumentName)
|
psiFactory.createArgument(replacement, functionLiteralArgumentName)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
+2
-1
@@ -385,6 +385,7 @@ public class JetFunctionParameterInfoHandler implements ParameterInfoHandlerWith
|
|||||||
|
|
||||||
ResolutionFacade resolutionFacade = ResolvePackage.getResolutionFacade(callNameExpression.getContainingJetFile());
|
ResolutionFacade resolutionFacade = ResolvePackage.getResolutionFacade(callNameExpression.getContainingJetFile());
|
||||||
BindingContext bindingContext = resolutionFacade.analyze(callNameExpression, BodyResolveMode.FULL);
|
BindingContext bindingContext = resolutionFacade.analyze(callNameExpression, BodyResolveMode.FULL);
|
||||||
|
ModuleDescriptor moduleDescriptor = resolutionFacade.findModuleDescriptor(callNameExpression);
|
||||||
|
|
||||||
JetScope scope = bindingContext.get(BindingContext.RESOLUTION_SCOPE, callNameExpression);
|
JetScope scope = bindingContext.get(BindingContext.RESOLUTION_SCOPE, callNameExpression);
|
||||||
final DeclarationDescriptor placeDescriptor;
|
final DeclarationDescriptor placeDescriptor;
|
||||||
@@ -409,7 +410,7 @@ public class JetFunctionParameterInfoHandler implements ParameterInfoHandlerWith
|
|||||||
return name.equals(refName);
|
return name.equals(refName);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Collection<DeclarationDescriptor> variants = new ReferenceVariantsHelper(bindingContext, visibilityFilter).getReferenceVariants(
|
Collection<DeclarationDescriptor> variants = new ReferenceVariantsHelper(bindingContext, moduleDescriptor, file.getProject(), visibilityFilter).getReferenceVariants(
|
||||||
callNameExpression, new DescriptorKindFilter(DescriptorKindFilter.FUNCTIONS_MASK | DescriptorKindFilter.CLASSIFIERS_MASK,
|
callNameExpression, new DescriptorKindFilter(DescriptorKindFilter.FUNCTIONS_MASK | DescriptorKindFilter.CLASSIFIERS_MASK,
|
||||||
Collections.<DescriptorKindExclude>emptyList()), false, nameFilter);
|
Collections.<DescriptorKindExclude>emptyList()), false, nameFilter);
|
||||||
|
|
||||||
|
|||||||
@@ -98,11 +98,11 @@ public abstract class ChangeFunctionSignatureFix extends JetIntentionAction<PsiE
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected static String getNewArgumentName(ValueArgument argument, JetNameValidator validator) {
|
protected static String getNewArgumentName(ValueArgument argument, JetNameValidator validator) {
|
||||||
JetValueArgumentName argumentName = argument.getArgumentName();
|
ValueArgumentName argumentName = argument.getArgumentName();
|
||||||
JetExpression expression = argument.getArgumentExpression();
|
JetExpression expression = argument.getArgumentExpression();
|
||||||
|
|
||||||
if (argumentName != null) {
|
if (argumentName != null) {
|
||||||
return validator.validateName(argumentName.getName());
|
return validator.validateName(argumentName.getAsName().asString());
|
||||||
}
|
}
|
||||||
else if (expression != null) {
|
else if (expression != null) {
|
||||||
return JetNameSuggester.suggestNames(expression, validator, "param")[0];
|
return JetNameSuggester.suggestNames(expression, validator, "param")[0];
|
||||||
|
|||||||
@@ -189,30 +189,4 @@ object ReplaceWithAnnotationAnalyzer {
|
|||||||
else -> throw IllegalArgumentException("Cannot find resolution scope for $descriptor")
|
else -> throw IllegalArgumentException("Cannot find resolution scope for $descriptor")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ExplicitImportsScope(val descriptors: Collection<DeclarationDescriptor>) : JetScope {
|
|
||||||
override fun getClassifier(name: Name) = descriptors.filter { it.getName() == name }.firstIsInstanceOrNull<ClassifierDescriptor>()
|
|
||||||
|
|
||||||
override fun getPackage(name: Name)= descriptors.filter { it.getName() == name }.firstIsInstanceOrNull<PackageViewDescriptor>()
|
|
||||||
|
|
||||||
override fun getProperties(name: Name) = descriptors.filter { it.getName() == name }.filterIsInstance<VariableDescriptor>()
|
|
||||||
|
|
||||||
override fun getLocalVariable(name: Name): VariableDescriptor? = null
|
|
||||||
|
|
||||||
override fun getFunctions(name: Name) = descriptors.filter { it.getName() == name }.filterIsInstance<FunctionDescriptor>()
|
|
||||||
|
|
||||||
override fun getContainingDeclaration() = throw UnsupportedOperationException()
|
|
||||||
|
|
||||||
override fun getDeclarationsByLabel(labelName: Name) = emptyList<DeclarationDescriptor>()
|
|
||||||
|
|
||||||
override fun getDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean) = descriptors
|
|
||||||
|
|
||||||
override fun getImplicitReceiversHierarchy() = emptyList<ReceiverParameterDescriptor>()
|
|
||||||
|
|
||||||
override fun getOwnDeclaredDescriptors() = emptyList<DeclarationDescriptor>()
|
|
||||||
|
|
||||||
override fun printScopeStructure(p: Printer) {
|
|
||||||
p.println(javaClass.getName())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+1
-1
@@ -59,7 +59,7 @@ object CreateConstructorFromDelegationCallActionFactory : JetSingleIntentionActi
|
|||||||
val parameters = delegationCall.getValueArguments().map {
|
val parameters = delegationCall.getValueArguments().map {
|
||||||
ParameterInfo(
|
ParameterInfo(
|
||||||
it.getArgumentExpression()?.let { TypeInfo(it, Variance.IN_VARIANCE) } ?: TypeInfo(anyType, Variance.IN_VARIANCE),
|
it.getArgumentExpression()?.let { TypeInfo(it, Variance.IN_VARIANCE) } ?: TypeInfo(anyType, Variance.IN_VARIANCE),
|
||||||
it.getArgumentName()?.getReferenceExpression()?.getReferencedName()
|
it.getArgumentName()?.asName?.asString()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -55,7 +55,7 @@ object CreateConstructorFromDelegatorToSuperCallActionFactory : JetSingleIntenti
|
|||||||
val parameters = delegationCall.getValueArguments().map {
|
val parameters = delegationCall.getValueArguments().map {
|
||||||
ParameterInfo(
|
ParameterInfo(
|
||||||
it.getArgumentExpression()?.let { TypeInfo(it, Variance.IN_VARIANCE) } ?: TypeInfo(anyType, Variance.IN_VARIANCE),
|
it.getArgumentExpression()?.let { TypeInfo(it, Variance.IN_VARIANCE) } ?: TypeInfo(anyType, Variance.IN_VARIANCE),
|
||||||
it.getArgumentName()?.getReferenceExpression()?.getReferencedName()
|
it.getArgumentName()?.asName?.asString()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -69,7 +69,7 @@ public object CreateClassFromCallWithConstructorCalleeActionFactory : JetSingleI
|
|||||||
val parameterInfos = valueArguments.map {
|
val parameterInfos = valueArguments.map {
|
||||||
ParameterInfo(
|
ParameterInfo(
|
||||||
it.getArgumentExpression()?.let { TypeInfo(it, Variance.IN_VARIANCE) } ?: TypeInfo(anyType, Variance.IN_VARIANCE),
|
it.getArgumentExpression()?.let { TypeInfo(it, Variance.IN_VARIANCE) } ?: TypeInfo(anyType, Variance.IN_VARIANCE),
|
||||||
it.getArgumentName()?.getReferenceExpression()?.getReferencedName() ?: defaultParamName
|
it.getArgumentName()?.asName?.asString() ?: defaultParamName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-6
@@ -293,7 +293,7 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
|
|||||||
assert arguments != null : "Argument list is expected: " + element.getText();
|
assert arguments != null : "Argument list is expected: " + element.getText();
|
||||||
List<? extends ValueArgument> oldArguments = element.getValueArguments();
|
List<? extends ValueArgument> oldArguments = element.getValueArguments();
|
||||||
|
|
||||||
boolean isNamedCall = oldArguments.size() > 1 && oldArguments.get(0).getArgumentName() != null;
|
boolean isNamedCall = oldArguments.size() > 1 && oldArguments.get(0).isNamed();
|
||||||
StringBuilder parametersBuilder = new StringBuilder("(");
|
StringBuilder parametersBuilder = new StringBuilder("(");
|
||||||
boolean isFirst = true;
|
boolean isFirst = true;
|
||||||
|
|
||||||
@@ -364,7 +364,7 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
|
|||||||
ValueArgument oldArgument = argumentMap.get(parameterInfo.getOldIndex());
|
ValueArgument oldArgument = argumentMap.get(parameterInfo.getOldIndex());
|
||||||
|
|
||||||
if (oldArgument != null) {
|
if (oldArgument != null) {
|
||||||
JetValueArgumentName argumentName = oldArgument.getArgumentName();
|
ValueArgumentName argumentName = oldArgument.getArgumentName();
|
||||||
JetSimpleNameExpression argumentNameExpression = argumentName != null ? argumentName.getReferenceExpression() : null;
|
JetSimpleNameExpression argumentNameExpression = argumentName != null ? argumentName.getReferenceExpression() : null;
|
||||||
changeArgumentName(argumentNameExpression, parameterInfo);
|
changeArgumentName(argumentNameExpression, parameterInfo);
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
@@ -457,9 +457,8 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
|
|||||||
|
|
||||||
for (int i = 0; i < oldArguments.size(); i++) {
|
for (int i = 0; i < oldArguments.size(); i++) {
|
||||||
ValueArgument argument = oldArguments.get(i);
|
ValueArgument argument = oldArguments.get(i);
|
||||||
JetValueArgumentName argumentName = argument.getArgumentName();
|
ValueArgumentName argumentName = argument.getArgumentName();
|
||||||
JetSimpleNameExpression argumentNameExpression = argumentName != null ? argumentName.getReferenceExpression() : null;
|
String oldParameterName = argumentName != null ? argumentName.getAsName().asString() : null;
|
||||||
String oldParameterName = argumentNameExpression != null ? argumentNameExpression.getReferencedName() : null;
|
|
||||||
|
|
||||||
if (oldParameterName != null) {
|
if (oldParameterName != null) {
|
||||||
Integer oldParameterIndex = changeInfo.getOldParameterIndex(oldParameterName);
|
Integer oldParameterIndex = changeInfo.getOldParameterIndex(oldParameterName);
|
||||||
@@ -476,7 +475,7 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
|
|||||||
|
|
||||||
private void changeArgumentNames(JetChangeInfo changeInfo, JetCallElement element) {
|
private void changeArgumentNames(JetChangeInfo changeInfo, JetCallElement element) {
|
||||||
for (ValueArgument argument : element.getValueArguments()) {
|
for (ValueArgument argument : element.getValueArguments()) {
|
||||||
JetValueArgumentName argumentName = argument.getArgumentName();
|
ValueArgumentName argumentName = argument.getArgumentName();
|
||||||
JetSimpleNameExpression argumentNameExpression = argumentName != null ? argumentName.getReferenceExpression() : null;
|
JetSimpleNameExpression argumentNameExpression = argumentName != null ? argumentName.getReferenceExpression() : null;
|
||||||
|
|
||||||
if (argumentNameExpression != null) {
|
if (argumentNameExpression != null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user