idea: cleanup code
This commit is contained in:
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core
|
||||
@@ -84,27 +73,43 @@ class ByExpectedTypeFilter(override val fuzzyType: FuzzyType) : ByTypeFilter {
|
||||
|
||||
data /* for copy() */
|
||||
class ExpectedInfo(
|
||||
val filter: ByTypeFilter,
|
||||
val expectedName: String?,
|
||||
val tail: Tail?,
|
||||
val itemOptions: ItemOptions = ItemOptions.DEFAULT,
|
||||
val additionalData: AdditionalData? = null
|
||||
val filter: ByTypeFilter,
|
||||
val expectedName: String?,
|
||||
val tail: Tail?,
|
||||
val itemOptions: ItemOptions = ItemOptions.DEFAULT,
|
||||
val additionalData: AdditionalData? = null
|
||||
) {
|
||||
// just a marker interface
|
||||
interface AdditionalData {}
|
||||
|
||||
constructor(fuzzyType: FuzzyType, expectedName: String?, tail: Tail?, itemOptions: ItemOptions = ItemOptions.DEFAULT, additionalData: AdditionalData? = null)
|
||||
: this(ByExpectedTypeFilter(fuzzyType), expectedName, tail, itemOptions, additionalData)
|
||||
constructor(
|
||||
fuzzyType: FuzzyType,
|
||||
expectedName: String?,
|
||||
tail: Tail?,
|
||||
itemOptions: ItemOptions = ItemOptions.DEFAULT,
|
||||
additionalData: AdditionalData? = null
|
||||
) : this(ByExpectedTypeFilter(fuzzyType), expectedName, tail, itemOptions, additionalData)
|
||||
|
||||
constructor(type: KotlinType, expectedName: String?, tail: Tail?, itemOptions: ItemOptions = ItemOptions.DEFAULT, additionalData: AdditionalData? = null)
|
||||
: this(type.toFuzzyType(emptyList()), expectedName, tail, itemOptions, additionalData)
|
||||
constructor(
|
||||
type: KotlinType,
|
||||
expectedName: String?,
|
||||
tail: Tail?,
|
||||
itemOptions: ItemOptions = ItemOptions.DEFAULT,
|
||||
additionalData: AdditionalData? = null
|
||||
) : this(type.toFuzzyType(emptyList()), expectedName, tail, itemOptions, additionalData)
|
||||
|
||||
fun matchingSubstitutor(descriptorType: FuzzyType): TypeSubstitutor? = filter.matchingSubstitutor(descriptorType)
|
||||
|
||||
fun matchingSubstitutor(descriptorType: KotlinType): TypeSubstitutor? = matchingSubstitutor(descriptorType.toFuzzyType(emptyList()))
|
||||
|
||||
companion object {
|
||||
fun createForArgument(type: KotlinType, expectedName: String?, tail: Tail?, argumentData: ArgumentPositionData, itemOptions: ItemOptions = ItemOptions.DEFAULT): ExpectedInfo {
|
||||
fun createForArgument(
|
||||
type: KotlinType,
|
||||
expectedName: String?,
|
||||
tail: Tail?,
|
||||
argumentData: ArgumentPositionData,
|
||||
itemOptions: ItemOptions = ItemOptions.DEFAULT
|
||||
): ExpectedInfo {
|
||||
return ExpectedInfo(type.toFuzzyType(argumentData.function.typeParameters), expectedName, tail, itemOptions, argumentData)
|
||||
}
|
||||
|
||||
@@ -127,11 +132,11 @@ val ExpectedInfo.multipleFuzzyTypes: Collection<FuzzyType>
|
||||
|
||||
sealed class ArgumentPositionData(val function: FunctionDescriptor, val callType: Call.CallType) : ExpectedInfo.AdditionalData {
|
||||
class Positional(
|
||||
function: FunctionDescriptor,
|
||||
callType: Call.CallType,
|
||||
val argumentIndex: Int,
|
||||
val isFunctionLiteralArgument: Boolean,
|
||||
val namedArgumentCandidates: Collection<ParameterDescriptor>
|
||||
function: FunctionDescriptor,
|
||||
callType: Call.CallType,
|
||||
val argumentIndex: Int,
|
||||
val isFunctionLiteralArgument: Boolean,
|
||||
val namedArgumentCandidates: Collection<ParameterDescriptor>
|
||||
) : ArgumentPositionData(function, callType)
|
||||
|
||||
class Named(function: FunctionDescriptor, callType: Call.CallType, val argumentName: Name) : ArgumentPositionData(function, callType)
|
||||
@@ -148,30 +153,30 @@ object PropertyDelegateAdditionalData : ExpectedInfo.AdditionalData
|
||||
class ComparisonOperandAdditionalData(val suppressNullLiteral: Boolean) : ExpectedInfo.AdditionalData
|
||||
|
||||
class ExpectedInfos(
|
||||
private val bindingContext: BindingContext,
|
||||
private val resolutionFacade: ResolutionFacade,
|
||||
private val indicesHelper: KotlinIndicesHelper?,
|
||||
private val useHeuristicSignatures: Boolean = true,
|
||||
private val useOuterCallsExpectedTypeCount: Int = 0
|
||||
private val bindingContext: BindingContext,
|
||||
private val resolutionFacade: ResolutionFacade,
|
||||
private val indicesHelper: KotlinIndicesHelper?,
|
||||
private val useHeuristicSignatures: Boolean = true,
|
||||
private val useOuterCallsExpectedTypeCount: Int = 0
|
||||
) {
|
||||
fun calculate(expressionWithType: KtExpression): Collection<ExpectedInfo> {
|
||||
val expectedInfos = calculateForArgument(expressionWithType)
|
||||
?: calculateForFunctionLiteralArgument(expressionWithType)
|
||||
?: calculateForIndexingArgument(expressionWithType)
|
||||
?: calculateForEqAndAssignment(expressionWithType)
|
||||
?: calculateForIf(expressionWithType)
|
||||
?: calculateForElvis(expressionWithType)
|
||||
?: calculateForBlockExpression(expressionWithType)
|
||||
?: calculateForWhenEntryValue(expressionWithType)
|
||||
?: calculateForExclOperand(expressionWithType)
|
||||
?: calculateForInitializer(expressionWithType)
|
||||
?: calculateForExpressionBody(expressionWithType)
|
||||
?: calculateForReturn(expressionWithType)
|
||||
?: calculateForLoopRange(expressionWithType)
|
||||
?: calculateForInOperatorArgument(expressionWithType)
|
||||
?: calculateForPropertyDelegate(expressionWithType)
|
||||
?: getFromBindingContext(expressionWithType)
|
||||
?: return emptyList()
|
||||
?: calculateForFunctionLiteralArgument(expressionWithType)
|
||||
?: calculateForIndexingArgument(expressionWithType)
|
||||
?: calculateForEqAndAssignment(expressionWithType)
|
||||
?: calculateForIf(expressionWithType)
|
||||
?: calculateForElvis(expressionWithType)
|
||||
?: calculateForBlockExpression(expressionWithType)
|
||||
?: calculateForWhenEntryValue(expressionWithType)
|
||||
?: calculateForExclOperand(expressionWithType)
|
||||
?: calculateForInitializer(expressionWithType)
|
||||
?: calculateForExpressionBody(expressionWithType)
|
||||
?: calculateForReturn(expressionWithType)
|
||||
?: calculateForLoopRange(expressionWithType)
|
||||
?: calculateForInOperatorArgument(expressionWithType)
|
||||
?: calculateForPropertyDelegate(expressionWithType)
|
||||
?: getFromBindingContext(expressionWithType)
|
||||
?: return emptyList()
|
||||
return expectedInfos.filterNot { it.fuzzyType?.type?.isError ?: false }
|
||||
}
|
||||
|
||||
@@ -212,21 +217,22 @@ class ExpectedInfos(
|
||||
fun makesSenseToUseOuterCallExpectedType(info: ExpectedInfo): Boolean {
|
||||
val data = info.additionalData as ArgumentPositionData
|
||||
return info.fuzzyType != null
|
||||
&& info.fuzzyType!!.freeParameters.isNotEmpty()
|
||||
&& data.function.fuzzyReturnType()?.freeParameters?.isNotEmpty() ?: false
|
||||
&& info.fuzzyType!!.freeParameters.isNotEmpty()
|
||||
&& data.function.fuzzyReturnType()?.freeParameters?.isNotEmpty() ?: false
|
||||
}
|
||||
|
||||
if (useOuterCallsExpectedTypeCount > 0 && results.any(::makesSenseToUseOuterCallExpectedType)) {
|
||||
val callExpression = (call.callElement as? KtExpression)?.getQualifiedExpressionForSelectorOrThis() ?: return results
|
||||
val expectedFuzzyTypes = ExpectedInfos(bindingContext, resolutionFacade, indicesHelper, useHeuristicSignatures, useOuterCallsExpectedTypeCount - 1)
|
||||
val expectedFuzzyTypes =
|
||||
ExpectedInfos(bindingContext, resolutionFacade, indicesHelper, useHeuristicSignatures, useOuterCallsExpectedTypeCount - 1)
|
||||
.calculate(callExpression)
|
||||
.mapNotNull { it.fuzzyType }
|
||||
if (expectedFuzzyTypes.isEmpty() || expectedFuzzyTypes.any { it.freeParameters.isNotEmpty() }) return results
|
||||
|
||||
return expectedFuzzyTypes
|
||||
.map { it.type }
|
||||
.toSet()
|
||||
.flatMap { calculateForArgument(call, it, argument) }
|
||||
.map { it.type }
|
||||
.toSet()
|
||||
.flatMap { calculateForArgument(call, it, argument) }
|
||||
}
|
||||
|
||||
return results
|
||||
@@ -239,7 +245,8 @@ class ExpectedInfos(
|
||||
|
||||
val argumentIndex = call.valueArguments.indexOf(argument)
|
||||
assert(argumentIndex >= 0) {
|
||||
"Could not find argument '$argument(${argument.asElement().text})' among arguments of call: $call. Call element text: '${call.callElement.text}'"
|
||||
"Could not find argument '$argument(${argument.asElement()
|
||||
.text})' among arguments of call: $call. Call element text: '${call.callElement.text}'"
|
||||
}
|
||||
|
||||
// leave only arguments before the current one
|
||||
@@ -269,11 +276,11 @@ class ExpectedInfos(
|
||||
}
|
||||
|
||||
private fun MutableCollection<ExpectedInfo>.addExpectedInfoForCandidate(
|
||||
candidate: ResolvedCall<FunctionDescriptor>,
|
||||
call: Call,
|
||||
argument: ValueArgument,
|
||||
argumentIndex: Int,
|
||||
checkPrevArgumentsMatched: Boolean
|
||||
candidate: ResolvedCall<FunctionDescriptor>,
|
||||
call: Call,
|
||||
argument: ValueArgument,
|
||||
argumentIndex: Int,
|
||||
checkPrevArgumentsMatched: Boolean
|
||||
) {
|
||||
// check that all arguments before the current has mappings to parameters
|
||||
if (!candidate.allArgumentsMapped()) return
|
||||
@@ -304,13 +311,11 @@ class ExpectedInfos(
|
||||
|
||||
val argumentPositionData = if (argumentName != null) {
|
||||
ArgumentPositionData.Named(descriptor, callType, argumentName)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
val namedArgumentCandidates = if (!isFunctionLiteralArgument && !isArrayAccess && descriptor.hasStableParameterNames()) {
|
||||
val usedParameters = argumentToParameter.filter { it.key != argument }.map { it.value }.toSet()
|
||||
descriptor.valueParameters.filter { it !in usedParameters }
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
ArgumentPositionData.Positional(descriptor, callType, argumentIndex, isFunctionLiteralArgument, namedArgumentCandidates)
|
||||
@@ -349,8 +354,7 @@ class ExpectedInfos(
|
||||
parameters.dropWhile { it != parameter }.drop(1).any(::needCommaForParameter) -> Tail.COMMA
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
namedArgumentTail(argumentToParameter, argumentName, descriptor)
|
||||
}
|
||||
|
||||
@@ -371,16 +375,14 @@ class ExpectedInfos(
|
||||
|
||||
val starOptions = if (!alreadyHasStar) ItemOptions.STAR_PREFIX else ItemOptions.DEFAULT
|
||||
add(ExpectedInfo.createForArgument(parameterType, expectedName, varargTail, argumentPositionData, starOptions))
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (alreadyHasStar) return
|
||||
|
||||
if (isFunctionLiteralArgument) {
|
||||
if (parameterType.isFunctionOrSuspendFunctionType) {
|
||||
add(ExpectedInfo.createForArgument(parameterType, expectedName, null, argumentPositionData))
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
add(ExpectedInfo.createForArgument(parameterType, expectedName, tail, argumentPositionData))
|
||||
}
|
||||
}
|
||||
@@ -395,13 +397,16 @@ class ExpectedInfos(
|
||||
return substitutedType.replace(newTypeArguments)
|
||||
}
|
||||
|
||||
private fun <D : CallableDescriptor> ResolvedCall<D>.allArgumentsMatched()
|
||||
= call.valueArguments.none { argument -> getArgumentMapping(argument).isError() && !argument.hasError() /* ignore arguments that has error type */ }
|
||||
private fun <D : CallableDescriptor> ResolvedCall<D>.allArgumentsMatched() = call.valueArguments
|
||||
.none { argument -> getArgumentMapping(argument).isError() && !argument.hasError() /* ignore arguments that has error type */ }
|
||||
|
||||
private fun ValueArgument.hasError()
|
||||
= getArgumentExpression()?.let { bindingContext.getType(it) }?.isError ?: true
|
||||
private fun ValueArgument.hasError() = getArgumentExpression()?.let { bindingContext.getType(it) }?.isError ?: true
|
||||
|
||||
private fun namedArgumentTail(argumentToParameter: Map<ValueArgument, ValueParameterDescriptor>, argumentName: Name, descriptor: FunctionDescriptor): Tail? {
|
||||
private fun namedArgumentTail(
|
||||
argumentToParameter: Map<ValueArgument, ValueParameterDescriptor>,
|
||||
argumentName: Name,
|
||||
descriptor: FunctionDescriptor
|
||||
): Tail? {
|
||||
val usedParameterNames = (argumentToParameter.values.map { it.name } + listOf(argumentName)).toSet()
|
||||
val notUsedParameters = descriptor.valueParameters.filter { it.name !in usedParameterNames }
|
||||
return when {
|
||||
@@ -429,7 +434,8 @@ class ExpectedInfos(
|
||||
var additionalData: ExpectedInfo.AdditionalData? = null
|
||||
if (operationToken in COMPARISON_TOKENS) {
|
||||
// if we complete argument of == or !=, make types in expected info's nullable to allow items of nullable type too
|
||||
additionalData = ComparisonOperandAdditionalData(suppressNullLiteral = expectedType.nullability() == TypeNullability.NOT_NULL)
|
||||
additionalData =
|
||||
ComparisonOperandAdditionalData(suppressNullLiteral = expectedType.nullability() == TypeNullability.NOT_NULL)
|
||||
expectedType = expectedType.makeNullable()
|
||||
}
|
||||
|
||||
@@ -441,14 +447,21 @@ class ExpectedInfos(
|
||||
}
|
||||
|
||||
private object NullableTypesFilter : ByTypeFilter {
|
||||
override fun matchingSubstitutor(descriptorType: FuzzyType)
|
||||
= if (descriptorType.type.nullability() != TypeNullability.NOT_NULL) TypeSubstitutor.EMPTY else null
|
||||
override fun matchingSubstitutor(descriptorType: FuzzyType) =
|
||||
if (descriptorType.type.nullability() != TypeNullability.NOT_NULL) TypeSubstitutor.EMPTY else null
|
||||
}
|
||||
|
||||
private fun calculateForIf(expressionWithType: KtExpression): Collection<ExpectedInfo>? {
|
||||
val ifExpression = (expressionWithType.parent as? KtContainerNode)?.parent as? KtIfExpression ?: return null
|
||||
when (expressionWithType) {
|
||||
ifExpression.condition -> return listOf(ExpectedInfo(resolutionFacade.moduleDescriptor.builtIns.booleanType, null, Tail.RPARENTH, additionalData = IfConditionAdditionalData))
|
||||
ifExpression.condition -> return listOf(
|
||||
ExpectedInfo(
|
||||
resolutionFacade.moduleDescriptor.builtIns.booleanType,
|
||||
null,
|
||||
Tail.RPARENTH,
|
||||
additionalData = IfConditionAdditionalData
|
||||
)
|
||||
)
|
||||
|
||||
ifExpression.then -> return calculate(ifExpression).map { ExpectedInfo(it.filter, it.expectedName, Tail.ELSE) }
|
||||
|
||||
@@ -462,8 +475,7 @@ class ExpectedInfos(
|
||||
else
|
||||
ifExpectedInfos
|
||||
return filteredInfo.copyWithNoAdditionalData()
|
||||
}
|
||||
else if (thenType != null) {
|
||||
} else if (thenType != null) {
|
||||
return listOf(ExpectedInfo(thenType, null, null))
|
||||
}
|
||||
}
|
||||
@@ -487,8 +499,7 @@ class ExpectedInfos(
|
||||
else
|
||||
expectedInfos
|
||||
return filteredInfo.copyWithNoAdditionalData()
|
||||
}
|
||||
else if (leftTypeNotNullable != null) {
|
||||
} else if (leftTypeNotNullable != null) {
|
||||
return listOf(ExpectedInfo(leftTypeNotNullable, null, null))
|
||||
}
|
||||
}
|
||||
@@ -504,14 +515,13 @@ class ExpectedInfos(
|
||||
return if (functionLiteral != null) {
|
||||
val literalExpression = functionLiteral.parent as KtLambdaExpression
|
||||
calculate(literalExpression)
|
||||
.mapNotNull { it.fuzzyType }
|
||||
.filter { it.type.isFunctionOrSuspendFunctionType }
|
||||
.map {
|
||||
val returnType = it.type.getReturnTypeFromFunctionType()
|
||||
ExpectedInfo(returnType.toFuzzyType(it.freeParameters), null, Tail.RBRACE)
|
||||
}
|
||||
}
|
||||
else {
|
||||
.mapNotNull { it.fuzzyType }
|
||||
.filter { it.type.isFunctionOrSuspendFunctionType }
|
||||
.map {
|
||||
val returnType = it.type.getReturnTypeFromFunctionType()
|
||||
ExpectedInfo(returnType.toFuzzyType(it.freeParameters), null, Tail.RBRACE)
|
||||
}
|
||||
} else {
|
||||
calculate(block).map { ExpectedInfo(it.filter, it.expectedName, null) }
|
||||
}
|
||||
}
|
||||
@@ -524,9 +534,15 @@ class ExpectedInfos(
|
||||
if (subject != null) {
|
||||
val subjectType = bindingContext.getType(subject) ?: return null
|
||||
return listOf(ExpectedInfo(subjectType, null, null, additionalData = WhenEntryAdditionalData(whenWithSubject = true)))
|
||||
}
|
||||
else {
|
||||
return listOf(ExpectedInfo(resolutionFacade.moduleDescriptor.builtIns.booleanType, null, null, additionalData = WhenEntryAdditionalData(whenWithSubject = false)))
|
||||
} else {
|
||||
return listOf(
|
||||
ExpectedInfo(
|
||||
resolutionFacade.moduleDescriptor.builtIns.booleanType,
|
||||
null,
|
||||
null,
|
||||
additionalData = WhenEntryAdditionalData(whenWithSubject = false)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -585,8 +601,7 @@ class ExpectedInfos(
|
||||
}
|
||||
|
||||
private fun calculateForLoopRange(expressionWithType: KtExpression): Collection<ExpectedInfo>? {
|
||||
val forExpression = (expressionWithType.parent as? KtContainerNode)
|
||||
?.parent as? KtForExpression ?: return null
|
||||
val forExpression = (expressionWithType.parent as? KtContainerNode)?.parent as? KtForExpression ?: return null
|
||||
if (expressionWithType != forExpression.loopRange) return null
|
||||
|
||||
val loopVar = forExpression.loopParameter
|
||||
@@ -630,11 +645,12 @@ class ExpectedInfos(
|
||||
|
||||
val scope = expressionWithType.getResolutionScope(bindingContext, resolutionFacade)
|
||||
val propertyOwnerType = property.fuzzyExtensionReceiverType()
|
||||
?: property.dispatchReceiverParameter?.type?.toFuzzyType(emptyList())
|
||||
?: property.builtIns.nullableNothingType.toFuzzyType(emptyList())
|
||||
?: property.dispatchReceiverParameter?.type?.toFuzzyType(emptyList())
|
||||
?: property.builtIns.nullableNothingType.toFuzzyType(emptyList())
|
||||
|
||||
val explicitPropertyType = property.fuzzyReturnType()?.takeIf { propertyDeclaration.typeReference != null }
|
||||
?: property.overriddenDescriptors.singleOrNull()?.fuzzyReturnType() // for override properties use super property type as explicit (if not specified)
|
||||
?: property.overriddenDescriptors.singleOrNull()
|
||||
?.fuzzyReturnType() // for override properties use super property type as explicit (if not specified)
|
||||
val typesWithGetDetector = TypesWithGetValueDetector(scope, indicesHelper, propertyOwnerType, explicitPropertyType)
|
||||
val typesWithSetDetector = if (property.isVar) TypesWithSetValueDetector(scope, indicesHelper, propertyOwnerType) else null
|
||||
|
||||
@@ -644,15 +660,16 @@ class ExpectedInfos(
|
||||
|
||||
if (typesWithSetDetector == null) return getOperatorSubstitutor
|
||||
|
||||
val substitutedType = getOperatorSubstitutor.substitute(descriptorType.type, Variance.INVARIANT)!!.toFuzzyType(descriptorType.freeParameters)
|
||||
val substitutedType =
|
||||
getOperatorSubstitutor.substitute(descriptorType.type, Variance.INVARIANT)!!.toFuzzyType(descriptorType.freeParameters)
|
||||
|
||||
val (setValueOperator, setOperatorSubstitutor) = typesWithSetDetector.findOperator(substitutedType) ?: return null
|
||||
val propertyType = explicitPropertyType ?: getValueOperator.fuzzyReturnType()!!
|
||||
val setParamType = setValueOperator.valueParameters.last().type.toFuzzyType(setValueOperator.typeParameters)
|
||||
val setParamTypeSubstitutor = setParamType.checkIsSuperTypeOf(propertyType) ?: return null
|
||||
return getOperatorSubstitutor
|
||||
.combineIfNoConflicts(setOperatorSubstitutor, descriptorType.freeParameters)
|
||||
?.combineIfNoConflicts(setParamTypeSubstitutor, descriptorType.freeParameters)
|
||||
.combineIfNoConflicts(setOperatorSubstitutor, descriptorType.freeParameters)
|
||||
?.combineIfNoConflicts(setParamTypeSubstitutor, descriptorType.freeParameters)
|
||||
}
|
||||
|
||||
override val multipleFuzzyTypes: Collection<FuzzyType> by lazy {
|
||||
@@ -692,10 +709,11 @@ class ExpectedInfos(
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.unpluralize()
|
||||
= StringUtil.unpluralize(this)
|
||||
private fun String.unpluralize() = StringUtil.unpluralize(this)
|
||||
|
||||
private fun Collection<ExpectedInfo>.copyWithNoAdditionalData() = map { it.copy(additionalData = null, itemOptions = ItemOptions.DEFAULT) }
|
||||
private fun Collection<ExpectedInfo>.copyWithNoAdditionalData() = map {
|
||||
it.copy(additionalData = null, itemOptions = ItemOptions.DEFAULT)
|
||||
}
|
||||
}
|
||||
|
||||
val COMPARISON_TOKENS = setOf(KtTokens.EQEQ, KtTokens.EXCLEQ, KtTokens.EQEQEQ, KtTokens.EXCLEQEQEQ)
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core
|
||||
@@ -41,7 +30,7 @@ class ImportableFqNameClassifier(private val file: KtFile) {
|
||||
preciseImportPackages.add(fqName.parent())
|
||||
}
|
||||
else -> excludedImports.add(fqName)
|
||||
// TODO: support aliased imports in completion
|
||||
// TODO: support aliased imports in completion
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,5 +79,5 @@ class ImportableFqNameClassifier(private val file: KtFile) {
|
||||
private fun hasPreciseImportFromPackage(packageName: FqName) = packageName in preciseImportPackages
|
||||
}
|
||||
|
||||
fun isJavaClassNotToBeUsedInKotlin(fqName: FqName): Boolean
|
||||
= JavaToKotlinClassMap.isJavaPlatformClass(fqName) || JavaAnnotationMapper.javaToKotlinNameMap[fqName] != null
|
||||
fun isJavaClassNotToBeUsedInKotlin(fqName: FqName): Boolean =
|
||||
JavaToKotlinClassMap.isJavaPlatformClass(fqName) || JavaAnnotationMapper.javaToKotlinNameMap[fqName] != null
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core
|
||||
@@ -40,10 +29,10 @@ import org.jetbrains.kotlin.utils.getOrPutNullable
|
||||
import java.util.*
|
||||
|
||||
class IterableTypesDetection(
|
||||
private val project: Project,
|
||||
private val forLoopConventionsChecker: ForLoopConventionsChecker,
|
||||
private val languageVersionSettings: LanguageVersionSettings,
|
||||
private val dataFlowValueFactory: DataFlowValueFactory
|
||||
private val project: Project,
|
||||
private val forLoopConventionsChecker: ForLoopConventionsChecker,
|
||||
private val languageVersionSettings: LanguageVersionSettings,
|
||||
private val dataFlowValueFactory: DataFlowValueFactory
|
||||
) {
|
||||
companion object {
|
||||
private val iteratorName = Name.identifier("iterator")
|
||||
@@ -52,28 +41,28 @@ class IterableTypesDetection(
|
||||
fun createDetector(scope: LexicalScope): IterableTypesDetector {
|
||||
return Detector(scope)
|
||||
}
|
||||
private inner class Detector(private val scope: LexicalScope): IterableTypesDetector {
|
||||
|
||||
private inner class Detector(private val scope: LexicalScope) : IterableTypesDetector {
|
||||
private val cache = HashMap<FuzzyType, FuzzyType?>()
|
||||
|
||||
private val typesWithExtensionIterator: Collection<KotlinType> = scope
|
||||
.collectFunctions(iteratorName, NoLookupLocation.FROM_IDE)
|
||||
.filter { it.isValidOperator() }
|
||||
.mapNotNull { it.extensionReceiverParameter?.type }
|
||||
.collectFunctions(iteratorName, NoLookupLocation.FROM_IDE)
|
||||
.filter { it.isValidOperator() }
|
||||
.mapNotNull { it.extensionReceiverParameter?.type }
|
||||
|
||||
override fun isIterable(type: FuzzyType, loopVarType: KotlinType?): Boolean {
|
||||
val elementType = elementType(type) ?: return false
|
||||
return loopVarType == null || elementType.checkIsSubtypeOf(loopVarType) != null
|
||||
}
|
||||
|
||||
override fun isIterable(type: KotlinType, loopVarType: KotlinType?): Boolean
|
||||
= isIterable(type.toFuzzyType(emptyList()), loopVarType)
|
||||
override fun isIterable(type: KotlinType, loopVarType: KotlinType?): Boolean =
|
||||
isIterable(type.toFuzzyType(emptyList()), loopVarType)
|
||||
|
||||
private fun elementType(type: FuzzyType): FuzzyType? {
|
||||
return cache.getOrPutNullable(type, { elementTypeNoCache(type) })
|
||||
}
|
||||
|
||||
override fun elementType(type: KotlinType): FuzzyType?
|
||||
= elementType(type.toFuzzyType(emptyList()))
|
||||
override fun elementType(type: KotlinType): FuzzyType? = elementType(type.toFuzzyType(emptyList()))
|
||||
|
||||
private fun elementTypeNoCache(type: FuzzyType): FuzzyType? {
|
||||
// optimization
|
||||
@@ -81,7 +70,8 @@ class IterableTypesDetection(
|
||||
|
||||
val expression = KtPsiFactory(project).createExpression("fake")
|
||||
val context = ExpressionTypingContext.newContext(
|
||||
BindingTraceContext(), scope, DataFlowInfo.EMPTY, TypeUtils.NO_EXPECTED_TYPE, languageVersionSettings, dataFlowValueFactory)
|
||||
BindingTraceContext(), scope, DataFlowInfo.EMPTY, TypeUtils.NO_EXPECTED_TYPE, languageVersionSettings, dataFlowValueFactory
|
||||
)
|
||||
val expressionReceiver = ExpressionReceiver.create(expression, type.type, context.trace.bindingContext)
|
||||
val elementType = forLoopConventionsChecker.checkIterableConvention(expressionReceiver, context)
|
||||
return elementType?.let { it.toFuzzyType(type.freeParameters) }
|
||||
@@ -90,10 +80,10 @@ class IterableTypesDetection(
|
||||
private fun canBeIterable(type: FuzzyType): Boolean {
|
||||
if (type.type.constructor is IntegerLiteralTypeConstructor) return false
|
||||
return type.type.memberScope.getContributedFunctions(iteratorName, NoLookupLocation.FROM_IDE).isNotEmpty() ||
|
||||
typesWithExtensionIterator.any {
|
||||
val freeParams = it.arguments.mapNotNull { it.type.constructor.declarationDescriptor as? TypeParameterDescriptor }
|
||||
type.checkIsSubtypeOf(it.toFuzzyType(freeParams)) != null
|
||||
}
|
||||
typesWithExtensionIterator.any {
|
||||
val freeParams = it.arguments.mapNotNull { it.type.constructor.declarationDescriptor as? TypeParameterDescriptor }
|
||||
type.checkIsSubtypeOf(it.toFuzzyType(freeParams)) != null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core
|
||||
@@ -37,13 +26,16 @@ import org.jetbrains.kotlin.utils.SmartList
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
|
||||
class KotlinNameSuggestionProvider : NameSuggestionProvider {
|
||||
override fun getSuggestedNames(element: PsiElement, nameSuggestionContext: PsiElement?, result: MutableSet<String>): SuggestedNameInfo? {
|
||||
override fun getSuggestedNames(
|
||||
element: PsiElement,
|
||||
nameSuggestionContext: PsiElement?,
|
||||
result: MutableSet<String>
|
||||
): SuggestedNameInfo? {
|
||||
if (element is KtCallableDeclaration) {
|
||||
val context = nameSuggestionContext ?: element.parent
|
||||
val target = if (element is KtProperty || element is KtParameter) {
|
||||
NewDeclarationNameValidator.Target.VARIABLES
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
NewDeclarationNameValidator.Target.FUNCTIONS_AND_CLASSES
|
||||
}
|
||||
val validator = NewDeclarationNameValidator(context, element, target, listOf(element))
|
||||
@@ -76,10 +68,10 @@ class KotlinNameSuggestionProvider : NameSuggestionProvider {
|
||||
override fun nameChosen(name: String?) {
|
||||
val psiVariable = element.toLightElements().firstIsInstanceOrNull<PsiVariable>() ?: return
|
||||
JavaStatisticsManager.incVariableNameUseCount(
|
||||
name,
|
||||
JavaCodeStyleManager.getInstance(element.project).getVariableKind(psiVariable),
|
||||
psiVariable.name,
|
||||
psiVariable.type
|
||||
name,
|
||||
JavaCodeStyleManager.getInstance(element.project).getVariableKind(psiVariable),
|
||||
psiVariable.name,
|
||||
psiVariable.type
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core
|
||||
@@ -42,9 +31,9 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import java.util.*
|
||||
|
||||
class CollectingNameValidator @JvmOverloads constructor(
|
||||
existingNames: Collection<String> = Collections.emptySet(),
|
||||
private val filter: (String) -> Boolean = { true }
|
||||
): (String) -> Boolean {
|
||||
existingNames: Collection<String> = Collections.emptySet(),
|
||||
private val filter: (String) -> Boolean = { true }
|
||||
) : (String) -> Boolean {
|
||||
private val existingNames = HashSet(existingNames)
|
||||
|
||||
override fun invoke(name: String): Boolean {
|
||||
@@ -61,20 +50,22 @@ class CollectingNameValidator @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
class NewDeclarationNameValidator(
|
||||
private val visibleDeclarationsContext: KtElement?,
|
||||
private val checkDeclarationsIn: Sequence<PsiElement>,
|
||||
private val target: Target,
|
||||
private val excludedDeclarations: List<KtDeclaration> = emptyList()
|
||||
private val visibleDeclarationsContext: KtElement?,
|
||||
private val checkDeclarationsIn: Sequence<PsiElement>,
|
||||
private val target: Target,
|
||||
private val excludedDeclarations: List<KtDeclaration> = emptyList()
|
||||
) : (String) -> Boolean {
|
||||
constructor(container: PsiElement,
|
||||
anchor: PsiElement?,
|
||||
target: Target,
|
||||
excludedDeclarations: List<KtDeclaration> = emptyList())
|
||||
: this(
|
||||
(anchor ?: container).parentsWithSelf.firstIsInstanceOrNull<KtElement>(),
|
||||
anchor?.siblings() ?: container.allChildren,
|
||||
target,
|
||||
excludedDeclarations)
|
||||
constructor(
|
||||
container: PsiElement,
|
||||
anchor: PsiElement?,
|
||||
target: Target,
|
||||
excludedDeclarations: List<KtDeclaration> = emptyList()
|
||||
) : this(
|
||||
(anchor ?: container).parentsWithSelf.firstIsInstanceOrNull<KtElement>(),
|
||||
anchor?.siblings() ?: container.allChildren,
|
||||
target,
|
||||
excludedDeclarations
|
||||
)
|
||||
|
||||
enum class Target {
|
||||
VARIABLES,
|
||||
@@ -86,7 +77,8 @@ class NewDeclarationNameValidator(
|
||||
|
||||
if (visibleDeclarationsContext != null) {
|
||||
val bindingContext = visibleDeclarationsContext.analyze(BodyResolveMode.PARTIAL_FOR_COMPLETION)
|
||||
val resolutionScope = visibleDeclarationsContext.getResolutionScope(bindingContext, visibleDeclarationsContext.getResolutionFacade())
|
||||
val resolutionScope =
|
||||
visibleDeclarationsContext.getResolutionScope(bindingContext, visibleDeclarationsContext.getResolutionFacade())
|
||||
if (resolutionScope.hasConflict(identifier)) return false
|
||||
}
|
||||
|
||||
@@ -105,12 +97,12 @@ class NewDeclarationNameValidator(
|
||||
}
|
||||
}
|
||||
|
||||
return when(target) {
|
||||
return when (target) {
|
||||
Target.VARIABLES ->
|
||||
getAllAccessibleVariables(name).any { !it.isExtension && it.isVisible() && !isExcluded(it) }
|
||||
Target.FUNCTIONS_AND_CLASSES ->
|
||||
getAllAccessibleFunctions(name).any { !it.isExtension && it.isVisible() && !isExcluded(it) } ||
|
||||
findClassifier(name, NoLookupLocation.FROM_IDE)?.let { it.isVisible() && !isExcluded(it) } ?: false
|
||||
findClassifier(name, NoLookupLocation.FROM_IDE)?.let { it.isVisible() && !isExcluded(it) } ?: false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +110,7 @@ class NewDeclarationNameValidator(
|
||||
if (this in excludedDeclarations) return false
|
||||
if (nameAsName != name) return false
|
||||
if (this is KtCallableDeclaration && receiverTypeReference != null) return false
|
||||
return when(target) {
|
||||
return when (target) {
|
||||
Target.VARIABLES -> this is KtVariableDeclaration || this is KtParameter
|
||||
Target.FUNCTIONS_AND_CLASSES -> this is KtNamedFunction || this is KtClassOrObject || this is KtTypeAlias
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core
|
||||
@@ -30,7 +19,6 @@ interface NotPropertiesService {
|
||||
return ServiceManager.getService(project, NotPropertiesService::class.java)
|
||||
}
|
||||
|
||||
fun getNotProperties(element: PsiElement) =
|
||||
getInstance(element.project).getNotProperties(element)
|
||||
fun getNotProperties(element: PsiElement) = getInstance(element.project).getNotProperties(element)
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core
|
||||
@@ -39,16 +28,16 @@ import java.util.*
|
||||
|
||||
object OptionalParametersHelper {
|
||||
fun detectArgumentsToDropForDefaults(
|
||||
resolvedCall: ResolvedCall<out CallableDescriptor>,
|
||||
project: Project,
|
||||
canDrop: (ValueArgument) -> Boolean = { true }
|
||||
resolvedCall: ResolvedCall<out CallableDescriptor>,
|
||||
project: Project,
|
||||
canDrop: (ValueArgument) -> Boolean = { true }
|
||||
): Collection<ValueArgument> {
|
||||
if (!resolvedCall.isReallySuccess()) return emptyList()
|
||||
val descriptor = resolvedCall.resultingDescriptor
|
||||
|
||||
val parameterToDefaultValue = descriptor.valueParameters
|
||||
.mapNotNull { parameter -> defaultParameterValue(parameter, project)?.let { parameter to it } }
|
||||
.toMap()
|
||||
.mapNotNull { parameter -> defaultParameterValue(parameter, project)?.let { parameter to it } }
|
||||
.toMap()
|
||||
if (parameterToDefaultValue.isEmpty()) return emptyList()
|
||||
|
||||
//TODO: drop functional literal out of parenthesis too
|
||||
@@ -65,7 +54,10 @@ object OptionalParametersHelper {
|
||||
return argumentsToDrop
|
||||
}
|
||||
|
||||
private fun ValueArgument.matchesDefault(resolvedCall: ResolvedCall<out CallableDescriptor>, parameterToDefaultValue: Map<ValueParameterDescriptor, DefaultValue>): Boolean {
|
||||
private fun ValueArgument.matchesDefault(
|
||||
resolvedCall: ResolvedCall<out CallableDescriptor>,
|
||||
parameterToDefaultValue: Map<ValueParameterDescriptor, DefaultValue>
|
||||
): Boolean {
|
||||
val parameter = resolvedCall.getParameterForArgument(this) ?: return false
|
||||
val defaultValue = parameterToDefaultValue[parameter] ?: return false
|
||||
val expression = defaultValue.substituteArguments(resolvedCall)
|
||||
@@ -110,8 +102,8 @@ object OptionalParametersHelper {
|
||||
}
|
||||
|
||||
data class DefaultValue(
|
||||
val expression: KtExpression,
|
||||
val parameterUsages: Map<ValueParameterDescriptor, Collection<KtExpression>>
|
||||
val expression: KtExpression,
|
||||
val parameterUsages: Map<ValueParameterDescriptor, Collection<KtExpression>>
|
||||
)
|
||||
|
||||
fun defaultParameterValueExpression(parameter: ValueParameterDescriptor, project: Project): KtExpression? {
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core
|
||||
@@ -39,19 +28,20 @@ import org.jetbrains.kotlin.util.javaslang.component2
|
||||
import java.util.*
|
||||
|
||||
class SmartCastCalculator(
|
||||
val bindingContext: BindingContext,
|
||||
val containingDeclarationOrModule: DeclarationDescriptor,
|
||||
contextElement: PsiElement,
|
||||
receiver: KtExpression?,
|
||||
resolutionFacade: ResolutionFacade
|
||||
val bindingContext: BindingContext,
|
||||
val containingDeclarationOrModule: DeclarationDescriptor,
|
||||
contextElement: PsiElement,
|
||||
receiver: KtExpression?,
|
||||
resolutionFacade: ResolutionFacade
|
||||
) {
|
||||
private val dataFlowValueFactory = resolutionFacade.frontendService<DataFlowValueFactory>()
|
||||
|
||||
// keys are VariableDescriptor's and ThisReceiver's
|
||||
private val entityToSmartCastInfo: Map<Any, SmartCastInfo> = processDataFlowInfo(
|
||||
bindingContext.getDataFlowInfoBefore(contextElement),
|
||||
contextElement.getResolutionScope(bindingContext, resolutionFacade),
|
||||
receiver)
|
||||
bindingContext.getDataFlowInfoBefore(contextElement),
|
||||
contextElement.getResolutionScope(bindingContext, resolutionFacade),
|
||||
receiver
|
||||
)
|
||||
|
||||
fun types(descriptor: VariableDescriptor): Collection<KotlinType> {
|
||||
val type = descriptor.returnType ?: return emptyList()
|
||||
@@ -80,27 +70,28 @@ class SmartCastCalculator(
|
||||
constructor() : this(emptyList(), false)
|
||||
}
|
||||
|
||||
private fun processDataFlowInfo(dataFlowInfo: DataFlowInfo, resolutionScope: LexicalScope?, receiver: KtExpression?): Map<Any, SmartCastInfo> {
|
||||
private fun processDataFlowInfo(
|
||||
dataFlowInfo: DataFlowInfo,
|
||||
resolutionScope: LexicalScope?,
|
||||
receiver: KtExpression?
|
||||
): Map<Any, SmartCastInfo> {
|
||||
if (dataFlowInfo == DataFlowInfo.EMPTY) return emptyMap()
|
||||
|
||||
val dataFlowValueToEntity: (DataFlowValue) -> Any?
|
||||
if (receiver != null) {
|
||||
val receiverType = bindingContext.getType(receiver) ?: return emptyMap()
|
||||
val receiverIdentifierInfo = dataFlowValueFactory.createDataFlowValue(
|
||||
receiver, receiverType, bindingContext, containingDeclarationOrModule
|
||||
receiver, receiverType, bindingContext, containingDeclarationOrModule
|
||||
).identifierInfo
|
||||
dataFlowValueToEntity = { value ->
|
||||
val identifierInfo = value.identifierInfo
|
||||
if (identifierInfo is IdentifierInfo.Qualified && identifierInfo.receiverInfo == receiverIdentifierInfo) {
|
||||
(identifierInfo.selectorInfo as? IdentifierInfo.Variable)?.variable
|
||||
}
|
||||
else null
|
||||
} else null
|
||||
}
|
||||
}
|
||||
else {
|
||||
dataFlowValueToEntity = fun (value: DataFlowValue): Any? {
|
||||
val identifierInfo = value.identifierInfo
|
||||
when(identifierInfo) {
|
||||
} else {
|
||||
dataFlowValueToEntity = fun(value: DataFlowValue): Any? {
|
||||
when (val identifierInfo = value.identifierInfo) {
|
||||
is IdentifierInfo.Variable -> return identifierInfo.variable
|
||||
is IdentifierInfo.Receiver -> return identifierInfo.value as? ImplicitReceiver
|
||||
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core
|
||||
@@ -33,11 +22,14 @@ import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.util.*
|
||||
|
||||
abstract class TypesWithOperatorDetector(
|
||||
private val name: Name,
|
||||
private val scope: LexicalScope,
|
||||
private val indicesHelper: KotlinIndicesHelper?
|
||||
private val name: Name,
|
||||
private val scope: LexicalScope,
|
||||
private val indicesHelper: KotlinIndicesHelper?
|
||||
) {
|
||||
protected abstract fun checkIsSuitableByType(operator: FunctionDescriptor, freeTypeParams: Collection<TypeParameterDescriptor>): TypeSubstitutor?
|
||||
protected abstract fun checkIsSuitableByType(
|
||||
operator: FunctionDescriptor,
|
||||
freeTypeParams: Collection<TypeParameterDescriptor>
|
||||
): TypeSubstitutor?
|
||||
|
||||
private val cache = HashMap<FuzzyType, Pair<FunctionDescriptor, TypeSubstitutor>?>()
|
||||
|
||||
@@ -45,8 +37,8 @@ abstract class TypesWithOperatorDetector(
|
||||
val result = ArrayList<FunctionDescriptor>()
|
||||
|
||||
val extensionsFromScope = scope
|
||||
.collectFunctions(name, NoLookupLocation.FROM_IDE)
|
||||
.filter { it.extensionReceiverParameter != null }
|
||||
.collectFunctions(name, NoLookupLocation.FROM_IDE)
|
||||
.filter { it.extensionReceiverParameter != null }
|
||||
result.addSuitableOperators(extensionsFromScope)
|
||||
|
||||
indicesHelper?.getTopLevelExtensionOperatorsByName(name.asString())?.let { result.addSuitableOperators(it) }
|
||||
@@ -76,15 +68,12 @@ abstract class TypesWithOperatorDetector(
|
||||
return this
|
||||
}
|
||||
|
||||
fun findOperator(type: FuzzyType): Pair<FunctionDescriptor, TypeSubstitutor>? {
|
||||
return if (cache.containsKey(type)) {
|
||||
cache[type]
|
||||
}
|
||||
else {
|
||||
val result = findOperatorNoCache(type)
|
||||
cache[type] = result
|
||||
result
|
||||
}
|
||||
fun findOperator(type: FuzzyType): Pair<FunctionDescriptor, TypeSubstitutor>? = if (cache.containsKey(type)) {
|
||||
cache[type]
|
||||
} else {
|
||||
val result = findOperatorNoCache(type)
|
||||
cache[type] = result
|
||||
result
|
||||
}
|
||||
|
||||
private fun findOperatorNoCache(type: FuzzyType): Pair<FunctionDescriptor, TypeSubstitutor>? {
|
||||
@@ -109,12 +98,15 @@ abstract class TypesWithOperatorDetector(
|
||||
}
|
||||
|
||||
class TypesWithContainsDetector(
|
||||
scope: LexicalScope,
|
||||
indicesHelper: KotlinIndicesHelper?,
|
||||
private val argumentType: KotlinType
|
||||
scope: LexicalScope,
|
||||
indicesHelper: KotlinIndicesHelper?,
|
||||
private val argumentType: KotlinType
|
||||
) : TypesWithOperatorDetector(OperatorNameConventions.CONTAINS, scope, indicesHelper) {
|
||||
|
||||
override fun checkIsSuitableByType(operator: FunctionDescriptor, freeTypeParams: Collection<TypeParameterDescriptor>): TypeSubstitutor? {
|
||||
override fun checkIsSuitableByType(
|
||||
operator: FunctionDescriptor,
|
||||
freeTypeParams: Collection<TypeParameterDescriptor>
|
||||
): TypeSubstitutor? {
|
||||
val parameter = operator.valueParameters.single()
|
||||
val fuzzyParameterType = parameter.type.toFuzzyType(operator.typeParameters + freeTypeParams)
|
||||
return fuzzyParameterType.checkIsSuperTypeOf(argumentType)
|
||||
@@ -122,13 +114,16 @@ class TypesWithContainsDetector(
|
||||
}
|
||||
|
||||
class TypesWithGetValueDetector(
|
||||
scope: LexicalScope,
|
||||
indicesHelper: KotlinIndicesHelper?,
|
||||
private val propertyOwnerType: FuzzyType,
|
||||
private val propertyType: FuzzyType?
|
||||
scope: LexicalScope,
|
||||
indicesHelper: KotlinIndicesHelper?,
|
||||
private val propertyOwnerType: FuzzyType,
|
||||
private val propertyType: FuzzyType?
|
||||
) : TypesWithOperatorDetector(OperatorNameConventions.GET_VALUE, scope, indicesHelper) {
|
||||
|
||||
override fun checkIsSuitableByType(operator: FunctionDescriptor, freeTypeParams: Collection<TypeParameterDescriptor>): TypeSubstitutor? {
|
||||
override fun checkIsSuitableByType(
|
||||
operator: FunctionDescriptor,
|
||||
freeTypeParams: Collection<TypeParameterDescriptor>
|
||||
): TypeSubstitutor? {
|
||||
val paramType = operator.valueParameters.first().type.toFuzzyType(freeTypeParams)
|
||||
val substitutor = paramType.checkIsSuperTypeOf(propertyOwnerType) ?: return null
|
||||
|
||||
@@ -141,12 +136,15 @@ class TypesWithGetValueDetector(
|
||||
}
|
||||
|
||||
class TypesWithSetValueDetector(
|
||||
scope: LexicalScope,
|
||||
indicesHelper: KotlinIndicesHelper?,
|
||||
private val propertyOwnerType: FuzzyType
|
||||
scope: LexicalScope,
|
||||
indicesHelper: KotlinIndicesHelper?,
|
||||
private val propertyOwnerType: FuzzyType
|
||||
) : TypesWithOperatorDetector(OperatorNameConventions.SET_VALUE, scope, indicesHelper) {
|
||||
|
||||
override fun checkIsSuitableByType(operator: FunctionDescriptor, freeTypeParams: Collection<TypeParameterDescriptor>): TypeSubstitutor? {
|
||||
override fun checkIsSuitableByType(
|
||||
operator: FunctionDescriptor,
|
||||
freeTypeParams: Collection<TypeParameterDescriptor>
|
||||
): TypeSubstitutor? {
|
||||
val paramType = operator.valueParameters.first().type.toFuzzyType(freeTypeParams)
|
||||
return paramType.checkIsSuperTypeOf(propertyOwnerType)
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core
|
||||
@@ -28,9 +17,9 @@ import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||
import org.jetbrains.kotlin.resolve.findOriginalTopMostOverriddenDescriptors
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
@@ -43,10 +32,10 @@ fun DeclarationDescriptorWithVisibility.isVisible(from: DeclarationDescriptor):
|
||||
}
|
||||
|
||||
fun DeclarationDescriptorWithVisibility.isVisible(
|
||||
context: PsiElement,
|
||||
receiverExpression: KtExpression?,
|
||||
bindingContext: BindingContext,
|
||||
resolutionFacade: ResolutionFacade
|
||||
context: PsiElement,
|
||||
receiverExpression: KtExpression?,
|
||||
bindingContext: BindingContext,
|
||||
resolutionFacade: ResolutionFacade
|
||||
): Boolean {
|
||||
val resolutionScope = context.getResolutionScope(bindingContext, resolutionFacade)
|
||||
val from = resolutionScope.ownerDescriptor
|
||||
@@ -54,10 +43,10 @@ fun DeclarationDescriptorWithVisibility.isVisible(
|
||||
}
|
||||
|
||||
private fun DeclarationDescriptorWithVisibility.isVisible(
|
||||
from: DeclarationDescriptor,
|
||||
receiverExpression: KtExpression?,
|
||||
bindingContext: BindingContext? = null,
|
||||
resolutionScope: LexicalScope? = null
|
||||
from: DeclarationDescriptor,
|
||||
receiverExpression: KtExpression?,
|
||||
bindingContext: BindingContext? = null,
|
||||
resolutionScope: LexicalScope? = null
|
||||
): Boolean {
|
||||
if (Visibilities.isVisibleWithAnyReceiver(this, from)) return true
|
||||
|
||||
@@ -68,8 +57,7 @@ private fun DeclarationDescriptorWithVisibility.isVisible(
|
||||
val receiverType = bindingContext.getType(receiverExpression) ?: return false
|
||||
val explicitReceiver = ExpressionReceiver.create(receiverExpression, receiverType, bindingContext)
|
||||
return Visibilities.isVisible(explicitReceiver, this, from)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return resolutionScope.getImplicitReceiversHierarchy().any {
|
||||
Visibilities.isVisible(it.value, this, from)
|
||||
}
|
||||
@@ -116,19 +104,15 @@ fun compareDescriptors(project: Project, currentDescriptor: DeclarationDescripto
|
||||
return false
|
||||
}
|
||||
|
||||
fun Visibility.toKeywordToken(): KtModifierKeywordToken {
|
||||
val normalized = normalize()
|
||||
return when (normalized) {
|
||||
Visibilities.PUBLIC -> KtTokens.PUBLIC_KEYWORD
|
||||
Visibilities.PROTECTED -> KtTokens.PROTECTED_KEYWORD
|
||||
Visibilities.INTERNAL -> KtTokens.INTERNAL_KEYWORD
|
||||
else -> {
|
||||
if (Visibilities.isPrivate(normalized)) {
|
||||
KtTokens.PRIVATE_KEYWORD
|
||||
}
|
||||
else {
|
||||
error("Unexpected visibility '$normalized'")
|
||||
}
|
||||
fun Visibility.toKeywordToken(): KtModifierKeywordToken = when (val normalized = normalize()) {
|
||||
Visibilities.PUBLIC -> KtTokens.PUBLIC_KEYWORD
|
||||
Visibilities.PROTECTED -> KtTokens.PROTECTED_KEYWORD
|
||||
Visibilities.INTERNAL -> KtTokens.INTERNAL_KEYWORD
|
||||
else -> {
|
||||
if (Visibilities.isPrivate(normalized)) {
|
||||
KtTokens.PRIVATE_KEYWORD
|
||||
} else {
|
||||
error("Unexpected visibility '$normalized'")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-24
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core
|
||||
@@ -24,21 +13,20 @@ import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
|
||||
private val exclusions =
|
||||
listOf(
|
||||
"kotlin.jvm.internal",
|
||||
"kotlin.coroutines.experimental.intrinsics",
|
||||
"kotlin.coroutines.intrinsics",
|
||||
"kotlin.coroutines.experimental.jvm.internal",
|
||||
"kotlin.coroutines.jvm.internal",
|
||||
"kotlin.reflect.jvm.internal"
|
||||
)
|
||||
listOf(
|
||||
"kotlin.jvm.internal",
|
||||
"kotlin.coroutines.experimental.intrinsics",
|
||||
"kotlin.coroutines.intrinsics",
|
||||
"kotlin.coroutines.experimental.jvm.internal",
|
||||
"kotlin.coroutines.jvm.internal",
|
||||
"kotlin.reflect.jvm.internal"
|
||||
)
|
||||
|
||||
private fun shouldBeHiddenAsInternalImplementationDetail(fqName: String, locationFqName: String) =
|
||||
exclusions.any { fqName.startsWith(it) }
|
||||
&& (locationFqName.isBlank() || !fqName.startsWith(locationFqName))
|
||||
exclusions.any { fqName.startsWith(it) } && (locationFqName.isBlank() || !fqName.startsWith(locationFqName))
|
||||
|
||||
fun DeclarationDescriptor.isExcludedFromAutoImport(project: Project, inFile: KtFile?): Boolean {
|
||||
val fqName = importableFqName?.asString() ?: return false
|
||||
return JavaProjectCodeInsightSettings.getSettings(project).isExcluded(fqName) ||
|
||||
shouldBeHiddenAsInternalImplementationDetail(fqName, inFile?.packageFqName?.asString() ?: "")
|
||||
shouldBeHiddenAsInternalImplementationDetail(fqName, inFile?.packageFqName?.asString() ?: "")
|
||||
}
|
||||
|
||||
+3
-14
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -26,7 +15,7 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
interface CompletionInformationProvider {
|
||||
companion object {
|
||||
val EP_NAME: ExtensionPointName<CompletionInformationProvider> =
|
||||
ExtensionPointName.create("org.jetbrains.kotlin.completionInformationProvider")
|
||||
ExtensionPointName.create("org.jetbrains.kotlin.completionInformationProvider")
|
||||
}
|
||||
|
||||
fun getContainerAndReceiverInformation(descriptor: DeclarationDescriptor): String?
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -10,7 +10,10 @@ import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.jps.model.java.JavaResourceRootType
|
||||
import org.jetbrains.jps.model.java.JavaSourceRootType
|
||||
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.config.ResourceKotlinRootType
|
||||
import org.jetbrains.kotlin.config.SourceKotlinRootType
|
||||
import org.jetbrains.kotlin.config.TestResourceKotlinRootType
|
||||
import org.jetbrains.kotlin.config.TestSourceKotlinRootType
|
||||
import org.jetbrains.kotlin.idea.caches.project.SourceType
|
||||
import org.jetbrains.kotlin.idea.util.isInSourceContentWithoutInjected
|
||||
|
||||
@@ -28,7 +31,7 @@ private val sourceRootTypes = setOf<JpsModuleSourceRootType<*>>(
|
||||
ResourceKotlinRootType
|
||||
)
|
||||
|
||||
fun JpsModuleSourceRootType<*>.getSourceType(): SourceType? = when(this) {
|
||||
fun JpsModuleSourceRootType<*>.getSourceType(): SourceType? = when (this) {
|
||||
in sourceRootTypes -> SourceType.PRODUCTION
|
||||
in testRootTypes -> SourceType.TEST
|
||||
else -> null
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core
|
||||
@@ -231,7 +220,9 @@ fun <T : KtDeclaration> insertMembersAfter(
|
||||
if (classOrObject !is KtClass) return@mapNotNullTo null
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
SmartPointerManager.createPointer(classOrObject.createPrimaryConstructorParameterListIfAbsent().addParameter(it as KtParameter) as T)
|
||||
SmartPointerManager.createPointer(
|
||||
classOrObject.createPrimaryConstructorParameterListIfAbsent().addParameter(it as KtParameter) as T
|
||||
)
|
||||
}
|
||||
|
||||
if (otherMembers.isNotEmpty()) {
|
||||
|
||||
+4
-14
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core.overrideImplement
|
||||
@@ -182,7 +171,8 @@ fun OverrideMemberChooserObject.generateMember(
|
||||
targetClass.resolveToDescriptorIfAny()?.expectedDescriptors()?.filterIsInstance<ClassDescriptor>().orEmpty()
|
||||
if (expectClassDescriptors.any { expectClassDescriptor ->
|
||||
val expectMemberDescriptor = expectClassDescriptor.findCallableMemberBySignature(immediateSuper)
|
||||
expectMemberDescriptor?.isExpect == true && expectMemberDescriptor.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE
|
||||
expectMemberDescriptor?.isExpect == true &&
|
||||
expectMemberDescriptor.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE
|
||||
}
|
||||
) {
|
||||
newMember.addModifier(KtTokens.ACTUAL_KEYWORD)
|
||||
|
||||
+17
-21
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core.overrideImplement
|
||||
@@ -34,8 +23,8 @@ class OverrideMembersHandler(private val preferConstructorParameters: Boolean =
|
||||
if (DescriptorUtils.isInterface(descriptor) && overridden.any { descriptor.builtIns.isMemberOfAny(it) }) continue
|
||||
|
||||
class Data(
|
||||
val realSuper: CallableMemberDescriptor,
|
||||
val immediateSupers: MutableList<CallableMemberDescriptor> = SmartList()
|
||||
val realSuper: CallableMemberDescriptor,
|
||||
val immediateSupers: MutableList<CallableMemberDescriptor> = SmartList()
|
||||
)
|
||||
|
||||
val byOriginalRealSupers = LinkedHashMap<CallableMemberDescriptor, Data>()
|
||||
@@ -49,8 +38,7 @@ class OverrideMembersHandler(private val preferConstructorParameters: Boolean =
|
||||
val nonAbstractRealSupers = realSupers.filter { it.modality != Modality.ABSTRACT }
|
||||
val realSupersToUse = if (nonAbstractRealSupers.isNotEmpty()) {
|
||||
nonAbstractRealSupers
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
listOf(realSupers.firstOrNull() ?: continue)
|
||||
}
|
||||
|
||||
@@ -60,9 +48,9 @@ class OverrideMembersHandler(private val preferConstructorParameters: Boolean =
|
||||
|
||||
val immediateSuperToUse = if (immediateSupers.size == 1) {
|
||||
immediateSupers.single()
|
||||
}
|
||||
else {
|
||||
immediateSupers.singleOrNull { (it.containingDeclaration as? ClassDescriptor)?.kind == ClassKind.CLASS } ?: immediateSupers.first()
|
||||
} else {
|
||||
immediateSupers.singleOrNull { (it.containingDeclaration as? ClassDescriptor)?.kind == ClassKind.CLASS }
|
||||
?: immediateSupers.first()
|
||||
}
|
||||
|
||||
val bodyType = when {
|
||||
@@ -76,7 +64,15 @@ class OverrideMembersHandler(private val preferConstructorParameters: Boolean =
|
||||
OverrideMemberChooserObject.BodyType.QUALIFIED_SUPER
|
||||
}
|
||||
|
||||
result.add(OverrideMemberChooserObject.create(project, realSuper, immediateSuperToUse, bodyType, preferConstructorParameters))
|
||||
result.add(
|
||||
OverrideMemberChooserObject.create(
|
||||
project,
|
||||
realSuper,
|
||||
immediateSuperToUse,
|
||||
bodyType,
|
||||
preferConstructorParameters
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core
|
||||
@@ -189,8 +178,6 @@ private fun FunctionDescriptor.allowsMoveOfLastParameterOutsideParentheses(
|
||||
return movableParametersOfCandidateCount == lambdaAndCallableReferencesInOriginalCallCount
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun KtCallExpression.moveFunctionLiteralOutsideParentheses() {
|
||||
assert(lambdaArguments.isEmpty())
|
||||
val argumentList = valueArgumentList!!
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core
|
||||
@@ -37,11 +26,11 @@ enum class TemplateKind(val templateFileName: String) {
|
||||
}
|
||||
|
||||
fun getFunctionBodyTextFromTemplate(
|
||||
project: Project,
|
||||
kind: TemplateKind,
|
||||
name: String?,
|
||||
returnType: String,
|
||||
classFqName: FqName? = null
|
||||
project: Project,
|
||||
kind: TemplateKind,
|
||||
name: String?,
|
||||
returnType: String,
|
||||
classFqName: FqName? = null
|
||||
): String {
|
||||
val fileTemplate = FileTemplateManager.getInstance(project)!!.getCodeTemplate(kind.templateFileName)
|
||||
|
||||
@@ -61,11 +50,9 @@ fun getFunctionBodyTextFromTemplate(
|
||||
|
||||
return try {
|
||||
fileTemplate.getText(properties)
|
||||
}
|
||||
catch (e: ProcessCanceledException) {
|
||||
} catch (e: ProcessCanceledException) {
|
||||
throw e
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
} catch (e: Throwable) {
|
||||
// TODO: This is dangerous.
|
||||
// Is there any way to avoid catching all exceptions?
|
||||
throw IncorrectOperationException("Failed to parse file template", e)
|
||||
|
||||
@@ -15,10 +15,16 @@ fun attachmentByPsiFile(file: PsiFile?): Attachment? {
|
||||
val virtualFile = file.virtualFile
|
||||
if (virtualFile != null) return AttachmentFactory.createAttachment(virtualFile)
|
||||
|
||||
val text = try { file.text
|
||||
} catch(e: Exception) { null }
|
||||
val name = try { file.name
|
||||
} catch(e: Exception) { null }
|
||||
val text = try {
|
||||
file.text
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
val name = try {
|
||||
file.name
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
|
||||
if (text != null && name != null) return Attachment(name, text)
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import com.intellij.openapi.progress.util.ProgressIndicatorUtils
|
||||
import com.intellij.openapi.project.Project
|
||||
|
||||
fun <T : Any> runInReadActionWithWriteActionPriorityWithPCE(f: () -> T): T =
|
||||
runInReadActionWithWriteActionPriority(f) ?: throw ProcessCanceledException()
|
||||
runInReadActionWithWriteActionPriority(f) ?: throw ProcessCanceledException()
|
||||
|
||||
fun <T : Any> runInReadActionWithWriteActionPriority(f: () -> T): T? {
|
||||
if (with(ApplicationManager.getApplication()) { isDispatchThread && isUnitTestMode }) {
|
||||
|
||||
@@ -11,10 +11,10 @@ import javax.swing.text.JTextComponent
|
||||
|
||||
fun JTextComponent.onTextChange(action: (DocumentEvent) -> Unit) {
|
||||
document.addDocumentListener(
|
||||
object : DocumentAdapter() {
|
||||
override fun textChanged(e: DocumentEvent) {
|
||||
action(e)
|
||||
}
|
||||
object : DocumentAdapter() {
|
||||
override fun textChanged(e: DocumentEvent) {
|
||||
action(e)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core.util
|
||||
@@ -26,8 +15,7 @@ import javax.swing.Icon
|
||||
fun showYesNoCancelDialog(key: String, project: Project, message: String, title: String, icon: Icon, default: Int?): Int {
|
||||
return if (!ApplicationManager.getApplication().isUnitTestMode) {
|
||||
Messages.showYesNoCancelDialog(project, message, title, icon)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
callInTestMode(key, default)
|
||||
}
|
||||
}
|
||||
@@ -44,7 +32,7 @@ fun clearDialogsResults() {
|
||||
dialogResults.clear()
|
||||
}
|
||||
|
||||
private fun <T: Any?> callInTestMode(key: String, default: T?): T {
|
||||
private fun <T : Any?> callInTestMode(key: String, default: T?): T {
|
||||
val result = dialogResults[key]
|
||||
if (result != null) {
|
||||
dialogResults.remove(key)
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.j2k
|
||||
@@ -28,8 +17,6 @@ import com.intellij.psi.xml.XmlFile
|
||||
import com.intellij.psi.xml.XmlTag
|
||||
import com.intellij.psi.xml.XmlText
|
||||
import com.intellij.psi.xml.XmlTokenType
|
||||
import org.jetbrains.kotlin.idea.j2k.DocCommentConverter
|
||||
import org.jetbrains.kotlin.idea.j2k.content
|
||||
|
||||
object IdeaDocCommentConverter : DocCommentConverter {
|
||||
override fun convertDocComment(docComment: PsiDocComment): String {
|
||||
@@ -55,7 +42,8 @@ object IdeaDocCommentConverter : DocCommentConverter {
|
||||
}
|
||||
|
||||
val htmlFile = PsiFileFactory.getInstance(docComment.project).createFileFromText(
|
||||
"javadoc.html", HtmlFileType.INSTANCE, html)
|
||||
"javadoc.html", HtmlFileType.INSTANCE, html
|
||||
)
|
||||
val htmlToMarkdownConverter = HtmlToMarkdownConverter()
|
||||
htmlFile.accept(htmlToMarkdownConverter)
|
||||
return htmlToMarkdownConverter.result
|
||||
@@ -65,8 +53,7 @@ object IdeaDocCommentConverter : DocCommentConverter {
|
||||
elements.forEach {
|
||||
if (it is PsiInlineDocTag) {
|
||||
append(convertInlineDocTag(it))
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (it.node?.elementType != JavaDocTokenType.DOC_COMMENT_LEADING_ASTERISKS) {
|
||||
append(it.text)
|
||||
}
|
||||
@@ -79,7 +66,7 @@ object IdeaDocCommentConverter : DocCommentConverter {
|
||||
* Returns true if the builder ends with a new-line optionally followed by some spaces
|
||||
*/
|
||||
private fun StringBuilder.endsWithNewline(): Boolean {
|
||||
for (i in length-1 downTo 0) {
|
||||
for (i in length - 1 downTo 0) {
|
||||
val c = get(i)
|
||||
if (c.isWhitespace()) {
|
||||
if (c == '\n' || c == '\r') return true
|
||||
@@ -109,17 +96,14 @@ object IdeaDocCommentConverter : DocCommentConverter {
|
||||
else -> tag.text
|
||||
}
|
||||
|
||||
private fun convertJavadocLink(link: String?): String =
|
||||
if (link != null) link.substringBefore('(').replace('#', '.') else ""
|
||||
private fun convertJavadocLink(link: String?): String = link?.substringBefore('(')?.replace('#', '.') ?: ""
|
||||
|
||||
private fun PsiDocTag.linkElement(): PsiElement? =
|
||||
valueElement ?: dataElements.firstOrNull { it !is PsiWhiteSpace }
|
||||
private fun PsiDocTag.linkElement(): PsiElement? = valueElement ?: dataElements.firstOrNull { it !is PsiWhiteSpace }
|
||||
|
||||
private fun XmlTag.attributesAsString() =
|
||||
if (attributes.isNotEmpty())
|
||||
attributes.joinToString(separator = " ", prefix = " ") { it.text }
|
||||
else
|
||||
""
|
||||
private fun XmlTag.attributesAsString() = if (attributes.isNotEmpty())
|
||||
attributes.joinToString(separator = " ", prefix = " ") { it.text }
|
||||
else
|
||||
""
|
||||
|
||||
private class HtmlToMarkdownConverter() : XmlRecursiveElementVisitor() {
|
||||
private enum class ListType { Ordered, Unordered; }
|
||||
@@ -131,7 +115,7 @@ object IdeaDocCommentConverter : DocCommentConverter {
|
||||
fun prefix(text: String) = MarkdownSpan(text, "")
|
||||
|
||||
fun preserveTag(tag: XmlTag) =
|
||||
MarkdownSpan("<${tag.name}${tag.attributesAsString()}>", "</${tag.name}>")
|
||||
MarkdownSpan("<${tag.name}${tag.attributesAsString()}>", "</${tag.name}>")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,9 +153,7 @@ object IdeaDocCommentConverter : DocCommentConverter {
|
||||
override fun visitElement(element: PsiElement) {
|
||||
super.visitElement(element)
|
||||
|
||||
val tokenType = element.node.elementType
|
||||
|
||||
when (tokenType) {
|
||||
when (element.node.elementType) {
|
||||
XmlTokenType.XML_DATA_CHARACTERS -> {
|
||||
appendPendingText()
|
||||
markdownBuilder.append(element.text)
|
||||
@@ -215,8 +197,7 @@ object IdeaDocCommentConverter : DocCommentConverter {
|
||||
whitespaceIsPartOfText = newValue
|
||||
try {
|
||||
block()
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
whitespaceIsPartOfText = oldValue
|
||||
}
|
||||
}
|
||||
@@ -243,11 +224,9 @@ object IdeaDocCommentConverter : DocCommentConverter {
|
||||
val docRef = tag.getAttributeValue("docref")
|
||||
val innerText = tag.value.text
|
||||
if (docRef == innerText) MarkdownSpan("[", "]") else MarkdownSpan("[", "][$docRef]")
|
||||
}
|
||||
else if (tag.getAttributeValue("href") != null) {
|
||||
} else if (tag.getAttributeValue("href") != null) {
|
||||
MarkdownSpan("[", "](${tag.getAttributeValue("href") ?: ""})")
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
MarkdownSpan.preserveTag(tag)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user