idea: cleanup code

This commit is contained in:
Dmitry Gridin
2019-12-13 22:11:25 +07:00
parent e77d8657f4
commit 8dbbd64beb
897 changed files with 13161 additions and 18514 deletions
@@ -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'")
}
}
}
@@ -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() ?: "")
}
@@ -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()) {
@@ -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)
@@ -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)
}
}