Reformat the rest of 'frontend'-module according to new codestyle
This commit is contained in:
@@ -70,7 +70,9 @@ class EmptyResolverForProject<M : ModuleInfo> : ResolverForProject<M>() {
|
|||||||
get() = "Empty resolver"
|
get() = "Empty resolver"
|
||||||
|
|
||||||
override fun tryGetResolverForModule(moduleInfo: M): ResolverForModule? = null
|
override fun tryGetResolverForModule(moduleInfo: M): ResolverForModule? = null
|
||||||
override fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): ResolverForModule = throw IllegalStateException("$descriptor is not contained in this resolver")
|
override fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): ResolverForModule =
|
||||||
|
throw IllegalStateException("$descriptor is not contained in this resolver")
|
||||||
|
|
||||||
override fun descriptorForModule(moduleInfo: M) = diagnoseUnknownModuleInfo(listOf(moduleInfo))
|
override fun descriptorForModule(moduleInfo: M) = diagnoseUnknownModuleInfo(listOf(moduleInfo))
|
||||||
override val allModules: Collection<M> = listOf()
|
override val allModules: Collection<M> = listOf()
|
||||||
override fun diagnoseUnknownModuleInfo(infos: List<ModuleInfo>) = throw IllegalStateException("Should not be called for $infos")
|
override fun diagnoseUnknownModuleInfo(infos: List<ModuleInfo>) = throw IllegalStateException("Should not be called for $infos")
|
||||||
@@ -117,16 +119,22 @@ class ResolverForProjectImpl<M : ModuleInfo>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setupModuleDescriptor(module: M, moduleDescriptor: ModuleDescriptorImpl) {
|
private fun setupModuleDescriptor(module: M, moduleDescriptor: ModuleDescriptorImpl) {
|
||||||
moduleDescriptor.setDependencies(LazyModuleDependencies(
|
moduleDescriptor.setDependencies(
|
||||||
|
LazyModuleDependencies(
|
||||||
projectContext.storageManager,
|
projectContext.storageManager,
|
||||||
module,
|
module,
|
||||||
firstDependency,
|
firstDependency,
|
||||||
this))
|
this
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
val content = modulesContent(module)
|
val content = modulesContent(module)
|
||||||
moduleDescriptor.initialize(
|
moduleDescriptor.initialize(
|
||||||
DelegatingPackageFragmentProvider(this, moduleDescriptor, content,
|
DelegatingPackageFragmentProvider(
|
||||||
packageOracleFactory.createOracle(module)))
|
this, moduleDescriptor, content,
|
||||||
|
packageOracleFactory.createOracle(module)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val resolverByModuleDescriptor = mutableMapOf<ModuleDescriptor, ResolverForModule>()
|
private val resolverByModuleDescriptor = mutableMapOf<ModuleDescriptor, ResolverForModule>()
|
||||||
@@ -156,7 +164,8 @@ class ResolverForProjectImpl<M : ModuleInfo>(
|
|||||||
module, descriptor as ModuleDescriptorImpl, projectContext.withModule(descriptor), modulesContent(module),
|
module, descriptor as ModuleDescriptorImpl, projectContext.withModule(descriptor), modulesContent(module),
|
||||||
platformParameters, targetEnvironment, this@ResolverForProjectImpl,
|
platformParameters, targetEnvironment, this@ResolverForProjectImpl,
|
||||||
languageSettingsProvider,
|
languageSettingsProvider,
|
||||||
packagePartProviderFactory(module, modulesContent(module)))
|
packagePartProviderFactory(module, modulesContent(module))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,12 +213,14 @@ class ResolverForProjectImpl<M : ModuleInfo>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createModuleDescriptor(module: M): ModuleData {
|
private fun createModuleDescriptor(module: M): ModuleData {
|
||||||
val moduleDescriptor = ModuleDescriptorImpl(module.name,
|
val moduleDescriptor = ModuleDescriptorImpl(
|
||||||
projectContext.storageManager, builtIns, modulePlatforms(module), module.capabilities)
|
module.name,
|
||||||
|
projectContext.storageManager, builtIns, modulePlatforms(module), module.capabilities
|
||||||
|
)
|
||||||
moduleInfoByDescriptor[moduleDescriptor] = module
|
moduleInfoByDescriptor[moduleDescriptor] = module
|
||||||
setupModuleDescriptor(module, moduleDescriptor)
|
setupModuleDescriptor(module, moduleDescriptor)
|
||||||
val modificationTracker = (module as? TrackableModuleInfo)?.createModificationTracker() ?:
|
val modificationTracker = (module as? TrackableModuleInfo)?.createModificationTracker()
|
||||||
(PsiModificationTracker.SERVICE.getInstance(projectContext.project).outOfCodeBlockModificationTracker.takeIf { invalidateOnOOCB })
|
?: (PsiModificationTracker.SERVICE.getInstance(projectContext.project).outOfCodeBlockModificationTracker.takeIf { invalidateOnOOCB })
|
||||||
return ModuleData(moduleDescriptor, modificationTracker, modificationTracker?.modificationCount)
|
return ModuleData(moduleDescriptor, modificationTracker, modificationTracker?.modificationCount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -366,6 +377,7 @@ interface ResolverForModuleComputationTracker {
|
|||||||
fun onResolverComputed(moduleInfo: ModuleInfo)
|
fun onResolverComputed(moduleInfo: ModuleInfo)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun getInstance(project: Project): ResolverForModuleComputationTracker? = ServiceManager.getService(project, ResolverForModuleComputationTracker::class.java) ?: null
|
fun getInstance(project: Project): ResolverForModuleComputationTracker? =
|
||||||
|
ServiceManager.getService(project, ResolverForModuleComputationTracker::class.java) ?: null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
|||||||
interface ControlFlowBuilder {
|
interface ControlFlowBuilder {
|
||||||
// Subroutines
|
// Subroutines
|
||||||
fun enterSubroutine(subroutine: KtElement, invocationKind: InvocationKind? = null)
|
fun enterSubroutine(subroutine: KtElement, invocationKind: InvocationKind? = null)
|
||||||
|
|
||||||
fun exitSubroutine(subroutine: KtElement, invocationKind: InvocationKind? = null): Pseudocode
|
fun exitSubroutine(subroutine: KtElement, invocationKind: InvocationKind? = null): Pseudocode
|
||||||
|
|
||||||
val currentSubroutine: KtElement
|
val currentSubroutine: KtElement
|
||||||
|
|||||||
@@ -1544,8 +1544,10 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
|||||||
//noinspection EnumSwitchStatementWhichMissesCases
|
//noinspection EnumSwitchStatementWhichMissesCases
|
||||||
when (kind) {
|
when (kind) {
|
||||||
ExplicitReceiverKind.DISPATCH_RECEIVER -> explicitReceiver = resolvedCall.dispatchReceiver
|
ExplicitReceiverKind.DISPATCH_RECEIVER -> explicitReceiver = resolvedCall.dispatchReceiver
|
||||||
ExplicitReceiverKind.EXTENSION_RECEIVER, ExplicitReceiverKind.BOTH_RECEIVERS -> explicitReceiver = resolvedCall.extensionReceiver
|
ExplicitReceiverKind.EXTENSION_RECEIVER, ExplicitReceiverKind.BOTH_RECEIVERS -> explicitReceiver =
|
||||||
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER -> {}
|
resolvedCall.extensionReceiver
|
||||||
|
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER -> {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,9 +74,11 @@ class PseudocodeVariableDataCollector(
|
|||||||
val variableDeclarationElement = instruction.variableDeclarationElement
|
val variableDeclarationElement = instruction.variableDeclarationElement
|
||||||
val descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, variableDeclarationElement) ?: return@traverse
|
val descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, variableDeclarationElement) ?: return@traverse
|
||||||
val variableDescriptor = BindingContextUtils.variableDescriptorForDeclaration(descriptor)
|
val variableDescriptor = BindingContextUtils.variableDescriptorForDeclaration(descriptor)
|
||||||
?: throw AssertionError("Variable or class descriptor should correspond to " +
|
?: throw AssertionError(
|
||||||
|
"Variable or class descriptor should correspond to " +
|
||||||
"the instruction for ${instruction.element.text}.\n" +
|
"the instruction for ${instruction.element.text}.\n" +
|
||||||
"Descriptor: $descriptor")
|
"Descriptor: $descriptor"
|
||||||
|
)
|
||||||
blockScopeVariableInfo.registerVariableDeclaredInScope(variableDescriptor, instruction.blockScope)
|
blockScopeVariableInfo.registerVariableDeclaredInScope(variableDescriptor, instruction.blockScope)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -113,8 +113,7 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
|
|||||||
|
|
||||||
if (!containsDoWhile && isValWithTrivialInitializer(variableDeclarationElement, descriptor)) {
|
if (!containsDoWhile && isValWithTrivialInitializer(variableDeclarationElement, descriptor)) {
|
||||||
valsWithTrivialInitializer.add(descriptor)
|
valsWithTrivialInitializer.add(descriptor)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
nonTrivialVariables.add(descriptor)
|
nonTrivialVariables.add(descriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -148,15 +147,17 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
|
|||||||
|
|
||||||
if (rootVariables.nonTrivialVariables.isEmpty()) return resultForValsWithTrivialInitializer
|
if (rootVariables.nonTrivialVariables.isEmpty()) return resultForValsWithTrivialInitializer
|
||||||
|
|
||||||
return pseudocodeVariableDataCollector.collectData(TraversalOrder.FORWARD, InitControlFlowInfo()) {
|
return pseudocodeVariableDataCollector.collectData(
|
||||||
instruction: Instruction, incomingEdgesData: Collection<InitControlFlowInfo> ->
|
TraversalOrder.FORWARD,
|
||||||
|
InitControlFlowInfo()
|
||||||
|
) { instruction: Instruction, incomingEdgesData: Collection<InitControlFlowInfo> ->
|
||||||
|
|
||||||
val enterInstructionData = mergeIncomingEdgesDataForInitializers(instruction, incomingEdgesData, blockScopeVariableInfo)
|
val enterInstructionData = mergeIncomingEdgesDataForInitializers(instruction, incomingEdgesData, blockScopeVariableInfo)
|
||||||
val exitInstructionData = addVariableInitStateFromCurrentInstructionIfAny(
|
val exitInstructionData = addVariableInitStateFromCurrentInstructionIfAny(
|
||||||
instruction, enterInstructionData, blockScopeVariableInfo)
|
instruction, enterInstructionData, blockScopeVariableInfo
|
||||||
|
)
|
||||||
Edges(enterInstructionData, exitInstructionData)
|
Edges(enterInstructionData, exitInstructionData)
|
||||||
}.mapValues {
|
}.mapValues { (instruction, edges) ->
|
||||||
(instruction, edges) ->
|
|
||||||
val trivialEdges = resultForValsWithTrivialInitializer[instruction]!!
|
val trivialEdges = resultForValsWithTrivialInitializer[instruction]!!
|
||||||
Edges(trivialEdges.incoming.replaceDelegate(edges.incoming), trivialEdges.outgoing.replaceDelegate(edges.outgoing))
|
Edges(trivialEdges.incoming.replaceDelegate(edges.incoming), trivialEdges.outgoing.replaceDelegate(edges.outgoing))
|
||||||
}
|
}
|
||||||
@@ -170,8 +171,7 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
|
|||||||
val enterState = ReadOnlyInitControlFlowInfoImpl(declaredSet, initSet, null)
|
val enterState = ReadOnlyInitControlFlowInfoImpl(declaredSet, initSet, null)
|
||||||
when (instruction) {
|
when (instruction) {
|
||||||
is VariableDeclarationInstruction ->
|
is VariableDeclarationInstruction ->
|
||||||
extractValWithTrivialInitializer(instruction)?.let {
|
extractValWithTrivialInitializer(instruction)?.let { variableDescriptor ->
|
||||||
variableDescriptor ->
|
|
||||||
declaredSet = declaredSet.add(variableDescriptor)
|
declaredSet = declaredSet.add(variableDescriptor)
|
||||||
}
|
}
|
||||||
is WriteValueInstruction -> {
|
is WriteValueInstruction -> {
|
||||||
@@ -216,8 +216,7 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
|
|||||||
override fun asMap(): ImmutableMap<VariableDescriptor, VariableControlFlowState> {
|
override fun asMap(): ImmutableMap<VariableDescriptor, VariableControlFlowState> {
|
||||||
val initial = delegate?.asMap() ?: ImmutableHashMap.empty()
|
val initial = delegate?.asMap() ?: ImmutableHashMap.empty()
|
||||||
|
|
||||||
return declaredSet.fold(initial) {
|
return declaredSet.fold(initial) { acc, variableDescriptor ->
|
||||||
acc, variableDescriptor ->
|
|
||||||
acc.put(variableDescriptor, getOrNull(variableDescriptor)!!)
|
acc.put(variableDescriptor, getOrNull(variableDescriptor)!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -246,15 +245,14 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
|
|||||||
private fun addVariableInitStateFromCurrentInstructionIfAny(
|
private fun addVariableInitStateFromCurrentInstructionIfAny(
|
||||||
instruction: Instruction,
|
instruction: Instruction,
|
||||||
enterInstructionData: InitControlFlowInfo,
|
enterInstructionData: InitControlFlowInfo,
|
||||||
blockScopeVariableInfo: BlockScopeVariableInfo): InitControlFlowInfo {
|
blockScopeVariableInfo: BlockScopeVariableInfo
|
||||||
|
): InitControlFlowInfo {
|
||||||
if (instruction is MagicInstruction) {
|
if (instruction is MagicInstruction) {
|
||||||
if (instruction.kind === MagicKind.EXHAUSTIVE_WHEN_ELSE) {
|
if (instruction.kind === MagicKind.EXHAUSTIVE_WHEN_ELSE) {
|
||||||
return enterInstructionData.iterator().fold(enterInstructionData) {
|
return enterInstructionData.iterator().fold(enterInstructionData) { result, (key, value) ->
|
||||||
result, (key, value) ->
|
|
||||||
if (!value.definitelyInitialized()) {
|
if (!value.definitelyInitialized()) {
|
||||||
result.put(key, VariableControlFlowState.createInitializedExhaustively(value.isDeclared))
|
result.put(key, VariableControlFlowState.createInitializedExhaustively(value.isDeclared))
|
||||||
}
|
} else result
|
||||||
else result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,8 +273,7 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
|
|||||||
val enterInitState = enterInstructionData.getOrNull(variable)
|
val enterInitState = enterInstructionData.getOrNull(variable)
|
||||||
val initializationAtThisElement = VariableControlFlowState.create(instruction.element is KtProperty, enterInitState)
|
val initializationAtThisElement = VariableControlFlowState.create(instruction.element is KtProperty, enterInitState)
|
||||||
exitInstructionData = exitInstructionData.put(variable, initializationAtThisElement, enterInitState)
|
exitInstructionData = exitInstructionData.put(variable, initializationAtThisElement, enterInitState)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// instruction instanceof VariableDeclarationInstruction
|
// instruction instanceof VariableDeclarationInstruction
|
||||||
val enterInitState =
|
val enterInitState =
|
||||||
enterInstructionData.getOrNull(variable)
|
enterInstructionData.getOrNull(variable)
|
||||||
@@ -303,12 +300,14 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pseudocodeVariableDataCollector.collectData(TraversalOrder.BACKWARD, UseControlFlowInfo()) { instruction: Instruction, incomingEdgesData: Collection<UseControlFlowInfo> ->
|
return pseudocodeVariableDataCollector.collectData(
|
||||||
|
TraversalOrder.BACKWARD,
|
||||||
|
UseControlFlowInfo()
|
||||||
|
) { instruction: Instruction, incomingEdgesData: Collection<UseControlFlowInfo> ->
|
||||||
|
|
||||||
val enterResult: UseControlFlowInfo = if (incomingEdgesData.size == 1) {
|
val enterResult: UseControlFlowInfo = if (incomingEdgesData.size == 1) {
|
||||||
incomingEdgesData.single()
|
incomingEdgesData.single()
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
incomingEdgesData.fold(UseControlFlowInfo()) { result, edgeData ->
|
incomingEdgesData.fold(UseControlFlowInfo()) { result, edgeData ->
|
||||||
edgeData.iterator().fold(result) { subResult, (variableDescriptor, variableUseState) ->
|
edgeData.iterator().fold(result) { subResult, (variableDescriptor, variableUseState) ->
|
||||||
subResult.put(variableDescriptor, variableUseState.merge(subResult.getOrNull(variableDescriptor)))
|
subResult.put(variableDescriptor, variableUseState.merge(subResult.getOrNull(variableDescriptor)))
|
||||||
@@ -321,13 +320,11 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
|
|||||||
?.takeIf { it in rootVariables.nonTrivialVariables }
|
?.takeIf { it in rootVariables.nonTrivialVariables }
|
||||||
if (variableDescriptor == null || instruction !is ReadValueInstruction && instruction !is WriteValueInstruction) {
|
if (variableDescriptor == null || instruction !is ReadValueInstruction && instruction !is WriteValueInstruction) {
|
||||||
Edges(enterResult, enterResult)
|
Edges(enterResult, enterResult)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val exitResult =
|
val exitResult =
|
||||||
if (instruction is ReadValueInstruction) {
|
if (instruction is ReadValueInstruction) {
|
||||||
enterResult.put(variableDescriptor, VariableUseState.READ)
|
enterResult.put(variableDescriptor, VariableUseState.READ)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
var variableUseState: VariableUseState? = enterResult.getOrNull(variableDescriptor)
|
var variableUseState: VariableUseState? = enterResult.getOrNull(variableDescriptor)
|
||||||
if (variableUseState == null) {
|
if (variableUseState == null) {
|
||||||
variableUseState = VariableUseState.UNUSED
|
variableUseState = VariableUseState.UNUSED
|
||||||
@@ -341,8 +338,7 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
|
|||||||
}
|
}
|
||||||
Edges(enterResult, exitResult)
|
Edges(enterResult, exitResult)
|
||||||
}
|
}
|
||||||
}.mapValues {
|
}.mapValues { (_, edges) ->
|
||||||
(_, edges) ->
|
|
||||||
|
|
||||||
Edges(
|
Edges(
|
||||||
edgesForTrivialVals.incoming.replaceDelegate(edges.incoming),
|
edgesForTrivialVals.incoming.replaceDelegate(edges.incoming),
|
||||||
@@ -387,8 +383,7 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
|
|||||||
override fun asMap(): ImmutableMap<VariableDescriptor, VariableUseState> {
|
override fun asMap(): ImmutableMap<VariableDescriptor, VariableUseState> {
|
||||||
val initial = delegate?.asMap() ?: ImmutableHashMap.empty()
|
val initial = delegate?.asMap() ?: ImmutableHashMap.empty()
|
||||||
|
|
||||||
return used.fold(initial) {
|
return used.fold(initial) { acc, variableDescriptor ->
|
||||||
acc, variableDescriptor ->
|
|
||||||
acc.put(variableDescriptor, getOrNull(variableDescriptor)!!)
|
acc.put(variableDescriptor, getOrNull(variableDescriptor)!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,8 +48,7 @@ class UnreachableCodeImpl(
|
|||||||
// element is dead but its only child is alive and has the same text range
|
// element is dead but its only child is alive and has the same text range
|
||||||
else listOf(element.textRange.endOffset.let { TextRange(it, it) })
|
else listOf(element.textRange.endOffset.let { TextRange(it, it) })
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
listOf(element.textRange!!)
|
listOf(element.textRange!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,11 +60,11 @@ class UnreachableCodeImpl(
|
|||||||
val children = ArrayList<PsiElement>()
|
val children = ArrayList<PsiElement>()
|
||||||
acceptChildren(object : PsiElementVisitor() {
|
acceptChildren(object : PsiElementVisitor() {
|
||||||
override fun visitElement(element: PsiElement) {
|
override fun visitElement(element: PsiElement) {
|
||||||
val isReachable = element is KtElement && reachableElements.contains(element) && !element.hasChildrenInSet(unreachableElements)
|
val isReachable =
|
||||||
|
element is KtElement && reachableElements.contains(element) && !element.hasChildrenInSet(unreachableElements)
|
||||||
if (isReachable || element.children.isEmpty()) {
|
if (isReachable || element.children.isEmpty()) {
|
||||||
children.add(element)
|
children.add(element)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
element.acceptChildren(this)
|
element.acceptChildren(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,8 +101,7 @@ class UnreachableCodeImpl(
|
|||||||
|
|
||||||
private fun List<PsiElement>.mergeAdjacentTextRanges(): List<TextRange> {
|
private fun List<PsiElement>.mergeAdjacentTextRanges(): List<TextRange> {
|
||||||
val result = ArrayList<TextRange>()
|
val result = ArrayList<TextRange>()
|
||||||
val lastRange = fold(null as TextRange?) {
|
val lastRange = fold(null as TextRange?) { currentTextRange, element ->
|
||||||
currentTextRange, element ->
|
|
||||||
|
|
||||||
val elementRange = element.textRange!!
|
val elementRange = element.textRange!!
|
||||||
when {
|
when {
|
||||||
|
|||||||
@@ -201,8 +201,7 @@ internal abstract class WhenOnClassExhaustivenessChecker : WhenExhaustivenessChe
|
|||||||
if (checkedDescriptors.containsAll(checkedDescriptorSubclasses)) return listOf()
|
if (checkedDescriptors.containsAll(checkedDescriptorSubclasses)) return listOf()
|
||||||
checkedDescriptors.addAll(subclasses)
|
checkedDescriptors.addAll(subclasses)
|
||||||
checkedDescriptors.removeAll(checkedDescriptorSubclasses)
|
checkedDescriptors.removeAll(checkedDescriptorSubclasses)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
checkedDescriptors.addAll(checkedDescriptorSubclasses)
|
checkedDescriptors.addAll(checkedDescriptorSubclasses)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -258,9 +257,11 @@ internal object WhenOnSealedExhaustivenessChecker : WhenOnClassExhaustivenessChe
|
|||||||
|
|
||||||
object WhenChecker {
|
object WhenChecker {
|
||||||
|
|
||||||
private val exhaustivenessCheckers = listOf(WhenOnBooleanExhaustivenessChecker,
|
private val exhaustivenessCheckers = listOf(
|
||||||
|
WhenOnBooleanExhaustivenessChecker,
|
||||||
WhenOnEnumExhaustivenessChecker,
|
WhenOnEnumExhaustivenessChecker,
|
||||||
WhenOnSealedExhaustivenessChecker)
|
WhenOnSealedExhaustivenessChecker
|
||||||
|
)
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun isWhenByEnum(expression: KtWhenExpression, context: BindingContext) =
|
fun isWhenByEnum(expression: KtWhenExpression, context: BindingContext) =
|
||||||
@@ -276,8 +277,8 @@ object WhenChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getClassDescriptorOfTypeIfSealed(type: KotlinType?): ClassDescriptor?
|
fun getClassDescriptorOfTypeIfSealed(type: KotlinType?): ClassDescriptor? =
|
||||||
= type?.let { TypeUtils.getClassDescriptor(it) }?.takeIf { DescriptorUtils.isSealedClass(it) }
|
type?.let { TypeUtils.getClassDescriptor(it) }?.takeIf { DescriptorUtils.isSealedClass(it) }
|
||||||
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@@ -331,11 +332,11 @@ object WhenChecker {
|
|||||||
is KtWhenConditionWithExpression -> {
|
is KtWhenConditionWithExpression -> {
|
||||||
val constantExpression = condition.expression ?: continue@conditions
|
val constantExpression = condition.expression ?: continue@conditions
|
||||||
val constant = ConstantExpressionEvaluator.getConstant(
|
val constant = ConstantExpressionEvaluator.getConstant(
|
||||||
constantExpression, trace.bindingContext) ?: continue@conditions
|
constantExpression, trace.bindingContext
|
||||||
|
) ?: continue@conditions
|
||||||
if (checkedConstants.contains(constant)) {
|
if (checkedConstants.contains(constant)) {
|
||||||
trace.report(Errors.DUPLICATE_LABEL_IN_WHEN.on(constantExpression))
|
trace.report(Errors.DUPLICATE_LABEL_IN_WHEN.on(constantExpression))
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
checkedConstants.add(constant)
|
checkedConstants.add(constant)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,12 +347,12 @@ object WhenChecker {
|
|||||||
val typeWithIsNegation = type to condition.isNegated
|
val typeWithIsNegation = type to condition.isNegated
|
||||||
if (checkedTypes.contains(typeWithIsNegation)) {
|
if (checkedTypes.contains(typeWithIsNegation)) {
|
||||||
trace.report(Errors.DUPLICATE_LABEL_IN_WHEN.on(typeReference))
|
trace.report(Errors.DUPLICATE_LABEL_IN_WHEN.on(typeReference))
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
checkedTypes.add(typeWithIsNegation)
|
checkedTypes.add(typeWithIsNegation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {}
|
else -> {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-15
@@ -58,8 +58,7 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
|||||||
val worker = builders.pop()
|
val worker = builders.pop()
|
||||||
builder = if (!builders.isEmpty()) {
|
builder = if (!builders.isEmpty()) {
|
||||||
builders.peek()
|
builders.peek()
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
return worker
|
return worker
|
||||||
@@ -70,8 +69,7 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
|||||||
val shouldInlnie = invocationKind != null
|
val shouldInlnie = invocationKind != null
|
||||||
if (builder != null && subroutine is KtFunctionLiteral) {
|
if (builder != null && subroutine is KtFunctionLiteral) {
|
||||||
pushBuilder(subroutine, builder.returnSubroutine, shouldInlnie)
|
pushBuilder(subroutine, builder.returnSubroutine, shouldInlnie)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
pushBuilder(subroutine, subroutine, shouldInlnie)
|
pushBuilder(subroutine, subroutine, shouldInlnie)
|
||||||
}
|
}
|
||||||
delegateBuilder.enterBlockScope(subroutine)
|
delegateBuilder.enterBlockScope(subroutine)
|
||||||
@@ -86,8 +84,7 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
|||||||
val builder = builders.peek()
|
val builder = builders.peek()
|
||||||
if (invocationKind == null) {
|
if (invocationKind == null) {
|
||||||
builder.declareFunction(subroutine, worker.pseudocode)
|
builder.declareFunction(subroutine, worker.pseudocode)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
builder.declareInlinedFunction(subroutine, worker.pseudocode, invocationKind)
|
builder.declareInlinedFunction(subroutine, worker.pseudocode, invocationKind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,7 +130,8 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
|||||||
createUnboundLabel("loop exit point"),
|
createUnboundLabel("loop exit point"),
|
||||||
createUnboundLabel("body entry point"),
|
createUnboundLabel("body entry point"),
|
||||||
createUnboundLabel("body exit point"),
|
createUnboundLabel("body exit point"),
|
||||||
createUnboundLabel("condition entry point"))
|
createUnboundLabel("condition entry point")
|
||||||
|
)
|
||||||
bindLabel(info.entryPoint)
|
bindLabel(info.entryPoint)
|
||||||
elementToLoopInfo.put(expression, info)
|
elementToLoopInfo.put(expression, info)
|
||||||
return info
|
return info
|
||||||
@@ -160,7 +158,8 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
|||||||
val blockInfo = SubroutineInfo(
|
val blockInfo = SubroutineInfo(
|
||||||
subroutine,
|
subroutine,
|
||||||
/* entry point */ createUnboundLabel(),
|
/* entry point */ createUnboundLabel(),
|
||||||
/* exit point */ createUnboundLabel())
|
/* exit point */ createUnboundLabel()
|
||||||
|
)
|
||||||
elementToSubroutineInfo.put(subroutine, blockInfo)
|
elementToSubroutineInfo.put(subroutine, blockInfo)
|
||||||
allBlocks.push(blockInfo)
|
allBlocks.push(blockInfo)
|
||||||
bindLabel(blockInfo.entryPoint)
|
bindLabel(blockInfo.entryPoint)
|
||||||
@@ -175,7 +174,8 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
|||||||
override fun getLoopExitPoint(loop: KtLoopExpression): Label? =// It's quite possible to have null here, see testBreakInsideLocal
|
override fun getLoopExitPoint(loop: KtLoopExpression): Label? =// It's quite possible to have null here, see testBreakInsideLocal
|
||||||
elementToLoopInfo[loop]?.exitPoint
|
elementToLoopInfo[loop]?.exitPoint
|
||||||
|
|
||||||
override fun getSubroutineExitPoint(labelElement: KtElement): Label? =// It's quite possible to have null here, e.g. for non-local returns (see KT-10823)
|
override fun getSubroutineExitPoint(labelElement: KtElement): Label? =
|
||||||
|
// It's quite possible to have null here, e.g. for non-local returns (see KT-10823)
|
||||||
elementToSubroutineInfo[labelElement]?.exitPoint
|
elementToSubroutineInfo[labelElement]?.exitPoint
|
||||||
|
|
||||||
private val currentScope: BlockScope
|
private val currentScope: BlockScope
|
||||||
@@ -256,7 +256,8 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
|||||||
lValue: KtElement,
|
lValue: KtElement,
|
||||||
rValue: PseudoValue,
|
rValue: PseudoValue,
|
||||||
target: AccessTarget,
|
target: AccessTarget,
|
||||||
receiverValues: Map<PseudoValue, ReceiverValue>) {
|
receiverValues: Map<PseudoValue, ReceiverValue>
|
||||||
|
) {
|
||||||
add(WriteValueInstruction(assignment, currentScope, target, receiverValues, lValue, rValue))
|
add(WriteValueInstruction(assignment, currentScope, target, receiverValues, lValue, rValue))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,9 +356,11 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
|||||||
instructionElement: KtElement,
|
instructionElement: KtElement,
|
||||||
valueElement: KtElement?,
|
valueElement: KtElement?,
|
||||||
inputValues: List<PseudoValue>,
|
inputValues: List<PseudoValue>,
|
||||||
kind: MagicKind): MagicInstruction {
|
kind: MagicKind
|
||||||
|
): MagicInstruction {
|
||||||
val instruction = MagicInstruction(
|
val instruction = MagicInstruction(
|
||||||
instructionElement, valueElement, currentScope, inputValues, kind, valueFactory)
|
instructionElement, valueElement, currentScope, inputValues, kind, valueFactory
|
||||||
|
)
|
||||||
add(instruction)
|
add(instruction)
|
||||||
return instruction
|
return instruction
|
||||||
}
|
}
|
||||||
@@ -378,7 +381,8 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
|||||||
valueElement: KtElement,
|
valueElement: KtElement,
|
||||||
resolvedCall: ResolvedCall<*>,
|
resolvedCall: ResolvedCall<*>,
|
||||||
receiverValues: Map<PseudoValue, ReceiverValue>,
|
receiverValues: Map<PseudoValue, ReceiverValue>,
|
||||||
arguments: Map<PseudoValue, ValueParameterDescriptor>): CallInstruction {
|
arguments: Map<PseudoValue, ValueParameterDescriptor>
|
||||||
|
): CallInstruction {
|
||||||
val returnType = resolvedCall.resultingDescriptor.returnType
|
val returnType = resolvedCall.resultingDescriptor.returnType
|
||||||
val instruction = CallInstruction(
|
val instruction = CallInstruction(
|
||||||
valueElement,
|
valueElement,
|
||||||
@@ -386,7 +390,8 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
|||||||
resolvedCall,
|
resolvedCall,
|
||||||
receiverValues,
|
receiverValues,
|
||||||
arguments,
|
arguments,
|
||||||
if (returnType != null && KotlinBuiltIns.isNothing(returnType)) null else valueFactory)
|
if (returnType != null && KotlinBuiltIns.isNothing(returnType)) null else valueFactory
|
||||||
|
)
|
||||||
add(instruction)
|
add(instruction)
|
||||||
return instruction
|
return instruction
|
||||||
}
|
}
|
||||||
@@ -394,7 +399,8 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
|
|||||||
override fun predefinedOperation(
|
override fun predefinedOperation(
|
||||||
expression: KtExpression,
|
expression: KtExpression,
|
||||||
operation: ControlFlowBuilder.PredefinedOperation,
|
operation: ControlFlowBuilder.PredefinedOperation,
|
||||||
inputValues: List<PseudoValue>): OperationInstruction = magic(expression, expression, inputValues, getMagicKind(operation))
|
inputValues: List<PseudoValue>
|
||||||
|
): OperationInstruction = magic(expression, expression, inputValues, getMagicKind(operation))
|
||||||
|
|
||||||
private fun getMagicKind(operation: ControlFlowBuilder.PredefinedOperation) = when (operation) {
|
private fun getMagicKind(operation: ControlFlowBuilder.PredefinedOperation) = when (operation) {
|
||||||
ControlFlowBuilder.PredefinedOperation.AND -> MagicKind.AND
|
ControlFlowBuilder.PredefinedOperation.AND -> MagicKind.AND
|
||||||
|
|||||||
@@ -63,7 +63,8 @@ fun getReceiverTypePredicate(resolvedCall: ResolvedCall<*>, receiverValue: Recei
|
|||||||
resolvedCall.dispatchReceiver -> {
|
resolvedCall.dispatchReceiver -> {
|
||||||
val rootCallableDescriptors = callableDescriptor.findTopMostOverriddenDescriptors()
|
val rootCallableDescriptors = callableDescriptor.findTopMostOverriddenDescriptors()
|
||||||
return or(rootCallableDescriptors.mapNotNull {
|
return or(rootCallableDescriptors.mapNotNull {
|
||||||
it.dispatchReceiverParameter?.type?.let { TypeUtils.makeNullableIfNeeded(it, resolvedCall.call.isSafeCall()) }?.getSubtypesPredicate()
|
it.dispatchReceiverParameter?.type?.let { TypeUtils.makeNullableIfNeeded(it, resolvedCall.call.isSafeCall()) }
|
||||||
|
?.getSubtypesPredicate()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,8 +165,7 @@ fun getExpectedTypePredicate(
|
|||||||
val receiverValue = it.receiverValues[value]
|
val receiverValue = it.receiverValues[value]
|
||||||
if (receiverValue != null) {
|
if (receiverValue != null) {
|
||||||
typePredicates.add(getReceiverTypePredicate((accessTarget as AccessTarget.Call).resolvedCall, receiverValue))
|
typePredicates.add(getReceiverTypePredicate((accessTarget as AccessTarget.Call).resolvedCall, receiverValue))
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val expectedType = when (accessTarget) {
|
val expectedType = when (accessTarget) {
|
||||||
is AccessTarget.Call ->
|
is AccessTarget.Call ->
|
||||||
(accessTarget.resolvedCall.resultingDescriptor as? VariableDescriptor)?.type
|
(accessTarget.resolvedCall.resultingDescriptor as? VariableDescriptor)?.type
|
||||||
@@ -182,8 +182,7 @@ fun getExpectedTypePredicate(
|
|||||||
val receiverValue = it.receiverValues[value]
|
val receiverValue = it.receiverValues[value]
|
||||||
if (receiverValue != null) {
|
if (receiverValue != null) {
|
||||||
typePredicates.add(getReceiverTypePredicate(it.resolvedCall, receiverValue))
|
typePredicates.add(getReceiverTypePredicate(it.resolvedCall, receiverValue))
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
it.arguments[value]?.let { parameter ->
|
it.arguments[value]?.let { parameter ->
|
||||||
val expectedType = when (it.resolvedCall.valueArguments[parameter]) {
|
val expectedType = when (it.resolvedCall.valueArguments[parameter]) {
|
||||||
is VarargValueArgument ->
|
is VarargValueArgument ->
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ import org.jetbrains.kotlin.resolve.BindingTrace
|
|||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||||
|
|
||||||
internal class PsiConditionParser(val trace: BindingTrace, val dispatcher: PsiContractParserDispatcher) : KtVisitor<BooleanExpression?, Unit>() {
|
internal class PsiConditionParser(val trace: BindingTrace, val dispatcher: PsiContractParserDispatcher) :
|
||||||
|
KtVisitor<BooleanExpression?, Unit>() {
|
||||||
override fun visitIsExpression(expression: KtIsExpression, data: Unit): BooleanExpression? {
|
override fun visitIsExpression(expression: KtIsExpression, data: Unit): BooleanExpression? {
|
||||||
val variable = dispatcher.parseVariable(expression.leftHandSide) ?: return null
|
val variable = dispatcher.parseVariable(expression.leftHandSide) ?: return null
|
||||||
val typeReference = expression.typeReference ?: return null
|
val typeReference = expression.typeReference ?: return null
|
||||||
@@ -101,7 +102,12 @@ internal class PsiConditionParser(val trace: BindingTrace, val dispatcher: PsiCo
|
|||||||
if (expression.operationToken != KtTokens.EXCL) return super.visitUnaryExpression(expression, data)
|
if (expression.operationToken != KtTokens.EXCL) return super.visitUnaryExpression(expression, data)
|
||||||
val arg = expression.baseExpression?.accept(this, data) ?: return null
|
val arg = expression.baseExpression?.accept(this, data) ?: return null
|
||||||
if (arg !is ContractDescriptionValue) {
|
if (arg !is ContractDescriptionValue) {
|
||||||
trace.report(Errors.ERROR_IN_CONTRACT_DESCRIPTION.on(expression.baseExpression!!, "negations in contract description can be applied only to variables/values"))
|
trace.report(
|
||||||
|
Errors.ERROR_IN_CONTRACT_DESCRIPTION.on(
|
||||||
|
expression.baseExpression!!,
|
||||||
|
"negations in contract description can be applied only to variables/values"
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return LogicalNot(arg)
|
return LogicalNot(arg)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,4 +24,5 @@ internal interface PsiEffectParser {
|
|||||||
fun tryParseEffect(expression: KtExpression): EffectDeclaration?
|
fun tryParseEffect(expression: KtExpression): EffectDeclaration?
|
||||||
}
|
}
|
||||||
|
|
||||||
internal abstract class AbstractPsiEffectParser(val trace: BindingTrace, val contractParserDispatcher: PsiContractParserDispatcher) : PsiEffectParser
|
internal abstract class AbstractPsiEffectParser(val trace: BindingTrace, val contractParserDispatcher: PsiContractParserDispatcher) :
|
||||||
|
PsiEffectParser
|
||||||
|
|||||||
@@ -47,7 +47,8 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val DEFAULT: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
|
@JvmField
|
||||||
|
val DEFAULT: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
|
||||||
override fun mark(element: PsiElement): List<TextRange> {
|
override fun mark(element: PsiElement): List<TextRange> {
|
||||||
when (element) {
|
when (element) {
|
||||||
is KtObjectLiteralExpression -> {
|
is KtObjectLiteralExpression -> {
|
||||||
@@ -75,7 +76,8 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val DECLARATION_RETURN_TYPE: PositioningStrategy<KtDeclaration> = object : PositioningStrategy<KtDeclaration>() {
|
@JvmField
|
||||||
|
val DECLARATION_RETURN_TYPE: PositioningStrategy<KtDeclaration> = object : PositioningStrategy<KtDeclaration>() {
|
||||||
override fun mark(element: KtDeclaration): List<TextRange> {
|
override fun mark(element: KtDeclaration): List<TextRange> {
|
||||||
return markElement(getElementToMark(element))
|
return markElement(getElementToMark(element))
|
||||||
}
|
}
|
||||||
@@ -97,7 +99,8 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val ACTUAL_DECLARATION_NAME: PositioningStrategy<KtNamedDeclaration> = object : DeclarationHeader<KtNamedDeclaration>() {
|
@JvmField
|
||||||
|
val ACTUAL_DECLARATION_NAME: PositioningStrategy<KtNamedDeclaration> = object : DeclarationHeader<KtNamedDeclaration>() {
|
||||||
override fun mark(element: KtNamedDeclaration): List<TextRange> {
|
override fun mark(element: KtNamedDeclaration): List<TextRange> {
|
||||||
val nameIdentifier = element.nameIdentifier
|
val nameIdentifier = element.nameIdentifier
|
||||||
return when {
|
return when {
|
||||||
@@ -125,7 +128,8 @@ object PositioningStrategies {
|
|||||||
|
|
||||||
private val classKindTokens = TokenSet.create(KtTokens.CLASS_KEYWORD, KtTokens.OBJECT_KEYWORD, KtTokens.INTERFACE_KEYWORD)
|
private val classKindTokens = TokenSet.create(KtTokens.CLASS_KEYWORD, KtTokens.OBJECT_KEYWORD, KtTokens.INTERFACE_KEYWORD)
|
||||||
|
|
||||||
@JvmField val INCOMPATIBLE_DECLARATION: PositioningStrategy<KtNamedDeclaration> = object : DeclarationHeader<KtNamedDeclaration>() {
|
@JvmField
|
||||||
|
val INCOMPATIBLE_DECLARATION: PositioningStrategy<KtNamedDeclaration> = object : DeclarationHeader<KtNamedDeclaration>() {
|
||||||
override fun markDiagnostic(diagnostic: ParametrizedDiagnostic<out KtNamedDeclaration>): List<TextRange> {
|
override fun markDiagnostic(diagnostic: ParametrizedDiagnostic<out KtNamedDeclaration>): List<TextRange> {
|
||||||
val element = diagnostic.psiElement
|
val element = diagnostic.psiElement
|
||||||
val callableDeclaration = element as? KtCallableDeclaration
|
val callableDeclaration = element as? KtCallableDeclaration
|
||||||
@@ -141,8 +145,7 @@ object PositioningStrategies {
|
|||||||
?: element.nameIdentifier
|
?: element.nameIdentifier
|
||||||
if (startElement != null && endElement != null) {
|
if (startElement != null && endElement != null) {
|
||||||
return markRange(startElement, endElement)
|
return markRange(startElement, endElement)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
endElement
|
endElement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -181,7 +184,8 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val DECLARATION_NAME: PositioningStrategy<KtNamedDeclaration> = object : DeclarationHeader<KtNamedDeclaration>() {
|
@JvmField
|
||||||
|
val DECLARATION_NAME: PositioningStrategy<KtNamedDeclaration> = object : DeclarationHeader<KtNamedDeclaration>() {
|
||||||
override fun mark(element: KtNamedDeclaration): List<TextRange> {
|
override fun mark(element: KtNamedDeclaration): List<TextRange> {
|
||||||
val nameIdentifier = element.nameIdentifier
|
val nameIdentifier = element.nameIdentifier
|
||||||
if (nameIdentifier != null) {
|
if (nameIdentifier != null) {
|
||||||
@@ -202,7 +206,8 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val DECLARATION_SIGNATURE: PositioningStrategy<KtDeclaration> = object : DeclarationHeader<KtDeclaration>() {
|
@JvmField
|
||||||
|
val DECLARATION_SIGNATURE: PositioningStrategy<KtDeclaration> = object : DeclarationHeader<KtDeclaration>() {
|
||||||
override fun mark(element: KtDeclaration): List<TextRange> {
|
override fun mark(element: KtDeclaration): List<TextRange> {
|
||||||
when (element) {
|
when (element) {
|
||||||
is KtConstructor<*> -> {
|
is KtConstructor<*> -> {
|
||||||
@@ -216,13 +221,11 @@ object PositioningStrategies {
|
|||||||
?: element.valueParameterList
|
?: element.valueParameterList
|
||||||
?: element.nameIdentifier
|
?: element.nameIdentifier
|
||||||
?: element
|
?: element
|
||||||
val startElement
|
val startElement = if (element is KtFunctionLiteral) {
|
||||||
= if (element is KtFunctionLiteral) {
|
|
||||||
element.getReceiverTypeReference()
|
element.getReceiverTypeReference()
|
||||||
?: element.getValueParameterList()
|
?: element.getValueParameterList()
|
||||||
?: element
|
?: element
|
||||||
}
|
} else element
|
||||||
else element
|
|
||||||
return markRange(startElement, endOfSignatureElement)
|
return markRange(startElement, endOfSignatureElement)
|
||||||
}
|
}
|
||||||
is KtProperty -> {
|
is KtProperty -> {
|
||||||
@@ -239,7 +242,8 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
is KtClass -> {
|
is KtClass -> {
|
||||||
val nameAsDeclaration = element.nameIdentifier ?: return markElement(element)
|
val nameAsDeclaration = element.nameIdentifier ?: return markElement(element)
|
||||||
val primaryConstructorParameterList = element.getPrimaryConstructorParameterList() ?: return markElement(nameAsDeclaration)
|
val primaryConstructorParameterList =
|
||||||
|
element.getPrimaryConstructorParameterList() ?: return markElement(nameAsDeclaration)
|
||||||
return markRange(nameAsDeclaration, primaryConstructorParameterList)
|
return markRange(nameAsDeclaration, primaryConstructorParameterList)
|
||||||
}
|
}
|
||||||
is KtObjectDeclaration -> {
|
is KtObjectDeclaration -> {
|
||||||
@@ -253,7 +257,8 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val DECLARATION_SIGNATURE_OR_DEFAULT: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
|
@JvmField
|
||||||
|
val DECLARATION_SIGNATURE_OR_DEFAULT: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
|
||||||
override fun mark(element: PsiElement): List<TextRange> {
|
override fun mark(element: PsiElement): List<TextRange> {
|
||||||
return if (element is KtDeclaration)
|
return if (element is KtDeclaration)
|
||||||
DECLARATION_SIGNATURE.mark(element)
|
DECLARATION_SIGNATURE.mark(element)
|
||||||
@@ -269,26 +274,24 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT: PositioningStrategy<KtDeclaration> = object : PositioningStrategy<KtDeclaration>() {
|
@JvmField
|
||||||
|
val NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT: PositioningStrategy<KtDeclaration> = object : PositioningStrategy<KtDeclaration>() {
|
||||||
override fun mark(element: KtDeclaration): List<TextRange> =
|
override fun mark(element: KtDeclaration): List<TextRange> =
|
||||||
markElement(
|
markElement(
|
||||||
when (element) {
|
when (element) {
|
||||||
is KtClassOrObject ->
|
is KtClassOrObject ->
|
||||||
element.getDeclarationKeyword() ?:
|
element.getDeclarationKeyword() ?: element.nameIdentifier ?: element
|
||||||
element.nameIdentifier ?:
|
|
||||||
element
|
|
||||||
|
|
||||||
is KtNamedFunction ->
|
is KtNamedFunction ->
|
||||||
element.modifierList?.getModifier(KtTokens.INLINE_KEYWORD) ?:
|
element.modifierList?.getModifier(KtTokens.INLINE_KEYWORD) ?: element.funKeyword ?: element
|
||||||
element.funKeyword ?:
|
|
||||||
element
|
|
||||||
|
|
||||||
else -> element
|
else -> element
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val TYPE_PARAMETERS_OR_DECLARATION_SIGNATURE: PositioningStrategy<KtDeclaration> = object : PositioningStrategy<KtDeclaration>() {
|
@JvmField
|
||||||
|
val TYPE_PARAMETERS_OR_DECLARATION_SIGNATURE: PositioningStrategy<KtDeclaration> = object : PositioningStrategy<KtDeclaration>() {
|
||||||
override fun mark(element: KtDeclaration): List<TextRange> {
|
override fun mark(element: KtDeclaration): List<TextRange> {
|
||||||
if (element is KtTypeParameterListOwner) {
|
if (element is KtTypeParameterListOwner) {
|
||||||
val jetTypeParameterList = element.typeParameterList
|
val jetTypeParameterList = element.typeParameterList
|
||||||
@@ -300,19 +303,26 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val ABSTRACT_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.ABSTRACT_KEYWORD)
|
@JvmField
|
||||||
|
val ABSTRACT_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.ABSTRACT_KEYWORD)
|
||||||
|
|
||||||
@JvmField val OPEN_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.OPEN_KEYWORD)
|
@JvmField
|
||||||
|
val OPEN_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.OPEN_KEYWORD)
|
||||||
|
|
||||||
@JvmField val OVERRIDE_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.OVERRIDE_KEYWORD)
|
@JvmField
|
||||||
|
val OVERRIDE_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.OVERRIDE_KEYWORD)
|
||||||
|
|
||||||
@JvmField val PRIVATE_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.PRIVATE_KEYWORD)
|
@JvmField
|
||||||
|
val PRIVATE_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.PRIVATE_KEYWORD)
|
||||||
|
|
||||||
@JvmField val LATEINIT_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.LATEINIT_KEYWORD)
|
@JvmField
|
||||||
|
val LATEINIT_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.LATEINIT_KEYWORD)
|
||||||
|
|
||||||
@JvmField val VARIANCE_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.IN_KEYWORD, KtTokens.OUT_KEYWORD)
|
@JvmField
|
||||||
|
val VARIANCE_MODIFIER: PositioningStrategy<KtModifierListOwner> = modifierSetPosition(KtTokens.IN_KEYWORD, KtTokens.OUT_KEYWORD)
|
||||||
|
|
||||||
@JvmField val FOR_REDECLARATION: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
|
@JvmField
|
||||||
|
val FOR_REDECLARATION: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
|
||||||
override fun mark(element: PsiElement): List<TextRange> {
|
override fun mark(element: PsiElement): List<TextRange> {
|
||||||
val nameIdentifier = when (element) {
|
val nameIdentifier = when (element) {
|
||||||
is KtNamedDeclaration -> element.nameIdentifier
|
is KtNamedDeclaration -> element.nameIdentifier
|
||||||
@@ -325,7 +335,8 @@ object PositioningStrategies {
|
|||||||
return markElement(nameIdentifier ?: element)
|
return markElement(nameIdentifier ?: element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@JvmField val FOR_UNRESOLVED_REFERENCE: PositioningStrategy<KtReferenceExpression> = object : PositioningStrategy<KtReferenceExpression>() {
|
@JvmField
|
||||||
|
val FOR_UNRESOLVED_REFERENCE: PositioningStrategy<KtReferenceExpression> = object : PositioningStrategy<KtReferenceExpression>() {
|
||||||
override fun mark(element: KtReferenceExpression): List<TextRange> {
|
override fun mark(element: KtReferenceExpression): List<TextRange> {
|
||||||
if (element is KtArrayAccessExpression) {
|
if (element is KtArrayAccessExpression) {
|
||||||
val ranges = element.bracketRanges
|
val ranges = element.bracketRanges
|
||||||
@@ -337,7 +348,8 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic fun modifierSetPosition(vararg tokens: KtModifierKeywordToken): PositioningStrategy<KtModifierListOwner> {
|
@JvmStatic
|
||||||
|
fun modifierSetPosition(vararg tokens: KtModifierKeywordToken): PositioningStrategy<KtModifierListOwner> {
|
||||||
return object : PositioningStrategy<KtModifierListOwner>() {
|
return object : PositioningStrategy<KtModifierListOwner>() {
|
||||||
override fun mark(element: KtModifierListOwner): List<TextRange> {
|
override fun mark(element: KtModifierListOwner): List<TextRange> {
|
||||||
val modifierList = element.modifierList.sure { "No modifier list, but modifier has been found by the analyzer" }
|
val modifierList = element.modifierList.sure { "No modifier list, but modifier has been found by the analyzer" }
|
||||||
@@ -353,15 +365,18 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val ARRAY_ACCESS: PositioningStrategy<KtArrayAccessExpression> = object : PositioningStrategy<KtArrayAccessExpression>() {
|
@JvmField
|
||||||
|
val ARRAY_ACCESS: PositioningStrategy<KtArrayAccessExpression> = object : PositioningStrategy<KtArrayAccessExpression>() {
|
||||||
override fun mark(element: KtArrayAccessExpression): List<TextRange> {
|
override fun mark(element: KtArrayAccessExpression): List<TextRange> {
|
||||||
return markElement(element.indicesNode)
|
return markElement(element.indicesNode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val VISIBILITY_MODIFIER: PositioningStrategy<KtModifierListOwner> = object : PositioningStrategy<KtModifierListOwner>() {
|
@JvmField
|
||||||
|
val VISIBILITY_MODIFIER: PositioningStrategy<KtModifierListOwner> = object : PositioningStrategy<KtModifierListOwner>() {
|
||||||
override fun mark(element: KtModifierListOwner): List<TextRange> {
|
override fun mark(element: KtModifierListOwner): List<TextRange> {
|
||||||
val visibilityTokens = listOf(KtTokens.PRIVATE_KEYWORD, KtTokens.PROTECTED_KEYWORD, KtTokens.PUBLIC_KEYWORD, KtTokens.INTERNAL_KEYWORD)
|
val visibilityTokens =
|
||||||
|
listOf(KtTokens.PRIVATE_KEYWORD, KtTokens.PROTECTED_KEYWORD, KtTokens.PUBLIC_KEYWORD, KtTokens.INTERNAL_KEYWORD)
|
||||||
val modifierList = element.modifierList
|
val modifierList = element.modifierList
|
||||||
|
|
||||||
val result = visibilityTokens.mapNotNull { modifierList?.getModifier(it)?.textRange }
|
val result = visibilityTokens.mapNotNull { modifierList?.getModifier(it)?.textRange }
|
||||||
@@ -380,38 +395,44 @@ object PositioningStrategies {
|
|||||||
is KtPropertyAccessor -> element.namePlaceholder
|
is KtPropertyAccessor -> element.namePlaceholder
|
||||||
is KtAnonymousInitializer -> element
|
is KtAnonymousInitializer -> element
|
||||||
else -> throw IllegalArgumentException(
|
else -> throw IllegalArgumentException(
|
||||||
"Can't find text range for element '${element::class.java.canonicalName}' with the text '${element.text}'")
|
"Can't find text range for element '${element::class.java.canonicalName}' with the text '${element.text}'"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return markElement(elementToMark)
|
return markElement(elementToMark)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val VARIANCE_IN_PROJECTION: PositioningStrategy<KtTypeProjection> = object : PositioningStrategy<KtTypeProjection>() {
|
@JvmField
|
||||||
|
val VARIANCE_IN_PROJECTION: PositioningStrategy<KtTypeProjection> = object : PositioningStrategy<KtTypeProjection>() {
|
||||||
override fun mark(element: KtTypeProjection): List<TextRange> {
|
override fun mark(element: KtTypeProjection): List<TextRange> {
|
||||||
return markElement(element.projectionToken!!)
|
return markElement(element.projectionToken!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val PARAMETER_DEFAULT_VALUE: PositioningStrategy<KtParameter> = object : PositioningStrategy<KtParameter>() {
|
@JvmField
|
||||||
|
val PARAMETER_DEFAULT_VALUE: PositioningStrategy<KtParameter> = object : PositioningStrategy<KtParameter>() {
|
||||||
override fun mark(element: KtParameter): List<TextRange> {
|
override fun mark(element: KtParameter): List<TextRange> {
|
||||||
return markNode(element.defaultValue!!.node)
|
return markNode(element.defaultValue!!.node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val PARAMETER_VARARG_MODIFIER: PositioningStrategy<KtParameter> = object : PositioningStrategy<KtParameter>() {
|
@JvmField
|
||||||
|
val PARAMETER_VARARG_MODIFIER: PositioningStrategy<KtParameter> = object : PositioningStrategy<KtParameter>() {
|
||||||
override fun mark(element: KtParameter): List<TextRange> {
|
override fun mark(element: KtParameter): List<TextRange> {
|
||||||
val varargModifier = element.modifierList!!.getModifier(KtTokens.VARARG_KEYWORD)!!
|
val varargModifier = element.modifierList!!.getModifier(KtTokens.VARARG_KEYWORD)!!
|
||||||
return markNode(varargModifier.node)
|
return markNode(varargModifier.node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val CALL_ELEMENT: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
|
@JvmField
|
||||||
|
val CALL_ELEMENT: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
|
||||||
override fun mark(element: PsiElement): List<TextRange> {
|
override fun mark(element: PsiElement): List<TextRange> {
|
||||||
return markElement((element as? KtCallElement)?.calleeExpression ?: element)
|
return markElement((element as? KtCallElement)?.calleeExpression ?: element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val DECLARATION_WITH_BODY: PositioningStrategy<KtDeclarationWithBody> = object : PositioningStrategy<KtDeclarationWithBody>() {
|
@JvmField
|
||||||
|
val DECLARATION_WITH_BODY: PositioningStrategy<KtDeclarationWithBody> = object : PositioningStrategy<KtDeclarationWithBody>() {
|
||||||
override fun mark(element: KtDeclarationWithBody): List<TextRange> {
|
override fun mark(element: KtDeclarationWithBody): List<TextRange> {
|
||||||
val lastBracketRange = (element.bodyExpression as? KtBlockExpression)?.lastBracketRange
|
val lastBracketRange = (element.bodyExpression as? KtBlockExpression)?.lastBracketRange
|
||||||
return if (lastBracketRange != null)
|
return if (lastBracketRange != null)
|
||||||
@@ -425,7 +446,8 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val VAL_OR_VAR_NODE: PositioningStrategy<KtNamedDeclaration> = object : PositioningStrategy<KtNamedDeclaration>() {
|
@JvmField
|
||||||
|
val VAL_OR_VAR_NODE: PositioningStrategy<KtNamedDeclaration> = object : PositioningStrategy<KtNamedDeclaration>() {
|
||||||
override fun mark(element: KtNamedDeclaration): List<TextRange> {
|
override fun mark(element: KtNamedDeclaration): List<TextRange> {
|
||||||
return when (element) {
|
return when (element) {
|
||||||
is KtParameter -> markElement(element.valOrVarKeyword ?: element)
|
is KtParameter -> markElement(element.valOrVarKeyword ?: element)
|
||||||
@@ -435,25 +457,29 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val ELSE_ENTRY: PositioningStrategy<KtWhenEntry> = object : PositioningStrategy<KtWhenEntry>() {
|
@JvmField
|
||||||
|
val ELSE_ENTRY: PositioningStrategy<KtWhenEntry> = object : PositioningStrategy<KtWhenEntry>() {
|
||||||
override fun mark(element: KtWhenEntry): List<TextRange> {
|
override fun mark(element: KtWhenEntry): List<TextRange> {
|
||||||
return markElement(element.elseKeyword!!)
|
return markElement(element.elseKeyword!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val WHEN_EXPRESSION: PositioningStrategy<KtWhenExpression> = object : PositioningStrategy<KtWhenExpression>() {
|
@JvmField
|
||||||
|
val WHEN_EXPRESSION: PositioningStrategy<KtWhenExpression> = object : PositioningStrategy<KtWhenExpression>() {
|
||||||
override fun mark(element: KtWhenExpression): List<TextRange> {
|
override fun mark(element: KtWhenExpression): List<TextRange> {
|
||||||
return markElement(element.whenKeyword)
|
return markElement(element.whenKeyword)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val WHEN_CONDITION_IN_RANGE: PositioningStrategy<KtWhenConditionInRange> = object : PositioningStrategy<KtWhenConditionInRange>() {
|
@JvmField
|
||||||
|
val WHEN_CONDITION_IN_RANGE: PositioningStrategy<KtWhenConditionInRange> = object : PositioningStrategy<KtWhenConditionInRange>() {
|
||||||
override fun mark(element: KtWhenConditionInRange): List<TextRange> {
|
override fun mark(element: KtWhenConditionInRange): List<TextRange> {
|
||||||
return markElement(element.operationReference)
|
return markElement(element.operationReference)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val SPECIAL_CONSTRUCT_TOKEN: PositioningStrategy<KtExpression> = object : PositioningStrategy<KtExpression>() {
|
@JvmField
|
||||||
|
val SPECIAL_CONSTRUCT_TOKEN: PositioningStrategy<KtExpression> = object : PositioningStrategy<KtExpression>() {
|
||||||
override fun mark(element: KtExpression): List<TextRange> =
|
override fun mark(element: KtExpression): List<TextRange> =
|
||||||
when (element) {
|
when (element) {
|
||||||
is KtWhenExpression -> markElement(element.whenKeyword)
|
is KtWhenExpression -> markElement(element.whenKeyword)
|
||||||
@@ -463,13 +489,15 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val NULLABLE_TYPE: PositioningStrategy<KtNullableType> = object : PositioningStrategy<KtNullableType>() {
|
@JvmField
|
||||||
|
val NULLABLE_TYPE: PositioningStrategy<KtNullableType> = object : PositioningStrategy<KtNullableType>() {
|
||||||
override fun mark(element: KtNullableType): List<TextRange> {
|
override fun mark(element: KtNullableType): List<TextRange> {
|
||||||
return markNode(element.questionMarkNode)
|
return markNode(element.questionMarkNode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val CALL_EXPRESSION: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
|
@JvmField
|
||||||
|
val CALL_EXPRESSION: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
|
||||||
override fun mark(element: PsiElement): List<TextRange> {
|
override fun mark(element: PsiElement): List<TextRange> {
|
||||||
if (element is KtCallExpression) {
|
if (element is KtCallExpression) {
|
||||||
return markRange(element, element.typeArgumentList ?: element.calleeExpression ?: element)
|
return markRange(element, element.typeArgumentList ?: element.calleeExpression ?: element)
|
||||||
@@ -478,13 +506,15 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val VALUE_ARGUMENTS: PositioningStrategy<KtElement> = object : PositioningStrategy<KtElement>() {
|
@JvmField
|
||||||
|
val VALUE_ARGUMENTS: PositioningStrategy<KtElement> = object : PositioningStrategy<KtElement>() {
|
||||||
override fun mark(element: KtElement): List<TextRange> {
|
override fun mark(element: KtElement): List<TextRange> {
|
||||||
return markElement((element as? KtValueArgumentList)?.rightParenthesis ?: element)
|
return markElement((element as? KtValueArgumentList)?.rightParenthesis ?: element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val FUNCTION_PARAMETERS: PositioningStrategy<KtFunction> = object : PositioningStrategy<KtFunction>() {
|
@JvmField
|
||||||
|
val FUNCTION_PARAMETERS: PositioningStrategy<KtFunction> = object : PositioningStrategy<KtFunction>() {
|
||||||
override fun mark(element: KtFunction): List<TextRange> {
|
override fun mark(element: KtFunction): List<TextRange> {
|
||||||
val valueParameterList = element.valueParameterList
|
val valueParameterList = element.valueParameterList
|
||||||
if (valueParameterList != null) {
|
if (valueParameterList != null) {
|
||||||
@@ -497,7 +527,8 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val CUT_CHAR_QUOTES: PositioningStrategy<KtElement> = object : PositioningStrategy<KtElement>() {
|
@JvmField
|
||||||
|
val CUT_CHAR_QUOTES: PositioningStrategy<KtElement> = object : PositioningStrategy<KtElement>() {
|
||||||
override fun mark(element: KtElement): List<TextRange> {
|
override fun mark(element: KtElement): List<TextRange> {
|
||||||
if (element is KtConstantExpression) {
|
if (element is KtConstantExpression) {
|
||||||
if (element.node.elementType == KtNodeTypes.CHARACTER_CONSTANT) {
|
if (element.node.elementType == KtNodeTypes.CHARACTER_CONSTANT) {
|
||||||
@@ -509,7 +540,8 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val LONG_LITERAL_SUFFIX: PositioningStrategy<KtElement> = object : PositioningStrategy<KtElement>() {
|
@JvmField
|
||||||
|
val LONG_LITERAL_SUFFIX: PositioningStrategy<KtElement> = object : PositioningStrategy<KtElement>() {
|
||||||
override fun mark(element: KtElement): List<TextRange> {
|
override fun mark(element: KtElement): List<TextRange> {
|
||||||
if (element is KtConstantExpression) {
|
if (element is KtConstantExpression) {
|
||||||
if (element.node.elementType == KtNodeTypes.INTEGER_CONSTANT) {
|
if (element.node.elementType == KtNodeTypes.INTEGER_CONSTANT) {
|
||||||
@@ -521,19 +553,22 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val UNREACHABLE_CODE: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
|
@JvmField
|
||||||
|
val UNREACHABLE_CODE: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
|
||||||
override fun markDiagnostic(diagnostic: ParametrizedDiagnostic<out PsiElement>): List<TextRange> {
|
override fun markDiagnostic(diagnostic: ParametrizedDiagnostic<out PsiElement>): List<TextRange> {
|
||||||
return Errors.UNREACHABLE_CODE.cast(diagnostic).a
|
return Errors.UNREACHABLE_CODE.cast(diagnostic).a
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val AS_TYPE: PositioningStrategy<KtBinaryExpressionWithTypeRHS> = object : PositioningStrategy<KtBinaryExpressionWithTypeRHS>() {
|
@JvmField
|
||||||
|
val AS_TYPE: PositioningStrategy<KtBinaryExpressionWithTypeRHS> = object : PositioningStrategy<KtBinaryExpressionWithTypeRHS>() {
|
||||||
override fun mark(element: KtBinaryExpressionWithTypeRHS): List<TextRange> {
|
override fun mark(element: KtBinaryExpressionWithTypeRHS): List<TextRange> {
|
||||||
return markRange(element.operationReference, element)
|
return markRange(element.operationReference, element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val COMPANION_OBJECT: PositioningStrategy<KtObjectDeclaration> = object : PositioningStrategy<KtObjectDeclaration>() {
|
@JvmField
|
||||||
|
val COMPANION_OBJECT: PositioningStrategy<KtObjectDeclaration> = object : PositioningStrategy<KtObjectDeclaration>() {
|
||||||
override fun mark(element: KtObjectDeclaration): List<TextRange> {
|
override fun mark(element: KtObjectDeclaration): List<TextRange> {
|
||||||
if (element.hasModifier(KtTokens.COMPANION_KEYWORD)) {
|
if (element.hasModifier(KtTokens.COMPANION_KEYWORD)) {
|
||||||
return modifierSetPosition(KtTokens.COMPANION_KEYWORD).mark(element)
|
return modifierSetPosition(KtTokens.COMPANION_KEYWORD).mark(element)
|
||||||
@@ -542,7 +577,8 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val SECONDARY_CONSTRUCTOR_DELEGATION_CALL: PositioningStrategy<KtConstructorDelegationCall> =
|
@JvmField
|
||||||
|
val SECONDARY_CONSTRUCTOR_DELEGATION_CALL: PositioningStrategy<KtConstructorDelegationCall> =
|
||||||
object : PositioningStrategy<KtConstructorDelegationCall>() {
|
object : PositioningStrategy<KtConstructorDelegationCall>() {
|
||||||
override fun mark(element: KtConstructorDelegationCall): List<TextRange> {
|
override fun mark(element: KtConstructorDelegationCall): List<TextRange> {
|
||||||
if (element.isImplicit) {
|
if (element.isImplicit) {
|
||||||
@@ -554,26 +590,30 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val DELEGATOR_SUPER_CALL: PositioningStrategy<KtEnumEntry> = object: PositioningStrategy<KtEnumEntry>() {
|
@JvmField
|
||||||
|
val DELEGATOR_SUPER_CALL: PositioningStrategy<KtEnumEntry> = object : PositioningStrategy<KtEnumEntry>() {
|
||||||
override fun mark(element: KtEnumEntry): List<TextRange> {
|
override fun mark(element: KtEnumEntry): List<TextRange> {
|
||||||
val specifiers = element.superTypeListEntries
|
val specifiers = element.superTypeListEntries
|
||||||
return markElement(if (specifiers.isEmpty()) element else specifiers[0])
|
return markElement(if (specifiers.isEmpty()) element else specifiers[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val UNUSED_VALUE: PositioningStrategy<KtBinaryExpression> = object: PositioningStrategy<KtBinaryExpression>() {
|
@JvmField
|
||||||
|
val UNUSED_VALUE: PositioningStrategy<KtBinaryExpression> = object : PositioningStrategy<KtBinaryExpression>() {
|
||||||
override fun mark(element: KtBinaryExpression): List<TextRange> {
|
override fun mark(element: KtBinaryExpression): List<TextRange> {
|
||||||
return listOf(TextRange(element.left!!.startOffset, element.operationReference.endOffset))
|
return listOf(TextRange(element.left!!.startOffset, element.operationReference.endOffset))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val USELESS_ELVIS: PositioningStrategy<KtBinaryExpression> = object: PositioningStrategy<KtBinaryExpression>() {
|
@JvmField
|
||||||
|
val USELESS_ELVIS: PositioningStrategy<KtBinaryExpression> = object : PositioningStrategy<KtBinaryExpression>() {
|
||||||
override fun mark(element: KtBinaryExpression): List<TextRange> {
|
override fun mark(element: KtBinaryExpression): List<TextRange> {
|
||||||
return listOf(TextRange(element.operationReference.startOffset, element.endOffset))
|
return listOf(TextRange(element.operationReference.startOffset, element.endOffset))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val IMPORT_ALIAS: PositioningStrategy<KtImportDirective> = object: PositioningStrategy<KtImportDirective>() {
|
@JvmField
|
||||||
|
val IMPORT_ALIAS: PositioningStrategy<KtImportDirective> = object : PositioningStrategy<KtImportDirective>() {
|
||||||
override fun mark(element: KtImportDirective): List<TextRange> {
|
override fun mark(element: KtImportDirective): List<TextRange> {
|
||||||
element.alias?.nameIdentifier?.let { return markElement(it) }
|
element.alias?.nameIdentifier?.let { return markElement(it) }
|
||||||
element.importedReference?.let {
|
element.importedReference?.let {
|
||||||
@@ -586,7 +626,8 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val RETURN_WITH_LABEL: PositioningStrategy<KtReturnExpression> = object: PositioningStrategy<KtReturnExpression>() {
|
@JvmField
|
||||||
|
val RETURN_WITH_LABEL: PositioningStrategy<KtReturnExpression> = object : PositioningStrategy<KtReturnExpression>() {
|
||||||
override fun mark(element: KtReturnExpression): List<TextRange> {
|
override fun mark(element: KtReturnExpression): List<TextRange> {
|
||||||
val labeledExpression = element.labeledExpression
|
val labeledExpression = element.labeledExpression
|
||||||
if (labeledExpression != null) {
|
if (labeledExpression != null) {
|
||||||
@@ -597,7 +638,8 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val RECEIVER: PositioningStrategy<KtCallableDeclaration> = object : DeclarationHeader<KtCallableDeclaration>() {
|
@JvmField
|
||||||
|
val RECEIVER: PositioningStrategy<KtCallableDeclaration> = object : DeclarationHeader<KtCallableDeclaration>() {
|
||||||
override fun mark(element: KtCallableDeclaration): List<TextRange> {
|
override fun mark(element: KtCallableDeclaration): List<TextRange> {
|
||||||
element.receiverTypeReference?.let { return markElement(it) }
|
element.receiverTypeReference?.let { return markElement(it) }
|
||||||
return DEFAULT.mark(element)
|
return DEFAULT.mark(element)
|
||||||
|
|||||||
+4
-3
@@ -20,10 +20,11 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
|
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
|
|
||||||
fun <P : Any> renderParameter(parameter: P, renderer: DiagnosticParameterRenderer<P>?, context: RenderingContext): Any
|
fun <P : Any> renderParameter(parameter: P, renderer: DiagnosticParameterRenderer<P>?, context: RenderingContext): Any =
|
||||||
= renderer?.render(parameter, context) ?: parameter
|
renderer?.render(parameter, context) ?: parameter
|
||||||
|
|
||||||
fun ClassifierDescriptorWithTypeParameters.renderKindWithName(): String = DescriptorRenderer.getClassifierKindPrefix(this) + " '" + name + "'"
|
fun ClassifierDescriptorWithTypeParameters.renderKindWithName(): String =
|
||||||
|
DescriptorRenderer.getClassifierKindPrefix(this) + " '" + name + "'"
|
||||||
|
|
||||||
fun ClassDescriptor.renderKind(): String = DescriptorRenderer.getClassifierKindPrefix(this)
|
fun ClassDescriptor.renderKind(): String = DescriptorRenderer.getClassifierKindPrefix(this)
|
||||||
|
|
||||||
|
|||||||
@@ -57,27 +57,33 @@ object Renderers {
|
|||||||
|
|
||||||
private val LOG = Logger.getInstance(Renderers::class.java)
|
private val LOG = Logger.getInstance(Renderers::class.java)
|
||||||
|
|
||||||
@JvmField val TO_STRING = Renderer<Any> {
|
@JvmField
|
||||||
element ->
|
val TO_STRING = Renderer<Any> { element ->
|
||||||
if (element is DeclarationDescriptor) {
|
if (element is DeclarationDescriptor) {
|
||||||
LOG.warn("Diagnostic renderer TO_STRING was used to render an instance of DeclarationDescriptor.\n"
|
LOG.warn(
|
||||||
|
"Diagnostic renderer TO_STRING was used to render an instance of DeclarationDescriptor.\n"
|
||||||
+ "This is usually a bad idea, because descriptors' toString() includes some debug information, "
|
+ "This is usually a bad idea, because descriptors' toString() includes some debug information, "
|
||||||
+ "which should not be seen by the user.\nDescriptor: " + element)
|
+ "which should not be seen by the user.\nDescriptor: " + element
|
||||||
|
)
|
||||||
}
|
}
|
||||||
element.toString()
|
element.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val STRING = Renderer<String> { it }
|
@JvmField
|
||||||
|
val STRING = Renderer<String> { it }
|
||||||
|
|
||||||
@JvmField val THROWABLE = Renderer<Throwable> {
|
@JvmField
|
||||||
|
val THROWABLE = Renderer<Throwable> {
|
||||||
val writer = StringWriter()
|
val writer = StringWriter()
|
||||||
it.printStackTrace(PrintWriter(writer))
|
it.printStackTrace(PrintWriter(writer))
|
||||||
StringUtil.first(writer.toString(), 2048, true)
|
StringUtil.first(writer.toString(), 2048, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val NAME = Renderer<Named> { it.name.asString() }
|
@JvmField
|
||||||
|
val NAME = Renderer<Named> { it.name.asString() }
|
||||||
|
|
||||||
@JvmField val PLATFORM = Renderer<ModuleDescriptor> {
|
@JvmField
|
||||||
|
val PLATFORM = Renderer<ModuleDescriptor> {
|
||||||
val platform = it.getMultiTargetPlatform()
|
val platform = it.getMultiTargetPlatform()
|
||||||
" ${it.getCapability(ModuleInfo.Capability)?.displayedName ?: ""}" + when (platform) {
|
" ${it.getCapability(ModuleInfo.Capability)?.displayedName ?: ""}" + when (platform) {
|
||||||
MultiTargetPlatform.Common -> ""
|
MultiTargetPlatform.Common -> ""
|
||||||
@@ -86,13 +92,15 @@ object Renderers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val VISIBILITY = Renderer<Visibility> {
|
@JvmField
|
||||||
|
val VISIBILITY = Renderer<Visibility> {
|
||||||
if (it == Visibilities.INVISIBLE_FAKE)
|
if (it == Visibilities.INVISIBLE_FAKE)
|
||||||
"invisible (private in a supertype)"
|
"invisible (private in a supertype)"
|
||||||
else it.displayName
|
else it.displayName
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val DECLARATION_NAME_WITH_KIND = Renderer<DeclarationDescriptor> {
|
@JvmField
|
||||||
|
val DECLARATION_NAME_WITH_KIND = Renderer<DeclarationDescriptor> {
|
||||||
val name = it.name.asString()
|
val name = it.name.asString()
|
||||||
when (it) {
|
when (it) {
|
||||||
is PackageFragmentDescriptor -> "package '$name'"
|
is PackageFragmentDescriptor -> "package '$name'"
|
||||||
@@ -108,7 +116,8 @@ object Renderers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val CAPITALIZED_DECLARATION_NAME_WITH_KIND_AND_PLATFORM = ContextDependentRenderer<DeclarationDescriptor> { descriptor, context ->
|
@JvmField
|
||||||
|
val CAPITALIZED_DECLARATION_NAME_WITH_KIND_AND_PLATFORM = ContextDependentRenderer<DeclarationDescriptor> { descriptor, context ->
|
||||||
val declarationWithNameAndKind = DECLARATION_NAME_WITH_KIND.render(descriptor, context)
|
val declarationWithNameAndKind = DECLARATION_NAME_WITH_KIND.render(descriptor, context)
|
||||||
val withPlatform = if (descriptor is MemberDescriptor && descriptor.isActual)
|
val withPlatform = if (descriptor is MemberDescriptor && descriptor.isActual)
|
||||||
"actual $declarationWithNameAndKind"
|
"actual $declarationWithNameAndKind"
|
||||||
@@ -119,37 +128,40 @@ object Renderers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@JvmField val NAME_OF_CONTAINING_DECLARATION_OR_FILE = Renderer<DeclarationDescriptor> {
|
@JvmField
|
||||||
|
val NAME_OF_CONTAINING_DECLARATION_OR_FILE = Renderer<DeclarationDescriptor> {
|
||||||
if (DescriptorUtils.isTopLevelDeclaration(it) && it is DeclarationDescriptorWithVisibility && it.visibility == Visibilities.PRIVATE) {
|
if (DescriptorUtils.isTopLevelDeclaration(it) && it is DeclarationDescriptorWithVisibility && it.visibility == Visibilities.PRIVATE) {
|
||||||
"file"
|
"file"
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val containingDeclaration = it.containingDeclaration
|
val containingDeclaration = it.containingDeclaration
|
||||||
if (containingDeclaration is PackageFragmentDescriptor) {
|
if (containingDeclaration is PackageFragmentDescriptor) {
|
||||||
containingDeclaration.fqName.asString().wrapIntoQuotes()
|
containingDeclaration.fqName.asString().wrapIntoQuotes()
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
containingDeclaration!!.name.asString().wrapIntoQuotes()
|
containingDeclaration!!.name.asString().wrapIntoQuotes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val ELEMENT_TEXT = Renderer<PsiElement> { it.text }
|
@JvmField
|
||||||
|
val ELEMENT_TEXT = Renderer<PsiElement> { it.text }
|
||||||
|
|
||||||
@JvmField val DECLARATION_NAME = Renderer<KtNamedDeclaration> { it.nameAsSafeName.asString() }
|
@JvmField
|
||||||
|
val DECLARATION_NAME = Renderer<KtNamedDeclaration> { it.nameAsSafeName.asString() }
|
||||||
|
|
||||||
@JvmField val RENDER_CLASS_OR_OBJECT = Renderer {
|
@JvmField
|
||||||
classOrObject: KtClassOrObject ->
|
val RENDER_CLASS_OR_OBJECT = Renderer { classOrObject: KtClassOrObject ->
|
||||||
val name = classOrObject.name?.let { " ${it.wrapIntoQuotes()}" } ?: ""
|
val name = classOrObject.name?.let { " ${it.wrapIntoQuotes()}" } ?: ""
|
||||||
if (classOrObject is KtClass) "Class" + name else "Object" + name
|
if (classOrObject is KtClass) "Class" + name else "Object" + name
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val RENDER_CLASS_OR_OBJECT_NAME = Renderer<ClassifierDescriptorWithTypeParameters> { it.renderKindWithName() }
|
@JvmField
|
||||||
|
val RENDER_CLASS_OR_OBJECT_NAME = Renderer<ClassifierDescriptorWithTypeParameters> { it.renderKindWithName() }
|
||||||
|
|
||||||
@JvmField val RENDER_TYPE = SmartTypeRenderer(DescriptorRenderer.FQ_NAMES_IN_TYPES.withOptions { parameterNamesInFunctionalTypes = false })
|
@JvmField
|
||||||
|
val RENDER_TYPE = SmartTypeRenderer(DescriptorRenderer.FQ_NAMES_IN_TYPES.withOptions { parameterNamesInFunctionalTypes = false })
|
||||||
|
|
||||||
@JvmField val RENDER_POSITION_VARIANCE = Renderer {
|
@JvmField
|
||||||
variance: Variance ->
|
val RENDER_POSITION_VARIANCE = Renderer { variance: Variance ->
|
||||||
when (variance) {
|
when (variance) {
|
||||||
Variance.INVARIANT -> "invariant"
|
Variance.INVARIANT -> "invariant"
|
||||||
Variance.IN_VARIANCE -> "in"
|
Variance.IN_VARIANCE -> "in"
|
||||||
@@ -157,8 +169,8 @@ object Renderers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val AMBIGUOUS_CALLS = Renderer {
|
@JvmField
|
||||||
calls: Collection<ResolvedCall<*>> ->
|
val AMBIGUOUS_CALLS = Renderer { calls: Collection<ResolvedCall<*>> ->
|
||||||
val descriptors = calls.map { it.resultingDescriptor }
|
val descriptors = calls.map { it.resultingDescriptor }
|
||||||
val context = RenderingContext.Impl(descriptors)
|
val context = RenderingContext.Impl(descriptors)
|
||||||
descriptors
|
descriptors
|
||||||
@@ -166,8 +178,8 @@ object Renderers {
|
|||||||
.joinToString(separator = "\n", prefix = "\n") { FQ_NAMES_IN_TYPES.render(it, context) }
|
.joinToString(separator = "\n", prefix = "\n") { FQ_NAMES_IN_TYPES.render(it, context) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic fun <T> commaSeparated(itemRenderer: DiagnosticParameterRenderer<T>) = ContextDependentRenderer<Collection<T>> {
|
@JvmStatic
|
||||||
collection, context ->
|
fun <T> commaSeparated(itemRenderer: DiagnosticParameterRenderer<T>) = ContextDependentRenderer<Collection<T>> { collection, context ->
|
||||||
buildString {
|
buildString {
|
||||||
val iterator = collection.iterator()
|
val iterator = collection.iterator()
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
@@ -180,31 +192,39 @@ object Renderers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS_RENDERER = Renderer<InferenceErrorData> {
|
@JvmField
|
||||||
|
val TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS_RENDERER = Renderer<InferenceErrorData> {
|
||||||
renderConflictingSubstitutionsInferenceError(it, TabledDescriptorRenderer.create()).toString()
|
renderConflictingSubstitutionsInferenceError(it, TabledDescriptorRenderer.create()).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR_RENDERER = Renderer<InferenceErrorData> {
|
@JvmField
|
||||||
|
val TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR_RENDERER = Renderer<InferenceErrorData> {
|
||||||
renderParameterConstraintError(it, TabledDescriptorRenderer.create()).toString()
|
renderParameterConstraintError(it, TabledDescriptorRenderer.create()).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER_RENDERER = Renderer<InferenceErrorData> {
|
@JvmField
|
||||||
|
val TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER_RENDERER = Renderer<InferenceErrorData> {
|
||||||
renderNoInformationForParameterError(it, TabledDescriptorRenderer.create()).toString()
|
renderNoInformationForParameterError(it, TabledDescriptorRenderer.create()).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER = Renderer<InferenceErrorData> {
|
@JvmField
|
||||||
|
val TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER = Renderer<InferenceErrorData> {
|
||||||
renderUpperBoundViolatedInferenceError(it, TabledDescriptorRenderer.create()).toString()
|
renderUpperBoundViolatedInferenceError(it, TabledDescriptorRenderer.create()).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val TYPE_INFERENCE_CANNOT_CAPTURE_TYPES_RENDERER = Renderer<InferenceErrorData> {
|
@JvmField
|
||||||
|
val TYPE_INFERENCE_CANNOT_CAPTURE_TYPES_RENDERER = Renderer<InferenceErrorData> {
|
||||||
renderCannotCaptureTypeParameterError(it, TabledDescriptorRenderer.create()).toString()
|
renderCannotCaptureTypeParameterError(it, TabledDescriptorRenderer.create()).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic fun renderConflictingSubstitutionsInferenceError(
|
@JvmStatic
|
||||||
|
fun renderConflictingSubstitutionsInferenceError(
|
||||||
inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer
|
inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer
|
||||||
): TabledDescriptorRenderer {
|
): TabledDescriptorRenderer {
|
||||||
LOG.assertTrue(inferenceErrorData.constraintSystem.status.hasConflictingConstraints(),
|
LOG.assertTrue(
|
||||||
debugMessage("Conflicting substitutions inference error renderer is applied for incorrect status", inferenceErrorData))
|
inferenceErrorData.constraintSystem.status.hasConflictingConstraints(),
|
||||||
|
debugMessage("Conflicting substitutions inference error renderer is applied for incorrect status", inferenceErrorData)
|
||||||
|
)
|
||||||
|
|
||||||
val substitutedDescriptors = Lists.newArrayList<CallableDescriptor>()
|
val substitutedDescriptors = Lists.newArrayList<CallableDescriptor>()
|
||||||
val substitutors = ConstraintsUtil.getSubstitutorsForConflictingParameters(inferenceErrorData.constraintSystem)
|
val substitutors = ConstraintsUtil.getSubstitutorsForConflictingParameters(inferenceErrorData.constraintSystem)
|
||||||
@@ -219,10 +239,12 @@ object Renderers {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
result.text(newText()
|
result.text(
|
||||||
|
newText()
|
||||||
.normal("Cannot infer type parameter ")
|
.normal("Cannot infer type parameter ")
|
||||||
.strong(firstConflictingVariable.name)
|
.strong(firstConflictingVariable.name)
|
||||||
.normal(" in "))
|
.normal(" in ")
|
||||||
|
)
|
||||||
val table = newTable()
|
val table = newTable()
|
||||||
result.table(table)
|
result.table(table)
|
||||||
table.descriptor(inferenceErrorData.descriptor).text("None of the following substitutions")
|
table.descriptor(inferenceErrorData.descriptor).text("None of the following substitutions")
|
||||||
@@ -249,12 +271,14 @@ object Renderers {
|
|||||||
table.functionArgumentTypeList(receiverType, parameterTypes, { errorPositions.contains(it) })
|
table.functionArgumentTypeList(receiverType, parameterTypes, { errorPositions.contains(it) })
|
||||||
}
|
}
|
||||||
|
|
||||||
table.text("can be applied to").functionArgumentTypeList(inferenceErrorData.receiverArgumentType, inferenceErrorData.valueArgumentsTypes)
|
table.text("can be applied to")
|
||||||
|
.functionArgumentTypeList(inferenceErrorData.receiverArgumentType, inferenceErrorData.valueArgumentsTypes)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic fun renderParameterConstraintError(
|
@JvmStatic
|
||||||
|
fun renderParameterConstraintError(
|
||||||
inferenceErrorData: InferenceErrorData, renderer: TabledDescriptorRenderer
|
inferenceErrorData: InferenceErrorData, renderer: TabledDescriptorRenderer
|
||||||
): TabledDescriptorRenderer {
|
): TabledDescriptorRenderer {
|
||||||
val constraintErrors = inferenceErrorData.constraintSystem.status.constraintErrors
|
val constraintErrors = inferenceErrorData.constraintSystem.status.constraintErrors
|
||||||
@@ -266,11 +290,13 @@ object Renderers {
|
|||||||
.text("cannot be applied to")
|
.text("cannot be applied to")
|
||||||
.functionArgumentTypeList(inferenceErrorData.receiverArgumentType,
|
.functionArgumentTypeList(inferenceErrorData.receiverArgumentType,
|
||||||
inferenceErrorData.valueArgumentsTypes,
|
inferenceErrorData.valueArgumentsTypes,
|
||||||
{ errorPositions.contains(it) }))
|
{ errorPositions.contains(it) })
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@JvmStatic fun renderNoInformationForParameterError(
|
@JvmStatic
|
||||||
|
fun renderNoInformationForParameterError(
|
||||||
inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer
|
inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer
|
||||||
): TabledDescriptorRenderer {
|
): TabledDescriptorRenderer {
|
||||||
val firstUnknownVariable = inferenceErrorData.constraintSystem.typeVariables.firstOrNull { variable ->
|
val firstUnknownVariable = inferenceErrorData.constraintSystem.typeVariables.firstOrNull { variable ->
|
||||||
@@ -280,21 +306,28 @@ object Renderers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
.text(newText().normal("Not enough information to infer parameter ")
|
.text(
|
||||||
|
newText().normal("Not enough information to infer parameter ")
|
||||||
.strong(firstUnknownVariable.name)
|
.strong(firstUnknownVariable.name)
|
||||||
.normal(" in "))
|
.normal(" in ")
|
||||||
.table(newTable()
|
)
|
||||||
|
.table(
|
||||||
|
newTable()
|
||||||
.descriptor(inferenceErrorData.descriptor)
|
.descriptor(inferenceErrorData.descriptor)
|
||||||
.text("Please specify it explicitly."))
|
.text("Please specify it explicitly.")
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic fun renderUpperBoundViolatedInferenceError(
|
@JvmStatic
|
||||||
|
fun renderUpperBoundViolatedInferenceError(
|
||||||
inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer
|
inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer
|
||||||
): TabledDescriptorRenderer {
|
): TabledDescriptorRenderer {
|
||||||
val constraintSystem = inferenceErrorData.constraintSystem
|
val constraintSystem = inferenceErrorData.constraintSystem
|
||||||
val status = constraintSystem.status
|
val status = constraintSystem.status
|
||||||
LOG.assertTrue(status.hasViolatedUpperBound(),
|
LOG.assertTrue(
|
||||||
debugMessage("Upper bound violated renderer is applied for incorrect status", inferenceErrorData))
|
status.hasViolatedUpperBound(),
|
||||||
|
debugMessage("Upper bound violated renderer is applied for incorrect status", inferenceErrorData)
|
||||||
|
)
|
||||||
|
|
||||||
val systemWithoutWeakConstraints = constraintSystem.filterConstraintsOut(TYPE_BOUND_POSITION)
|
val systemWithoutWeakConstraints = constraintSystem.filterConstraintsOut(TYPE_BOUND_POSITION)
|
||||||
val typeParameterDescriptor = inferenceErrorData.descriptor.typeParameters.firstOrNull {
|
val typeParameterDescriptor = inferenceErrorData.descriptor.typeParameters.firstOrNull {
|
||||||
@@ -313,7 +346,12 @@ object Renderers {
|
|||||||
return if (status.hasConflictingConstraints())
|
return if (status.hasConflictingConstraints())
|
||||||
renderConflictingSubstitutionsInferenceError(inferenceErrorData, result)
|
renderConflictingSubstitutionsInferenceError(inferenceErrorData, result)
|
||||||
else {
|
else {
|
||||||
LOG.error(debugMessage("There is no type parameter with violated upper bound for 'upper bound violated' error", inferenceErrorData))
|
LOG.error(
|
||||||
|
debugMessage(
|
||||||
|
"There is no type parameter with violated upper bound for 'upper bound violated' error",
|
||||||
|
inferenceErrorData
|
||||||
|
)
|
||||||
|
)
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -321,21 +359,30 @@ object Renderers {
|
|||||||
val typeVariable = systemWithoutWeakConstraints.descriptorToVariable(inferenceErrorData.call.toHandle(), typeParameterDescriptor)
|
val typeVariable = systemWithoutWeakConstraints.descriptorToVariable(inferenceErrorData.call.toHandle(), typeParameterDescriptor)
|
||||||
val inferredValueForTypeParameter = systemWithoutWeakConstraints.getTypeBounds(typeVariable).value
|
val inferredValueForTypeParameter = systemWithoutWeakConstraints.getTypeBounds(typeVariable).value
|
||||||
if (inferredValueForTypeParameter == null) {
|
if (inferredValueForTypeParameter == null) {
|
||||||
LOG.error(debugMessage("System without weak constraints is not successful, there is no value for type parameter " +
|
LOG.error(
|
||||||
typeParameterDescriptor.name + "\n: " + systemWithoutWeakConstraints, inferenceErrorData))
|
debugMessage(
|
||||||
|
"System without weak constraints is not successful, there is no value for type parameter " +
|
||||||
|
typeParameterDescriptor.name + "\n: " + systemWithoutWeakConstraints, inferenceErrorData
|
||||||
|
)
|
||||||
|
)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
result.text(newText()
|
result.text(
|
||||||
|
newText()
|
||||||
.normal("Type parameter bound for ")
|
.normal("Type parameter bound for ")
|
||||||
.strong(typeParameterDescriptor.name)
|
.strong(typeParameterDescriptor.name)
|
||||||
.normal(" in "))
|
.normal(" in ")
|
||||||
.table(newTable()
|
)
|
||||||
.descriptor(inferenceErrorData.descriptor))
|
.table(
|
||||||
|
newTable()
|
||||||
|
.descriptor(inferenceErrorData.descriptor)
|
||||||
|
)
|
||||||
|
|
||||||
var violatedUpperBound: KotlinType? = null
|
var violatedUpperBound: KotlinType? = null
|
||||||
for (upperBound in typeParameterDescriptor.upperBounds) {
|
for (upperBound in typeParameterDescriptor.upperBounds) {
|
||||||
val upperBoundWithSubstitutedInferredTypes = systemWithoutWeakConstraints.resultingSubstitutor.substitute(upperBound, Variance.INVARIANT)
|
val upperBoundWithSubstitutedInferredTypes =
|
||||||
|
systemWithoutWeakConstraints.resultingSubstitutor.substitute(upperBound, Variance.INVARIANT)
|
||||||
if (upperBoundWithSubstitutedInferredTypes != null
|
if (upperBoundWithSubstitutedInferredTypes != null
|
||||||
&& !KotlinTypeChecker.DEFAULT.isSubtypeOf(inferredValueForTypeParameter, upperBoundWithSubstitutedInferredTypes)) {
|
&& !KotlinTypeChecker.DEFAULT.isSubtypeOf(inferredValueForTypeParameter, upperBoundWithSubstitutedInferredTypes)) {
|
||||||
violatedUpperBound = upperBoundWithSubstitutedInferredTypes
|
violatedUpperBound = upperBoundWithSubstitutedInferredTypes
|
||||||
@@ -343,19 +390,25 @@ object Renderers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (violatedUpperBound == null) {
|
if (violatedUpperBound == null) {
|
||||||
LOG.error(debugMessage("Type parameter (chosen as violating its upper bound)" +
|
LOG.error(
|
||||||
typeParameterDescriptor.name + " violates no bounds after substitution", inferenceErrorData))
|
debugMessage(
|
||||||
|
"Type parameter (chosen as violating its upper bound)" +
|
||||||
|
typeParameterDescriptor.name + " violates no bounds after substitution", inferenceErrorData
|
||||||
|
)
|
||||||
|
)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: context should be in fact shared for the table and these two types
|
// TODO: context should be in fact shared for the table and these two types
|
||||||
val context = RenderingContext.of(inferredValueForTypeParameter, violatedUpperBound)
|
val context = RenderingContext.of(inferredValueForTypeParameter, violatedUpperBound)
|
||||||
val typeRenderer = result.typeRenderer
|
val typeRenderer = result.typeRenderer
|
||||||
result.text(newText()
|
result.text(
|
||||||
|
newText()
|
||||||
.normal(" is not satisfied: inferred type ")
|
.normal(" is not satisfied: inferred type ")
|
||||||
.error(typeRenderer.render(inferredValueForTypeParameter, context))
|
.error(typeRenderer.render(inferredValueForTypeParameter, context))
|
||||||
.normal(" is not a subtype of ")
|
.normal(" is not a subtype of ")
|
||||||
.strong(typeRenderer.render(violatedUpperBound, context)))
|
.strong(typeRenderer.render(violatedUpperBound, context))
|
||||||
|
)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,12 +444,16 @@ object Renderers {
|
|||||||
val context = RenderingContext.of(violatingInferredType, violatedUpperBound)
|
val context = RenderingContext.of(violatingInferredType, violatedUpperBound)
|
||||||
val typeRenderer = result.typeRenderer
|
val typeRenderer = result.typeRenderer
|
||||||
|
|
||||||
result.text(newText().normal("Type parameter bound for ").strong(constraintInfo.typeParameter.name)
|
result.text(
|
||||||
.normal(" in type inferred from type alias expansion for "))
|
newText().normal("Type parameter bound for ").strong(constraintInfo.typeParameter.name)
|
||||||
|
.normal(" in type inferred from type alias expansion for ")
|
||||||
|
)
|
||||||
.table(newTable().descriptor(inferenceErrorData.descriptor))
|
.table(newTable().descriptor(inferenceErrorData.descriptor))
|
||||||
|
|
||||||
result.text(newText().normal(" is not satisfied: inferred type ").error(typeRenderer.render(violatingInferredType, context))
|
result.text(
|
||||||
.normal(" is not a subtype of ").strong(typeRenderer.render(violatedUpperBound, context)))
|
newText().normal(" is not satisfied: inferred type ").error(typeRenderer.render(violatingInferredType, context))
|
||||||
|
.normal(" is not a subtype of ").strong(typeRenderer.render(violatedUpperBound, context))
|
||||||
|
)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -404,7 +461,8 @@ object Renderers {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic fun renderCannotCaptureTypeParameterError(
|
@JvmStatic
|
||||||
|
fun renderCannotCaptureTypeParameterError(
|
||||||
inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer
|
inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer
|
||||||
): TabledDescriptorRenderer {
|
): TabledDescriptorRenderer {
|
||||||
val system = inferenceErrorData.constraintSystem
|
val system = inferenceErrorData.constraintSystem
|
||||||
@@ -419,7 +477,12 @@ object Renderers {
|
|||||||
val boundWithCapturedType = typeBounds.bounds.firstOrNull { it.constrainingType.isCaptured() }
|
val boundWithCapturedType = typeBounds.bounds.firstOrNull { it.constrainingType.isCaptured() }
|
||||||
val capturedTypeConstructor = boundWithCapturedType?.constrainingType?.constructor as? CapturedTypeConstructor
|
val capturedTypeConstructor = boundWithCapturedType?.constrainingType?.constructor as? CapturedTypeConstructor
|
||||||
if (capturedTypeConstructor == null) {
|
if (capturedTypeConstructor == null) {
|
||||||
LOG.error(debugMessage("There is no captured type in bounds, but there is an error 'cannot capture type parameter'", inferenceErrorData))
|
LOG.error(
|
||||||
|
debugMessage(
|
||||||
|
"There is no captured type in bounds, but there is an error 'cannot capture type parameter'",
|
||||||
|
inferenceErrorData
|
||||||
|
)
|
||||||
|
)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,20 +494,25 @@ object Renderers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val explanation =
|
val explanation =
|
||||||
"Type parameter has an upper bound ${result.typeRenderer.render(upperBound, RenderingContext.of(upperBound)).wrapIntoQuotes()}" +
|
"Type parameter has an upper bound ${result.typeRenderer.render(
|
||||||
|
upperBound,
|
||||||
|
RenderingContext.of(upperBound)
|
||||||
|
).wrapIntoQuotes()}" +
|
||||||
" that cannot be satisfied capturing 'in' projection"
|
" that cannot be satisfied capturing 'in' projection"
|
||||||
|
|
||||||
result.text(newText().normal(
|
result.text(
|
||||||
|
newText().normal(
|
||||||
typeParameter.name.wrapIntoQuotes() +
|
typeParameter.name.wrapIntoQuotes() +
|
||||||
" cannot capture " +
|
" cannot capture " +
|
||||||
"${capturedTypeConstructor.typeProjection.toString().wrapIntoQuotes()}. " +
|
"${capturedTypeConstructor.typeProjection.toString().wrapIntoQuotes()}. " +
|
||||||
explanation
|
explanation
|
||||||
))
|
)
|
||||||
|
)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val CLASSES_OR_SEPARATED = Renderer<Collection<ClassDescriptor>> {
|
@JvmField
|
||||||
descriptors ->
|
val CLASSES_OR_SEPARATED = Renderer<Collection<ClassDescriptor>> { descriptors ->
|
||||||
buildString {
|
buildString {
|
||||||
var index = 0
|
var index = 0
|
||||||
for (descriptor in descriptors) {
|
for (descriptor in descriptors) {
|
||||||
@@ -452,17 +520,18 @@ object Renderers {
|
|||||||
index++
|
index++
|
||||||
if (index <= descriptors.size - 2) {
|
if (index <= descriptors.size - 2) {
|
||||||
append(", ")
|
append(", ")
|
||||||
}
|
} else if (index == descriptors.size - 1) {
|
||||||
else if (index == descriptors.size - 1) {
|
|
||||||
append(" or ")
|
append(" or ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renderTypes(types: Collection<KotlinType>, context: RenderingContext) = StringUtil.join(types, { RENDER_TYPE.render(it, context) }, ", ")
|
private fun renderTypes(types: Collection<KotlinType>, context: RenderingContext) =
|
||||||
|
StringUtil.join(types, { RENDER_TYPE.render(it, context) }, ", ")
|
||||||
|
|
||||||
@JvmField val RENDER_COLLECTION_OF_TYPES = ContextDependentRenderer<Collection<KotlinType>> { types, context -> renderTypes(types, context) }
|
@JvmField
|
||||||
|
val RENDER_COLLECTION_OF_TYPES = ContextDependentRenderer<Collection<KotlinType>> { types, context -> renderTypes(types, context) }
|
||||||
|
|
||||||
fun renderConstraintSystem(constraintSystem: ConstraintSystem, shortTypeBounds: Boolean): String {
|
fun renderConstraintSystem(constraintSystem: ConstraintSystem, shortTypeBounds: Boolean): String {
|
||||||
val typeBounds = linkedSetOf<TypeBounds>()
|
val typeBounds = linkedSetOf<TypeBounds>()
|
||||||
@@ -488,8 +557,7 @@ object Renderers {
|
|||||||
val typeVariableName = typeBounds.typeVariable.name
|
val typeVariableName = typeBounds.typeVariable.name
|
||||||
return if (typeBounds.bounds.isEmpty()) {
|
return if (typeBounds.bounds.isEmpty()) {
|
||||||
typeVariableName.asString()
|
typeVariableName.asString()
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
"$typeVariableName ${StringUtil.join(typeBounds.bounds, renderBound, ", ")}"
|
"$typeVariableName ${StringUtil.join(typeBounds.bounds, renderBound, ", ")}"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -503,8 +571,7 @@ object Renderers {
|
|||||||
val context = RenderingContext.Empty
|
val context = RenderingContext.Empty
|
||||||
if (TypeUtils.noExpectedType(inferenceErrorData.expectedType)) {
|
if (TypeUtils.noExpectedType(inferenceErrorData.expectedType)) {
|
||||||
append(inferenceErrorData.expectedType)
|
append(inferenceErrorData.expectedType)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
append(RENDER_TYPE.render(inferenceErrorData.expectedType, context))
|
append(RENDER_TYPE.render(inferenceErrorData.expectedType, context))
|
||||||
}
|
}
|
||||||
append("\nArgument types:\n")
|
append("\nArgument types:\n")
|
||||||
@@ -519,26 +586,33 @@ object Renderers {
|
|||||||
|
|
||||||
private val WHEN_MISSING_LIMIT = 7
|
private val WHEN_MISSING_LIMIT = 7
|
||||||
|
|
||||||
@JvmField val RENDER_WHEN_MISSING_CASES = Renderer<List<WhenMissingCase>> {
|
@JvmField
|
||||||
|
val RENDER_WHEN_MISSING_CASES = Renderer<List<WhenMissingCase>> {
|
||||||
if (!it.hasUnknown) {
|
if (!it.hasUnknown) {
|
||||||
val list = it.joinToString(", ", limit = WHEN_MISSING_LIMIT) { "'$it'" }
|
val list = it.joinToString(", ", limit = WHEN_MISSING_LIMIT) { "'$it'" }
|
||||||
val branches = if (it.size > 1) "branches" else "branch"
|
val branches = if (it.size > 1) "branches" else "branch"
|
||||||
"$list $branches or 'else' branch instead"
|
"$list $branches or 'else' branch instead"
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
"'else' branch"
|
"'else' branch"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val FQ_NAMES_IN_TYPES = DescriptorRenderer.FQ_NAMES_IN_TYPES.asRenderer()
|
@JvmField
|
||||||
@JvmField val COMPACT = DescriptorRenderer.COMPACT.asRenderer()
|
val FQ_NAMES_IN_TYPES = DescriptorRenderer.FQ_NAMES_IN_TYPES.asRenderer()
|
||||||
@JvmField val COMPACT_WITHOUT_SUPERTYPES = DescriptorRenderer.COMPACT_WITHOUT_SUPERTYPES.asRenderer()
|
@JvmField
|
||||||
@JvmField val WITHOUT_MODIFIERS = DescriptorRenderer.withOptions {
|
val COMPACT = DescriptorRenderer.COMPACT.asRenderer()
|
||||||
|
@JvmField
|
||||||
|
val COMPACT_WITHOUT_SUPERTYPES = DescriptorRenderer.COMPACT_WITHOUT_SUPERTYPES.asRenderer()
|
||||||
|
@JvmField
|
||||||
|
val WITHOUT_MODIFIERS = DescriptorRenderer.withOptions {
|
||||||
modifiers = emptySet()
|
modifiers = emptySet()
|
||||||
}.asRenderer()
|
}.asRenderer()
|
||||||
@JvmField val SHORT_NAMES_IN_TYPES = DescriptorRenderer.SHORT_NAMES_IN_TYPES.asRenderer()
|
@JvmField
|
||||||
@JvmField val COMPACT_WITH_MODIFIERS = DescriptorRenderer.COMPACT_WITH_MODIFIERS.asRenderer()
|
val SHORT_NAMES_IN_TYPES = DescriptorRenderer.SHORT_NAMES_IN_TYPES.asRenderer()
|
||||||
@JvmField val DEPRECATION_RENDERER = DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES.withOptions {
|
@JvmField
|
||||||
|
val COMPACT_WITH_MODIFIERS = DescriptorRenderer.COMPACT_WITH_MODIFIERS.asRenderer()
|
||||||
|
@JvmField
|
||||||
|
val DEPRECATION_RENDERER = DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES.withOptions {
|
||||||
withoutTypeParameters = false
|
withoutTypeParameters = false
|
||||||
receiverAfterName = false
|
receiverAfterName = false
|
||||||
renderAccessors = true
|
renderAccessors = true
|
||||||
|
|||||||
+5
-4
@@ -83,8 +83,7 @@ private fun collectMentionedClassifiersFqNames(contextObjects: Collection<Any?>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
contextObjects.filterIsInstance<KotlinType>().forEach { diagnosticType ->
|
contextObjects.filterIsInstance<KotlinType>().forEach { diagnosticType ->
|
||||||
diagnosticType.contains {
|
diagnosticType.contains { innerType ->
|
||||||
innerType ->
|
|
||||||
innerType.addMentionedTypeConstructor()
|
innerType.addMentionedTypeConstructor()
|
||||||
innerType.getAbbreviation()?.addMentionedTypeConstructor()
|
innerType.getAbbreviation()?.addMentionedTypeConstructor()
|
||||||
false
|
false
|
||||||
@@ -101,12 +100,14 @@ private fun collectMentionedClassifiersFqNames(contextObjects: Collection<Any?>,
|
|||||||
collectMentionedClassifiersFqNames(it.upperBounds, result)
|
collectMentionedClassifiersFqNames(it.upperBounds, result)
|
||||||
}
|
}
|
||||||
contextObjects.filterIsInstance<CallableDescriptor>().forEach {
|
contextObjects.filterIsInstance<CallableDescriptor>().forEach {
|
||||||
collectMentionedClassifiersFqNames(listOf(
|
collectMentionedClassifiersFqNames(
|
||||||
|
listOf(
|
||||||
it.typeParameters,
|
it.typeParameters,
|
||||||
it.returnType,
|
it.returnType,
|
||||||
it.valueParameters,
|
it.valueParameters,
|
||||||
it.dispatchReceiverParameter?.type,
|
it.dispatchReceiverParameter?.type,
|
||||||
it.extensionReceiverParameter?.type
|
it.extensionReceiverParameter?.type
|
||||||
), result)
|
), result
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ class MainFunctionDetector {
|
|||||||
/** Assumes that the function declaration is already resolved and the descriptor can be found in the `bindingContext`. */
|
/** Assumes that the function declaration is already resolved and the descriptor can be found in the `bindingContext`. */
|
||||||
constructor(bindingContext: BindingContext) {
|
constructor(bindingContext: BindingContext) {
|
||||||
this.getFunctionDescriptor = { function ->
|
this.getFunctionDescriptor = { function ->
|
||||||
bindingContext.get(BindingContext.FUNCTION, function) ?: throw IllegalStateException("No descriptor resolved for " + function + " " + function.text)
|
bindingContext.get(BindingContext.FUNCTION, function)
|
||||||
|
?: throw IllegalStateException("No descriptor resolved for " + function + " " + function.text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,14 +29,17 @@ import org.jetbrains.kotlin.lexer.KtTokens
|
|||||||
*/
|
*/
|
||||||
class KDocLinkParser : PsiParser {
|
class KDocLinkParser : PsiParser {
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic fun parseMarkdownLink(root: IElementType, chameleon: ASTNode): ASTNode {
|
@JvmStatic
|
||||||
|
fun parseMarkdownLink(root: IElementType, chameleon: ASTNode): ASTNode {
|
||||||
val parentElement = chameleon.treeParent.psi
|
val parentElement = chameleon.treeParent.psi
|
||||||
val project = parentElement.project
|
val project = parentElement.project
|
||||||
val builder = PsiBuilderFactory.getInstance().createBuilder(project,
|
val builder = PsiBuilderFactory.getInstance().createBuilder(
|
||||||
|
project,
|
||||||
chameleon,
|
chameleon,
|
||||||
KotlinLexer(),
|
KotlinLexer(),
|
||||||
root.language,
|
root.language,
|
||||||
chameleon.text)
|
chameleon.text
|
||||||
|
)
|
||||||
val parser = KDocLinkParser()
|
val parser = KDocLinkParser()
|
||||||
|
|
||||||
return parser.parse(root, builder).firstChildNode
|
return parser.parse(root, builder).firstChildNode
|
||||||
@@ -60,8 +63,7 @@ class KDocLinkParser : PsiParser {
|
|||||||
if (builder.tokenType == KtTokens.RBRACKET) {
|
if (builder.tokenType == KtTokens.RBRACKET) {
|
||||||
builder.advanceLexer()
|
builder.advanceLexer()
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (!builder.eof()) {
|
if (!builder.eof()) {
|
||||||
builder.error("Expression expected")
|
builder.error("Expression expected")
|
||||||
while (!builder.eof()) {
|
while (!builder.eof()) {
|
||||||
|
|||||||
@@ -44,6 +44,5 @@ class KDocSection(node: ASTNode) : KDocTag(node) {
|
|||||||
return getChildrenOfType<KDocTag>().filter { it.name == name }
|
return getChildrenOfType<KDocTag>().filter { it.name == name }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findTagByName(name: String): KDocTag?
|
fun findTagByName(name: String): KDocTag? = findTagsByName(name).firstOrNull()
|
||||||
= findTagsByName(name).firstOrNull()
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,8 +109,7 @@ open class KDocTag(node: ASTNode) : KDocElementImpl(node) {
|
|||||||
if (!isCodeBlock())
|
if (!isCodeBlock())
|
||||||
indentedCodeBlock = indentedCodeBlock || node.text.startsWith(indentationWhiteSpaces) || node.text.startsWith("\t")
|
indentedCodeBlock = indentedCodeBlock || node.text.startsWith(indentationWhiteSpaces) || node.text.startsWith("\t")
|
||||||
startCodeBlock()
|
startCodeBlock()
|
||||||
}
|
} else if (KDocTokens.CONTENT_TOKENS.contains(type)) {
|
||||||
else if (KDocTokens.CONTENT_TOKENS.contains(type)) {
|
|
||||||
flushCodeBlock()
|
flushCodeBlock()
|
||||||
indentedCodeBlock = false
|
indentedCodeBlock = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,9 @@ class KotlinParserDefinition : ParserDefinition {
|
|||||||
|
|
||||||
return when (elementType) {
|
return when (elementType) {
|
||||||
is KtStubElementType<*, *> -> elementType.createPsiFromAst(astNode)
|
is KtStubElementType<*, *> -> elementType.createPsiFromAst(astNode)
|
||||||
KtNodeTypes.TYPE_CODE_FRAGMENT, KtNodeTypes.EXPRESSION_CODE_FRAGMENT, KtNodeTypes.BLOCK_CODE_FRAGMENT -> ASTWrapperPsiElement(astNode)
|
KtNodeTypes.TYPE_CODE_FRAGMENT, KtNodeTypes.EXPRESSION_CODE_FRAGMENT, KtNodeTypes.BLOCK_CODE_FRAGMENT -> ASTWrapperPsiElement(
|
||||||
|
astNode
|
||||||
|
)
|
||||||
is KDocElementType -> elementType.createPsi(astNode)
|
is KDocElementType -> elementType.createPsi(astNode)
|
||||||
KDocTokens.MARKDOWN_LINK -> KDocLink(astNode)
|
KDocTokens.MARKDOWN_LINK -> KDocLink(astNode)
|
||||||
else -> (elementType as KtNodeType).createPsi(astNode)
|
else -> (elementType as KtNodeType).createPsi(astNode)
|
||||||
|
|||||||
+14
-7
@@ -23,7 +23,8 @@ import org.jetbrains.kotlin.lexer.KtTokens
|
|||||||
|
|
||||||
object PrecedingCommentsBinder : WhitespacesAndCommentsBinder {
|
object PrecedingCommentsBinder : WhitespacesAndCommentsBinder {
|
||||||
override fun getEdgePosition(
|
override fun getEdgePosition(
|
||||||
tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
|
tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter
|
||||||
|
): Int {
|
||||||
if (tokens.isEmpty()) return 0
|
if (tokens.isEmpty()) return 0
|
||||||
|
|
||||||
// 1. bind doc comment
|
// 1. bind doc comment
|
||||||
@@ -54,7 +55,8 @@ object PrecedingCommentsBinder : WhitespacesAndCommentsBinder {
|
|||||||
|
|
||||||
object PrecedingDocCommentsBinder : WhitespacesAndCommentsBinder {
|
object PrecedingDocCommentsBinder : WhitespacesAndCommentsBinder {
|
||||||
override fun getEdgePosition(
|
override fun getEdgePosition(
|
||||||
tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
|
tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter
|
||||||
|
): Int {
|
||||||
if (tokens.isEmpty()) return 0
|
if (tokens.isEmpty()) return 0
|
||||||
|
|
||||||
for (idx in tokens.indices.reversed()) {
|
for (idx in tokens.indices.reversed()) {
|
||||||
@@ -68,7 +70,8 @@ object PrecedingDocCommentsBinder : WhitespacesAndCommentsBinder {
|
|||||||
// Binds comments on the same line
|
// Binds comments on the same line
|
||||||
object TrailingCommentsBinder : WhitespacesAndCommentsBinder {
|
object TrailingCommentsBinder : WhitespacesAndCommentsBinder {
|
||||||
override fun getEdgePosition(
|
override fun getEdgePosition(
|
||||||
tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
|
tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter
|
||||||
|
): Int {
|
||||||
if (tokens.isEmpty()) return 0
|
if (tokens.isEmpty()) return 0
|
||||||
|
|
||||||
var result = 0
|
var result = 0
|
||||||
@@ -89,7 +92,8 @@ object TrailingCommentsBinder : WhitespacesAndCommentsBinder {
|
|||||||
|
|
||||||
private class AllCommentsBinder(val isTrailing: Boolean) : WhitespacesAndCommentsBinder {
|
private class AllCommentsBinder(val isTrailing: Boolean) : WhitespacesAndCommentsBinder {
|
||||||
override fun getEdgePosition(
|
override fun getEdgePosition(
|
||||||
tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
|
tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter
|
||||||
|
): Int {
|
||||||
if (tokens.isEmpty()) return 0
|
if (tokens.isEmpty()) return 0
|
||||||
|
|
||||||
val size = tokens.size
|
val size = tokens.size
|
||||||
@@ -110,14 +114,16 @@ val TRAILING_ALL_COMMENTS_BINDER: WhitespacesAndCommentsBinder = AllCommentsBind
|
|||||||
|
|
||||||
object DoNotBindAnything : WhitespacesAndCommentsBinder {
|
object DoNotBindAnything : WhitespacesAndCommentsBinder {
|
||||||
override fun getEdgePosition(
|
override fun getEdgePosition(
|
||||||
tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
|
tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter
|
||||||
|
): Int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object BindFirstShebangWithWhitespaceOnly : WhitespacesAndCommentsBinder {
|
object BindFirstShebangWithWhitespaceOnly : WhitespacesAndCommentsBinder {
|
||||||
override fun getEdgePosition(
|
override fun getEdgePosition(
|
||||||
tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
|
tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter
|
||||||
|
): Int {
|
||||||
if (tokens.firstOrNull() == KtTokens.SHEBANG_COMMENT) {
|
if (tokens.firstOrNull() == KtTokens.SHEBANG_COMMENT) {
|
||||||
return if (tokens.getOrNull(1) == KtTokens.WHITE_SPACE) 2 else 1
|
return if (tokens.getOrNull(1) == KtTokens.WHITE_SPACE) 2 else 1
|
||||||
}
|
}
|
||||||
@@ -128,7 +134,8 @@ object BindFirstShebangWithWhitespaceOnly : WhitespacesAndCommentsBinder {
|
|||||||
|
|
||||||
class BindAll(val isTrailing: Boolean) : WhitespacesAndCommentsBinder {
|
class BindAll(val isTrailing: Boolean) : WhitespacesAndCommentsBinder {
|
||||||
override fun getEdgePosition(
|
override fun getEdgePosition(
|
||||||
tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
|
tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter
|
||||||
|
): Int {
|
||||||
return if (!isTrailing) 0 else tokens.size
|
return if (!isTrailing) 0 else tokens.size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ abstract class KtExpressionImpl(node: ASTNode) : KtElementImpl(node), KtExpressi
|
|||||||
}
|
}
|
||||||
is KtSimpleNameStringTemplateEntry -> {
|
is KtSimpleNameStringTemplateEntry -> {
|
||||||
if (newElement !is KtSimpleNameExpression && !newElement.isThisWithoutLabel()) {
|
if (newElement !is KtSimpleNameExpression && !newElement.isThisWithoutLabel()) {
|
||||||
val newEntry = parent.replace(KtPsiFactory(expression).createBlockStringTemplateEntry(newElement)) as KtBlockStringTemplateEntry
|
val newEntry =
|
||||||
|
parent.replace(KtPsiFactory(expression).createBlockStringTemplateEntry(newElement)) as KtBlockStringTemplateEntry
|
||||||
return newEntry.expression!!
|
return newEntry.expression!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,8 +43,7 @@ class KtPrimaryConstructor : KtConstructor<KtPrimaryConstructor> {
|
|||||||
if (this.modifierList == null) {
|
if (this.modifierList == null) {
|
||||||
getConstructorKeyword()?.delete()
|
getConstructorKeyword()?.delete()
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (modifier == KtTokens.PUBLIC_KEYWORD) return
|
if (modifier == KtTokens.PUBLIC_KEYWORD) return
|
||||||
val newModifierList = KtPsiFactory(this).createModifierList(modifier)
|
val newModifierList = KtPsiFactory(this).createModifierList(modifier)
|
||||||
addBefore(newModifierList, getOrCreateConstructorKeyword())
|
addBefore(newModifierList, getOrCreateConstructorKeyword())
|
||||||
@@ -62,8 +61,7 @@ class KtPrimaryConstructor : KtConstructor<KtPrimaryConstructor> {
|
|||||||
val modifierList = modifierList
|
val modifierList = modifierList
|
||||||
return if (modifierList != null) {
|
return if (modifierList != null) {
|
||||||
modifierList.addBefore(annotationEntry, modifierList.firstChild) as KtAnnotationEntry
|
modifierList.addBefore(annotationEntry, modifierList.firstChild) as KtAnnotationEntry
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val parameterList = valueParameterList!!
|
val parameterList = valueParameterList!!
|
||||||
val newModifierList = KtPsiFactory(project).createModifierList(annotationEntry.text)
|
val newModifierList = KtPsiFactory(project).createModifierList(annotationEntry.text)
|
||||||
(addBefore(newModifierList, parameterList) as KtModifierList).annotationEntries.first()
|
(addBefore(newModifierList, parameterList) as KtModifierList).annotationEntries.first()
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ import org.jetbrains.kotlin.resolve.TargetPlatform
|
|||||||
fun KtPsiFactory(project: Project?, markGenerated: Boolean = true): KtPsiFactory = KtPsiFactory(project!!, markGenerated)
|
fun KtPsiFactory(project: Project?, markGenerated: Boolean = true): KtPsiFactory = KtPsiFactory(project!!, markGenerated)
|
||||||
|
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun KtPsiFactory(elementForProject: PsiElement, markGenerated: Boolean = true): KtPsiFactory = KtPsiFactory(elementForProject.project, markGenerated)
|
fun KtPsiFactory(elementForProject: PsiElement, markGenerated: Boolean = true): KtPsiFactory =
|
||||||
|
KtPsiFactory(elementForProject.project, markGenerated)
|
||||||
|
|
||||||
private val DO_NOT_ANALYZE_NOTIFICATION = "This file was created by KtPsiFactory and should not be analyzed\n" +
|
private val DO_NOT_ANALYZE_NOTIFICATION = "This file was created by KtPsiFactory and should not be analyzed\n" +
|
||||||
"Use createAnalyzableFile to create file that can be analyzed\n"
|
"Use createAnalyzableFile to create file that can be analyzed\n"
|
||||||
@@ -109,7 +110,8 @@ class KtPsiFactory @JvmOverloads constructor(private val project: Project, val m
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun createFunctionTypeParameter(typeReference: KtTypeReference): KtParameter {
|
fun createFunctionTypeParameter(typeReference: KtTypeReference): KtParameter {
|
||||||
return (createType("(A) -> B").typeElement as KtFunctionType).parameters.first().apply { this.typeReference!!.replace(typeReference) }
|
return (createType("(A) -> B").typeElement as KtFunctionType).parameters.first()
|
||||||
|
.apply { this.typeReference!!.replace(typeReference) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createTypeAlias(name: String, typeParameters: List<String>, typeElement: KtTypeElement): KtTypeAlias {
|
fun createTypeAlias(name: String, typeParameters: List<String>, typeElement: KtTypeElement): KtTypeAlias {
|
||||||
@@ -193,7 +195,14 @@ class KtPsiFactory @JvmOverloads constructor(private val project: Project, val m
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun doCreateFile(fileName: String, text: String): KtFile {
|
private fun doCreateFile(fileName: String, text: String): KtFile {
|
||||||
return PsiFileFactory.getInstance(project).createFileFromText(fileName, KotlinFileType.INSTANCE, text, LocalTimeCounter.currentTime(), false, markGenerated) as KtFile
|
return PsiFileFactory.getInstance(project).createFileFromText(
|
||||||
|
fileName,
|
||||||
|
KotlinFileType.INSTANCE,
|
||||||
|
text,
|
||||||
|
LocalTimeCounter.currentTime(),
|
||||||
|
false,
|
||||||
|
markGenerated
|
||||||
|
) as KtFile
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createFile(fileName: String, text: String): KtFile {
|
fun createFile(fileName: String, text: String): KtFile {
|
||||||
@@ -217,7 +226,13 @@ class KtPsiFactory @JvmOverloads constructor(private val project: Project, val m
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun createPhysicalFile(fileName: String, text: String): KtFile {
|
fun createPhysicalFile(fileName: String, text: String): KtFile {
|
||||||
return PsiFileFactory.getInstance(project).createFileFromText(fileName, KotlinFileType.INSTANCE, text, LocalTimeCounter.currentTime(), true) as KtFile
|
return PsiFileFactory.getInstance(project).createFileFromText(
|
||||||
|
fileName,
|
||||||
|
KotlinFileType.INSTANCE,
|
||||||
|
text,
|
||||||
|
LocalTimeCounter.currentTime(),
|
||||||
|
true
|
||||||
|
) as KtFile
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createProperty(modifiers: String?, name: String, type: String?, isVar: Boolean, initializer: String?): KtProperty {
|
fun createProperty(modifiers: String?, name: String, type: String?, isVar: Boolean, initializer: String?): KtProperty {
|
||||||
@@ -445,8 +460,7 @@ class KtPsiFactory @JvmOverloads constructor(private val project: Project, val m
|
|||||||
fun createConstructorKeyword(): PsiElement =
|
fun createConstructorKeyword(): PsiElement =
|
||||||
createClass("class A constructor()").primaryConstructor!!.getConstructorKeyword()!!
|
createClass("class A constructor()").primaryConstructor!!.getConstructorKeyword()!!
|
||||||
|
|
||||||
fun createLabeledExpression(labelName: String): KtLabeledExpression
|
fun createLabeledExpression(labelName: String): KtLabeledExpression = createExpression("$labelName@ 1") as KtLabeledExpression
|
||||||
= createExpression("$labelName@ 1") as KtLabeledExpression
|
|
||||||
|
|
||||||
fun createTypeCodeFragment(text: String, context: PsiElement?): KtTypeCodeFragment {
|
fun createTypeCodeFragment(text: String, context: PsiElement?): KtTypeCodeFragment {
|
||||||
return KtTypeCodeFragment(project, "fragment.kt", text, context)
|
return KtTypeCodeFragment(project, "fragment.kt", text, context)
|
||||||
@@ -512,6 +526,7 @@ class KtPsiFactory @JvmOverloads constructor(private val project: Project, val m
|
|||||||
TYPE_CONSTRAINTS,
|
TYPE_CONSTRAINTS,
|
||||||
DONE
|
DONE
|
||||||
}
|
}
|
||||||
|
|
||||||
private val sb = StringBuilder()
|
private val sb = StringBuilder()
|
||||||
private var state = State.MODIFIERS
|
private var state = State.MODIFIERS
|
||||||
|
|
||||||
@@ -820,7 +835,8 @@ class KtPsiFactory @JvmOverloads constructor(private val project: Project, val m
|
|||||||
return BlockWrapper(block, expression)
|
return BlockWrapper(block, expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BlockWrapper(fakeBlockExpression: KtBlockExpression, private val expression: KtExpression) : KtBlockExpression(fakeBlockExpression.node), KtPsiUtil.KtExpressionWrapper {
|
private class BlockWrapper(fakeBlockExpression: KtBlockExpression, private val expression: KtExpression) :
|
||||||
|
KtBlockExpression(fakeBlockExpression.node), KtPsiUtil.KtExpressionWrapper {
|
||||||
override fun getStatements(): List<KtExpression> {
|
override fun getStatements(): List<KtExpression> {
|
||||||
return listOf(expression)
|
return listOf(expression)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,10 +42,10 @@ class KtTypeAlias : KtTypeParameterListOwnerStub<KotlinTypeAliasStub>, KtNamedDe
|
|||||||
@IfNotParsed
|
@IfNotParsed
|
||||||
fun getTypeReference(): KtTypeReference? {
|
fun getTypeReference(): KtTypeReference? {
|
||||||
return if (stub != null) {
|
return if (stub != null) {
|
||||||
val typeReferences = getStubOrPsiChildrenAsList<KtTypeReference, KotlinPlaceHolderStub<KtTypeReference>>(KtStubElementTypes.TYPE_REFERENCE)
|
val typeReferences =
|
||||||
|
getStubOrPsiChildrenAsList<KtTypeReference, KotlinPlaceHolderStub<KtTypeReference>>(KtStubElementTypes.TYPE_REFERENCE)
|
||||||
typeReferences[0]
|
typeReferences[0]
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
findChildByType(KtNodeTypes.TYPE_REFERENCE)
|
findChildByType(KtNodeTypes.TYPE_REFERENCE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,8 +40,7 @@ fun KtModifierListOwner.setModifierList(newModifierList: KtModifierList) {
|
|||||||
val currentModifierList = modifierList
|
val currentModifierList = modifierList
|
||||||
if (currentModifierList != null) {
|
if (currentModifierList != null) {
|
||||||
currentModifierList.replace(newModifierList)
|
currentModifierList.replace(newModifierList)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
addModifierList(newModifierList)
|
addModifierList(newModifierList)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -50,8 +49,7 @@ fun addModifier(owner: KtModifierListOwner, modifier: KtModifierKeywordToken) {
|
|||||||
val modifierList = owner.modifierList
|
val modifierList = owner.modifierList
|
||||||
if (modifierList == null) {
|
if (modifierList == null) {
|
||||||
createModifierList(modifier.value, owner)
|
createModifierList(modifier.value, owner)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
addModifier(modifierList, modifier)
|
addModifier(modifierList, modifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,8 +58,7 @@ fun addAnnotationEntry(owner: KtModifierListOwner, annotationEntry: KtAnnotation
|
|||||||
val modifierList = owner.modifierList
|
val modifierList = owner.modifierList
|
||||||
return if (modifierList == null) {
|
return if (modifierList == null) {
|
||||||
createModifierList(annotationEntry.text, owner).annotationEntries.first()
|
createModifierList(annotationEntry.text, owner).annotationEntries.first()
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
modifierList.addBefore(annotationEntry, modifierList.firstChild) as KtAnnotationEntry
|
modifierList.addBefore(annotationEntry, modifierList.firstChild) as KtAnnotationEntry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -85,8 +82,7 @@ internal fun addModifier(modifierList: KtModifierList, modifier: KtModifierKeywo
|
|||||||
}
|
}
|
||||||
if (modifierToReplace != null && modifierList.firstChild == modifierList.lastChild) {
|
if (modifierToReplace != null && modifierList.firstChild == modifierList.lastChild) {
|
||||||
modifierToReplace.replace(newModifier)
|
modifierToReplace.replace(newModifier)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
modifierToReplace?.delete()
|
modifierToReplace?.delete()
|
||||||
val newModifierOrder = MODIFIERS_ORDER.indexOf(modifier)
|
val newModifierOrder = MODIFIERS_ORDER.indexOf(modifier)
|
||||||
|
|
||||||
@@ -143,7 +139,8 @@ private val MODIFIERS_TO_REPLACE = mapOf(
|
|||||||
ACTUAL_KEYWORD to listOf(HEADER_KEYWORD, EXPECT_KEYWORD, IMPL_KEYWORD)
|
ACTUAL_KEYWORD to listOf(HEADER_KEYWORD, EXPECT_KEYWORD, IMPL_KEYWORD)
|
||||||
)
|
)
|
||||||
|
|
||||||
val MODIFIERS_ORDER = listOf(PUBLIC_KEYWORD, PROTECTED_KEYWORD, PRIVATE_KEYWORD, INTERNAL_KEYWORD,
|
val MODIFIERS_ORDER = listOf(
|
||||||
|
PUBLIC_KEYWORD, PROTECTED_KEYWORD, PRIVATE_KEYWORD, INTERNAL_KEYWORD,
|
||||||
HEADER_KEYWORD, IMPL_KEYWORD, EXPECT_KEYWORD, ACTUAL_KEYWORD,
|
HEADER_KEYWORD, IMPL_KEYWORD, EXPECT_KEYWORD, ACTUAL_KEYWORD,
|
||||||
FINAL_KEYWORD, OPEN_KEYWORD, ABSTRACT_KEYWORD, SEALED_KEYWORD,
|
FINAL_KEYWORD, OPEN_KEYWORD, ABSTRACT_KEYWORD, SEALED_KEYWORD,
|
||||||
CONST_KEYWORD,
|
CONST_KEYWORD,
|
||||||
@@ -159,4 +156,5 @@ val MODIFIERS_ORDER = listOf(PUBLIC_KEYWORD, PROTECTED_KEYWORD, PRIVATE_KEYWORD,
|
|||||||
INLINE_KEYWORD,
|
INLINE_KEYWORD,
|
||||||
INFIX_KEYWORD,
|
INFIX_KEYWORD,
|
||||||
OPERATOR_KEYWORD,
|
OPERATOR_KEYWORD,
|
||||||
DATA_KEYWORD)
|
DATA_KEYWORD
|
||||||
|
)
|
||||||
|
|||||||
@@ -28,8 +28,7 @@ val SUPPRESS_DIAGNOSTICS_IN_DEBUG_MODE: Key<Boolean> = Key.create<Boolean>("SUPP
|
|||||||
fun KtElement.suppressDiagnosticsInDebugMode(): Boolean {
|
fun KtElement.suppressDiagnosticsInDebugMode(): Boolean {
|
||||||
return if (this is KtFile) {
|
return if (this is KtFile) {
|
||||||
this.suppressDiagnosticsInDebugMode
|
this.suppressDiagnosticsInDebugMode
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val file = this.containingFile
|
val file = this.containingFile
|
||||||
file is KtFile && file.suppressDiagnosticsInDebugMode
|
file is KtFile && file.suppressDiagnosticsInDebugMode
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,23 +31,32 @@ import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
|||||||
import org.jetbrains.kotlin.renderer.render
|
import org.jetbrains.kotlin.renderer.render
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
fun KtPsiFactory.createExpressionByPattern(pattern: String, vararg args: Any, reformat: Boolean = true): KtExpression
|
fun KtPsiFactory.createExpressionByPattern(pattern: String, vararg args: Any, reformat: Boolean = true): KtExpression =
|
||||||
= createByPattern(pattern, *args, reformat = reformat) { createExpression(it) }
|
createByPattern(pattern, *args, reformat = reformat) { createExpression(it) }
|
||||||
|
|
||||||
fun KtPsiFactory.createValueArgumentListByPattern(pattern: String, vararg args: Any, reformat: Boolean = true): KtValueArgumentList
|
fun KtPsiFactory.createValueArgumentListByPattern(pattern: String, vararg args: Any, reformat: Boolean = true): KtValueArgumentList =
|
||||||
= createByPattern(pattern, *args, reformat = reformat) { createCallArguments(it) }
|
createByPattern(pattern, *args, reformat = reformat) { createCallArguments(it) }
|
||||||
|
|
||||||
fun <TDeclaration : KtDeclaration> KtPsiFactory.createDeclarationByPattern(pattern: String, vararg args: Any, reformat: Boolean = true): TDeclaration
|
fun <TDeclaration : KtDeclaration> KtPsiFactory.createDeclarationByPattern(
|
||||||
= createByPattern(pattern, *args, reformat = reformat) { createDeclaration<TDeclaration>(it) }
|
pattern: String,
|
||||||
|
vararg args: Any,
|
||||||
|
reformat: Boolean = true
|
||||||
|
): TDeclaration = createByPattern(pattern, *args, reformat = reformat) { createDeclaration<TDeclaration>(it) }
|
||||||
|
|
||||||
fun KtPsiFactory.createDestructuringDeclarationByPattern(pattern: String, vararg args: Any, reformat: Boolean = true): KtDestructuringDeclaration
|
fun KtPsiFactory.createDestructuringDeclarationByPattern(
|
||||||
= createByPattern(pattern, *args, reformat = reformat) { createDestructuringDeclaration(it) }
|
pattern: String,
|
||||||
|
vararg args: Any,
|
||||||
|
reformat: Boolean = true
|
||||||
|
): KtDestructuringDeclaration = createByPattern(pattern, *args, reformat = reformat) { createDestructuringDeclaration(it) }
|
||||||
|
|
||||||
private abstract class ArgumentType<T : Any>(val klass: Class<T>)
|
private abstract class ArgumentType<T : Any>(val klass: Class<T>)
|
||||||
|
|
||||||
private class PlainTextArgumentType<T : Any>(klass: Class<T>, val toPlainText: (T) -> String) : ArgumentType<T>(klass)
|
private class PlainTextArgumentType<T : Any>(klass: Class<T>, val toPlainText: (T) -> String) : ArgumentType<T>(klass)
|
||||||
|
|
||||||
private abstract class PsiElementPlaceholderArgumentType<T : Any, TPlaceholder : PsiElement>(klass: Class<T>, val placeholderClass: Class<TPlaceholder>) : ArgumentType<T>(klass) {
|
private abstract class PsiElementPlaceholderArgumentType<T : Any, TPlaceholder : PsiElement>(
|
||||||
|
klass: Class<T>,
|
||||||
|
val placeholderClass: Class<TPlaceholder>
|
||||||
|
) : ArgumentType<T>(klass) {
|
||||||
abstract fun replacePlaceholderElement(placeholder: TPlaceholder, argument: T): PsiChildRange
|
abstract fun replacePlaceholderElement(placeholder: TPlaceholder, argument: T): PsiChildRange
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +73,8 @@ private class PsiElementArgumentType<T : PsiElement>(klass: Class<T>) : PsiEleme
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private object PsiChildRangeArgumentType : PsiElementPlaceholderArgumentType<PsiChildRange, KtElement>(PsiChildRange::class.java, KtElement::class.java) {
|
private object PsiChildRangeArgumentType :
|
||||||
|
PsiElementPlaceholderArgumentType<PsiChildRange, KtElement>(PsiChildRange::class.java, KtElement::class.java) {
|
||||||
override fun replacePlaceholderElement(placeholder: KtElement, argument: PsiChildRange): PsiChildRange {
|
override fun replacePlaceholderElement(placeholder: KtElement, argument: PsiChildRange): PsiChildRange {
|
||||||
val project = placeholder.project
|
val project = placeholder.project
|
||||||
val codeStyleManager = CodeStyleManager.getInstance(project)
|
val codeStyleManager = CodeStyleManager.getInstance(project)
|
||||||
@@ -79,8 +89,7 @@ private object PsiChildRangeArgumentType : PsiElementPlaceholderArgumentType<Psi
|
|||||||
codeStyleManager.reformatNewlyAddedElement(last.node.treeParent, last.node)
|
codeStyleManager.reformatNewlyAddedElement(last.node.treeParent, last.node)
|
||||||
}
|
}
|
||||||
PsiChildRange(first, last)
|
PsiChildRange(first, last)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
placeholder.delete()
|
placeholder.delete()
|
||||||
PsiChildRange.EMPTY
|
PsiChildRange.EMPTY
|
||||||
}
|
}
|
||||||
@@ -98,7 +107,12 @@ private val SUPPORTED_ARGUMENT_TYPES = listOf(
|
|||||||
@TestOnly
|
@TestOnly
|
||||||
var CREATEBYPATTERN_MAY_NOT_REFORMAT = false
|
var CREATEBYPATTERN_MAY_NOT_REFORMAT = false
|
||||||
|
|
||||||
fun <TElement : KtElement> createByPattern(pattern: String, vararg args: Any, reformat: Boolean = true, factory: (String) -> TElement): TElement {
|
fun <TElement : KtElement> createByPattern(
|
||||||
|
pattern: String,
|
||||||
|
vararg args: Any,
|
||||||
|
reformat: Boolean = true,
|
||||||
|
factory: (String) -> TElement
|
||||||
|
): TElement {
|
||||||
val argumentTypes = args.map { arg ->
|
val argumentTypes = args.map { arg ->
|
||||||
SUPPORTED_ARGUMENT_TYPES.firstOrNull { it.klass.isInstance(arg) }
|
SUPPORTED_ARGUMENT_TYPES.firstOrNull { it.klass.isInstance(arg) }
|
||||||
?: throw IllegalArgumentException("Unsupported argument type: ${arg::class.java}, should be one of: ${SUPPORTED_ARGUMENT_TYPES.joinToString { it.klass.simpleName }}")
|
?: throw IllegalArgumentException("Unsupported argument type: ${arg::class.java}, should be one of: ${SUPPORTED_ARGUMENT_TYPES.joinToString { it.klass.simpleName }}")
|
||||||
@@ -164,8 +178,7 @@ fun <TElement : KtElement> createByPattern(pattern: String, vararg args: Any, re
|
|||||||
// reformat whole text except for String arguments (as they can contain user's formatting to be preserved)
|
// reformat whole text except for String arguments (as they can contain user's formatting to be preserved)
|
||||||
resultElement = if (stringPlaceholderRanges.none()) {
|
resultElement = if (stringPlaceholderRanges.none()) {
|
||||||
codeStyleManager.reformat(resultElement, true) as TElement
|
codeStyleManager.reformat(resultElement, true) as TElement
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
var bound = resultElement.endOffset - 1
|
var bound = resultElement.endOffset - 1
|
||||||
for (range in stringPlaceholderRanges) {
|
for (range in stringPlaceholderRanges) {
|
||||||
// we extend reformatting range by 1 to the right because otherwise some of spaces are not reformatted
|
// we extend reformatting range by 1 to the right because otherwise some of spaces are not reformatted
|
||||||
@@ -223,8 +236,7 @@ private fun processPattern(pattern: String, args: List<Any>): PatternData {
|
|||||||
val nextChar = charOrNull(++i)
|
val nextChar = charOrNull(++i)
|
||||||
if (nextChar == '$') {
|
if (nextChar == '$') {
|
||||||
append(nextChar)
|
append(nextChar)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
check(nextChar?.isDigit() ?: false, "unclosed '$'")
|
check(nextChar?.isDigit() ?: false, "unclosed '$'")
|
||||||
|
|
||||||
val lastIndex = (i..pattern.length - 1).firstOrNull { !pattern[it].isDigit() } ?: pattern.length
|
val lastIndex = (i..pattern.length - 1).firstOrNull { !pattern[it].isDigit() } ?: pattern.length
|
||||||
@@ -235,8 +247,7 @@ private fun processPattern(pattern: String, args: List<Any>): PatternData {
|
|||||||
val arg: Any? = if (n < args.size) args[n] else null /* report wrong number of arguments later */
|
val arg: Any? = if (n < args.size) args[n] else null /* report wrong number of arguments later */
|
||||||
val placeholderText = if (charOrNull(i) != ':' || charOrNull(i + 1) != '\'') {
|
val placeholderText = if (charOrNull(i) != ':' || charOrNull(i + 1) != '\'') {
|
||||||
arg as? String ?: "xyz"
|
arg as? String ?: "xyz"
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
check(arg !is String, "do not specify placeholder text for $$n - plain text argument passed")
|
check(arg !is String, "do not specify placeholder text for $$n - plain text argument passed")
|
||||||
i += 2 // skip ':' and '\''
|
i += 2 // skip ':' and '\''
|
||||||
val endIndex = pattern.indexOf('\'', i)
|
val endIndex = pattern.indexOf('\'', i)
|
||||||
@@ -252,8 +263,7 @@ private fun processPattern(pattern: String, args: List<Any>): PatternData {
|
|||||||
ranges.getOrPut(n, { ArrayList() }).add(Placeholder(range, placeholderText))
|
ranges.getOrPut(n, { ArrayList() }).add(Placeholder(range, placeholderText))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
append(c)
|
append(c)
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
|
|||||||
@@ -159,8 +159,7 @@ fun KtExpression.isDotReceiver(): Boolean =
|
|||||||
fun KtElement.blockExpressionsOrSingle(): Sequence<KtElement> =
|
fun KtElement.blockExpressionsOrSingle(): Sequence<KtElement> =
|
||||||
if (this is KtBlockExpression) statements.asSequence() else sequenceOf(this)
|
if (this is KtBlockExpression) statements.asSequence() else sequenceOf(this)
|
||||||
|
|
||||||
fun KtExpression.lastBlockStatementOrThis(): KtExpression
|
fun KtExpression.lastBlockStatementOrThis(): KtExpression = (this as? KtBlockExpression)?.statements?.lastOrNull() ?: this
|
||||||
= (this as? KtBlockExpression)?.statements?.lastOrNull() ?: this
|
|
||||||
|
|
||||||
fun KtBlockExpression.contentRange(): PsiChildRange {
|
fun KtBlockExpression.contentRange(): PsiChildRange {
|
||||||
val first = (lBrace?.nextSibling ?: firstChild)
|
val first = (lBrace?.nextSibling ?: firstChild)
|
||||||
@@ -248,8 +247,7 @@ fun KtAnnotationsContainer.collectAnnotationEntriesFromStubOrPsi(): List<KtAnnot
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun StubElement<*>.collectAnnotationEntriesFromStubElement(): List<KtAnnotationEntry> {
|
private fun StubElement<*>.collectAnnotationEntriesFromStubElement(): List<KtAnnotationEntry> {
|
||||||
return childrenStubs.flatMap {
|
return childrenStubs.flatMap { child ->
|
||||||
child ->
|
|
||||||
when (child.stubType) {
|
when (child.stubType) {
|
||||||
KtNodeTypes.ANNOTATION_ENTRY -> listOf(child.psi as KtAnnotationEntry)
|
KtNodeTypes.ANNOTATION_ENTRY -> listOf(child.psi as KtAnnotationEntry)
|
||||||
KtNodeTypes.ANNOTATION -> (child.psi as KtAnnotation).entries
|
KtNodeTypes.ANNOTATION -> (child.psi as KtAnnotation).entries
|
||||||
@@ -283,7 +281,10 @@ inline fun <reified T : KtElement> forEachDescendantOfTypeVisitor(noinline block
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T : KtElement, R> flatMapDescendantsOfTypeVisitor(accumulator: MutableCollection<R>, noinline map: (T) -> Collection<R>): KtVisitorVoid {
|
inline fun <reified T : KtElement, R> flatMapDescendantsOfTypeVisitor(
|
||||||
|
accumulator: MutableCollection<R>,
|
||||||
|
noinline map: (T) -> Collection<R>
|
||||||
|
): KtVisitorVoid {
|
||||||
return forEachDescendantOfTypeVisitor<T> { accumulator.addAll(map(it)) }
|
return forEachDescendantOfTypeVisitor<T> { accumulator.addAll(map(it)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,8 +377,7 @@ fun KtSimpleNameExpression.isCallee(): Boolean {
|
|||||||
if (callElement != null) {
|
if (callElement != null) {
|
||||||
val ktConstructorCalleeExpression = callElement.calleeExpression as? KtConstructorCalleeExpression
|
val ktConstructorCalleeExpression = callElement.calleeExpression as? KtConstructorCalleeExpression
|
||||||
(ktConstructorCalleeExpression?.typeReference?.typeElement as? KtUserType)?.referenceExpression == this
|
(ktConstructorCalleeExpression?.typeReference?.typeElement as? KtUserType)?.referenceExpression == this
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -387,8 +387,7 @@ fun KtSimpleNameExpression.isCallee(): Boolean {
|
|||||||
val KtStringTemplateExpression.plainContent: String
|
val KtStringTemplateExpression.plainContent: String
|
||||||
get() = getContentRange().substring(text)
|
get() = getContentRange().substring(text)
|
||||||
|
|
||||||
fun KtStringTemplateExpression.isSingleQuoted(): Boolean
|
fun KtStringTemplateExpression.isSingleQuoted(): Boolean = node.firstChildNode.textLength == 1
|
||||||
= node.firstChildNode.textLength == 1
|
|
||||||
|
|
||||||
fun KtNamedDeclaration.getValueParameters(): List<KtParameter> {
|
fun KtNamedDeclaration.getValueParameters(): List<KtParameter> {
|
||||||
return getValueParameterList()?.parameters ?: Collections.emptyList()
|
return getValueParameterList()?.parameters ?: Collections.emptyList()
|
||||||
@@ -423,13 +422,12 @@ private fun KtModifierListOwner.modifierFromTokenSet(set: TokenSet) = modifierLi
|
|||||||
|
|
||||||
fun KtModifierList.visibilityModifier() = modifierFromTokenSet(KtTokens.VISIBILITY_MODIFIERS)
|
fun KtModifierList.visibilityModifier() = modifierFromTokenSet(KtTokens.VISIBILITY_MODIFIERS)
|
||||||
|
|
||||||
fun KtModifierList.visibilityModifierType(): KtModifierKeywordToken?
|
fun KtModifierList.visibilityModifierType(): KtModifierKeywordToken? = visibilityModifier()?.node?.elementType as KtModifierKeywordToken?
|
||||||
= visibilityModifier()?.node?.elementType as KtModifierKeywordToken?
|
|
||||||
|
|
||||||
fun KtModifierListOwner.visibilityModifier() = modifierList?.modifierFromTokenSet(KtTokens.VISIBILITY_MODIFIERS)
|
fun KtModifierListOwner.visibilityModifier() = modifierList?.modifierFromTokenSet(KtTokens.VISIBILITY_MODIFIERS)
|
||||||
|
|
||||||
fun KtModifierListOwner.visibilityModifierType(): KtModifierKeywordToken?
|
fun KtModifierListOwner.visibilityModifierType(): KtModifierKeywordToken? =
|
||||||
= visibilityModifier()?.node?.elementType as KtModifierKeywordToken?
|
visibilityModifier()?.node?.elementType as KtModifierKeywordToken?
|
||||||
|
|
||||||
private val MODALITY_MODIFIERS = TokenSet.create(
|
private val MODALITY_MODIFIERS = TokenSet.create(
|
||||||
KtTokens.ABSTRACT_KEYWORD, KtTokens.FINAL_KEYWORD, KtTokens.SEALED_KEYWORD, KtTokens.OPEN_KEYWORD
|
KtTokens.ABSTRACT_KEYWORD, KtTokens.FINAL_KEYWORD, KtTokens.SEALED_KEYWORD, KtTokens.OPEN_KEYWORD
|
||||||
@@ -438,7 +436,8 @@ private val MODALITY_MODIFIERS = TokenSet.create(
|
|||||||
fun KtDeclaration.modalityModifier() = modifierFromTokenSet(MODALITY_MODIFIERS)
|
fun KtDeclaration.modalityModifier() = modifierFromTokenSet(MODALITY_MODIFIERS)
|
||||||
|
|
||||||
fun KtStringTemplateExpression.isPlain() = entries.all { it is KtLiteralStringTemplateEntry }
|
fun KtStringTemplateExpression.isPlain() = entries.all { it is KtLiteralStringTemplateEntry }
|
||||||
fun KtStringTemplateExpression.isPlainWithEscapes() = entries.all { it is KtLiteralStringTemplateEntry || it is KtEscapeStringTemplateEntry }
|
fun KtStringTemplateExpression.isPlainWithEscapes() =
|
||||||
|
entries.all { it is KtLiteralStringTemplateEntry || it is KtEscapeStringTemplateEntry }
|
||||||
|
|
||||||
// Correct for class members only (including constructors and nested classes)
|
// Correct for class members only (including constructors and nested classes)
|
||||||
// Returns null e.g. for member function parameters, member function locals, property accessors
|
// Returns null e.g. for member function parameters, member function locals, property accessors
|
||||||
@@ -516,7 +515,8 @@ fun isTypeConstructorReference(e: PsiElement): Boolean {
|
|||||||
|
|
||||||
fun KtParameter.isPropertyParameter() = ownerFunction is KtPrimaryConstructor && hasValOrVar()
|
fun KtParameter.isPropertyParameter() = ownerFunction is KtPrimaryConstructor && hasValOrVar()
|
||||||
|
|
||||||
fun isDoubleColonReceiver(expression: KtExpression) = expression.getParentOfTypeAndBranch<KtDoubleColonExpression> { this.receiverExpression } != null
|
fun isDoubleColonReceiver(expression: KtExpression) =
|
||||||
|
expression.getParentOfTypeAndBranch<KtDoubleColonExpression> { this.receiverExpression } != null
|
||||||
|
|
||||||
fun KtFunctionLiteral.getOrCreateParameterList(): KtParameterList {
|
fun KtFunctionLiteral.getOrCreateParameterList(): KtParameterList {
|
||||||
valueParameterList?.let { return it }
|
valueParameterList?.let { return it }
|
||||||
@@ -535,15 +535,16 @@ fun KtFunctionLiteral.getOrCreateParameterList(): KtParameterList {
|
|||||||
|
|
||||||
fun KtCallExpression.getOrCreateValueArgumentList(): KtValueArgumentList {
|
fun KtCallExpression.getOrCreateValueArgumentList(): KtValueArgumentList {
|
||||||
valueArgumentList?.let { return it }
|
valueArgumentList?.let { return it }
|
||||||
return addAfter(KtPsiFactory(this).createCallArguments("()"),
|
return addAfter(
|
||||||
typeArgumentList ?: calleeExpression) as KtValueArgumentList
|
KtPsiFactory(this).createCallArguments("()"),
|
||||||
|
typeArgumentList ?: calleeExpression
|
||||||
|
) as KtValueArgumentList
|
||||||
}
|
}
|
||||||
|
|
||||||
fun KtCallExpression.addTypeArgument(typeArgument: KtTypeProjection) {
|
fun KtCallExpression.addTypeArgument(typeArgument: KtTypeProjection) {
|
||||||
if (typeArgumentList != null) {
|
if (typeArgumentList != null) {
|
||||||
typeArgumentList?.addArgument(typeArgument)
|
typeArgumentList?.addArgument(typeArgument)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
addAfter(KtPsiFactory(this).createTypeArguments("<${typeArgument.text}>"), calleeExpression)
|
addAfter(KtPsiFactory(this).createTypeArguments("<${typeArgument.text}>"), calleeExpression)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,11 +68,9 @@ val PsiElement.parentsWithSelf: Sequence<PsiElement>
|
|||||||
val PsiElement.parents: Sequence<PsiElement>
|
val PsiElement.parents: Sequence<PsiElement>
|
||||||
get() = parentsWithSelf.drop(1)
|
get() = parentsWithSelf.drop(1)
|
||||||
|
|
||||||
fun PsiElement.prevLeaf(skipEmptyElements: Boolean = false): PsiElement?
|
fun PsiElement.prevLeaf(skipEmptyElements: Boolean = false): PsiElement? = PsiTreeUtil.prevLeaf(this, skipEmptyElements)
|
||||||
= PsiTreeUtil.prevLeaf(this, skipEmptyElements)
|
|
||||||
|
|
||||||
fun PsiElement.nextLeaf(skipEmptyElements: Boolean = false): PsiElement?
|
fun PsiElement.nextLeaf(skipEmptyElements: Boolean = false): PsiElement? = PsiTreeUtil.nextLeaf(this, skipEmptyElements)
|
||||||
= PsiTreeUtil.nextLeaf(this, skipEmptyElements)
|
|
||||||
|
|
||||||
val PsiElement.prevLeafs: Sequence<PsiElement>
|
val PsiElement.prevLeafs: Sequence<PsiElement>
|
||||||
get() = generateSequence({ prevLeaf() }, { it.prevLeaf() })
|
get() = generateSequence({ prevLeaf() }, { it.prevLeaf() })
|
||||||
@@ -175,7 +173,10 @@ inline fun <reified T : PsiElement> PsiElement.getParentOfTypeAndBranch(strict:
|
|||||||
return getParentOfType<T>(strict)?.getIfChildIsInBranch(this, branch)
|
return getParentOfType<T>(strict)?.getIfChildIsInBranch(this, branch)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T : PsiElement> PsiElement.getParentOfTypeAndBranches(strict: Boolean = false, noinline branches: T.() -> Iterable<PsiElement?>): T? {
|
inline fun <reified T : PsiElement> PsiElement.getParentOfTypeAndBranches(
|
||||||
|
strict: Boolean = false,
|
||||||
|
noinline branches: T.() -> Iterable<PsiElement?>
|
||||||
|
): T? {
|
||||||
return getParentOfType<T>(strict)?.getIfChildIsInBranches(this, branches)
|
return getParentOfType<T>(strict)?.getIfChildIsInBranches(this, branches)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +189,9 @@ fun PsiElement.isInsideOf(elements: Iterable<PsiElement>): Boolean = elements.an
|
|||||||
|
|
||||||
fun PsiChildRange.trimWhiteSpaces(): PsiChildRange {
|
fun PsiChildRange.trimWhiteSpaces(): PsiChildRange {
|
||||||
if (first == null) return this
|
if (first == null) return this
|
||||||
return PsiChildRange(first.siblings().firstOrNull { it !is PsiWhiteSpace }, last!!.siblings(forward = false).firstOrNull { it !is PsiWhiteSpace })
|
return PsiChildRange(
|
||||||
|
first.siblings().firstOrNull { it !is PsiWhiteSpace },
|
||||||
|
last!!.siblings(forward = false).firstOrNull { it !is PsiWhiteSpace })
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------- Recursive tree visiting --------------------------------------------------------------------------------------------
|
// -------------------- Recursive tree visiting --------------------------------------------------------------------------------------------
|
||||||
@@ -197,7 +200,10 @@ inline fun <reified T : PsiElement> PsiElement.forEachDescendantOfType(noinline
|
|||||||
forEachDescendantOfType({ true }, action)
|
forEachDescendantOfType({ true }, action)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T : PsiElement> PsiElement.forEachDescendantOfType(crossinline canGoInside: (PsiElement) -> Boolean, noinline action: (T) -> Unit) {
|
inline fun <reified T : PsiElement> PsiElement.forEachDescendantOfType(
|
||||||
|
crossinline canGoInside: (PsiElement) -> Boolean,
|
||||||
|
noinline action: (T) -> Unit
|
||||||
|
) {
|
||||||
this.accept(object : PsiRecursiveElementVisitor() {
|
this.accept(object : PsiRecursiveElementVisitor() {
|
||||||
override fun visitElement(element: PsiElement) {
|
override fun visitElement(element: PsiElement) {
|
||||||
if (canGoInside(element)) {
|
if (canGoInside(element)) {
|
||||||
@@ -215,7 +221,10 @@ inline fun <reified T : PsiElement> PsiElement.anyDescendantOfType(noinline pred
|
|||||||
return findDescendantOfType(predicate) != null
|
return findDescendantOfType(predicate) != null
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T : PsiElement> PsiElement.anyDescendantOfType(crossinline canGoInside: (PsiElement) -> Boolean, noinline predicate: (T) -> Boolean = { true }): Boolean {
|
inline fun <reified T : PsiElement> PsiElement.anyDescendantOfType(
|
||||||
|
crossinline canGoInside: (PsiElement) -> Boolean,
|
||||||
|
noinline predicate: (T) -> Boolean = { true }
|
||||||
|
): Boolean {
|
||||||
return findDescendantOfType(canGoInside, predicate) != null
|
return findDescendantOfType(canGoInside, predicate) != null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +232,10 @@ inline fun <reified T : PsiElement> PsiElement.findDescendantOfType(noinline pre
|
|||||||
return findDescendantOfType({ true }, predicate)
|
return findDescendantOfType({ true }, predicate)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T : PsiElement> PsiElement.findDescendantOfType(crossinline canGoInside: (PsiElement) -> Boolean, noinline predicate: (T) -> Boolean = { true }): T? {
|
inline fun <reified T : PsiElement> PsiElement.findDescendantOfType(
|
||||||
|
crossinline canGoInside: (PsiElement) -> Boolean,
|
||||||
|
noinline predicate: (T) -> Boolean = { true }
|
||||||
|
): T? {
|
||||||
var result: T? = null
|
var result: T? = null
|
||||||
this.accept(object : PsiRecursiveElementWalkingVisitor() {
|
this.accept(object : PsiRecursiveElementWalkingVisitor() {
|
||||||
override fun visitElement(element: PsiElement) {
|
override fun visitElement(element: PsiElement) {
|
||||||
@@ -245,7 +257,10 @@ inline fun <reified T : PsiElement> PsiElement.collectDescendantsOfType(noinline
|
|||||||
return collectDescendantsOfType({ true }, predicate)
|
return collectDescendantsOfType({ true }, predicate)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T : PsiElement> PsiElement.collectDescendantsOfType(crossinline canGoInside: (PsiElement) -> Boolean, noinline predicate: (T) -> Boolean = { true }): List<T> {
|
inline fun <reified T : PsiElement> PsiElement.collectDescendantsOfType(
|
||||||
|
crossinline canGoInside: (PsiElement) -> Boolean,
|
||||||
|
noinline predicate: (T) -> Boolean = { true }
|
||||||
|
): List<T> {
|
||||||
val result = ArrayList<T>()
|
val result = ArrayList<T>()
|
||||||
forEachDescendantOfType<T>(canGoInside) {
|
forEachDescendantOfType<T>(canGoInside) {
|
||||||
if (predicate(it)) {
|
if (predicate(it)) {
|
||||||
@@ -333,8 +348,8 @@ fun PsiElement.getElementTextWithContext(): String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find parent for element among file children
|
// Find parent for element among file children
|
||||||
val topLevelElement = PsiTreeUtil.findFirstParent(this, { it.parent is PsiFile }) ?:
|
val topLevelElement = PsiTreeUtil.findFirstParent(this, { it.parent is PsiFile })
|
||||||
throw AssertionError("For non-file element we should always be able to find parent in file children")
|
?: throw AssertionError("For non-file element we should always be able to find parent in file children")
|
||||||
|
|
||||||
val startContextOffset = topLevelElement.startOffset
|
val startContextOffset = topLevelElement.startOffset
|
||||||
val elementContextOffset = textRange.startOffset
|
val elementContextOffset = textRange.startOffset
|
||||||
|
|||||||
+2
-1
@@ -25,7 +25,8 @@ import org.jetbrains.kotlin.psi.KtAnnotationUseSiteTarget
|
|||||||
import org.jetbrains.kotlin.psi.stubs.KotlinAnnotationUseSiteTargetStub
|
import org.jetbrains.kotlin.psi.stubs.KotlinAnnotationUseSiteTargetStub
|
||||||
import org.jetbrains.kotlin.psi.stubs.impl.KotlinAnnotationUseSiteTargetStubImpl
|
import org.jetbrains.kotlin.psi.stubs.impl.KotlinAnnotationUseSiteTargetStubImpl
|
||||||
|
|
||||||
class KtAnnotationUseSiteTargetElementType(debugName: String) : KtStubElementType<KotlinAnnotationUseSiteTargetStub, KtAnnotationUseSiteTarget>(
|
class KtAnnotationUseSiteTargetElementType(debugName: String) :
|
||||||
|
KtStubElementType<KotlinAnnotationUseSiteTargetStub, KtAnnotationUseSiteTarget>(
|
||||||
debugName, KtAnnotationUseSiteTarget::class.java, KotlinAnnotationUseSiteTargetStub::class.java
|
debugName, KtAnnotationUseSiteTarget::class.java, KotlinAnnotationUseSiteTargetStub::class.java
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
|||||||
+6
-3
@@ -25,14 +25,17 @@ import org.jetbrains.kotlin.psi.KtEnumEntrySuperclassReferenceExpression
|
|||||||
import org.jetbrains.kotlin.psi.stubs.KotlinEnumEntrySuperclassReferenceExpressionStub
|
import org.jetbrains.kotlin.psi.stubs.KotlinEnumEntrySuperclassReferenceExpressionStub
|
||||||
import org.jetbrains.kotlin.psi.stubs.impl.KotlinEnumEntrySuperclassReferenceExpressionStubImpl
|
import org.jetbrains.kotlin.psi.stubs.impl.KotlinEnumEntrySuperclassReferenceExpressionStubImpl
|
||||||
|
|
||||||
class KtEnumEntrySuperClassReferenceExpressionElementType(@NonNls debugName: String)
|
class KtEnumEntrySuperClassReferenceExpressionElementType(@NonNls debugName: String) :
|
||||||
: KtStubElementType<KotlinEnumEntrySuperclassReferenceExpressionStub, KtEnumEntrySuperclassReferenceExpression>(
|
KtStubElementType<KotlinEnumEntrySuperclassReferenceExpressionStub, KtEnumEntrySuperclassReferenceExpression>(
|
||||||
debugName,
|
debugName,
|
||||||
KtEnumEntrySuperclassReferenceExpression::class.java,
|
KtEnumEntrySuperclassReferenceExpression::class.java,
|
||||||
KotlinEnumEntrySuperclassReferenceExpressionStub::class.java
|
KotlinEnumEntrySuperclassReferenceExpressionStub::class.java
|
||||||
) {
|
) {
|
||||||
|
|
||||||
override fun createStub(psi: KtEnumEntrySuperclassReferenceExpression, parentStub: StubElement<*>): KotlinEnumEntrySuperclassReferenceExpressionStub {
|
override fun createStub(
|
||||||
|
psi: KtEnumEntrySuperclassReferenceExpression,
|
||||||
|
parentStub: StubElement<*>
|
||||||
|
): KotlinEnumEntrySuperclassReferenceExpressionStub {
|
||||||
return KotlinEnumEntrySuperclassReferenceExpressionStubImpl(parentStub, StringRef.fromString(psi.getReferencedName())!!)
|
return KotlinEnumEntrySuperclassReferenceExpressionStubImpl(parentStub, StringRef.fromString(psi.getReferencedName())!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ class KotlinFunctionStubImpl(
|
|||||||
throw IllegalArgumentException("fqName shouldn't be null for top level functions")
|
throw IllegalArgumentException("fqName shouldn't be null for top level functions")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getFqName() = fqName
|
override fun getFqName() = fqName
|
||||||
|
|
||||||
override fun getName() = StringRef.toString(nameRef)
|
override fun getName() = StringRef.toString(nameRef)
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ import java.util.ArrayList
|
|||||||
|
|
||||||
val STUB_TO_STRING_PREFIX = "KotlinStub$"
|
val STUB_TO_STRING_PREFIX = "KotlinStub$"
|
||||||
|
|
||||||
open class KotlinStubBaseImpl<T : KtElementImplStub<*>>(parent: StubElement<*>?, elementType: IStubElementType<*, *>) : StubBase<T>(parent, elementType) {
|
open class KotlinStubBaseImpl<T : KtElementImplStub<*>>(parent: StubElement<*>?, elementType: IStubElementType<*, *>) :
|
||||||
|
StubBase<T>(parent, elementType) {
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
val stubInterface = this::class.java.interfaces.single { it.name.contains("Stub") }
|
val stubInterface = this::class.java.interfaces.single { it.name.contains("Stub") }
|
||||||
@@ -62,8 +63,7 @@ open class KotlinStubBaseImpl<T : KtElementImplStub<*>>(parent: StubElement<*>?,
|
|||||||
val value = property.invoke(this)
|
val value = property.invoke(this)
|
||||||
val name = getPropertyName(property)
|
val name = getPropertyName(property)
|
||||||
"$name=$value"
|
"$name=$value"
|
||||||
}
|
} catch (e: Exception) {
|
||||||
catch (e: Exception) {
|
|
||||||
LOGGER.error(e)
|
LOGGER.error(e)
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
@@ -80,6 +80,11 @@ open class KotlinStubBaseImpl<T : KtElementImplStub<*>>(parent: StubElement<*>?,
|
|||||||
companion object {
|
companion object {
|
||||||
private val LOGGER: Logger = Logger.getInstance(KotlinStubBaseImpl::class.java)
|
private val LOGGER: Logger = Logger.getInstance(KotlinStubBaseImpl::class.java)
|
||||||
|
|
||||||
private val BASE_STUB_INTERFACES = listOf(KotlinStubWithFqName::class.java, KotlinClassOrObjectStub::class.java, NamedStub::class.java, KotlinCallableStubBase::class.java)
|
private val BASE_STUB_INTERFACES = listOf(
|
||||||
|
KotlinStubWithFqName::class.java,
|
||||||
|
KotlinClassOrObjectStub::class.java,
|
||||||
|
NamedStub::class.java,
|
||||||
|
KotlinCallableStubBase::class.java
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-6
@@ -62,8 +62,10 @@ class SyntheticClassOrObjectDescriptor(
|
|||||||
private val thisDescriptor: SyntheticClassOrObjectDescriptor get() = this // code readability
|
private val thisDescriptor: SyntheticClassOrObjectDescriptor get() = this // code readability
|
||||||
private val typeConstructor = SyntheticTypeConstructor(c.storageManager)
|
private val typeConstructor = SyntheticTypeConstructor(c.storageManager)
|
||||||
private val resolutionScopesSupport = ClassResolutionScopesSupport(thisDescriptor, c.storageManager, { outerScope })
|
private val resolutionScopesSupport = ClassResolutionScopesSupport(thisDescriptor, c.storageManager, { outerScope })
|
||||||
private val syntheticSupertypes = mutableListOf<KotlinType>().apply { c.syntheticResolveExtension.addSyntheticSupertypes(thisDescriptor, this) }
|
private val syntheticSupertypes =
|
||||||
private val unsubstitutedMemberScope = LazyClassMemberScope(c, SyntheticClassMemberDeclarationProvider(syntheticDeclaration), this, c.trace)
|
mutableListOf<KotlinType>().apply { c.syntheticResolveExtension.addSyntheticSupertypes(thisDescriptor, this) }
|
||||||
|
private val unsubstitutedMemberScope =
|
||||||
|
LazyClassMemberScope(c, SyntheticClassMemberDeclarationProvider(syntheticDeclaration), this, c.trace)
|
||||||
private val unsubstitutedPrimaryConstructor = createUnsubstitutedPrimaryConstructor(constructorVisibility)
|
private val unsubstitutedPrimaryConstructor = createUnsubstitutedPrimaryConstructor(constructorVisibility)
|
||||||
|
|
||||||
override val annotations: Annotations get() = Annotations.EMPTY
|
override val annotations: Annotations get() = Annotations.EMPTY
|
||||||
@@ -97,11 +99,15 @@ class SyntheticClassOrObjectDescriptor(
|
|||||||
|
|
||||||
override fun getScopeForClassHeaderResolution(): LexicalScope = resolutionScopesSupport.scopeForClassHeaderResolution()
|
override fun getScopeForClassHeaderResolution(): LexicalScope = resolutionScopesSupport.scopeForClassHeaderResolution()
|
||||||
override fun getScopeForConstructorHeaderResolution(): LexicalScope = resolutionScopesSupport.scopeForConstructorHeaderResolution()
|
override fun getScopeForConstructorHeaderResolution(): LexicalScope = resolutionScopesSupport.scopeForConstructorHeaderResolution()
|
||||||
override fun getScopeForCompanionObjectHeaderResolution(): LexicalScope = resolutionScopesSupport.scopeForCompanionObjectHeaderResolution()
|
override fun getScopeForCompanionObjectHeaderResolution(): LexicalScope =
|
||||||
override fun getScopeForMemberDeclarationResolution(): LexicalScope = resolutionScopesSupport.scopeForMemberDeclarationResolution()
|
resolutionScopesSupport.scopeForCompanionObjectHeaderResolution()
|
||||||
override fun getScopeForStaticMemberDeclarationResolution(): LexicalScope = resolutionScopesSupport.scopeForStaticMemberDeclarationResolution()
|
|
||||||
|
|
||||||
override fun getScopeForInitializerResolution(): LexicalScope = throw UnsupportedOperationException("Not supported for synthetic class or object")
|
override fun getScopeForMemberDeclarationResolution(): LexicalScope = resolutionScopesSupport.scopeForMemberDeclarationResolution()
|
||||||
|
override fun getScopeForStaticMemberDeclarationResolution(): LexicalScope =
|
||||||
|
resolutionScopesSupport.scopeForStaticMemberDeclarationResolution()
|
||||||
|
|
||||||
|
override fun getScopeForInitializerResolution(): LexicalScope =
|
||||||
|
throw UnsupportedOperationException("Not supported for synthetic class or object")
|
||||||
|
|
||||||
override fun toString(): String = "synthetic class " + name.toString() + " in " + containingDeclaration
|
override fun toString(): String = "synthetic class " + name.toString() + " in " + containingDeclaration
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,7 @@ class AllUnderImportScope(
|
|||||||
|
|
||||||
private val scopes: List<MemberScope> = if (descriptor is ClassDescriptor) {
|
private val scopes: List<MemberScope> = if (descriptor is ClassDescriptor) {
|
||||||
listOf(descriptor.staticScope, descriptor.unsubstitutedInnerClassesScope)
|
listOf(descriptor.staticScope, descriptor.unsubstitutedInnerClassesScope)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
assert(descriptor is PackageViewDescriptor) {
|
assert(descriptor is PackageViewDescriptor) {
|
||||||
"Must be class or package view descriptor: $descriptor"
|
"Must be class or package view descriptor: $descriptor"
|
||||||
}
|
}
|
||||||
@@ -44,8 +43,7 @@ class AllUnderImportScope(
|
|||||||
|
|
||||||
private val excludedNames: Set<Name> = if (excludedImportNames.isEmpty()) { // optimization
|
private val excludedNames: Set<Name> = if (excludedImportNames.isEmpty()) { // optimization
|
||||||
emptySet<Name>()
|
emptySet<Name>()
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val fqName = DescriptorUtils.getFqNameSafe(descriptor)
|
val fqName = DescriptorUtils.getFqNameSafe(descriptor)
|
||||||
// toSet() is used here instead mapNotNullTo(hashSetOf()) because it results in not keeping empty sets as separate instances
|
// toSet() is used here instead mapNotNullTo(hashSetOf()) because it results in not keeping empty sets as separate instances
|
||||||
excludedImportNames.mapNotNull { if (it.parent() == fqName) it.shortName() else null }.toSet()
|
excludedImportNames.mapNotNull { if (it.parent() == fqName) it.shortName() else null }.toSet()
|
||||||
@@ -60,8 +58,7 @@ class AllUnderImportScope(
|
|||||||
): Collection<DeclarationDescriptor> {
|
): Collection<DeclarationDescriptor> {
|
||||||
val nameFilterToUse = if (excludedNames.isEmpty()) { // optimization
|
val nameFilterToUse = if (excludedNames.isEmpty()) { // optimization
|
||||||
nameFilter
|
nameFilter
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
{ it !in excludedNames && nameFilter(it) }
|
{ it !in excludedNames && nameFilter(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,22 +34,18 @@ object DataClassDescriptorResolver {
|
|||||||
|
|
||||||
private val COMPONENT_FUNCTION_NAME_PREFIX = "component"
|
private val COMPONENT_FUNCTION_NAME_PREFIX = "component"
|
||||||
|
|
||||||
fun createComponentName(index: Int): Name
|
fun createComponentName(index: Int): Name = Name.identifier(COMPONENT_FUNCTION_NAME_PREFIX + index)
|
||||||
= Name.identifier(COMPONENT_FUNCTION_NAME_PREFIX + index)
|
|
||||||
|
|
||||||
fun getComponentIndex(componentName: String): Int
|
fun getComponentIndex(componentName: String): Int = componentName.substring(COMPONENT_FUNCTION_NAME_PREFIX.length).toInt()
|
||||||
= componentName.substring(COMPONENT_FUNCTION_NAME_PREFIX.length).toInt()
|
|
||||||
|
|
||||||
fun isComponentLike(name: Name): Boolean
|
fun isComponentLike(name: Name): Boolean = isComponentLike(name.asString())
|
||||||
= isComponentLike(name.asString())
|
|
||||||
|
|
||||||
private fun isComponentLike(name: String): Boolean {
|
private fun isComponentLike(name: String): Boolean {
|
||||||
if (!name.startsWith(COMPONENT_FUNCTION_NAME_PREFIX)) return false
|
if (!name.startsWith(COMPONENT_FUNCTION_NAME_PREFIX)) return false
|
||||||
|
|
||||||
try {
|
try {
|
||||||
getComponentIndex(name)
|
getComponentIndex(name)
|
||||||
}
|
} catch (e: NumberFormatException) {
|
||||||
catch (e: NumberFormatException) {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,10 @@ class DeclarationResolver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkRedeclarationsInPackages(topLevelDescriptorProvider: TopLevelDescriptorProvider, topLevelFqNames: Multimap<FqName, KtElement>) {
|
fun checkRedeclarationsInPackages(
|
||||||
|
topLevelDescriptorProvider: TopLevelDescriptorProvider,
|
||||||
|
topLevelFqNames: Multimap<FqName, KtElement>
|
||||||
|
) {
|
||||||
for ((fqName, declarationsOrPackageDirectives) in topLevelFqNames.asMap()) {
|
for ((fqName, declarationsOrPackageDirectives) in topLevelFqNames.asMap()) {
|
||||||
if (fqName.isRoot) continue
|
if (fqName.isRoot) continue
|
||||||
|
|
||||||
@@ -94,7 +97,11 @@ class DeclarationResolver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getTopLevelDescriptorsByFqName(topLevelDescriptorProvider: TopLevelDescriptorProvider, fqName: FqName, location: LookupLocation): Set<DeclarationDescriptor> {
|
private fun getTopLevelDescriptorsByFqName(
|
||||||
|
topLevelDescriptorProvider: TopLevelDescriptorProvider,
|
||||||
|
fqName: FqName,
|
||||||
|
location: LookupLocation
|
||||||
|
): Set<DeclarationDescriptor> {
|
||||||
val descriptors = HashSet<DeclarationDescriptor>()
|
val descriptors = HashSet<DeclarationDescriptor>()
|
||||||
|
|
||||||
descriptors.addIfNotNull(topLevelDescriptorProvider.getPackageFragment(fqName))
|
descriptors.addIfNotNull(topLevelDescriptorProvider.getPackageFragment(fqName))
|
||||||
|
|||||||
@@ -204,7 +204,11 @@ class DeclarationsChecker(
|
|||||||
// Do nothing: this should've been reported during type resolution.
|
// Do nothing: this should've been reported during type resolution.
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun conflictingProjection(typeAlias: TypeAliasDescriptor, typeParameter: TypeParameterDescriptor?, substitutedArgument: KotlinType) {
|
override fun conflictingProjection(
|
||||||
|
typeAlias: TypeAliasDescriptor,
|
||||||
|
typeParameter: TypeParameterDescriptor?,
|
||||||
|
substitutedArgument: KotlinType
|
||||||
|
) {
|
||||||
trace.report(CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION.on(typeReference, substitutedArgument))
|
trace.report(CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION.on(typeReference, substitutedArgument))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,7 +216,12 @@ class DeclarationsChecker(
|
|||||||
trace.report(RECURSIVE_TYPEALIAS_EXPANSION.on(typeReference, typeAlias))
|
trace.report(RECURSIVE_TYPEALIAS_EXPANSION.on(typeReference, typeAlias))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun boundsViolationInSubstitution(bound: KotlinType, unsubstitutedArgument: KotlinType, argument: KotlinType, typeParameter: TypeParameterDescriptor) {
|
override fun boundsViolationInSubstitution(
|
||||||
|
bound: KotlinType,
|
||||||
|
unsubstitutedArgument: KotlinType,
|
||||||
|
argument: KotlinType,
|
||||||
|
typeParameter: TypeParameterDescriptor
|
||||||
|
) {
|
||||||
// TODO more precise diagnostics
|
// TODO more precise diagnostics
|
||||||
if (!argument.containsTypeAliasParameters() && !bound.containsTypeAliasParameters()) {
|
if (!argument.containsTypeAliasParameters() && !bound.containsTypeAliasParameters()) {
|
||||||
trace.report(UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION.on(typeReference, bound, argument, typeParameter))
|
trace.report(UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION.on(typeReference, bound, argument, typeParameter))
|
||||||
@@ -272,8 +281,7 @@ class DeclarationsChecker(
|
|||||||
val classDescriptor = constructorDescriptor.containingDeclaration
|
val classDescriptor = constructorDescriptor.containingDeclaration
|
||||||
if (classDescriptor.kind == ClassKind.ENUM_CLASS) {
|
if (classDescriptor.kind == ClassKind.ENUM_CLASS) {
|
||||||
trace.report(NON_PRIVATE_CONSTRUCTOR_IN_ENUM.on(visibilityModifier))
|
trace.report(NON_PRIVATE_CONSTRUCTOR_IN_ENUM.on(visibilityModifier))
|
||||||
}
|
} else if (classDescriptor.modality == Modality.SEALED) {
|
||||||
else if (classDescriptor.modality == Modality.SEALED) {
|
|
||||||
trace.report(NON_PRIVATE_CONSTRUCTOR_IN_SEALED.on(visibilityModifier))
|
trace.report(NON_PRIVATE_CONSTRUCTOR_IN_SEALED.on(visibilityModifier))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -301,7 +309,8 @@ class DeclarationsChecker(
|
|||||||
is KtClass -> {
|
is KtClass -> {
|
||||||
checkClassButNotObject(classOrObject, classDescriptor)
|
checkClassButNotObject(classOrObject, classDescriptor)
|
||||||
descriptorResolver.checkNamesInConstraints(
|
descriptorResolver.checkNamesInConstraints(
|
||||||
classOrObject, classDescriptor, classDescriptor.scopeForClassHeaderResolution, trace)
|
classOrObject, classDescriptor, classDescriptor.scopeForClassHeaderResolution, trace
|
||||||
|
)
|
||||||
}
|
}
|
||||||
is KtObjectDeclaration -> {
|
is KtObjectDeclaration -> {
|
||||||
checkObject(classOrObject, classDescriptor)
|
checkObject(classOrObject, classDescriptor)
|
||||||
@@ -370,8 +379,7 @@ class DeclarationsChecker(
|
|||||||
allBounds.firstOrNull { bound -> bound.second?.constructor != boundsWhichAreTypeParameters.first() }
|
allBounds.firstOrNull { bound -> bound.second?.constructor != boundsWhichAreTypeParameters.first() }
|
||||||
|
|
||||||
problematicBound?.first ?: declaration
|
problematicBound?.first ?: declaration
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// Otherwise report the diagnostic on the type parameter declaration
|
// Otherwise report the diagnostic on the type parameter declaration
|
||||||
declaration
|
declaration
|
||||||
}
|
}
|
||||||
@@ -403,14 +411,17 @@ class DeclarationsChecker(
|
|||||||
?: throw AssertionError("Not a class descriptor: " + typeParameterDescriptor.containingDeclaration)
|
?: throw AssertionError("Not a class descriptor: " + typeParameterDescriptor.containingDeclaration)
|
||||||
if (sourceElement is KtClassOrObject) {
|
if (sourceElement is KtClassOrObject) {
|
||||||
val delegationSpecifierList = sourceElement.getSuperTypeList() ?: continue
|
val delegationSpecifierList = sourceElement.getSuperTypeList() ?: continue
|
||||||
trace.report(INCONSISTENT_TYPE_PARAMETER_VALUES.on(
|
trace.report(
|
||||||
|
INCONSISTENT_TYPE_PARAMETER_VALUES.on(
|
||||||
delegationSpecifierList, typeParameterDescriptor, containingDeclaration, conflictingTypes
|
delegationSpecifierList, typeParameterDescriptor, containingDeclaration, conflictingTypes
|
||||||
))
|
)
|
||||||
}
|
)
|
||||||
else if (sourceElement is KtTypeParameter) {
|
} else if (sourceElement is KtTypeParameter) {
|
||||||
trace.report(INCONSISTENT_TYPE_PARAMETER_BOUNDS.on(
|
trace.report(
|
||||||
|
INCONSISTENT_TYPE_PARAMETER_BOUNDS.on(
|
||||||
sourceElement, typeParameterDescriptor, containingDeclaration, conflictingTypes
|
sourceElement, typeParameterDescriptor, containingDeclaration, conflictingTypes
|
||||||
))
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -521,8 +532,7 @@ class DeclarationsChecker(
|
|||||||
for (parameter in aClass.primaryConstructorParameters) {
|
for (parameter in aClass.primaryConstructorParameters) {
|
||||||
if (!parameter.hasValOrVar()) {
|
if (!parameter.hasValOrVar()) {
|
||||||
trace.report(MISSING_VAL_ON_ANNOTATION_PARAMETER.on(parameter))
|
trace.report(MISSING_VAL_ON_ANNOTATION_PARAMETER.on(parameter))
|
||||||
}
|
} else if (parameter.isMutable) {
|
||||||
else if (parameter.isMutable) {
|
|
||||||
trace.report(VAR_ANNOTATION_PARAMETER.on(parameter))
|
trace.report(VAR_ANNOTATION_PARAMETER.on(parameter))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -537,8 +547,7 @@ class DeclarationsChecker(
|
|||||||
if (member != null && member.hasModifier(KtTokens.OPEN_KEYWORD)) {
|
if (member != null && member.hasModifier(KtTokens.OPEN_KEYWORD)) {
|
||||||
if (classDescriptor.kind == ClassKind.OBJECT) {
|
if (classDescriptor.kind == ClassKind.OBJECT) {
|
||||||
trace.report(NON_FINAL_MEMBER_IN_OBJECT.on(member))
|
trace.report(NON_FINAL_MEMBER_IN_OBJECT.on(member))
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
trace.report(NON_FINAL_MEMBER_IN_FINAL_CLASS.on(member))
|
trace.report(NON_FINAL_MEMBER_IN_FINAL_CLASS.on(member))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -607,8 +616,7 @@ class DeclarationsChecker(
|
|||||||
trace.report(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS.on(property, property.name ?: "", classDescriptor))
|
trace.report(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS.on(property, property.name ?: "", classDescriptor))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
} else if (classDescriptor.kind == ClassKind.INTERFACE &&
|
||||||
else if (classDescriptor.kind == ClassKind.INTERFACE &&
|
|
||||||
modifierList.hasModifier(KtTokens.OPEN_KEYWORD) &&
|
modifierList.hasModifier(KtTokens.OPEN_KEYWORD) &&
|
||||||
propertyDescriptor.modality == Modality.ABSTRACT) {
|
propertyDescriptor.modality == Modality.ABSTRACT) {
|
||||||
trace.report(REDUNDANT_OPEN_IN_INTERFACE.on(property))
|
trace.report(REDUNDANT_OPEN_IN_INTERFACE.on(property))
|
||||||
@@ -659,35 +667,33 @@ class DeclarationsChecker(
|
|||||||
!backingFieldRequired -> trace.report(PROPERTY_INITIALIZER_NO_BACKING_FIELD.on(initializer))
|
!backingFieldRequired -> trace.report(PROPERTY_INITIALIZER_NO_BACKING_FIELD.on(initializer))
|
||||||
property.receiverTypeReference != null -> trace.report(EXTENSION_PROPERTY_WITH_BACKING_FIELD.on(initializer))
|
property.receiverTypeReference != null -> trace.report(EXTENSION_PROPERTY_WITH_BACKING_FIELD.on(initializer))
|
||||||
}
|
}
|
||||||
}
|
} else if (delegate != null) {
|
||||||
else if (delegate != null) {
|
|
||||||
if (inInterface) {
|
if (inInterface) {
|
||||||
trace.report(DELEGATED_PROPERTY_IN_INTERFACE.on(delegate))
|
trace.report(DELEGATED_PROPERTY_IN_INTERFACE.on(delegate))
|
||||||
}
|
} else if (isExpect) {
|
||||||
else if (isExpect) {
|
|
||||||
trace.report(EXPECTED_DELEGATED_PROPERTY.on(delegate))
|
trace.report(EXPECTED_DELEGATED_PROPERTY.on(delegate))
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val isUninitialized = trace.bindingContext.get(BindingContext.IS_UNINITIALIZED, propertyDescriptor) ?: false
|
val isUninitialized = trace.bindingContext.get(BindingContext.IS_UNINITIALIZED, propertyDescriptor) ?: false
|
||||||
val isExternal = propertyDescriptor.isEffectivelyExternal()
|
val isExternal = propertyDescriptor.isEffectivelyExternal()
|
||||||
if (backingFieldRequired && !inInterface && !propertyDescriptor.isLateInit && !isExpect && isUninitialized && !isExternal) {
|
if (backingFieldRequired && !inInterface && !propertyDescriptor.isLateInit && !isExpect && isUninitialized && !isExternal) {
|
||||||
if (propertyDescriptor.extensionReceiverParameter != null && !hasAccessorImplementation) {
|
if (propertyDescriptor.extensionReceiverParameter != null && !hasAccessorImplementation) {
|
||||||
trace.report(EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT.on(property))
|
trace.report(EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT.on(property))
|
||||||
}
|
} else if (diagnosticSuppressor.shouldReportNoBody(propertyDescriptor)) {
|
||||||
else if (diagnosticSuppressor.shouldReportNoBody(propertyDescriptor)) {
|
|
||||||
if (containingDeclaration !is ClassDescriptor || hasAccessorImplementation) {
|
if (containingDeclaration !is ClassDescriptor || hasAccessorImplementation) {
|
||||||
trace.report(MUST_BE_INITIALIZED.on(property))
|
trace.report(MUST_BE_INITIALIZED.on(property))
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
trace.report(MUST_BE_INITIALIZED_OR_BE_ABSTRACT.on(property))
|
trace.report(MUST_BE_INITIALIZED_OR_BE_ABSTRACT.on(property))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (property.typeReference == null && !languageVersionSettings.supportsFeature(LanguageFeature.ShortSyntaxForPropertyGetters)) {
|
||||||
else if (property.typeReference == null && !languageVersionSettings.supportsFeature(LanguageFeature.ShortSyntaxForPropertyGetters)) {
|
trace.report(
|
||||||
trace.report(Errors.UNSUPPORTED_FEATURE.on(property, LanguageFeature.ShortSyntaxForPropertyGetters to languageVersionSettings))
|
Errors.UNSUPPORTED_FEATURE.on(
|
||||||
}
|
property,
|
||||||
else if (noExplicitTypeOrGetterType(property)) {
|
LanguageFeature.ShortSyntaxForPropertyGetters to languageVersionSettings
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else if (noExplicitTypeOrGetterType(property)) {
|
||||||
trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(property))
|
trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(property))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -744,8 +750,7 @@ class DeclarationsChecker(
|
|||||||
diagnosticSuppressor.shouldReportNoBody(functionDescriptor)) {
|
diagnosticSuppressor.shouldReportNoBody(functionDescriptor)) {
|
||||||
trace.report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor))
|
trace.report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor))
|
||||||
}
|
}
|
||||||
}
|
} else /* top-level only */ {
|
||||||
else /* top-level only */ {
|
|
||||||
if (!function.hasBody() && !hasAbstractModifier && !hasExternalModifier && !functionDescriptor.isExpect &&
|
if (!function.hasBody() && !hasAbstractModifier && !hasExternalModifier && !functionDescriptor.isExpect &&
|
||||||
diagnosticSuppressor.shouldReportNoBody(functionDescriptor)) {
|
diagnosticSuppressor.shouldReportNoBody(functionDescriptor)) {
|
||||||
trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor))
|
trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor))
|
||||||
@@ -785,8 +790,7 @@ class DeclarationsChecker(
|
|||||||
if (it.contains { type -> type.constructor is IntersectionTypeConstructor }) {
|
if (it.contains { type -> type.constructor is IntersectionTypeConstructor }) {
|
||||||
trace.report(IMPLICIT_INTERSECTION_TYPE.on(target, it))
|
trace.report(IMPLICIT_INTERSECTION_TYPE.on(target, it))
|
||||||
}
|
}
|
||||||
}
|
} else if (it.isNothing() && it is AbbreviatedType) {
|
||||||
else if (it.isNothing() && it is AbbreviatedType) {
|
|
||||||
trace.report(
|
trace.report(
|
||||||
(if (declaration is KtProperty) ABBREVIATED_NOTHING_PROPERTY_TYPE else ABBREVIATED_NOTHING_RETURN_TYPE).on(target)
|
(if (declaration is KtProperty) ABBREVIATED_NOTHING_PROPERTY_TYPE else ABBREVIATED_NOTHING_RETURN_TYPE).on(target)
|
||||||
)
|
)
|
||||||
@@ -800,8 +804,7 @@ class DeclarationsChecker(
|
|||||||
if (accessor != null) {
|
if (accessor != null) {
|
||||||
modifiersChecker.checkModifiersForDeclaration(accessor, accessorDescriptor)
|
modifiersChecker.checkModifiersForDeclaration(accessor, accessorDescriptor)
|
||||||
identifierChecker.checkDeclaration(accessor, trace)
|
identifierChecker.checkDeclaration(accessor, trace)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
modifiersChecker.runDeclarationCheckers(property, accessorDescriptor)
|
modifiersChecker.runDeclarationCheckers(property, accessorDescriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -833,23 +836,19 @@ class DeclarationsChecker(
|
|||||||
if (accessor.isGetter) {
|
if (accessor.isGetter) {
|
||||||
if (accessorDescriptor.visibility != propertyDescriptor.visibility) {
|
if (accessorDescriptor.visibility != propertyDescriptor.visibility) {
|
||||||
reportVisibilityModifierDiagnostics(tokens.values, Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY)
|
reportVisibilityModifierDiagnostics(tokens.values, Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
reportVisibilityModifierDiagnostics(tokens.values, Errors.REDUNDANT_MODIFIER_IN_GETTER)
|
reportVisibilityModifierDiagnostics(tokens.values, Errors.REDUNDANT_MODIFIER_IN_GETTER)
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (propertyDescriptor.isOverridable
|
if (propertyDescriptor.isOverridable
|
||||||
&& accessorDescriptor.visibility == Visibilities.PRIVATE
|
&& accessorDescriptor.visibility == Visibilities.PRIVATE
|
||||||
&& propertyDescriptor.visibility != Visibilities.PRIVATE) {
|
&& propertyDescriptor.visibility != Visibilities.PRIVATE) {
|
||||||
if (propertyDescriptor.modality == Modality.ABSTRACT) {
|
if (propertyDescriptor.modality == Modality.ABSTRACT) {
|
||||||
reportVisibilityModifierDiagnostics(tokens.values, Errors.PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY)
|
reportVisibilityModifierDiagnostics(tokens.values, Errors.PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
reportVisibilityModifierDiagnostics(tokens.values, Errors.PRIVATE_SETTER_FOR_OPEN_PROPERTY)
|
reportVisibilityModifierDiagnostics(tokens.values, Errors.PRIVATE_SETTER_FOR_OPEN_PROPERTY)
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val compare = Visibilities.compare(accessorDescriptor.visibility, propertyDescriptor.visibility)
|
val compare = Visibilities.compare(accessorDescriptor.visibility, propertyDescriptor.visibility)
|
||||||
if (compare == null || compare > 0) {
|
if (compare == null || compare > 0) {
|
||||||
reportVisibilityModifierDiagnostics(tokens.values, Errors.SETTER_VISIBILITY_INCONSISTENT_WITH_PROPERTY_VISIBILITY)
|
reportVisibilityModifierDiagnostics(tokens.values, Errors.SETTER_VISIBILITY_INCONSISTENT_WITH_PROPERTY_VISIBILITY)
|
||||||
@@ -866,8 +865,7 @@ class DeclarationsChecker(
|
|||||||
trace.report(EXPECTED_ENUM_ENTRY_WITH_BODY.on(enumEntry))
|
trace.report(EXPECTED_ENUM_ENTRY_WITH_BODY.on(enumEntry))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
assert(DescriptorUtils.isInterface(enumClass)) { "Enum entry should be declared in enum class: " + enumEntryClass }
|
assert(DescriptorUtils.isInterface(enumClass)) { "Enum entry should be declared in enum class: " + enumEntryClass }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -922,7 +920,10 @@ class DeclarationsChecker(
|
|||||||
return isImplementingMethodOfAnyInternal(member, HashSet<ClassDescriptor>())
|
return isImplementingMethodOfAnyInternal(member, HashSet<ClassDescriptor>())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isImplementingMethodOfAnyInternal(member: CallableMemberDescriptor, visitedClasses: MutableSet<ClassDescriptor>): Boolean {
|
private fun isImplementingMethodOfAnyInternal(
|
||||||
|
member: CallableMemberDescriptor,
|
||||||
|
visitedClasses: MutableSet<ClassDescriptor>
|
||||||
|
): Boolean {
|
||||||
for (overridden in member.overriddenDescriptors) {
|
for (overridden in member.overriddenDescriptors) {
|
||||||
val containingDeclaration = overridden.containingDeclaration
|
val containingDeclaration = overridden.containingDeclaration
|
||||||
if (containingDeclaration !is ClassDescriptor) continue
|
if (containingDeclaration !is ClassDescriptor) continue
|
||||||
|
|||||||
@@ -122,7 +122,16 @@ class DelegationResolver<T : CallableMemberDescriptor> private constructor(
|
|||||||
delegationFilter: DelegationFilter,
|
delegationFilter: DelegationFilter,
|
||||||
languageVersionSettings: LanguageVersionSettings
|
languageVersionSettings: LanguageVersionSettings
|
||||||
): Collection<T> =
|
): Collection<T> =
|
||||||
DelegationResolver(classOrObject, ownerDescriptor, existingMembers, trace, memberExtractor, typeResolver, delegationFilter, languageVersionSettings)
|
DelegationResolver(
|
||||||
|
classOrObject,
|
||||||
|
ownerDescriptor,
|
||||||
|
existingMembers,
|
||||||
|
trace,
|
||||||
|
memberExtractor,
|
||||||
|
typeResolver,
|
||||||
|
delegationFilter,
|
||||||
|
languageVersionSettings
|
||||||
|
)
|
||||||
.generateDelegatedMembers()
|
.generateDelegatedMembers()
|
||||||
|
|
||||||
private fun isOverridingAnyOf(
|
private fun isOverridingAnyOf(
|
||||||
|
|||||||
@@ -47,14 +47,16 @@ object DescriptorToSourceUtils {
|
|||||||
result.add(descriptor)
|
result.add(descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic fun getEffectiveReferencedDescriptors(descriptor: DeclarationDescriptor): Collection<DeclarationDescriptor> {
|
@JvmStatic
|
||||||
|
fun getEffectiveReferencedDescriptors(descriptor: DeclarationDescriptor): Collection<DeclarationDescriptor> {
|
||||||
val result = ArrayList<DeclarationDescriptor>()
|
val result = ArrayList<DeclarationDescriptor>()
|
||||||
collectEffectiveReferencedDescriptors(result, descriptor.original)
|
collectEffectiveReferencedDescriptors(result, descriptor.original)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Fix in descriptor
|
// TODO Fix in descriptor
|
||||||
@JvmStatic private fun getSourceForExtensionReceiverParameterDescriptor(descriptor: ReceiverParameterDescriptor): PsiElement? {
|
@JvmStatic
|
||||||
|
private fun getSourceForExtensionReceiverParameterDescriptor(descriptor: ReceiverParameterDescriptor): PsiElement? {
|
||||||
// Only for extension receivers
|
// Only for extension receivers
|
||||||
if (descriptor.source != SourceElement.NO_SOURCE || descriptor.value !is ExtensionReceiver) return null
|
if (descriptor.source != SourceElement.NO_SOURCE || descriptor.value !is ExtensionReceiver) return null
|
||||||
val containingDeclaration = descriptor.containingDeclaration as? CallableDescriptor ?: return null
|
val containingDeclaration = descriptor.containingDeclaration as? CallableDescriptor ?: return null
|
||||||
@@ -62,7 +64,8 @@ object DescriptorToSourceUtils {
|
|||||||
return psi.receiverTypeReference
|
return psi.receiverTypeReference
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic fun getSourceFromDescriptor(descriptor: DeclarationDescriptor): PsiElement? {
|
@JvmStatic
|
||||||
|
fun getSourceFromDescriptor(descriptor: DeclarationDescriptor): PsiElement? {
|
||||||
if (descriptor is ReceiverParameterDescriptor) {
|
if (descriptor is ReceiverParameterDescriptor) {
|
||||||
getSourceForExtensionReceiverParameterDescriptor(descriptor)?.let { return it }
|
getSourceForExtensionReceiverParameterDescriptor(descriptor)?.let { return it }
|
||||||
}
|
}
|
||||||
@@ -70,7 +73,8 @@ object DescriptorToSourceUtils {
|
|||||||
return (descriptor as? DeclarationDescriptorWithSource)?.source?.getPsi()
|
return (descriptor as? DeclarationDescriptorWithSource)?.source?.getPsi()
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic fun getSourceFromAnnotation(descriptor: AnnotationDescriptor): KtAnnotationEntry? {
|
@JvmStatic
|
||||||
|
fun getSourceFromAnnotation(descriptor: AnnotationDescriptor): KtAnnotationEntry? {
|
||||||
return descriptor.source.getPsi() as? KtAnnotationEntry
|
return descriptor.source.getPsi() as? KtAnnotationEntry
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,12 +82,14 @@ object DescriptorToSourceUtils {
|
|||||||
// Returns PSI element for descriptor. If there are many relevant elements (e.g. it is fake override
|
// Returns PSI element for descriptor. If there are many relevant elements (e.g. it is fake override
|
||||||
// with multiple declarations), returns null. It can't find declarations in builtins or decompiled code.
|
// with multiple declarations), returns null. It can't find declarations in builtins or decompiled code.
|
||||||
// In IDE, use DescriptorToSourceUtilsIde instead.
|
// In IDE, use DescriptorToSourceUtilsIde instead.
|
||||||
@JvmStatic fun descriptorToDeclaration(descriptor: DeclarationDescriptor): PsiElement? {
|
@JvmStatic
|
||||||
|
fun descriptorToDeclaration(descriptor: DeclarationDescriptor): PsiElement? {
|
||||||
val effectiveReferencedDescriptors = getEffectiveReferencedDescriptors(descriptor)
|
val effectiveReferencedDescriptors = getEffectiveReferencedDescriptors(descriptor)
|
||||||
return if (effectiveReferencedDescriptors.size == 1) getSourceFromDescriptor(effectiveReferencedDescriptors.firstOrNull()!!) else null
|
return if (effectiveReferencedDescriptors.size == 1) getSourceFromDescriptor(effectiveReferencedDescriptors.firstOrNull()!!) else null
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic fun getContainingFile(declarationDescriptor: DeclarationDescriptor): KtFile? {
|
@JvmStatic
|
||||||
|
fun getContainingFile(declarationDescriptor: DeclarationDescriptor): KtFile? {
|
||||||
// declarationDescriptor may describe a synthesized element which doesn't have PSI
|
// declarationDescriptor may describe a synthesized element which doesn't have PSI
|
||||||
// To workaround that, we find a top-level parent (which is inside a PackageFragmentDescriptor), which is guaranteed to have PSI
|
// To workaround that, we find a top-level parent (which is inside a PackageFragmentDescriptor), which is guaranteed to have PSI
|
||||||
val descriptor = findTopLevelParent(declarationDescriptor) ?: return null
|
val descriptor = findTopLevelParent(declarationDescriptor) ?: return null
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ class ExposedVisibilityChecker(private val trace: DiagnosticSink = DO_NOTHING) {
|
|||||||
return result and checkFunction(constructor, constructorDescriptor)
|
return result and checkFunction(constructor, constructorDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkDeclarationWithVisibility(modifierListOwner: KtModifierListOwner,
|
fun checkDeclarationWithVisibility(
|
||||||
|
modifierListOwner: KtModifierListOwner,
|
||||||
descriptor: DeclarationDescriptorWithVisibility,
|
descriptor: DeclarationDescriptorWithVisibility,
|
||||||
visibility: Visibility
|
visibility: Visibility
|
||||||
): Boolean {
|
): Boolean {
|
||||||
@@ -60,12 +61,17 @@ class ExposedVisibilityChecker(private val trace: DiagnosticSink = DO_NOTHING) {
|
|||||||
val typeAliasVisibility = typeAliasDescriptor.effectiveVisibility()
|
val typeAliasVisibility = typeAliasDescriptor.effectiveVisibility()
|
||||||
val restricting = expandedType.leastPermissiveDescriptor(typeAliasVisibility)
|
val restricting = expandedType.leastPermissiveDescriptor(typeAliasVisibility)
|
||||||
if (restricting != null) {
|
if (restricting != null) {
|
||||||
trace.report(Errors.EXPOSED_TYPEALIAS_EXPANDED_TYPE.on(typeAlias.nameIdentifier ?: typeAlias,
|
trace.report(
|
||||||
typeAliasVisibility, restricting, restricting.effectiveVisibility()))
|
Errors.EXPOSED_TYPEALIAS_EXPANDED_TYPE.on(
|
||||||
|
typeAlias.nameIdentifier ?: typeAlias,
|
||||||
|
typeAliasVisibility, restricting, restricting.effectiveVisibility()
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkFunction(function: KtFunction,
|
fun checkFunction(
|
||||||
|
function: KtFunction,
|
||||||
functionDescriptor: FunctionDescriptor,
|
functionDescriptor: FunctionDescriptor,
|
||||||
// for checking situation with modified basic visibility
|
// for checking situation with modified basic visibility
|
||||||
visibility: Visibility = functionDescriptor.visibility
|
visibility: Visibility = functionDescriptor.visibility
|
||||||
@@ -75,23 +81,32 @@ class ExposedVisibilityChecker(private val trace: DiagnosticSink = DO_NOTHING) {
|
|||||||
if (function !is KtConstructor<*>) {
|
if (function !is KtConstructor<*>) {
|
||||||
val restricting = functionDescriptor.returnType?.leastPermissiveDescriptor(functionVisibility)
|
val restricting = functionDescriptor.returnType?.leastPermissiveDescriptor(functionVisibility)
|
||||||
if (restricting != null) {
|
if (restricting != null) {
|
||||||
trace.report(Errors.EXPOSED_FUNCTION_RETURN_TYPE.on(function.nameIdentifier ?: function, functionVisibility,
|
trace.report(
|
||||||
restricting, restricting.effectiveVisibility()))
|
Errors.EXPOSED_FUNCTION_RETURN_TYPE.on(
|
||||||
|
function.nameIdentifier ?: function, functionVisibility,
|
||||||
|
restricting, restricting.effectiveVisibility()
|
||||||
|
)
|
||||||
|
)
|
||||||
result = false
|
result = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
functionDescriptor.valueParameters.forEachIndexed { i, parameterDescriptor ->
|
functionDescriptor.valueParameters.forEachIndexed { i, parameterDescriptor ->
|
||||||
val restricting = parameterDescriptor.type.leastPermissiveDescriptor(functionVisibility)
|
val restricting = parameterDescriptor.type.leastPermissiveDescriptor(functionVisibility)
|
||||||
if (restricting != null && i < function.valueParameters.size) {
|
if (restricting != null && i < function.valueParameters.size) {
|
||||||
trace.report(Errors.EXPOSED_PARAMETER_TYPE.on(function.valueParameters[i], functionVisibility,
|
trace.report(
|
||||||
restricting, restricting.effectiveVisibility()))
|
Errors.EXPOSED_PARAMETER_TYPE.on(
|
||||||
|
function.valueParameters[i], functionVisibility,
|
||||||
|
restricting, restricting.effectiveVisibility()
|
||||||
|
)
|
||||||
|
)
|
||||||
result = false
|
result = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result and checkMemberReceiver(function.receiverTypeReference, functionDescriptor)
|
return result and checkMemberReceiver(function.receiverTypeReference, functionDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkProperty(property: KtProperty,
|
fun checkProperty(
|
||||||
|
property: KtProperty,
|
||||||
propertyDescriptor: PropertyDescriptor,
|
propertyDescriptor: PropertyDescriptor,
|
||||||
// for checking situation with modified basic visibility
|
// for checking situation with modified basic visibility
|
||||||
visibility: Visibility = propertyDescriptor.visibility
|
visibility: Visibility = propertyDescriptor.visibility
|
||||||
@@ -100,8 +115,12 @@ class ExposedVisibilityChecker(private val trace: DiagnosticSink = DO_NOTHING) {
|
|||||||
val restricting = propertyDescriptor.type.leastPermissiveDescriptor(propertyVisibility)
|
val restricting = propertyDescriptor.type.leastPermissiveDescriptor(propertyVisibility)
|
||||||
var result = true
|
var result = true
|
||||||
if (restricting != null) {
|
if (restricting != null) {
|
||||||
trace.report(Errors.EXPOSED_PROPERTY_TYPE.on(property.nameIdentifier ?: property, propertyVisibility,
|
trace.report(
|
||||||
restricting, restricting.effectiveVisibility()))
|
Errors.EXPOSED_PROPERTY_TYPE.on(
|
||||||
|
property.nameIdentifier ?: property, propertyVisibility,
|
||||||
|
restricting, restricting.effectiveVisibility()
|
||||||
|
)
|
||||||
|
)
|
||||||
result = false
|
result = false
|
||||||
}
|
}
|
||||||
return result and checkMemberReceiver(property.receiverTypeReference, propertyDescriptor)
|
return result and checkMemberReceiver(property.receiverTypeReference, propertyDescriptor)
|
||||||
@@ -113,8 +132,12 @@ class ExposedVisibilityChecker(private val trace: DiagnosticSink = DO_NOTHING) {
|
|||||||
val memberVisibility = memberDescriptor.effectiveVisibility()
|
val memberVisibility = memberDescriptor.effectiveVisibility()
|
||||||
val restricting = receiverParameterDescriptor.type.leastPermissiveDescriptor(memberVisibility)
|
val restricting = receiverParameterDescriptor.type.leastPermissiveDescriptor(memberVisibility)
|
||||||
if (restricting != null) {
|
if (restricting != null) {
|
||||||
trace.report(Errors.EXPOSED_RECEIVER_TYPE.on(typeReference, memberVisibility,
|
trace.report(
|
||||||
restricting, restricting.effectiveVisibility()))
|
Errors.EXPOSED_RECEIVER_TYPE.on(
|
||||||
|
typeReference, memberVisibility,
|
||||||
|
restricting, restricting.effectiveVisibility()
|
||||||
|
)
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -135,12 +158,19 @@ class ExposedVisibilityChecker(private val trace: DiagnosticSink = DO_NOTHING) {
|
|||||||
val restricting = superType.leastPermissiveDescriptor(classVisibility)
|
val restricting = superType.leastPermissiveDescriptor(classVisibility)
|
||||||
if (restricting != null) {
|
if (restricting != null) {
|
||||||
if (isInterface) {
|
if (isInterface) {
|
||||||
trace.report(Errors.EXPOSED_SUPER_INTERFACE.on(delegationList[i], classVisibility,
|
trace.report(
|
||||||
restricting, restricting.effectiveVisibility()))
|
Errors.EXPOSED_SUPER_INTERFACE.on(
|
||||||
}
|
delegationList[i], classVisibility,
|
||||||
else {
|
restricting, restricting.effectiveVisibility()
|
||||||
trace.report(Errors.EXPOSED_SUPER_CLASS.on(delegationList[i], classVisibility,
|
)
|
||||||
restricting, restricting.effectiveVisibility()))
|
)
|
||||||
|
} else {
|
||||||
|
trace.report(
|
||||||
|
Errors.EXPOSED_SUPER_CLASS.on(
|
||||||
|
delegationList[i], classVisibility,
|
||||||
|
restricting, restricting.effectiveVisibility()
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
result = false
|
result = false
|
||||||
}
|
}
|
||||||
@@ -157,8 +187,12 @@ class ExposedVisibilityChecker(private val trace: DiagnosticSink = DO_NOTHING) {
|
|||||||
for (upperBound in typeParameterDescriptor.upperBounds) {
|
for (upperBound in typeParameterDescriptor.upperBounds) {
|
||||||
val restricting = upperBound.leastPermissiveDescriptor(classVisibility)
|
val restricting = upperBound.leastPermissiveDescriptor(classVisibility)
|
||||||
if (restricting != null) {
|
if (restricting != null) {
|
||||||
trace.report(Errors.EXPOSED_TYPE_PARAMETER_BOUND.on(typeParameterList[i], classVisibility,
|
trace.report(
|
||||||
restricting, restricting.effectiveVisibility()))
|
Errors.EXPOSED_TYPE_PARAMETER_BOUND.on(
|
||||||
|
typeParameterList[i], classVisibility,
|
||||||
|
restricting, restricting.effectiveVisibility()
|
||||||
|
)
|
||||||
|
)
|
||||||
result = false
|
result = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,8 +109,10 @@ class LazyTopDownAnalyzer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitClassOrObject(classOrObject: KtClassOrObject) {
|
override fun visitClassOrObject(classOrObject: KtClassOrObject) {
|
||||||
val location = if (classOrObject.isTopLevel()) KotlinLookupLocation(classOrObject) else NoLookupLocation.WHEN_RESOLVE_DECLARATION
|
val location =
|
||||||
val descriptor = lazyDeclarationResolver.getClassDescriptor(classOrObject, location) as ClassDescriptorWithResolutionScopes
|
if (classOrObject.isTopLevel()) KotlinLookupLocation(classOrObject) else NoLookupLocation.WHEN_RESOLVE_DECLARATION
|
||||||
|
val descriptor =
|
||||||
|
lazyDeclarationResolver.getClassDescriptor(classOrObject, location) as ClassDescriptorWithResolutionScopes
|
||||||
|
|
||||||
c.declaredClasses.put(classOrObject, descriptor)
|
c.declaredClasses.put(classOrObject, descriptor)
|
||||||
registerDeclarations(classOrObject.declarations)
|
registerDeclarations(classOrObject.declarations)
|
||||||
@@ -127,12 +129,10 @@ class LazyTopDownAnalyzer(
|
|||||||
trace.report(MANY_COMPANION_OBJECTS.on(jetDeclaration))
|
trace.report(MANY_COMPANION_OBJECTS.on(jetDeclaration))
|
||||||
}
|
}
|
||||||
companionObjectAlreadyFound = true
|
companionObjectAlreadyFound = true
|
||||||
}
|
} else if (jetDeclaration is KtSecondaryConstructor) {
|
||||||
else if (jetDeclaration is KtSecondaryConstructor) {
|
|
||||||
if (DescriptorUtils.isSingletonOrAnonymousObject(classDescriptor)) {
|
if (DescriptorUtils.isSingletonOrAnonymousObject(classDescriptor)) {
|
||||||
trace.report(CONSTRUCTOR_IN_OBJECT.on(jetDeclaration))
|
trace.report(CONSTRUCTOR_IN_OBJECT.on(jetDeclaration))
|
||||||
}
|
} else if (classDescriptor.kind == ClassKind.INTERFACE) {
|
||||||
else if (classDescriptor.kind == ClassKind.INTERFACE) {
|
|
||||||
trace.report(CONSTRUCTOR_IN_INTERFACE.on(jetDeclaration))
|
trace.report(CONSTRUCTOR_IN_INTERFACE.on(jetDeclaration))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,13 +147,19 @@ class LazyTopDownAnalyzer(
|
|||||||
private fun registerPrimaryConstructorParameters(klass: KtClass) {
|
private fun registerPrimaryConstructorParameters(klass: KtClass) {
|
||||||
for (jetParameter in klass.primaryConstructorParameters) {
|
for (jetParameter in klass.primaryConstructorParameters) {
|
||||||
if (jetParameter.hasValOrVar()) {
|
if (jetParameter.hasValOrVar()) {
|
||||||
c.primaryConstructorParameterProperties.put(jetParameter, lazyDeclarationResolver.resolveToDescriptor(jetParameter) as PropertyDescriptor)
|
c.primaryConstructorParameterProperties.put(
|
||||||
|
jetParameter,
|
||||||
|
lazyDeclarationResolver.resolveToDescriptor(jetParameter) as PropertyDescriptor
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitSecondaryConstructor(constructor: KtSecondaryConstructor) {
|
override fun visitSecondaryConstructor(constructor: KtSecondaryConstructor) {
|
||||||
c.secondaryConstructors.put(constructor, lazyDeclarationResolver.resolveToDescriptor(constructor) as ClassConstructorDescriptor)
|
c.secondaryConstructors.put(
|
||||||
|
constructor,
|
||||||
|
lazyDeclarationResolver.resolveToDescriptor(constructor) as ClassConstructorDescriptor
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitEnumEntry(enumEntry: KtEnumEntry) {
|
override fun visitEnumEntry(enumEntry: KtEnumEntry) {
|
||||||
@@ -165,7 +171,8 @@ class LazyTopDownAnalyzer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitAnonymousInitializer(initializer: KtAnonymousInitializer) {
|
override fun visitAnonymousInitializer(initializer: KtAnonymousInitializer) {
|
||||||
val containerDescriptor = lazyDeclarationResolver.resolveToDescriptor(initializer.containingDeclaration) as ClassDescriptorWithResolutionScopes
|
val containerDescriptor =
|
||||||
|
lazyDeclarationResolver.resolveToDescriptor(initializer.containingDeclaration) as ClassDescriptorWithResolutionScopes
|
||||||
c.anonymousInitializers.put(initializer, containerDescriptor)
|
c.anonymousInitializers.put(initializer, containerDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,7 +244,11 @@ class LazyTopDownAnalyzer(
|
|||||||
fileScopeProvider.getImportResolver(file).forceResolveAllImports()
|
fileScopeProvider.getImportResolver(file).forceResolveAllImports()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createTypeAliasDescriptors(c: TopDownAnalysisContext, topLevelFqNames: Multimap<FqName, KtElement>, typeAliases: List<KtTypeAlias>) {
|
private fun createTypeAliasDescriptors(
|
||||||
|
c: TopDownAnalysisContext,
|
||||||
|
topLevelFqNames: Multimap<FqName, KtElement>,
|
||||||
|
typeAliases: List<KtTypeAlias>
|
||||||
|
) {
|
||||||
for (typeAlias in typeAliases) {
|
for (typeAlias in typeAliases) {
|
||||||
val descriptor = lazyDeclarationResolver.resolveToDescriptor(typeAlias) as TypeAliasDescriptor
|
val descriptor = lazyDeclarationResolver.resolveToDescriptor(typeAlias) as TypeAliasDescriptor
|
||||||
|
|
||||||
@@ -247,7 +258,11 @@ class LazyTopDownAnalyzer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createPropertyDescriptors(c: TopDownAnalysisContext, topLevelFqNames: Multimap<FqName, KtElement>, properties: List<KtProperty>) {
|
private fun createPropertyDescriptors(
|
||||||
|
c: TopDownAnalysisContext,
|
||||||
|
topLevelFqNames: Multimap<FqName, KtElement>,
|
||||||
|
properties: List<KtProperty>
|
||||||
|
) {
|
||||||
for (property in properties) {
|
for (property in properties) {
|
||||||
val descriptor = lazyDeclarationResolver.resolveToDescriptor(property) as PropertyDescriptor
|
val descriptor = lazyDeclarationResolver.resolveToDescriptor(property) as PropertyDescriptor
|
||||||
|
|
||||||
@@ -271,7 +286,8 @@ class LazyTopDownAnalyzer(
|
|||||||
private fun createPropertiesFromDestructuringDeclarations(
|
private fun createPropertiesFromDestructuringDeclarations(
|
||||||
c: TopDownAnalysisContext,
|
c: TopDownAnalysisContext,
|
||||||
topLevelFqNames: Multimap<FqName, KtElement>,
|
topLevelFqNames: Multimap<FqName, KtElement>,
|
||||||
destructuringDeclarations: List<KtDestructuringDeclaration>) {
|
destructuringDeclarations: List<KtDestructuringDeclaration>
|
||||||
|
) {
|
||||||
for (destructuringDeclaration in destructuringDeclarations) {
|
for (destructuringDeclaration in destructuringDeclarations) {
|
||||||
for (entry in destructuringDeclaration.entries) {
|
for (entry in destructuringDeclaration.entries) {
|
||||||
val descriptor = lazyDeclarationResolver.resolveToDescriptor(entry) as PropertyDescriptor
|
val descriptor = lazyDeclarationResolver.resolveToDescriptor(entry) as PropertyDescriptor
|
||||||
@@ -283,7 +299,11 @@ class LazyTopDownAnalyzer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerTopLevelFqName(topLevelFqNames: Multimap<FqName, KtElement>, declaration: KtNamedDeclaration, descriptor: DeclarationDescriptor) {
|
private fun registerTopLevelFqName(
|
||||||
|
topLevelFqNames: Multimap<FqName, KtElement>,
|
||||||
|
declaration: KtNamedDeclaration,
|
||||||
|
descriptor: DeclarationDescriptor
|
||||||
|
) {
|
||||||
if (DescriptorUtils.isTopLevelDeclaration(descriptor)) {
|
if (DescriptorUtils.isTopLevelDeclaration(descriptor)) {
|
||||||
val fqName = declaration.fqName
|
val fqName = declaration.fqName
|
||||||
if (fqName != null) {
|
if (fqName != null) {
|
||||||
|
|||||||
@@ -52,9 +52,11 @@ object ModifierCheckerCore {
|
|||||||
COMPATIBLE_FOR_CLASSES_ONLY
|
COMPATIBLE_FOR_CLASSES_ONLY
|
||||||
}
|
}
|
||||||
|
|
||||||
private val defaultVisibilityTargets = EnumSet.of(CLASS_ONLY, OBJECT, INTERFACE, ENUM_CLASS, ANNOTATION_CLASS,
|
private val defaultVisibilityTargets = EnumSet.of(
|
||||||
|
CLASS_ONLY, OBJECT, INTERFACE, ENUM_CLASS, ANNOTATION_CLASS,
|
||||||
MEMBER_FUNCTION, TOP_LEVEL_FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER,
|
MEMBER_FUNCTION, TOP_LEVEL_FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER,
|
||||||
MEMBER_PROPERTY, TOP_LEVEL_PROPERTY, CONSTRUCTOR, TYPEALIAS)
|
MEMBER_PROPERTY, TOP_LEVEL_PROPERTY, CONSTRUCTOR, TYPEALIAS
|
||||||
|
)
|
||||||
|
|
||||||
val possibleTargetMap = mapOf<KtModifierKeywordToken, Set<KotlinTarget>>(
|
val possibleTargetMap = mapOf<KtModifierKeywordToken, Set<KotlinTarget>>(
|
||||||
ENUM_KEYWORD to EnumSet.of(ENUM_CLASS),
|
ENUM_KEYWORD to EnumSet.of(ENUM_CLASS),
|
||||||
@@ -67,8 +69,10 @@ object ModifierCheckerCore {
|
|||||||
PRIVATE_KEYWORD to defaultVisibilityTargets,
|
PRIVATE_KEYWORD to defaultVisibilityTargets,
|
||||||
PUBLIC_KEYWORD to defaultVisibilityTargets,
|
PUBLIC_KEYWORD to defaultVisibilityTargets,
|
||||||
INTERNAL_KEYWORD to defaultVisibilityTargets,
|
INTERNAL_KEYWORD to defaultVisibilityTargets,
|
||||||
PROTECTED_KEYWORD to EnumSet.of(CLASS_ONLY, OBJECT, INTERFACE, ENUM_CLASS, ANNOTATION_CLASS,
|
PROTECTED_KEYWORD to EnumSet.of(
|
||||||
MEMBER_FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER, MEMBER_PROPERTY, CONSTRUCTOR, TYPEALIAS),
|
CLASS_ONLY, OBJECT, INTERFACE, ENUM_CLASS, ANNOTATION_CLASS,
|
||||||
|
MEMBER_FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER, MEMBER_PROPERTY, CONSTRUCTOR, TYPEALIAS
|
||||||
|
),
|
||||||
IN_KEYWORD to EnumSet.of(TYPE_PARAMETER, TYPE_PROJECTION),
|
IN_KEYWORD to EnumSet.of(TYPE_PARAMETER, TYPE_PROJECTION),
|
||||||
OUT_KEYWORD to EnumSet.of(TYPE_PARAMETER, TYPE_PROJECTION),
|
OUT_KEYWORD to EnumSet.of(TYPE_PARAMETER, TYPE_PROJECTION),
|
||||||
REIFIED_KEYWORD to EnumSet.of(TYPE_PARAMETER),
|
REIFIED_KEYWORD to EnumSet.of(TYPE_PARAMETER),
|
||||||
@@ -87,9 +91,33 @@ object ModifierCheckerCore {
|
|||||||
OPERATOR_KEYWORD to EnumSet.of(FUNCTION),
|
OPERATOR_KEYWORD to EnumSet.of(FUNCTION),
|
||||||
INFIX_KEYWORD to EnumSet.of(FUNCTION),
|
INFIX_KEYWORD to EnumSet.of(FUNCTION),
|
||||||
HEADER_KEYWORD to EnumSet.of(TOP_LEVEL_FUNCTION, TOP_LEVEL_PROPERTY, CLASS_ONLY, OBJECT, INTERFACE, ENUM_CLASS, ANNOTATION_CLASS),
|
HEADER_KEYWORD to EnumSet.of(TOP_LEVEL_FUNCTION, TOP_LEVEL_PROPERTY, CLASS_ONLY, OBJECT, INTERFACE, ENUM_CLASS, ANNOTATION_CLASS),
|
||||||
IMPL_KEYWORD to EnumSet.of(TOP_LEVEL_FUNCTION, MEMBER_FUNCTION, TOP_LEVEL_PROPERTY, MEMBER_PROPERTY, CONSTRUCTOR, CLASS_ONLY, OBJECT, INTERFACE, ENUM_CLASS, ANNOTATION_CLASS, TYPEALIAS),
|
IMPL_KEYWORD to EnumSet.of(
|
||||||
|
TOP_LEVEL_FUNCTION,
|
||||||
|
MEMBER_FUNCTION,
|
||||||
|
TOP_LEVEL_PROPERTY,
|
||||||
|
MEMBER_PROPERTY,
|
||||||
|
CONSTRUCTOR,
|
||||||
|
CLASS_ONLY,
|
||||||
|
OBJECT,
|
||||||
|
INTERFACE,
|
||||||
|
ENUM_CLASS,
|
||||||
|
ANNOTATION_CLASS,
|
||||||
|
TYPEALIAS
|
||||||
|
),
|
||||||
EXPECT_KEYWORD to EnumSet.of(TOP_LEVEL_FUNCTION, TOP_LEVEL_PROPERTY, CLASS_ONLY, OBJECT, INTERFACE, ENUM_CLASS, ANNOTATION_CLASS),
|
EXPECT_KEYWORD to EnumSet.of(TOP_LEVEL_FUNCTION, TOP_LEVEL_PROPERTY, CLASS_ONLY, OBJECT, INTERFACE, ENUM_CLASS, ANNOTATION_CLASS),
|
||||||
ACTUAL_KEYWORD to EnumSet.of(TOP_LEVEL_FUNCTION, MEMBER_FUNCTION, TOP_LEVEL_PROPERTY, MEMBER_PROPERTY, CONSTRUCTOR, CLASS_ONLY, OBJECT, INTERFACE, ENUM_CLASS, ANNOTATION_CLASS, TYPEALIAS)
|
ACTUAL_KEYWORD to EnumSet.of(
|
||||||
|
TOP_LEVEL_FUNCTION,
|
||||||
|
MEMBER_FUNCTION,
|
||||||
|
TOP_LEVEL_PROPERTY,
|
||||||
|
MEMBER_PROPERTY,
|
||||||
|
CONSTRUCTOR,
|
||||||
|
CLASS_ONLY,
|
||||||
|
OBJECT,
|
||||||
|
INTERFACE,
|
||||||
|
ENUM_CLASS,
|
||||||
|
ANNOTATION_CLASS,
|
||||||
|
TYPEALIAS
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val featureDependencies = mapOf(
|
private val featureDependencies = mapOf(
|
||||||
@@ -122,8 +150,10 @@ object ModifierCheckerCore {
|
|||||||
)
|
)
|
||||||
|
|
||||||
private val possibleParentTargetPredicateMap = mapOf<KtModifierKeywordToken, TargetAllowedPredicate>(
|
private val possibleParentTargetPredicateMap = mapOf<KtModifierKeywordToken, TargetAllowedPredicate>(
|
||||||
INNER_KEYWORD to or(always(CLASS_ONLY, LOCAL_CLASS, ENUM_CLASS),
|
INNER_KEYWORD to or(
|
||||||
ifSupported(LanguageFeature.InnerClassInEnumEntryClass, ENUM_ENTRY)),
|
always(CLASS_ONLY, LOCAL_CLASS, ENUM_CLASS),
|
||||||
|
ifSupported(LanguageFeature.InnerClassInEnumEntryClass, ENUM_ENTRY)
|
||||||
|
),
|
||||||
OVERRIDE_KEYWORD to always(CLASS_ONLY, LOCAL_CLASS, OBJECT, OBJECT_LITERAL, INTERFACE, ENUM_CLASS, ENUM_ENTRY),
|
OVERRIDE_KEYWORD to always(CLASS_ONLY, LOCAL_CLASS, OBJECT, OBJECT_LITERAL, INTERFACE, ENUM_CLASS, ENUM_ENTRY),
|
||||||
PROTECTED_KEYWORD to always(CLASS_ONLY, LOCAL_CLASS, ENUM_CLASS, COMPANION_OBJECT),
|
PROTECTED_KEYWORD to always(CLASS_ONLY, LOCAL_CLASS, ENUM_CLASS, COMPANION_OBJECT),
|
||||||
INTERNAL_KEYWORD to always(CLASS_ONLY, LOCAL_CLASS, OBJECT, OBJECT_LITERAL, ENUM_CLASS, ENUM_ENTRY, FILE),
|
INTERNAL_KEYWORD to always(CLASS_ONLY, LOCAL_CLASS, OBJECT, OBJECT_LITERAL, ENUM_CLASS, ENUM_ENTRY, FILE),
|
||||||
@@ -201,8 +231,10 @@ object ModifierCheckerCore {
|
|||||||
sufficient: KtModifierKeywordToken,
|
sufficient: KtModifierKeywordToken,
|
||||||
redundant: KtModifierKeywordToken
|
redundant: KtModifierKeywordToken
|
||||||
): Map<Pair<KtModifierKeywordToken, KtModifierKeywordToken>, Compatibility> {
|
): Map<Pair<KtModifierKeywordToken, KtModifierKeywordToken>, Compatibility> {
|
||||||
return mapOf(Pair(sufficient, redundant) to Compatibility.REDUNDANT,
|
return mapOf(
|
||||||
Pair(redundant, sufficient) to Compatibility.REVERSE_REDUNDANT)
|
Pair(sufficient, redundant) to Compatibility.REDUNDANT,
|
||||||
|
Pair(redundant, sufficient) to Compatibility.REVERSE_REDUNDANT
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun compatibilityRegister(
|
private fun compatibilityRegister(
|
||||||
@@ -229,22 +261,24 @@ object ModifierCheckerCore {
|
|||||||
private fun compatibility(first: KtModifierKeywordToken, second: KtModifierKeywordToken): Compatibility {
|
private fun compatibility(first: KtModifierKeywordToken, second: KtModifierKeywordToken): Compatibility {
|
||||||
return if (first == second) {
|
return if (first == second) {
|
||||||
Compatibility.REPEATED
|
Compatibility.REPEATED
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
mutualCompatibility[Pair(first, second)] ?: Compatibility.COMPATIBLE
|
mutualCompatibility[Pair(first, second)] ?: Compatibility.COMPATIBLE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkCompatibility(trace: BindingTrace,
|
private fun checkCompatibility(
|
||||||
|
trace: BindingTrace,
|
||||||
firstNode: ASTNode,
|
firstNode: ASTNode,
|
||||||
secondNode: ASTNode,
|
secondNode: ASTNode,
|
||||||
owner: PsiElement,
|
owner: PsiElement,
|
||||||
incorrectNodes: MutableSet<ASTNode>) {
|
incorrectNodes: MutableSet<ASTNode>
|
||||||
|
) {
|
||||||
val first = firstNode.elementType as KtModifierKeywordToken
|
val first = firstNode.elementType as KtModifierKeywordToken
|
||||||
val second = secondNode.elementType as KtModifierKeywordToken
|
val second = secondNode.elementType as KtModifierKeywordToken
|
||||||
val compatibility = compatibility(first, second)
|
val compatibility = compatibility(first, second)
|
||||||
when (compatibility) {
|
when (compatibility) {
|
||||||
Compatibility.COMPATIBLE -> {}
|
Compatibility.COMPATIBLE -> {
|
||||||
|
}
|
||||||
Compatibility.REPEATED -> if (incorrectNodes.add(secondNode)) {
|
Compatibility.REPEATED -> if (incorrectNodes.add(secondNode)) {
|
||||||
trace.report(Errors.REPEATED_MODIFIER.on(secondNode.psi, first))
|
trace.report(Errors.REPEATED_MODIFIER.on(secondNode.psi, first))
|
||||||
}
|
}
|
||||||
@@ -285,9 +319,21 @@ object ModifierCheckerCore {
|
|||||||
deprecatedModifierReplacement != null ->
|
deprecatedModifierReplacement != null ->
|
||||||
trace.report(Errors.DEPRECATED_MODIFIER.on(node.psi, modifier, deprecatedModifierReplacement))
|
trace.report(Errors.DEPRECATED_MODIFIER.on(node.psi, modifier, deprecatedModifierReplacement))
|
||||||
actualTargets.any { it in deprecatedTargets } ->
|
actualTargets.any { it in deprecatedTargets } ->
|
||||||
trace.report(Errors.DEPRECATED_MODIFIER_FOR_TARGET.on(node.psi, modifier, actualTargets.firstOrNull()?.description ?: "this"))
|
trace.report(
|
||||||
|
Errors.DEPRECATED_MODIFIER_FOR_TARGET.on(
|
||||||
|
node.psi,
|
||||||
|
modifier,
|
||||||
|
actualTargets.firstOrNull()?.description ?: "this"
|
||||||
|
)
|
||||||
|
)
|
||||||
actualTargets.any { it in redundantTargets } ->
|
actualTargets.any { it in redundantTargets } ->
|
||||||
trace.report(Errors.REDUNDANT_MODIFIER_FOR_TARGET.on(node.psi, modifier, actualTargets.firstOrNull()?.description ?: "this"))
|
trace.report(
|
||||||
|
Errors.REDUNDANT_MODIFIER_FOR_TARGET.on(
|
||||||
|
node.psi,
|
||||||
|
modifier,
|
||||||
|
actualTargets.firstOrNull()?.description ?: "this"
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -313,8 +359,7 @@ object ModifierCheckerCore {
|
|||||||
|
|
||||||
if (featureSupport == LanguageFeature.State.DISABLED) {
|
if (featureSupport == LanguageFeature.State.DISABLED) {
|
||||||
trace.report(Errors.UNSUPPORTED_FEATURE.on(node.psi, diagnosticData))
|
trace.report(Errors.UNSUPPORTED_FEATURE.on(node.psi, diagnosticData))
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
trace.report(Errors.EXPERIMENTAL_FEATURE_ERROR.on(node.psi, diagnosticData))
|
trace.report(Errors.EXPERIMENTAL_FEATURE_ERROR.on(node.psi, diagnosticData))
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -330,7 +375,12 @@ object ModifierCheckerCore {
|
|||||||
|
|
||||||
|
|
||||||
// Should return false if error is reported, true otherwise
|
// Should return false if error is reported, true otherwise
|
||||||
private fun checkParent(trace: BindingTrace, node: ASTNode, parentDescriptor: DeclarationDescriptor?, languageVersionSettings: LanguageVersionSettings): Boolean {
|
private fun checkParent(
|
||||||
|
trace: BindingTrace,
|
||||||
|
node: ASTNode,
|
||||||
|
parentDescriptor: DeclarationDescriptor?,
|
||||||
|
languageVersionSettings: LanguageVersionSettings
|
||||||
|
): Boolean {
|
||||||
val modifier = node.elementType as KtModifierKeywordToken
|
val modifier = node.elementType as KtModifierKeywordToken
|
||||||
val actualParents: List<KotlinTarget> = when (parentDescriptor) {
|
val actualParents: List<KotlinTarget> = when (parentDescriptor) {
|
||||||
is ClassDescriptor -> KotlinTarget.classActualTargets(parentDescriptor)
|
is ClassDescriptor -> KotlinTarget.classActualTargets(parentDescriptor)
|
||||||
@@ -341,12 +391,24 @@ object ModifierCheckerCore {
|
|||||||
}
|
}
|
||||||
val deprecatedParents = deprecatedParentTargetMap[modifier]
|
val deprecatedParents = deprecatedParentTargetMap[modifier]
|
||||||
if (deprecatedParents != null && actualParents.any { it in deprecatedParents }) {
|
if (deprecatedParents != null && actualParents.any { it in deprecatedParents }) {
|
||||||
trace.report(Errors.DEPRECATED_MODIFIER_CONTAINING_DECLARATION.on(node.psi, modifier, actualParents.firstOrNull()?.description ?: "this scope"))
|
trace.report(
|
||||||
|
Errors.DEPRECATED_MODIFIER_CONTAINING_DECLARATION.on(
|
||||||
|
node.psi,
|
||||||
|
modifier,
|
||||||
|
actualParents.firstOrNull()?.description ?: "this scope"
|
||||||
|
)
|
||||||
|
)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
val possibleParentPredicate = possibleParentTargetPredicateMap[modifier] ?: return true
|
val possibleParentPredicate = possibleParentTargetPredicateMap[modifier] ?: return true
|
||||||
if (actualParents.any { possibleParentPredicate.isAllowed(it, languageVersionSettings) }) return true
|
if (actualParents.any { possibleParentPredicate.isAllowed(it, languageVersionSettings) }) return true
|
||||||
trace.report(Errors.WRONG_MODIFIER_CONTAINING_DECLARATION.on(node.psi, modifier, actualParents.firstOrNull()?.description ?: "this scope"))
|
trace.report(
|
||||||
|
Errors.WRONG_MODIFIER_CONTAINING_DECLARATION.on(
|
||||||
|
node.psi,
|
||||||
|
modifier,
|
||||||
|
actualParents.firstOrNull()?.description ?: "this scope"
|
||||||
|
)
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,7 +475,8 @@ private fun always(target: KotlinTarget, vararg targets: KotlinTarget) = object
|
|||||||
target in targetSet
|
target in targetSet
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ifSupported(languageFeature: LanguageFeature, target: KotlinTarget, vararg targets: KotlinTarget) = object : TargetAllowedPredicate {
|
private fun ifSupported(languageFeature: LanguageFeature, target: KotlinTarget, vararg targets: KotlinTarget) =
|
||||||
|
object : TargetAllowedPredicate {
|
||||||
private val targetSet = EnumSet.of(target, *targets)
|
private val targetSet = EnumSet.of(target, *targets)
|
||||||
|
|
||||||
override fun isAllowed(target: KotlinTarget, languageVersionSettings: LanguageVersionSettings) =
|
override fun isAllowed(target: KotlinTarget, languageVersionSettings: LanguageVersionSettings) =
|
||||||
|
|||||||
+8
-4
@@ -104,11 +104,14 @@ object NonExpansiveInheritanceRestrictionChecker {
|
|||||||
|
|
||||||
for (typeParameter in typeParameters) {
|
for (typeParameter in typeParameters) {
|
||||||
if (typeParameter.defaultType in constituents || typeParameter.defaultType.makeNullableAsSpecified(true) in constituents) {
|
if (typeParameter.defaultType in constituents || typeParameter.defaultType.makeNullableAsSpecified(true) in constituents) {
|
||||||
addEdge(typeParameter, constituentTypeConstructor.parameters[i], !TypeUtils.isTypeParameter(typeProjection.type))
|
addEdge(
|
||||||
|
typeParameter,
|
||||||
|
constituentTypeConstructor.parameters[i],
|
||||||
|
!TypeUtils.isTypeParameter(typeProjection.type)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// Furthermore, if T appears as a constituent type of an element of the B-closure of the set of lower and
|
// Furthermore, if T appears as a constituent type of an element of the B-closure of the set of lower and
|
||||||
// upper bounds of a skolem type variable Q in a skolemization of a projected generic type in ST, add an
|
// upper bounds of a skolem type variable Q in a skolemization of a projected generic type in ST, add an
|
||||||
// expanding edge from T to V, where V is the type parameter corresponding to Q.
|
// expanding edge from T to V, where V is the type parameter corresponding to Q.
|
||||||
@@ -116,7 +119,8 @@ object NonExpansiveInheritanceRestrictionChecker {
|
|||||||
val bounds = hashSetOf<KotlinType>()
|
val bounds = hashSetOf<KotlinType>()
|
||||||
|
|
||||||
val substitutor = TypeConstructorSubstitution.create(constituentType).buildSubstitutor()
|
val substitutor = TypeConstructorSubstitution.create(constituentType).buildSubstitutor()
|
||||||
val adaptedUpperBounds = originalTypeParameter.upperBounds.mapNotNull { substitutor.substitute(it, Variance.INVARIANT) }
|
val adaptedUpperBounds =
|
||||||
|
originalTypeParameter.upperBounds.mapNotNull { substitutor.substitute(it, Variance.INVARIANT) }
|
||||||
bounds.addAll(adaptedUpperBounds)
|
bounds.addAll(adaptedUpperBounds)
|
||||||
|
|
||||||
if (!typeProjection.isStarProjection) {
|
if (!typeProjection.isStarProjection) {
|
||||||
|
|||||||
@@ -106,7 +106,10 @@ class OverrideResolver(
|
|||||||
// don't care
|
// don't care
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun abstractMemberWithMoreSpecificType(abstractMember: CallableMemberDescriptor, concreteMember: CallableMemberDescriptor) {
|
override fun abstractMemberWithMoreSpecificType(
|
||||||
|
abstractMember: CallableMemberDescriptor,
|
||||||
|
concreteMember: CallableMemberDescriptor
|
||||||
|
) {
|
||||||
shouldImplement.add(abstractMember)
|
shouldImplement.add(abstractMember)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,17 +150,18 @@ class OverrideResolver(
|
|||||||
if (descriptor1 is PropertyDescriptor && descriptor2 is PropertyDescriptor) {
|
if (descriptor1 is PropertyDescriptor && descriptor2 is PropertyDescriptor) {
|
||||||
if (descriptor1.isVar || descriptor2.isVar) {
|
if (descriptor1.isVar || descriptor2.isVar) {
|
||||||
reportInheritanceConflictIfRequired(VAR_TYPE_MISMATCH_ON_INHERITANCE, descriptor1, descriptor2)
|
reportInheritanceConflictIfRequired(VAR_TYPE_MISMATCH_ON_INHERITANCE, descriptor1, descriptor2)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
reportInheritanceConflictIfRequired(PROPERTY_TYPE_MISMATCH_ON_INHERITANCE, descriptor1, descriptor2)
|
reportInheritanceConflictIfRequired(PROPERTY_TYPE_MISMATCH_ON_INHERITANCE, descriptor1, descriptor2)
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
reportInheritanceConflictIfRequired(RETURN_TYPE_MISMATCH_ON_INHERITANCE, descriptor1, descriptor2)
|
reportInheritanceConflictIfRequired(RETURN_TYPE_MISMATCH_ON_INHERITANCE, descriptor1, descriptor2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun abstractMemberWithMoreSpecificType(abstractMember: CallableMemberDescriptor, concreteMember: CallableMemberDescriptor) {
|
override fun abstractMemberWithMoreSpecificType(
|
||||||
|
abstractMember: CallableMemberDescriptor,
|
||||||
|
concreteMember: CallableMemberDescriptor
|
||||||
|
) {
|
||||||
typeMismatchOnInheritance(abstractMember, concreteMember)
|
typeMismatchOnInheritance(abstractMember, concreteMember)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,7 +185,8 @@ class OverrideResolver(
|
|||||||
overridden: CallableMemberDescriptor
|
overridden: CallableMemberDescriptor
|
||||||
) {
|
) {
|
||||||
reportDelegationProblemIfRequired(
|
reportDelegationProblemIfRequired(
|
||||||
RETURN_TYPE_MISMATCH_BY_DELEGATION, RETURN_TYPE_MISMATCH_ON_INHERITANCE, overriding, overridden)
|
RETURN_TYPE_MISMATCH_BY_DELEGATION, RETURN_TYPE_MISMATCH_ON_INHERITANCE, overriding, overridden
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun propertyTypeMismatchOnOverride(
|
override fun propertyTypeMismatchOnOverride(
|
||||||
@@ -189,7 +194,8 @@ class OverrideResolver(
|
|||||||
overridden: PropertyDescriptor
|
overridden: PropertyDescriptor
|
||||||
) {
|
) {
|
||||||
reportDelegationProblemIfRequired(
|
reportDelegationProblemIfRequired(
|
||||||
PROPERTY_TYPE_MISMATCH_BY_DELEGATION, PROPERTY_TYPE_MISMATCH_ON_INHERITANCE, overriding, overridden)
|
PROPERTY_TYPE_MISMATCH_BY_DELEGATION, PROPERTY_TYPE_MISMATCH_ON_INHERITANCE, overriding, overridden
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun varOverriddenByVal(overriding: CallableMemberDescriptor, overridden: CallableMemberDescriptor) {
|
override fun varOverriddenByVal(overriding: CallableMemberDescriptor, overridden: CallableMemberDescriptor) {
|
||||||
@@ -204,7 +210,9 @@ class OverrideResolver(
|
|||||||
) {
|
) {
|
||||||
assert(delegate.kind == DELEGATION) { "Delegate expected, got " + delegate + " of kind " + delegate.kind }
|
assert(delegate.kind == DELEGATION) { "Delegate expected, got " + delegate + " of kind " + delegate.kind }
|
||||||
|
|
||||||
if (!onceErrorsReported.contains(diagnosticFactory) && (relevantDiagnosticFromInheritance == null || !onceErrorsReported.contains(relevantDiagnosticFromInheritance))) {
|
if (!onceErrorsReported.contains(diagnosticFactory) && (relevantDiagnosticFromInheritance == null || !onceErrorsReported.contains(
|
||||||
|
relevantDiagnosticFromInheritance
|
||||||
|
))) {
|
||||||
onceErrorsReported.add(diagnosticFactory)
|
onceErrorsReported.add(diagnosticFactory)
|
||||||
trace.report(diagnosticFactory.on(klass, delegate, overridden))
|
trace.report(diagnosticFactory.on(klass, delegate, overridden))
|
||||||
}
|
}
|
||||||
@@ -214,8 +222,7 @@ class OverrideResolver(
|
|||||||
val canHaveAbstractMembers = classCanHaveAbstractFakeOverride(classDescriptor)
|
val canHaveAbstractMembers = classCanHaveAbstractFakeOverride(classDescriptor)
|
||||||
if (abstractInBaseClassNoImpl.isNotEmpty() && !canHaveAbstractMembers) {
|
if (abstractInBaseClassNoImpl.isNotEmpty() && !canHaveAbstractMembers) {
|
||||||
trace.report(ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED.on(klass, klass, abstractInBaseClassNoImpl.first()))
|
trace.report(ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED.on(klass, klass, abstractInBaseClassNoImpl.first()))
|
||||||
}
|
} else if (abstractNoImpl.isNotEmpty() && !canHaveAbstractMembers) {
|
||||||
else if (abstractNoImpl.isNotEmpty() && !canHaveAbstractMembers) {
|
|
||||||
trace.report(ABSTRACT_MEMBER_NOT_IMPLEMENTED.on(klass, klass, abstractNoImpl.first()))
|
trace.report(ABSTRACT_MEMBER_NOT_IMPLEMENTED.on(klass, klass, abstractNoImpl.first()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,8 +230,7 @@ class OverrideResolver(
|
|||||||
multipleImplementations.removeAll(conflictingReturnTypes)
|
multipleImplementations.removeAll(conflictingReturnTypes)
|
||||||
if (!conflictingInterfaceMembers.isEmpty()) {
|
if (!conflictingInterfaceMembers.isEmpty()) {
|
||||||
trace.report(MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED.on(klass, klass, conflictingInterfaceMembers.iterator().next()))
|
trace.report(MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED.on(klass, klass, conflictingInterfaceMembers.iterator().next()))
|
||||||
}
|
} else if (!multipleImplementations.isEmpty()) {
|
||||||
else if (!multipleImplementations.isEmpty()) {
|
|
||||||
trace.report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(klass, klass, multipleImplementations.iterator().next()))
|
trace.report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(klass, klass, multipleImplementations.iterator().next()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -246,8 +252,7 @@ class OverrideResolver(
|
|||||||
if (declared.kind == CallableMemberDescriptor.Kind.SYNTHESIZED) {
|
if (declared.kind == CallableMemberDescriptor.Kind.SYNTHESIZED) {
|
||||||
if (DataClassDescriptorResolver.isComponentLike(declared.name)) {
|
if (DataClassDescriptorResolver.isComponentLike(declared.name)) {
|
||||||
checkOverrideForComponentFunction(declared)
|
checkOverrideForComponentFunction(declared)
|
||||||
}
|
} else if (declared.name == DataClassDescriptorResolver.COPY_METHOD_NAME) {
|
||||||
else if (declared.name == DataClassDescriptorResolver.COPY_METHOD_NAME) {
|
|
||||||
checkOverrideForCopyFunction(declared)
|
checkOverrideForCopyFunction(declared)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -257,7 +262,8 @@ class OverrideResolver(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val member = DescriptorToSourceUtils.descriptorToDeclaration(declared) as KtNamedDeclaration? ?: throw IllegalStateException("declared descriptor is not resolved to declaration: " + declared)
|
val member = DescriptorToSourceUtils.descriptorToDeclaration(declared) as KtNamedDeclaration?
|
||||||
|
?: throw IllegalStateException("declared descriptor is not resolved to declaration: " + declared)
|
||||||
|
|
||||||
val modifierList = member.modifierList
|
val modifierList = member.modifierList
|
||||||
val hasOverrideNode = modifierList != null && modifierList.hasModifier(KtTokens.OVERRIDE_KEYWORD)
|
val hasOverrideNode = modifierList != null && modifierList.hasModifier(KtTokens.OVERRIDE_KEYWORD)
|
||||||
@@ -288,8 +294,7 @@ class OverrideResolver(
|
|||||||
typeMismatchError = true
|
typeMismatchError = true
|
||||||
if (overridden.isVar) {
|
if (overridden.isVar) {
|
||||||
trace.report(VAR_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden))
|
trace.report(VAR_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden))
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
trace.report(PROPERTY_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden))
|
trace.report(PROPERTY_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -302,7 +307,10 @@ class OverrideResolver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun cannotOverrideInvisibleMember(overriding: CallableMemberDescriptor, invisibleOverridden: CallableMemberDescriptor) {
|
override fun cannotOverrideInvisibleMember(
|
||||||
|
overriding: CallableMemberDescriptor,
|
||||||
|
invisibleOverridden: CallableMemberDescriptor
|
||||||
|
) {
|
||||||
trace.report(CANNOT_OVERRIDE_INVISIBLE_MEMBER.on(member, declared, invisibleOverridden))
|
trace.report(CANNOT_OVERRIDE_INVISIBLE_MEMBER.on(member, declared, invisibleOverridden))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,8 +318,7 @@ class OverrideResolver(
|
|||||||
trace.report(NOTHING_TO_OVERRIDE.on(member, declared))
|
trace.report(NOTHING_TO_OVERRIDE.on(member, declared))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
} else if (!overriddenDescriptors.isEmpty() && !overridesBackwardCompatibilityHelper.overrideCanBeOmitted(declared)) {
|
||||||
else if (!overriddenDescriptors.isEmpty() && !overridesBackwardCompatibilityHelper.overrideCanBeOmitted(declared)) {
|
|
||||||
val overridden = overriddenDescriptors.iterator().next()
|
val overridden = overriddenDescriptors.iterator().next()
|
||||||
trace.report(VIRTUAL_MEMBER_HIDDEN.on(member, declared, overridden, overridden.containingDeclaration))
|
trace.report(VIRTUAL_MEMBER_HIDDEN.on(member, declared, overridden, overridden.containingDeclaration))
|
||||||
}
|
}
|
||||||
@@ -354,8 +361,7 @@ class OverrideResolver(
|
|||||||
val dataModifier = findDataModifierForDataClass(copyFunction.containingDeclaration)
|
val dataModifier = findDataModifierForDataClass(copyFunction.containingDeclaration)
|
||||||
if (languageVersionSettings.supportsFeature(LanguageFeature.ProhibitDataClassesOverridingCopy)) {
|
if (languageVersionSettings.supportsFeature(LanguageFeature.ProhibitDataClassesOverridingCopy)) {
|
||||||
trace.report(DATA_CLASS_OVERRIDE_DEFAULT_VALUES_ERROR.on(dataModifier, copyFunction, baseClassifier))
|
trace.report(DATA_CLASS_OVERRIDE_DEFAULT_VALUES_ERROR.on(dataModifier, copyFunction, baseClassifier))
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
trace.report(DATA_CLASS_OVERRIDE_DEFAULT_VALUES_WARNING.on(dataModifier, copyFunction, baseClassifier))
|
trace.report(DATA_CLASS_OVERRIDE_DEFAULT_VALUES_WARNING.on(dataModifier, copyFunction, baseClassifier))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -397,15 +403,15 @@ class OverrideResolver(
|
|||||||
|
|
||||||
if (isDeclaration) {
|
if (isDeclaration) {
|
||||||
checkNameAndDefaultForDeclaredParameter(parameterFromSubclass, multipleDefaultsInSuper)
|
checkNameAndDefaultForDeclaredParameter(parameterFromSubclass, multipleDefaultsInSuper)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
checkNameAndDefaultForFakeOverrideParameter(declared, parameterFromSubclass, multipleDefaultsInSuper)
|
checkNameAndDefaultForFakeOverrideParameter(declared, parameterFromSubclass, multipleDefaultsInSuper)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkNameAndDefaultForDeclaredParameter(descriptor: ValueParameterDescriptor, multipleDefaultsInSuper: Boolean) {
|
private fun checkNameAndDefaultForDeclaredParameter(descriptor: ValueParameterDescriptor, multipleDefaultsInSuper: Boolean) {
|
||||||
val parameter = DescriptorToSourceUtils.descriptorToDeclaration(descriptor) as? KtParameter ?: error("Declaration not found for parameter: " + descriptor)
|
val parameter = DescriptorToSourceUtils.descriptorToDeclaration(descriptor) as? KtParameter
|
||||||
|
?: error("Declaration not found for parameter: " + descriptor)
|
||||||
|
|
||||||
if (descriptor.declaresDefaultValue()) {
|
if (descriptor.declaresDefaultValue()) {
|
||||||
trace.report(DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE.on(parameter))
|
trace.report(DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE.on(parameter))
|
||||||
@@ -418,10 +424,12 @@ class OverrideResolver(
|
|||||||
for (parameterFromSuperclass in descriptor.overriddenDescriptors) {
|
for (parameterFromSuperclass in descriptor.overriddenDescriptors) {
|
||||||
if (shouldReportParameterNameOverrideWarning(descriptor, parameterFromSuperclass)) {
|
if (shouldReportParameterNameOverrideWarning(descriptor, parameterFromSuperclass)) {
|
||||||
|
|
||||||
trace.report(PARAMETER_NAME_CHANGED_ON_OVERRIDE.on(
|
trace.report(
|
||||||
|
PARAMETER_NAME_CHANGED_ON_OVERRIDE.on(
|
||||||
parameter,
|
parameter,
|
||||||
parameterFromSuperclass.containingDeclaration.containingDeclaration as ClassDescriptor,
|
parameterFromSuperclass.containingDeclaration.containingDeclaration as ClassDescriptor,
|
||||||
parameterFromSuperclass)
|
parameterFromSuperclass
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -433,7 +441,8 @@ class OverrideResolver(
|
|||||||
multipleDefaultsInSuper: Boolean
|
multipleDefaultsInSuper: Boolean
|
||||||
) {
|
) {
|
||||||
val containingClass = containingFunction.containingDeclaration
|
val containingClass = containingFunction.containingDeclaration
|
||||||
val classElement = DescriptorToSourceUtils.descriptorToDeclaration(containingClass) as KtClassOrObject? ?: error("Declaration not found for class: " + containingClass)
|
val classElement = DescriptorToSourceUtils.descriptorToDeclaration(containingClass) as KtClassOrObject?
|
||||||
|
?: error("Declaration not found for class: " + containingClass)
|
||||||
|
|
||||||
if (multipleDefaultsInSuper) {
|
if (multipleDefaultsInSuper) {
|
||||||
trace.report(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE.on(classElement, descriptor))
|
trace.report(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE.on(classElement, descriptor))
|
||||||
@@ -441,10 +450,12 @@ class OverrideResolver(
|
|||||||
|
|
||||||
for (parameterFromSuperclass in descriptor.overriddenDescriptors) {
|
for (parameterFromSuperclass in descriptor.overriddenDescriptors) {
|
||||||
if (shouldReportParameterNameOverrideWarning(descriptor, parameterFromSuperclass)) {
|
if (shouldReportParameterNameOverrideWarning(descriptor, parameterFromSuperclass)) {
|
||||||
trace.report(DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES.on(
|
trace.report(
|
||||||
|
DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES.on(
|
||||||
classElement,
|
classElement,
|
||||||
containingFunction.overriddenDescriptors,
|
containingFunction.overriddenDescriptors,
|
||||||
parameterFromSuperclass.index + 1)
|
parameterFromSuperclass.index + 1
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -468,11 +479,24 @@ class OverrideResolver(
|
|||||||
for (descriptor in memberDescriptor.overriddenDescriptors) {
|
for (descriptor in memberDescriptor.overriddenDescriptors) {
|
||||||
val compare = Visibilities.compare(visibility, descriptor.visibility)
|
val compare = Visibilities.compare(visibility, descriptor.visibility)
|
||||||
if (compare == null) {
|
if (compare == null) {
|
||||||
trace.report(CANNOT_CHANGE_ACCESS_PRIVILEGE.on(declaration, descriptor.visibility, descriptor, descriptor.containingDeclaration))
|
trace.report(
|
||||||
|
CANNOT_CHANGE_ACCESS_PRIVILEGE.on(
|
||||||
|
declaration,
|
||||||
|
descriptor.visibility,
|
||||||
|
descriptor,
|
||||||
|
descriptor.containingDeclaration
|
||||||
|
)
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
} else if (compare < 0) {
|
||||||
else if (compare < 0) {
|
trace.report(
|
||||||
trace.report(CANNOT_WEAKEN_ACCESS_PRIVILEGE.on(declaration, descriptor.visibility, descriptor, descriptor.containingDeclaration))
|
CANNOT_WEAKEN_ACCESS_PRIVILEGE.on(
|
||||||
|
declaration,
|
||||||
|
descriptor.visibility,
|
||||||
|
descriptor,
|
||||||
|
descriptor.containingDeclaration
|
||||||
|
)
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -545,9 +569,11 @@ class OverrideResolver(
|
|||||||
|
|
||||||
val allOverriddenDeclarations = ContainerUtil.flatten(overriddenDeclarationsByDirectParent.values)
|
val allOverriddenDeclarations = ContainerUtil.flatten(overriddenDeclarationsByDirectParent.values)
|
||||||
val allFilteredOverriddenDeclarations = OverridingUtil.filterOutOverridden(
|
val allFilteredOverriddenDeclarations = OverridingUtil.filterOutOverridden(
|
||||||
Sets.newLinkedHashSet(allOverriddenDeclarations))
|
Sets.newLinkedHashSet(allOverriddenDeclarations)
|
||||||
|
)
|
||||||
|
|
||||||
val relevantDirectlyOverridden = getRelevantDirectlyOverridden(overriddenDeclarationsByDirectParent, allFilteredOverriddenDeclarations)
|
val relevantDirectlyOverridden =
|
||||||
|
getRelevantDirectlyOverridden(overriddenDeclarationsByDirectParent, allFilteredOverriddenDeclarations)
|
||||||
|
|
||||||
checkInheritedDescriptorsGroup(descriptor, relevantDirectlyOverridden, reportingStrategy)
|
checkInheritedDescriptorsGroup(descriptor, relevantDirectlyOverridden, reportingStrategy)
|
||||||
|
|
||||||
@@ -608,8 +634,7 @@ class OverrideResolver(
|
|||||||
if (overridden.modality === Modality.ABSTRACT) {
|
if (overridden.modality === Modality.ABSTRACT) {
|
||||||
overridesAbstractInBaseClass = overridden
|
overridesAbstractInBaseClass = overridden
|
||||||
}
|
}
|
||||||
}
|
} else if (containingDeclaration.kind == ClassKind.INTERFACE) {
|
||||||
else if (containingDeclaration.kind == ClassKind.INTERFACE) {
|
|
||||||
overriddenInterfaceMembers.add(overridden)
|
overriddenInterfaceMembers.add(overridden)
|
||||||
if (overridden.modality !== Modality.ABSTRACT) {
|
if (overridden.modality !== Modality.ABSTRACT) {
|
||||||
overridesNonAbstractInterfaceMember = true
|
overridesNonAbstractInterfaceMember = true
|
||||||
@@ -713,12 +738,12 @@ class OverrideResolver(
|
|||||||
|
|
||||||
for (overriddenDescriptor in overriddenDescriptors) {
|
for (overriddenDescriptor in overriddenDescriptors) {
|
||||||
if (propertyDescriptor != null) {
|
if (propertyDescriptor != null) {
|
||||||
val overriddenPropertyDescriptor = overriddenDescriptor.assertedCast<PropertyDescriptor> { "$overriddenDescriptor is not a property" }
|
val overriddenPropertyDescriptor =
|
||||||
|
overriddenDescriptor.assertedCast<PropertyDescriptor> { "$overriddenDescriptor is not a property" }
|
||||||
if (!isPropertyTypeOkForOverride(overriddenPropertyDescriptor, propertyDescriptor)) {
|
if (!isPropertyTypeOkForOverride(overriddenPropertyDescriptor, propertyDescriptor)) {
|
||||||
reportingStrategy.typeMismatchOnInheritance(propertyDescriptor, overriddenPropertyDescriptor)
|
reportingStrategy.typeMismatchOnInheritance(propertyDescriptor, overriddenPropertyDescriptor)
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (!isReturnTypeOkForOverride(overriddenDescriptor, descriptor)) {
|
if (!isReturnTypeOkForOverride(overriddenDescriptor, descriptor)) {
|
||||||
reportingStrategy.typeMismatchOnInheritance(descriptor, overriddenDescriptor)
|
reportingStrategy.typeMismatchOnInheritance(descriptor, overriddenDescriptor)
|
||||||
}
|
}
|
||||||
@@ -743,8 +768,7 @@ class OverrideResolver(
|
|||||||
val invisibleOverriddenDescriptor = findInvisibleOverriddenDescriptor(declared, declaringClass)
|
val invisibleOverriddenDescriptor = findInvisibleOverriddenDescriptor(declared, declaringClass)
|
||||||
if (invisibleOverriddenDescriptor != null) {
|
if (invisibleOverriddenDescriptor != null) {
|
||||||
reportError.cannotOverrideInvisibleMember(declared, invisibleOverriddenDescriptor)
|
reportError.cannotOverrideInvisibleMember(declared, invisibleOverriddenDescriptor)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
reportError.nothingToOverride(declared)
|
reportError.nothingToOverride(declared)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -769,8 +793,7 @@ class OverrideResolver(
|
|||||||
if (!isPropertyTypeOkForOverride(overriddenProperty, propertyMemberDescriptor)) {
|
if (!isPropertyTypeOkForOverride(overriddenProperty, propertyMemberDescriptor)) {
|
||||||
reportError.propertyTypeMismatchOnOverride(propertyMemberDescriptor, overriddenProperty)
|
reportError.propertyTypeMismatchOnOverride(propertyMemberDescriptor, overriddenProperty)
|
||||||
}
|
}
|
||||||
}
|
} else if (!isReturnTypeOkForOverride(overridden, memberDescriptor)) {
|
||||||
else if (!isReturnTypeOkForOverride(overridden, memberDescriptor)) {
|
|
||||||
reportError.returnTypeMismatchOnOverride(memberDescriptor, overridden)
|
reportError.returnTypeMismatchOnOverride(memberDescriptor, overridden)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -821,8 +844,7 @@ class OverrideResolver(
|
|||||||
|
|
||||||
return if (superDescriptor.isVar) {
|
return if (superDescriptor.isVar) {
|
||||||
KotlinTypeChecker.DEFAULT.equalTypes(subDescriptor.type, substitutedSuperReturnType)
|
KotlinTypeChecker.DEFAULT.equalTypes(subDescriptor.type, substitutedSuperReturnType)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
KotlinTypeChecker.DEFAULT.isSubtypeOf(subDescriptor.type, substitutedSuperReturnType)
|
KotlinTypeChecker.DEFAULT.isSubtypeOf(subDescriptor.type, substitutedSuperReturnType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -850,8 +872,10 @@ class OverrideResolver(
|
|||||||
for (fromSuper in all) {
|
for (fromSuper in all) {
|
||||||
if (OverridingUtil.DEFAULT.isOverridableBy(fromSuper, declared, null).result == OVERRIDABLE) {
|
if (OverridingUtil.DEFAULT.isOverridableBy(fromSuper, declared, null).result == OVERRIDABLE) {
|
||||||
if (OverridingUtil.isVisibleForOverride(declared, fromSuper)) {
|
if (OverridingUtil.isVisibleForOverride(declared, fromSuper)) {
|
||||||
throw IllegalStateException("Descriptor " + fromSuper + " is overridable by " + declared +
|
throw IllegalStateException(
|
||||||
" and visible but does not appear in its getOverriddenDescriptors()")
|
"Descriptor " + fromSuper + " is overridable by " + declared +
|
||||||
|
" and visible but does not appear in its getOverriddenDescriptors()"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return fromSuper
|
return fromSuper
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,8 +116,7 @@ private class AbbreviatedTypeBinding(
|
|||||||
override val isInAbbreviation: Boolean get() = true
|
override val isInAbbreviation: Boolean get() = true
|
||||||
|
|
||||||
override val arguments: List<TypeArgumentBinding<KtTypeElement>?>
|
override val arguments: List<TypeArgumentBinding<KtTypeElement>?>
|
||||||
get() = createTypeArgumentBindingsWithSinglePsiElement(type) {
|
get() = createTypeArgumentBindingsWithSinglePsiElement(type) { argumentType ->
|
||||||
argumentType ->
|
|
||||||
AbbreviatedTypeBinding(argumentType, psiElement)
|
AbbreviatedTypeBinding(argumentType, psiElement)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,8 +129,7 @@ private class NoTypeElementBinding<out P : PsiElement>(
|
|||||||
override val isInAbbreviation: Boolean get() = false
|
override val isInAbbreviation: Boolean get() = false
|
||||||
|
|
||||||
override val arguments: List<TypeArgumentBinding<P>?>
|
override val arguments: List<TypeArgumentBinding<P>?>
|
||||||
get() = createTypeArgumentBindingsWithSinglePsiElement(type) {
|
get() = createTypeArgumentBindingsWithSinglePsiElement(type) { argumentType ->
|
||||||
argumentType ->
|
|
||||||
NoTypeElementBinding(trace, psiElement, argumentType)
|
NoTypeElementBinding(trace, psiElement, argumentType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,16 +113,20 @@ class CallCompleter(
|
|||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val candidates = (if (context.collectAllCandidates) {
|
val candidates = (if (context.collectAllCandidates) {
|
||||||
results.allCandidates!!
|
results.allCandidates!!
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
results.resultingCalls
|
results.resultingCalls
|
||||||
}) as Collection<MutableResolvedCall<D>>
|
}) as Collection<MutableResolvedCall<D>>
|
||||||
|
|
||||||
val temporaryBindingTrace = TemporaryBindingTrace.create(context.trace, "Trace to complete a candidate that is not a resulting call")
|
val temporaryBindingTrace =
|
||||||
candidates.filterNot { resolvedCall -> resolvedCall.isCompleted }.forEach {
|
TemporaryBindingTrace.create(context.trace, "Trace to complete a candidate that is not a resulting call")
|
||||||
resolvedCall ->
|
candidates.filterNot { resolvedCall -> resolvedCall.isCompleted }.forEach { resolvedCall ->
|
||||||
|
|
||||||
completeResolvedCallAndArguments(resolvedCall, results, context.replaceBindingTrace(temporaryBindingTrace), TracingStrategy.EMPTY)
|
completeResolvedCallAndArguments(
|
||||||
|
resolvedCall,
|
||||||
|
results,
|
||||||
|
context.replaceBindingTrace(temporaryBindingTrace),
|
||||||
|
TracingStrategy.EMPTY
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,8 +163,7 @@ class CallCompleter(
|
|||||||
// TODO: compute generic type argument for R in the kotlin.Function<R> supertype (KT-12963)
|
// TODO: compute generic type argument for R in the kotlin.Function<R> supertype (KT-12963)
|
||||||
if (!TypeUtils.noExpectedType(expectedType) && expectedType.isFunctionType) expectedType.getReturnTypeFromFunctionType()
|
if (!TypeUtils.noExpectedType(expectedType) && expectedType.isFunctionType) expectedType.getReturnTypeFromFunctionType()
|
||||||
else TypeUtils.NO_EXPECTED_TYPE
|
else TypeUtils.NO_EXPECTED_TYPE
|
||||||
}
|
} else expectedType
|
||||||
else expectedType
|
|
||||||
|
|
||||||
fun ConstraintSystem.Builder.typeInSystem(type: KotlinType?): KotlinType? =
|
fun ConstraintSystem.Builder.typeInSystem(type: KotlinType?): KotlinType? =
|
||||||
type?.let {
|
type?.let {
|
||||||
@@ -181,8 +184,7 @@ class CallCompleter(
|
|||||||
if (returnTypeInSystem != null) {
|
if (returnTypeInSystem != null) {
|
||||||
builder.addSubtypeConstraint(returnTypeInSystem, expectedReturnType, EXPECTED_TYPE_POSITION.position())
|
builder.addSubtypeConstraint(returnTypeInSystem, expectedReturnType, EXPECTED_TYPE_POSITION.position())
|
||||||
builder.build()
|
builder.build()
|
||||||
}
|
} else null
|
||||||
else null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,16 +208,20 @@ class CallCompleter(
|
|||||||
builder.addSubtypeConstraint(returnTypeInSystem, builtIns.unitType, EXPECTED_TYPE_POSITION.position())
|
builder.addSubtypeConstraint(returnTypeInSystem, builtIns.unitType, EXPECTED_TYPE_POSITION.position())
|
||||||
val system = builder.build()
|
val system = builder.build()
|
||||||
if (system.status.isSuccessful()) system else null
|
if (system.status.isSuccessful()) system else null
|
||||||
}
|
} else null
|
||||||
else null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (call.isCallableReference() && !TypeUtils.noExpectedType(expectedType) && expectedType.isFunctionType) {
|
if (call.isCallableReference() && !TypeUtils.noExpectedType(expectedType) && expectedType.isFunctionType) {
|
||||||
updateSystemIfNeeded { builder ->
|
updateSystemIfNeeded { builder ->
|
||||||
candidateDescriptor.valueParameters.zip(expectedType.getValueParameterTypesFromFunctionType()).forEach { (parameter, argument) ->
|
candidateDescriptor.valueParameters.zip(expectedType.getValueParameterTypesFromFunctionType())
|
||||||
|
.forEach { (parameter, argument) ->
|
||||||
val valueParameterInSystem = builder.typeInSystem(parameter.type)
|
val valueParameterInSystem = builder.typeInSystem(parameter.type)
|
||||||
builder.addSubtypeConstraint(valueParameterInSystem, argument.type, VALUE_PARAMETER_POSITION.position(parameter.index))
|
builder.addSubtypeConstraint(
|
||||||
|
valueParameterInSystem,
|
||||||
|
argument.type,
|
||||||
|
VALUE_PARAMETER_POSITION.position(parameter.index)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.build()
|
builder.build()
|
||||||
@@ -268,8 +274,7 @@ class CallCompleter(
|
|||||||
val resolvedCall = results.resultingCall
|
val resolvedCall = results.resultingCall
|
||||||
getArgumentMapping = { argument -> resolvedCall.getArgumentMapping(argument) }
|
getArgumentMapping = { argument -> resolvedCall.getArgumentMapping(argument) }
|
||||||
getDataFlowInfoForArgument = { argument -> resolvedCall.dataFlowInfoForArguments.getInfo(argument) }
|
getDataFlowInfoForArgument = { argument -> resolvedCall.dataFlowInfoForArguments.getInfo(argument) }
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
getArgumentMapping = { ArgumentUnmapped }
|
getArgumentMapping = { ArgumentUnmapped }
|
||||||
getDataFlowInfoForArgument = { context.dataFlowInfo }
|
getDataFlowInfoForArgument = { context.dataFlowInfo }
|
||||||
}
|
}
|
||||||
@@ -279,7 +284,8 @@ class CallCompleter(
|
|||||||
val (expectedType, callPosition) = when (argumentMapping) {
|
val (expectedType, callPosition) = when (argumentMapping) {
|
||||||
is ArgumentMatch -> Pair(
|
is ArgumentMatch -> Pair(
|
||||||
getEffectiveExpectedType(argumentMapping.valueParameter, valueArgument, context),
|
getEffectiveExpectedType(argumentMapping.valueParameter, valueArgument, context),
|
||||||
CallPosition.ValueArgumentPosition(results.resultingCall, argumentMapping.valueParameter, valueArgument))
|
CallPosition.ValueArgumentPosition(results.resultingCall, argumentMapping.valueParameter, valueArgument)
|
||||||
|
)
|
||||||
else -> Pair(TypeUtils.NO_EXPECTED_TYPE, CallPosition.Unknown)
|
else -> Pair(TypeUtils.NO_EXPECTED_TYPE, CallPosition.Unknown)
|
||||||
}
|
}
|
||||||
val newContext =
|
val newContext =
|
||||||
@@ -307,8 +313,7 @@ class CallCompleter(
|
|||||||
val resolvedCall = results.resultingCall
|
val resolvedCall = results.resultingCall
|
||||||
updatedType = if (resolvedCall.hasInferredReturnType()) {
|
updatedType = if (resolvedCall.hasInferredReturnType()) {
|
||||||
resolvedCall.makeNullableTypeIfSafeReceiver(resolvedCall.resultingDescriptor?.returnType, context)
|
resolvedCall.makeNullableTypeIfSafeReceiver(resolvedCall.resultingDescriptor?.returnType, context)
|
||||||
}
|
} else null
|
||||||
else null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the cases like 'foo(1)' the type of '1' depends on expected type (it can be Int, Byte, etc.),
|
// For the cases like 'foo(1)' the type of '1' depends on expected type (it can be Int, Byte, etc.),
|
||||||
|
|||||||
+57
-38
@@ -89,8 +89,11 @@ class CallExpressionResolver(
|
|||||||
checkArguments: CheckArgumentTypesMode,
|
checkArguments: CheckArgumentTypesMode,
|
||||||
initialDataFlowInfoForArguments: DataFlowInfo
|
initialDataFlowInfoForArguments: DataFlowInfo
|
||||||
): Pair<Boolean, ResolvedCall<FunctionDescriptor>?> {
|
): Pair<Boolean, ResolvedCall<FunctionDescriptor>?> {
|
||||||
val results = callResolver.resolveFunctionCall(BasicCallResolutionContext.create(
|
val results = callResolver.resolveFunctionCall(
|
||||||
context, call, checkArguments, DataFlowInfoForArgumentsImpl(initialDataFlowInfoForArguments, call)))
|
BasicCallResolutionContext.create(
|
||||||
|
context, call, checkArguments, DataFlowInfoForArgumentsImpl(initialDataFlowInfoForArguments, call)
|
||||||
|
)
|
||||||
|
)
|
||||||
return if (!results.isNothing)
|
return if (!results.isNothing)
|
||||||
Pair(true, OverloadResolutionResultsUtil.getResultingCall(results, context))
|
Pair(true, OverloadResolutionResultsUtil.getResultingCall(results, context))
|
||||||
else
|
else
|
||||||
@@ -102,11 +105,13 @@ class CallExpressionResolver(
|
|||||||
callOperationNode: ASTNode?, context: ExpressionTypingContext
|
callOperationNode: ASTNode?, context: ExpressionTypingContext
|
||||||
): Pair<Boolean, KotlinType?> {
|
): Pair<Boolean, KotlinType?> {
|
||||||
val temporaryForVariable = TemporaryTraceAndCache.create(
|
val temporaryForVariable = TemporaryTraceAndCache.create(
|
||||||
context, "trace to resolve as local variable or property", nameExpression)
|
context, "trace to resolve as local variable or property", nameExpression
|
||||||
|
)
|
||||||
val call = CallMaker.makePropertyCall(receiver, callOperationNode, nameExpression)
|
val call = CallMaker.makePropertyCall(receiver, callOperationNode, nameExpression)
|
||||||
val contextForVariable = BasicCallResolutionContext.create(
|
val contextForVariable = BasicCallResolutionContext.create(
|
||||||
context.replaceTraceAndCache(temporaryForVariable),
|
context.replaceTraceAndCache(temporaryForVariable),
|
||||||
call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS)
|
call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS
|
||||||
|
)
|
||||||
val resolutionResult = callResolver.resolveSimpleProperty(contextForVariable)
|
val resolutionResult = callResolver.resolveSimpleProperty(contextForVariable)
|
||||||
|
|
||||||
// if the expression is a receiver in a qualified expression, it should be resolved after the selector is resolved
|
// if the expression is a receiver in a qualified expression, it should be resolved after the selector is resolved
|
||||||
@@ -122,8 +127,10 @@ class CallExpressionResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
temporaryForVariable.commit()
|
temporaryForVariable.commit()
|
||||||
return Pair(!resolutionResult.isNothing,
|
return Pair(
|
||||||
if (resolutionResult.isSingleResult) resolutionResult.resultingDescriptor.returnType else null)
|
!resolutionResult.isNothing,
|
||||||
|
if (resolutionResult.isSingleResult) resolutionResult.resultingDescriptor.returnType else null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSimpleNameExpressionTypeInfo(
|
fun getSimpleNameExpressionTypeInfo(
|
||||||
@@ -138,9 +145,12 @@ class CallExpressionResolver(
|
|||||||
): KotlinTypeInfo {
|
): KotlinTypeInfo {
|
||||||
|
|
||||||
val temporaryForVariable = TemporaryTraceAndCache.create(
|
val temporaryForVariable = TemporaryTraceAndCache.create(
|
||||||
context, "trace to resolve as variable", nameExpression)
|
context, "trace to resolve as variable", nameExpression
|
||||||
val (notNothing, type) = getVariableType(nameExpression, receiver, callOperationNode,
|
)
|
||||||
context.replaceTraceAndCache(temporaryForVariable))
|
val (notNothing, type) = getVariableType(
|
||||||
|
nameExpression, receiver, callOperationNode,
|
||||||
|
context.replaceTraceAndCache(temporaryForVariable)
|
||||||
|
)
|
||||||
|
|
||||||
if (notNothing) {
|
if (notNothing) {
|
||||||
temporaryForVariable.commit()
|
temporaryForVariable.commit()
|
||||||
@@ -149,10 +159,12 @@ class CallExpressionResolver(
|
|||||||
|
|
||||||
val call = CallMaker.makeCall(nameExpression, receiver, callOperationNode, nameExpression, emptyList())
|
val call = CallMaker.makeCall(nameExpression, receiver, callOperationNode, nameExpression, emptyList())
|
||||||
val temporaryForFunction = TemporaryTraceAndCache.create(
|
val temporaryForFunction = TemporaryTraceAndCache.create(
|
||||||
context, "trace to resolve as function", nameExpression)
|
context, "trace to resolve as function", nameExpression
|
||||||
|
)
|
||||||
val newContext = context.replaceTraceAndCache(temporaryForFunction)
|
val newContext = context.replaceTraceAndCache(temporaryForFunction)
|
||||||
val (resolveResult, resolvedCall) = getResolvedCallForFunction(
|
val (resolveResult, resolvedCall) = getResolvedCallForFunction(
|
||||||
call, newContext, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, initialDataFlowInfoForArguments)
|
call, newContext, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, initialDataFlowInfoForArguments
|
||||||
|
)
|
||||||
if (resolveResult) {
|
if (resolveResult) {
|
||||||
val functionDescriptor = resolvedCall?.resultingDescriptor
|
val functionDescriptor = resolvedCall?.resultingDescriptor
|
||||||
if (functionDescriptor !is ConstructorDescriptor) {
|
if (functionDescriptor !is ConstructorDescriptor) {
|
||||||
@@ -177,7 +189,8 @@ class CallExpressionResolver(
|
|||||||
callOperationNode: ASTNode?, context: ExpressionTypingContext
|
callOperationNode: ASTNode?, context: ExpressionTypingContext
|
||||||
): KotlinTypeInfo {
|
): KotlinTypeInfo {
|
||||||
val typeInfo = getCallExpressionTypeInfoWithoutFinalTypeCheck(
|
val typeInfo = getCallExpressionTypeInfoWithoutFinalTypeCheck(
|
||||||
callExpression, receiver, callOperationNode, context, context.dataFlowInfo)
|
callExpression, receiver, callOperationNode, context, context.dataFlowInfo
|
||||||
|
)
|
||||||
if (context.contextDependency == INDEPENDENT) {
|
if (context.contextDependency == INDEPENDENT) {
|
||||||
dataFlowAnalyzer.checkType(typeInfo.type, callExpression, context)
|
dataFlowAnalyzer.checkType(typeInfo.type, callExpression, context)
|
||||||
}
|
}
|
||||||
@@ -196,12 +209,14 @@ class CallExpressionResolver(
|
|||||||
val call = CallMaker.makeCall(receiver, callOperationNode, callExpression)
|
val call = CallMaker.makeCall(receiver, callOperationNode, callExpression)
|
||||||
|
|
||||||
val temporaryForFunction = TemporaryTraceAndCache.create(
|
val temporaryForFunction = TemporaryTraceAndCache.create(
|
||||||
context, "trace to resolve as function call", callExpression)
|
context, "trace to resolve as function call", callExpression
|
||||||
|
)
|
||||||
val (resolveResult, resolvedCall) = getResolvedCallForFunction(
|
val (resolveResult, resolvedCall) = getResolvedCallForFunction(
|
||||||
call,
|
call,
|
||||||
context.replaceTraceAndCache(temporaryForFunction),
|
context.replaceTraceAndCache(temporaryForFunction),
|
||||||
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
||||||
initialDataFlowInfoForArguments)
|
initialDataFlowInfoForArguments
|
||||||
|
)
|
||||||
if (resolveResult) {
|
if (resolveResult) {
|
||||||
val functionDescriptor = resolvedCall?.resultingDescriptor
|
val functionDescriptor = resolvedCall?.resultingDescriptor
|
||||||
temporaryForFunction.commit()
|
temporaryForFunction.commit()
|
||||||
@@ -246,9 +261,12 @@ class CallExpressionResolver(
|
|||||||
val calleeExpression = callExpression.calleeExpression
|
val calleeExpression = callExpression.calleeExpression
|
||||||
if (calleeExpression is KtSimpleNameExpression && callExpression.typeArgumentList == null) {
|
if (calleeExpression is KtSimpleNameExpression && callExpression.typeArgumentList == null) {
|
||||||
val temporaryForVariable = TemporaryTraceAndCache.create(
|
val temporaryForVariable = TemporaryTraceAndCache.create(
|
||||||
context, "trace to resolve as variable with 'invoke' call", callExpression)
|
context, "trace to resolve as variable with 'invoke' call", callExpression
|
||||||
val (notNothing, type) = getVariableType(calleeExpression, receiver, callOperationNode,
|
)
|
||||||
context.replaceTraceAndCache(temporaryForVariable))
|
val (notNothing, type) = getVariableType(
|
||||||
|
calleeExpression, receiver, callOperationNode,
|
||||||
|
context.replaceTraceAndCache(temporaryForVariable)
|
||||||
|
)
|
||||||
val qualifier = temporaryForVariable.trace.get(BindingContext.QUALIFIER, calleeExpression)
|
val qualifier = temporaryForVariable.trace.get(BindingContext.QUALIFIER, calleeExpression)
|
||||||
if (notNothing && (qualifier == null || qualifier !is PackageQualifier)) {
|
if (notNothing && (qualifier == null || qualifier !is PackageQualifier)) {
|
||||||
|
|
||||||
@@ -258,8 +276,12 @@ class CallExpressionResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
temporaryForVariable.commit()
|
temporaryForVariable.commit()
|
||||||
context.trace.report(FUNCTION_EXPECTED.on(calleeExpression, calleeExpression,
|
context.trace.report(
|
||||||
type ?: ErrorUtils.createErrorType("")))
|
FUNCTION_EXPECTED.on(
|
||||||
|
calleeExpression, calleeExpression,
|
||||||
|
type ?: ErrorUtils.createErrorType("")
|
||||||
|
)
|
||||||
|
)
|
||||||
argumentTypeResolver.analyzeArgumentsAndRecordTypes(
|
argumentTypeResolver.analyzeArgumentsAndRecordTypes(
|
||||||
BasicCallResolutionContext.create(
|
BasicCallResolutionContext.create(
|
||||||
context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
||||||
@@ -275,14 +297,12 @@ class CallExpressionResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun KtQualifiedExpression.elementChain(context: ExpressionTypingContext) =
|
private fun KtQualifiedExpression.elementChain(context: ExpressionTypingContext) =
|
||||||
qualifiedExpressionResolver.resolveQualifierInExpressionAndUnroll(this, context) {
|
qualifiedExpressionResolver.resolveQualifierInExpressionAndUnroll(this, context) { nameExpression ->
|
||||||
nameExpression ->
|
|
||||||
val resolutionResult = resolveSimpleName(context, nameExpression)
|
val resolutionResult = resolveSimpleName(context, nameExpression)
|
||||||
|
|
||||||
if (resolutionResult.isSingleResult && resolutionResult.resultingDescriptor is FakeCallableDescriptorForObject) {
|
if (resolutionResult.isSingleResult && resolutionResult.resultingDescriptor is FakeCallableDescriptorForObject) {
|
||||||
false
|
false
|
||||||
}
|
} else when (resolutionResult.resultCode) {
|
||||||
else when (resolutionResult.resultCode) {
|
|
||||||
NAME_NOT_FOUND, CANDIDATES_WITH_WRONG_RECEIVER -> false
|
NAME_NOT_FOUND, CANDIDATES_WITH_WRONG_RECEIVER -> false
|
||||||
else -> !context.languageVersionSettings.supportsFeature(LanguageFeature.NewInference) || resolutionResult.isSuccess
|
else -> !context.languageVersionSettings.supportsFeature(LanguageFeature.NewInference) || resolutionResult.isSuccess
|
||||||
}
|
}
|
||||||
@@ -307,9 +327,11 @@ class CallExpressionResolver(
|
|||||||
initialDataFlowInfoForArguments: DataFlowInfo
|
initialDataFlowInfoForArguments: DataFlowInfo
|
||||||
): KotlinTypeInfo = when (selectorExpression) {
|
): KotlinTypeInfo = when (selectorExpression) {
|
||||||
is KtCallExpression -> getCallExpressionTypeInfoWithoutFinalTypeCheck(
|
is KtCallExpression -> getCallExpressionTypeInfoWithoutFinalTypeCheck(
|
||||||
selectorExpression, receiver, callOperationNode, context, initialDataFlowInfoForArguments)
|
selectorExpression, receiver, callOperationNode, context, initialDataFlowInfoForArguments
|
||||||
|
)
|
||||||
is KtSimpleNameExpression -> getSimpleNameExpressionTypeInfo(
|
is KtSimpleNameExpression -> getSimpleNameExpressionTypeInfo(
|
||||||
selectorExpression, receiver, callOperationNode, context, initialDataFlowInfoForArguments)
|
selectorExpression, receiver, callOperationNode, context, initialDataFlowInfoForArguments
|
||||||
|
)
|
||||||
is KtExpression -> {
|
is KtExpression -> {
|
||||||
expressionTypingServices.getTypeInfo(selectorExpression, context)
|
expressionTypingServices.getTypeInfo(selectorExpression, context)
|
||||||
context.trace.report(ILLEGAL_SELECTOR.on(selectorExpression))
|
context.trace.report(ILLEGAL_SELECTOR.on(selectorExpression))
|
||||||
@@ -328,9 +350,9 @@ class CallExpressionResolver(
|
|||||||
// Additional "receiver != null" information should be applied if we consider a safe call
|
// Additional "receiver != null" information should be applied if we consider a safe call
|
||||||
if (receiverCanBeNull) {
|
if (receiverCanBeNull) {
|
||||||
initialDataFlowInfoForArguments = initialDataFlowInfoForArguments.disequate(
|
initialDataFlowInfoForArguments = initialDataFlowInfoForArguments.disequate(
|
||||||
receiverDataFlowValue, DataFlowValue.nullValue(builtIns), languageVersionSettings)
|
receiverDataFlowValue, DataFlowValue.nullValue(builtIns), languageVersionSettings
|
||||||
}
|
)
|
||||||
else if (receiver is ReceiverValue) {
|
} else if (receiver is ReceiverValue) {
|
||||||
reportUnnecessarySafeCall(context.trace, receiver.type, element.node, receiver)
|
reportUnnecessarySafeCall(context.trace, receiver.type, element.node, receiver)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -361,8 +383,7 @@ class CallExpressionResolver(
|
|||||||
val value = constantExpressionEvaluator.evaluateExpression(qualified, context.trace, context.expectedType)
|
val value = constantExpressionEvaluator.evaluateExpression(qualified, context.trace, context.expectedType)
|
||||||
return if (value != null && value.isPure) {
|
return if (value != null && value.isPure) {
|
||||||
dataFlowAnalyzer.createCompileTimeConstantTypeInfo(value, qualified, context)
|
dataFlowAnalyzer.createCompileTimeConstantTypeInfo(value, qualified, context)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (context.contextDependency == INDEPENDENT) {
|
if (context.contextDependency == INDEPENDENT) {
|
||||||
dataFlowAnalyzer.checkType(selectorTypeInfo.type, qualified, context)
|
dataFlowAnalyzer.checkType(selectorTypeInfo.type, qualified, context)
|
||||||
}
|
}
|
||||||
@@ -418,8 +439,7 @@ class CallExpressionResolver(
|
|||||||
if (receiver is ReceiverValue && TypeUtils.isNullableType(receiver.type) && !element.safe) {
|
if (receiver is ReceiverValue && TypeUtils.isNullableType(receiver.type) && !element.safe) {
|
||||||
// Call with nullable receiver: take data flow info from branch point
|
// Call with nullable receiver: take data flow info from branch point
|
||||||
branchPointDataFlowInfo
|
branchPointDataFlowInfo
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// Take data flow info from the current receiver
|
// Take data flow info from the current receiver
|
||||||
receiverTypeInfo.dataFlowInfo
|
receiverTypeInfo.dataFlowInfo
|
||||||
}
|
}
|
||||||
@@ -432,8 +452,9 @@ class CallExpressionResolver(
|
|||||||
branchPointDataFlowInfo = selectorTypeInfo.dataFlowInfo
|
branchPointDataFlowInfo = selectorTypeInfo.dataFlowInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
resultTypeInfo = checkSelectorTypeInfo(qualifiedExpression, selectorTypeInfo, contextForSelector).
|
resultTypeInfo = checkSelectorTypeInfo(qualifiedExpression, selectorTypeInfo, contextForSelector).replaceDataFlowInfo(
|
||||||
replaceDataFlowInfo(branchPointDataFlowInfo)
|
branchPointDataFlowInfo
|
||||||
|
)
|
||||||
if (!lastStage) {
|
if (!lastStage) {
|
||||||
recordResultTypeInfo(qualifiedExpression, resultTypeInfo, contextForSelector)
|
recordResultTypeInfo(qualifiedExpression, resultTypeInfo, contextForSelector)
|
||||||
}
|
}
|
||||||
@@ -469,8 +490,7 @@ class CallExpressionResolver(
|
|||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
return isUnderAnnotationClassDeclaration(trace, parent)
|
return isUnderAnnotationClassDeclaration(trace, parent)
|
||||||
}
|
}
|
||||||
}
|
} else if (parent is KtParameter) {
|
||||||
else if (parent is KtParameter) {
|
|
||||||
return isUnderAnnotationClassDeclaration(trace, parent)
|
return isUnderAnnotationClassDeclaration(trace, parent)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -487,8 +507,7 @@ class CallExpressionResolver(
|
|||||||
) = trace.report(
|
) = trace.report(
|
||||||
if (explicitReceiver is ExpressionReceiver && explicitReceiver.expression is KtSuperExpression) {
|
if (explicitReceiver is ExpressionReceiver && explicitReceiver.expression is KtSuperExpression) {
|
||||||
UNEXPECTED_SAFE_CALL.on(callOperationNode.psi)
|
UNEXPECTED_SAFE_CALL.on(callOperationNode.psi)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
UNNECESSARY_SAFE_CALL.on(callOperationNode.psi, type)
|
UNNECESSARY_SAFE_CALL.on(callOperationNode.psi, type)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -125,8 +125,10 @@ fun getErasedReceiverType(receiverParameterDescriptor: ReceiverParameterDescript
|
|||||||
receiverType.constructor
|
receiverType.constructor
|
||||||
}
|
}
|
||||||
|
|
||||||
return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(receiverType.annotations, receiverTypeConstructor, fakeTypeArguments,
|
return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
|
||||||
receiverType.isMarkedNullable, ErrorUtils.createErrorScope("Error scope for erased receiver type", /*throwExceptions=*/true))
|
receiverType.annotations, receiverTypeConstructor, fakeTypeArguments,
|
||||||
|
receiverType.isMarkedNullable, ErrorUtils.createErrorScope("Error scope for erased receiver type", /*throwExceptions=*/true)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isOrOverridesSynthesized(descriptor: CallableMemberDescriptor): Boolean {
|
fun isOrOverridesSynthesized(descriptor: CallableMemberDescriptor): Boolean {
|
||||||
@@ -245,7 +247,8 @@ fun createResolutionCandidatesForConstructors(
|
|||||||
else
|
else
|
||||||
null
|
null
|
||||||
|
|
||||||
val constructors = typeAliasDescriptor?.constructors?.mapNotNull(TypeAliasConstructorDescriptor::withDispatchReceiver) ?: classWithConstructors.constructors
|
val constructors = typeAliasDescriptor?.constructors?.mapNotNull(TypeAliasConstructorDescriptor::withDispatchReceiver)
|
||||||
|
?: classWithConstructors.constructors
|
||||||
|
|
||||||
if (constructors.isEmpty()) return emptyList()
|
if (constructors.isEmpty()) return emptyList()
|
||||||
|
|
||||||
@@ -262,8 +265,7 @@ fun createResolutionCandidatesForConstructors(
|
|||||||
|
|
||||||
receiverKind = ExplicitReceiverKind.DISPATCH_RECEIVER
|
receiverKind = ExplicitReceiverKind.DISPATCH_RECEIVER
|
||||||
dispatchReceiver = receiver.value
|
dispatchReceiver = receiver.value
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
receiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
|
receiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
|
||||||
dispatchReceiver = null
|
dispatchReceiver = null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,8 +107,7 @@ class CandidateResolver(
|
|||||||
&& candidateCall.knownTypeParametersSubstitutor == null
|
&& candidateCall.knownTypeParametersSubstitutor == null
|
||||||
) {
|
) {
|
||||||
genericCandidateResolver.inferTypeArguments(this)
|
genericCandidateResolver.inferTypeArguments(this)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
checkAllValueArguments(this, SHAPE_FUNCTION_ARGUMENTS).status
|
checkAllValueArguments(this, SHAPE_FUNCTION_ARGUMENTS).status
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -117,8 +116,7 @@ class CandidateResolver(
|
|||||||
val ktTypeArguments = call.typeArguments
|
val ktTypeArguments = call.typeArguments
|
||||||
if (candidateCall.knownTypeParametersSubstitutor != null) {
|
if (candidateCall.knownTypeParametersSubstitutor != null) {
|
||||||
candidateCall.setResultingSubstitutor(candidateCall.knownTypeParametersSubstitutor!!)
|
candidateCall.setResultingSubstitutor(candidateCall.knownTypeParametersSubstitutor!!)
|
||||||
}
|
} else if (ktTypeArguments.isNotEmpty()) {
|
||||||
else if (ktTypeArguments.isNotEmpty()) {
|
|
||||||
// Explicit type arguments passed
|
// Explicit type arguments passed
|
||||||
|
|
||||||
val typeArguments = ArrayList<KotlinType>()
|
val typeArguments = ArrayList<KotlinType>()
|
||||||
@@ -130,9 +128,11 @@ class CandidateResolver(
|
|||||||
|
|
||||||
val expectedTypeArgumentCount = candidateDescriptor.typeParameters.size
|
val expectedTypeArgumentCount = candidateDescriptor.typeParameters.size
|
||||||
for (index in ktTypeArguments.size..expectedTypeArgumentCount - 1) {
|
for (index in ktTypeArguments.size..expectedTypeArgumentCount - 1) {
|
||||||
typeArguments.add(ErrorUtils.createErrorType(
|
typeArguments.add(
|
||||||
|
ErrorUtils.createErrorType(
|
||||||
"Explicit type argument expected for " + candidateDescriptor.typeParameters[index].name
|
"Explicit type argument expected for " + candidateDescriptor.typeParameters[index].name
|
||||||
))
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
val substitution = FunctionDescriptorUtil.createSubstitution(candidateDescriptor as FunctionDescriptor, typeArguments)
|
val substitution = FunctionDescriptorUtil.createSubstitution(candidateDescriptor as FunctionDescriptor, typeArguments)
|
||||||
val substitutor = TypeSubstitutor.create(SubstitutionFilteringInternalResolveAnnotations(substitution))
|
val substitutor = TypeSubstitutor.create(SubstitutionFilteringInternalResolveAnnotations(substitution))
|
||||||
@@ -140,8 +140,7 @@ class CandidateResolver(
|
|||||||
if (expectedTypeArgumentCount != ktTypeArguments.size) {
|
if (expectedTypeArgumentCount != ktTypeArguments.size) {
|
||||||
candidateCall.addStatus(WRONG_NUMBER_OF_TYPE_ARGUMENTS_ERROR)
|
candidateCall.addStatus(WRONG_NUMBER_OF_TYPE_ARGUMENTS_ERROR)
|
||||||
tracing.wrongNumberOfTypeArguments(trace, expectedTypeArgumentCount, candidateDescriptor)
|
tracing.wrongNumberOfTypeArguments(trace, expectedTypeArgumentCount, candidateDescriptor)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
checkGenericBoundsInAFunctionCall(ktTypeArguments, typeArguments, candidateDescriptor, substitutor, trace)
|
checkGenericBoundsInAFunctionCall(ktTypeArguments, typeArguments, candidateDescriptor, substitutor, trace)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,17 +148,16 @@ class CandidateResolver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <D : CallableDescriptor> CallCandidateResolutionContext<D>.mapArguments()
|
private fun <D : CallableDescriptor> CallCandidateResolutionContext<D>.mapArguments() = check {
|
||||||
= check {
|
|
||||||
val argumentMappingStatus = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(
|
val argumentMappingStatus = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(
|
||||||
call, tracing, candidateCall)
|
call, tracing, candidateCall
|
||||||
|
)
|
||||||
if (!argumentMappingStatus.isSuccess) {
|
if (!argumentMappingStatus.isSuccess) {
|
||||||
candidateCall.addStatus(ARGUMENTS_MAPPING_ERROR)
|
candidateCall.addStatus(ARGUMENTS_MAPPING_ERROR)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <D : CallableDescriptor> CallCandidateResolutionContext<D>.checkExpectedCallableType()
|
private fun <D : CallableDescriptor> CallCandidateResolutionContext<D>.checkExpectedCallableType() = check {
|
||||||
= check {
|
|
||||||
if (!noExpectedType(expectedType)) {
|
if (!noExpectedType(expectedType)) {
|
||||||
val candidateKCallableType = DoubleColonExpressionResolver.createKCallableTypeForReference(
|
val candidateKCallableType = DoubleColonExpressionResolver.createKCallableTypeForReference(
|
||||||
candidateCall.candidateDescriptor,
|
candidateCall.candidateDescriptor,
|
||||||
@@ -195,7 +193,8 @@ class CandidateResolver(
|
|||||||
smartCastType: KotlinType?
|
smartCastType: KotlinType?
|
||||||
): ResolutionStatus {
|
): ResolutionStatus {
|
||||||
val invisibleMember = Visibilities.findInvisibleMember(
|
val invisibleMember = Visibilities.findInvisibleMember(
|
||||||
getReceiverValueWithSmartCast(receiverArgument, smartCastType), candidateDescriptor, scope.ownerDescriptor)
|
getReceiverValueWithSmartCast(receiverArgument, smartCastType), candidateDescriptor, scope.ownerDescriptor
|
||||||
|
)
|
||||||
return if (invisibleMember != null) {
|
return if (invisibleMember != null) {
|
||||||
tracing.invisibleMember(trace, invisibleMember)
|
tracing.invisibleMember(trace, invisibleMember)
|
||||||
INVISIBLE_MEMBER_ERROR
|
INVISIBLE_MEMBER_ERROR
|
||||||
@@ -224,17 +223,14 @@ class CandidateResolver(
|
|||||||
if (receiverParameter != null && receiverArgument == null) {
|
if (receiverParameter != null && receiverArgument == null) {
|
||||||
tracing.missingReceiver(candidateCall.trace, receiverParameter)
|
tracing.missingReceiver(candidateCall.trace, receiverParameter)
|
||||||
OTHER_ERROR
|
OTHER_ERROR
|
||||||
}
|
} else if (receiverParameter == null && receiverArgument != null) {
|
||||||
else if (receiverParameter == null && receiverArgument != null) {
|
|
||||||
tracing.noReceiverAllowed(candidateCall.trace)
|
tracing.noReceiverAllowed(candidateCall.trace)
|
||||||
if (call.calleeExpression is KtSimpleNameExpression) {
|
if (call.calleeExpression is KtSimpleNameExpression) {
|
||||||
RECEIVER_PRESENCE_ERROR
|
RECEIVER_PRESENCE_ERROR
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
OTHER_ERROR
|
OTHER_ERROR
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
SUCCESS
|
SUCCESS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -248,8 +244,7 @@ class CandidateResolver(
|
|||||||
&& DescriptorUtils.isStaticNestedClass(candidateDescriptor.containingDeclaration)
|
&& DescriptorUtils.isStaticNestedClass(candidateDescriptor.containingDeclaration)
|
||||||
) {
|
) {
|
||||||
nestedClass = candidateDescriptor.containingDeclaration
|
nestedClass = candidateDescriptor.containingDeclaration
|
||||||
}
|
} else if (candidateDescriptor is FakeCallableDescriptorForObject) {
|
||||||
else if (candidateDescriptor is FakeCallableDescriptorForObject) {
|
|
||||||
nestedClass = candidateDescriptor.getReferencedObject()
|
nestedClass = candidateDescriptor.getReferencedObject()
|
||||||
}
|
}
|
||||||
if (nestedClass != null) {
|
if (nestedClass != null) {
|
||||||
@@ -342,7 +337,8 @@ class CandidateResolver(
|
|||||||
|
|
||||||
fun <D : CallableDescriptor> checkAllValueArguments(
|
fun <D : CallableDescriptor> checkAllValueArguments(
|
||||||
context: CallCandidateResolutionContext<D>,
|
context: CallCandidateResolutionContext<D>,
|
||||||
resolveFunctionArgumentBodies: ResolveArgumentsMode): ValueArgumentsCheckingResult {
|
resolveFunctionArgumentBodies: ResolveArgumentsMode
|
||||||
|
): ValueArgumentsCheckingResult {
|
||||||
val checkingResult = checkValueArgumentTypes(context, context.candidateCall, resolveFunctionArgumentBodies)
|
val checkingResult = checkValueArgumentTypes(context, context.candidateCall, resolveFunctionArgumentBodies)
|
||||||
var resultStatus = checkingResult.status
|
var resultStatus = checkingResult.status
|
||||||
resultStatus = resultStatus.combine(checkReceivers(context))
|
resultStatus = resultStatus.combine(checkReceivers(context))
|
||||||
@@ -373,27 +369,26 @@ class CandidateResolver(
|
|||||||
var resultingType: KotlinType? = type
|
var resultingType: KotlinType? = type
|
||||||
if (type == null || (type.isError && !type.isFunctionPlaceholder)) {
|
if (type == null || (type.isError && !type.isFunctionPlaceholder)) {
|
||||||
matchStatus = ArgumentMatchStatus.ARGUMENT_HAS_NO_TYPE
|
matchStatus = ArgumentMatchStatus.ARGUMENT_HAS_NO_TYPE
|
||||||
}
|
} else if (!noExpectedType(expectedType)) {
|
||||||
else if (!noExpectedType(expectedType)) {
|
|
||||||
if (!ArgumentTypeResolver.isSubtypeOfForArgumentType(type, expectedType)) {
|
if (!ArgumentTypeResolver.isSubtypeOfForArgumentType(type, expectedType)) {
|
||||||
val smartCast = smartCastValueArgumentTypeIfPossible(expression, newContext.expectedType, type, newContext)
|
val smartCast = smartCastValueArgumentTypeIfPossible(expression, newContext.expectedType, type, newContext)
|
||||||
if (smartCast == null) {
|
if (smartCast == null) {
|
||||||
resultStatus = tryNotNullableArgument(type, expectedType) ?: OTHER_ERROR
|
resultStatus = tryNotNullableArgument(type, expectedType) ?: OTHER_ERROR
|
||||||
matchStatus = ArgumentMatchStatus.TYPE_MISMATCH
|
matchStatus = ArgumentMatchStatus.TYPE_MISMATCH
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
resultingType = smartCast
|
resultingType = smartCast
|
||||||
}
|
}
|
||||||
}
|
} else if (ErrorUtils.containsUninferredParameter(expectedType)) {
|
||||||
else if (ErrorUtils.containsUninferredParameter(expectedType)) {
|
|
||||||
matchStatus = ArgumentMatchStatus.MATCH_MODULO_UNINFERRED_TYPES
|
matchStatus = ArgumentMatchStatus.MATCH_MODULO_UNINFERRED_TYPES
|
||||||
}
|
}
|
||||||
|
|
||||||
val spreadElement = argument.getSpreadElement()
|
val spreadElement = argument.getSpreadElement()
|
||||||
if (spreadElement != null && !type.isFlexible() && type.isMarkedNullable) {
|
if (spreadElement != null && !type.isFlexible() && type.isMarkedNullable) {
|
||||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, context)
|
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, context)
|
||||||
val smartCastResult = SmartCastManager.checkAndRecordPossibleCast(dataFlowValue, expectedType, expression, context,
|
val smartCastResult = SmartCastManager.checkAndRecordPossibleCast(
|
||||||
call = null, recordExpressionType = false)
|
dataFlowValue, expectedType, expression, context,
|
||||||
|
call = null, recordExpressionType = false
|
||||||
|
)
|
||||||
if (smartCastResult == null || !smartCastResult.isCorrect) {
|
if (smartCastResult == null || !smartCastResult.isCorrect) {
|
||||||
context.trace.report(Errors.SPREAD_OF_NULLABLE.on(spreadElement))
|
context.trace.report(Errors.SPREAD_OF_NULLABLE.on(spreadElement))
|
||||||
}
|
}
|
||||||
@@ -463,22 +458,26 @@ class CandidateResolver(
|
|||||||
// both 'b' (receiver) and 'foo' (this object) might be nullable. In the first case we mark dot, in the second 'foo'.
|
// both 'b' (receiver) and 'foo' (this object) might be nullable. In the first case we mark dot, in the second 'foo'.
|
||||||
// Class 'CallForImplicitInvoke' helps up to recognise this case, and parameter 'implicitInvokeCheck' helps us to distinguish whether we check receiver or this object.
|
// Class 'CallForImplicitInvoke' helps up to recognise this case, and parameter 'implicitInvokeCheck' helps us to distinguish whether we check receiver or this object.
|
||||||
|
|
||||||
resultStatus = resultStatus.combine(context.checkReceiver(
|
resultStatus = resultStatus.combine(
|
||||||
|
context.checkReceiver(
|
||||||
candidateCall,
|
candidateCall,
|
||||||
candidateCall.resultingDescriptor.extensionReceiverParameter,
|
candidateCall.resultingDescriptor.extensionReceiverParameter,
|
||||||
candidateCall.extensionReceiver,
|
candidateCall.extensionReceiver,
|
||||||
candidateCall.explicitReceiverKind.isExtensionReceiver,
|
candidateCall.explicitReceiverKind.isExtensionReceiver,
|
||||||
implicitInvokeCheck = false, isDispatchReceiver = false
|
implicitInvokeCheck = false, isDispatchReceiver = false
|
||||||
))
|
)
|
||||||
|
)
|
||||||
|
|
||||||
resultStatus = resultStatus.combine(context.checkReceiver(
|
resultStatus = resultStatus.combine(
|
||||||
|
context.checkReceiver(
|
||||||
candidateCall,
|
candidateCall,
|
||||||
candidateCall.resultingDescriptor.dispatchReceiverParameter, candidateCall.dispatchReceiver,
|
candidateCall.resultingDescriptor.dispatchReceiverParameter, candidateCall.dispatchReceiver,
|
||||||
candidateCall.explicitReceiverKind.isDispatchReceiver,
|
candidateCall.explicitReceiverKind.isDispatchReceiver,
|
||||||
// for the invocation 'foo(1)' where foo is a variable of function type we should mark 'foo' if there is unsafe call error
|
// for the invocation 'foo(1)' where foo is a variable of function type we should mark 'foo' if there is unsafe call error
|
||||||
implicitInvokeCheck = context.call is CallForImplicitInvoke,
|
implicitInvokeCheck = context.call is CallForImplicitInvoke,
|
||||||
isDispatchReceiver = true
|
isDispatchReceiver = true
|
||||||
))
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if (!context.isDebuggerContext
|
if (!context.isDebuggerContext
|
||||||
&& candidateCall.dispatchReceiver != null
|
&& candidateCall.dispatchReceiver != null
|
||||||
@@ -486,7 +485,9 @@ class CandidateResolver(
|
|||||||
&& context.isCandidateVisible(receiverArgument = Visibilities.ALWAYS_SUITABLE_RECEIVER, smartCastType = null)) {
|
&& context.isCandidateVisible(receiverArgument = Visibilities.ALWAYS_SUITABLE_RECEIVER, smartCastType = null)) {
|
||||||
resultStatus = resultStatus.combine(
|
resultStatus = resultStatus.combine(
|
||||||
context.checkVisibilityWithDispatchReceiver(
|
context.checkVisibilityWithDispatchReceiver(
|
||||||
candidateCall.dispatchReceiver, candidateCall.smartCastDispatchReceiverType))
|
candidateCall.dispatchReceiver, candidateCall.smartCastDispatchReceiverType
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return resultStatus
|
return resultStatus
|
||||||
@@ -514,7 +515,8 @@ class CandidateResolver(
|
|||||||
if (smartCastSubtypingResult == null) {
|
if (smartCastSubtypingResult == null) {
|
||||||
tracing.wrongReceiverType(
|
tracing.wrongReceiverType(
|
||||||
trace, receiverParameter, receiverArgument,
|
trace, receiverParameter, receiverArgument,
|
||||||
this.replaceCallPosition(CallPosition.ExtensionReceiverPosition(candidateCall)))
|
this.replaceCallPosition(CallPosition.ExtensionReceiverPosition(candidateCall))
|
||||||
|
)
|
||||||
return OTHER_ERROR
|
return OTHER_ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -547,8 +549,7 @@ class CandidateResolver(
|
|||||||
if (dataFlowValue.immanentNullability.canBeNonNull()) {
|
if (dataFlowValue.immanentNullability.canBeNonNull()) {
|
||||||
expression?.let { trace.record(BindingContext.SMARTCAST_NULL, it) }
|
expression?.let { trace.record(BindingContext.SMARTCAST_NULL, it) }
|
||||||
}
|
}
|
||||||
}
|
} else if (!nullableImplicitInvokeReceiver && smartCastNeeded) {
|
||||||
else if (!nullableImplicitInvokeReceiver && smartCastNeeded) {
|
|
||||||
// Look if smart cast has some useful nullability info
|
// Look if smart cast has some useful nullability info
|
||||||
|
|
||||||
val smartCastResult = SmartCastManager.checkAndRecordPossibleCast(
|
val smartCastResult = SmartCastManager.checkAndRecordPossibleCast(
|
||||||
@@ -561,12 +562,10 @@ class CandidateResolver(
|
|||||||
if (notNullReceiverExpected) {
|
if (notNullReceiverExpected) {
|
||||||
reportUnsafeCall = true
|
reportUnsafeCall = true
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (isDispatchReceiver) {
|
if (isDispatchReceiver) {
|
||||||
candidateCall.setSmartCastDispatchReceiverType(smartCastResult.resultType)
|
candidateCall.setSmartCastDispatchReceiverType(smartCastResult.resultType)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
candidateCall.updateExtensionReceiverWithSmartCastIfNeeded(smartCastResult.resultType)
|
candidateCall.updateExtensionReceiverWithSmartCastIfNeeded(smartCastResult.resultType)
|
||||||
}
|
}
|
||||||
if (!smartCastResult.isCorrect) {
|
if (!smartCastResult.isCorrect) {
|
||||||
@@ -627,7 +626,11 @@ class CandidateResolver(
|
|||||||
// can't happen in single-step expansion
|
// can't happen in single-step expansion
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun conflictingProjection(typeAlias: TypeAliasDescriptor, typeParameter: TypeParameterDescriptor?, substitutedArgument: KotlinType) {
|
override fun conflictingProjection(
|
||||||
|
typeAlias: TypeAliasDescriptor,
|
||||||
|
typeParameter: TypeParameterDescriptor?,
|
||||||
|
substitutedArgument: KotlinType
|
||||||
|
) {
|
||||||
// can't happen in single-step expansion
|
// can't happen in single-step expansion
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,14 +642,18 @@ class CandidateResolver(
|
|||||||
// can't happen in single-step expansion
|
// can't happen in single-step expansion
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun boundsViolationInSubstitution(bound: KotlinType, unsubstitutedArgument: KotlinType, argument: KotlinType, typeParameter: TypeParameterDescriptor) {
|
override fun boundsViolationInSubstitution(
|
||||||
|
bound: KotlinType,
|
||||||
|
unsubstitutedArgument: KotlinType,
|
||||||
|
argument: KotlinType,
|
||||||
|
typeParameter: TypeParameterDescriptor
|
||||||
|
) {
|
||||||
val descriptorForUnsubstitutedArgument = unsubstitutedArgument.constructor.declarationDescriptor
|
val descriptorForUnsubstitutedArgument = unsubstitutedArgument.constructor.declarationDescriptor
|
||||||
val argumentElement = argumentsMapping[descriptorForUnsubstitutedArgument]
|
val argumentElement = argumentsMapping[descriptorForUnsubstitutedArgument]
|
||||||
val argumentTypeReferenceElement = argumentElement?.typeReference
|
val argumentTypeReferenceElement = argumentElement?.typeReference
|
||||||
if (argumentTypeReferenceElement != null) {
|
if (argumentTypeReferenceElement != null) {
|
||||||
trace.report(UPPER_BOUND_VIOLATED.on(argumentTypeReferenceElement, bound, argument))
|
trace.report(UPPER_BOUND_VIOLATED.on(argumentTypeReferenceElement, bound, argument))
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
trace.report(UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION.on(callElement, bound, argument, typeParameter))
|
trace.report(UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION.on(callElement, bound, argument, typeParameter))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -695,9 +702,20 @@ class CandidateResolver(
|
|||||||
val typeParameter = typeParameters[i]
|
val typeParameter = typeParameters[i]
|
||||||
val substitutedTypeArgument = substitutedTypeProjection.type
|
val substitutedTypeArgument = substitutedTypeProjection.type
|
||||||
val unsubstitutedTypeArgument = unsubstitutedType.arguments[i].type
|
val unsubstitutedTypeArgument = unsubstitutedType.arguments[i].type
|
||||||
DescriptorResolver.checkBoundsInTypeAlias(reportStrategy, unsubstitutedTypeArgument, substitutedTypeArgument, typeParameter, boundsSubstitutor)
|
DescriptorResolver.checkBoundsInTypeAlias(
|
||||||
|
reportStrategy,
|
||||||
|
unsubstitutedTypeArgument,
|
||||||
|
substitutedTypeArgument,
|
||||||
|
typeParameter,
|
||||||
|
boundsSubstitutor
|
||||||
|
)
|
||||||
|
|
||||||
checkTypeInTypeAliasSubstitutionRec(reportStrategy, unsubstitutedTypeArgument, typeAliasParametersSubstitutor, boundsSubstitutor)
|
checkTypeInTypeAliasSubstitutionRec(
|
||||||
|
reportStrategy,
|
||||||
|
unsubstitutedTypeArgument,
|
||||||
|
typeAliasParametersSubstitutor,
|
||||||
|
boundsSubstitutor
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+26
-10
@@ -53,7 +53,10 @@ class DiagnosticReporterByTrackingStrategy(
|
|||||||
override fun onCall(diagnostic: KotlinCallDiagnostic) {
|
override fun onCall(diagnostic: KotlinCallDiagnostic) {
|
||||||
when (diagnostic.javaClass) {
|
when (diagnostic.javaClass) {
|
||||||
VisibilityError::class.java -> tracingStrategy.invisibleMember(trace, (diagnostic as VisibilityError).invisibleMember)
|
VisibilityError::class.java -> tracingStrategy.invisibleMember(trace, (diagnostic as VisibilityError).invisibleMember)
|
||||||
NoValueForParameter::class.java -> tracingStrategy.noValueForParameter(trace, (diagnostic as NoValueForParameter).parameterDescriptor)
|
NoValueForParameter::class.java -> tracingStrategy.noValueForParameter(
|
||||||
|
trace,
|
||||||
|
(diagnostic as NoValueForParameter).parameterDescriptor
|
||||||
|
)
|
||||||
InstantiationOfAbstractClass::class.java -> tracingStrategy.instantiationOfAbstractClass(trace)
|
InstantiationOfAbstractClass::class.java -> tracingStrategy.instantiationOfAbstractClass(trace)
|
||||||
AbstractSuperCall::class.java -> tracingStrategy.abstractSuperCall(trace)
|
AbstractSuperCall::class.java -> tracingStrategy.abstractSuperCall(trace)
|
||||||
}
|
}
|
||||||
@@ -123,8 +126,8 @@ class DiagnosticReporterByTrackingStrategy(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onCallArgumentName(callArgument: KotlinCallArgument, diagnostic: KotlinCallDiagnostic) {
|
override fun onCallArgumentName(callArgument: KotlinCallArgument, diagnostic: KotlinCallDiagnostic) {
|
||||||
val nameReference = callArgument.psiCallArgument.valueArgument.getArgumentName()?.referenceExpression ?:
|
val nameReference = callArgument.psiCallArgument.valueArgument.getArgumentName()?.referenceExpression
|
||||||
error("Argument name should be not null for argument: $callArgument")
|
?: error("Argument name should be not null for argument: $callArgument")
|
||||||
when (diagnostic.javaClass) {
|
when (diagnostic.javaClass) {
|
||||||
NamedArgumentReference::class.java -> {
|
NamedArgumentReference::class.java -> {
|
||||||
trace.record(BindingContext.REFERENCE_TARGET, nameReference, (diagnostic as NamedArgumentReference).parameterDescriptor)
|
trace.record(BindingContext.REFERENCE_TARGET, nameReference, (diagnostic as NamedArgumentReference).parameterDescriptor)
|
||||||
@@ -133,10 +136,12 @@ class DiagnosticReporterByTrackingStrategy(
|
|||||||
NameForAmbiguousParameter::class.java -> trace.report(NAME_FOR_AMBIGUOUS_PARAMETER.on(nameReference))
|
NameForAmbiguousParameter::class.java -> trace.report(NAME_FOR_AMBIGUOUS_PARAMETER.on(nameReference))
|
||||||
NameNotFound::class.java -> trace.report(NAMED_PARAMETER_NOT_FOUND.on(nameReference, nameReference))
|
NameNotFound::class.java -> trace.report(NAMED_PARAMETER_NOT_FOUND.on(nameReference, nameReference))
|
||||||
|
|
||||||
NamedArgumentNotAllowed::class.java -> trace.report(NAMED_ARGUMENTS_NOT_ALLOWED.on(
|
NamedArgumentNotAllowed::class.java -> trace.report(
|
||||||
|
NAMED_ARGUMENTS_NOT_ALLOWED.on(
|
||||||
nameReference,
|
nameReference,
|
||||||
if ((diagnostic as NamedArgumentNotAllowed).descriptor is FunctionInvokeDescriptor) INVOKE_ON_FUNCTION_TYPE else NON_KOTLIN_FUNCTION
|
if ((diagnostic as NamedArgumentNotAllowed).descriptor is FunctionInvokeDescriptor) INVOKE_ON_FUNCTION_TYPE else NON_KOTLIN_FUNCTION
|
||||||
))
|
)
|
||||||
|
)
|
||||||
ArgumentPassedTwice::class.java -> trace.report(ARGUMENT_PASSED_TWICE.on(nameReference))
|
ArgumentPassedTwice::class.java -> trace.report(ARGUMENT_PASSED_TWICE.on(nameReference))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,11 +161,15 @@ class DiagnosticReporterByTrackingStrategy(
|
|||||||
is ExpressionKotlinCallArgumentImpl -> {
|
is ExpressionKotlinCallArgumentImpl -> {
|
||||||
trace.markAsReported()
|
trace.markAsReported()
|
||||||
val context = context.replaceDataFlowInfo(expressionArgument.dataFlowInfoBeforeThisArgument)
|
val context = context.replaceDataFlowInfo(expressionArgument.dataFlowInfoBeforeThisArgument)
|
||||||
val argumentExpression = KtPsiUtil.getLastElementDeparenthesized(expressionArgument.valueArgument.getArgumentExpression (), context.statementFilter)
|
val argumentExpression = KtPsiUtil.getLastElementDeparenthesized(
|
||||||
|
expressionArgument.valueArgument.getArgumentExpression(),
|
||||||
|
context.statementFilter
|
||||||
|
)
|
||||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(expressionArgument.receiver.receiverValue, context)
|
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(expressionArgument.receiver.receiverValue, context)
|
||||||
SmartCastManager.checkAndRecordPossibleCast(
|
SmartCastManager.checkAndRecordPossibleCast(
|
||||||
dataFlowValue, smartCastDiagnostic.smartCastType, argumentExpression, context, call,
|
dataFlowValue, smartCastDiagnostic.smartCastType, argumentExpression, context, call,
|
||||||
recordExpressionType = true)
|
recordExpressionType = true
|
||||||
|
)
|
||||||
}
|
}
|
||||||
is ReceiverExpressionKotlinCallArgument -> {
|
is ReceiverExpressionKotlinCallArgument -> {
|
||||||
trace.markAsReported()
|
trace.markAsReported()
|
||||||
@@ -168,11 +177,13 @@ class DiagnosticReporterByTrackingStrategy(
|
|||||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverValue, context)
|
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverValue, context)
|
||||||
SmartCastManager.checkAndRecordPossibleCast(
|
SmartCastManager.checkAndRecordPossibleCast(
|
||||||
dataFlowValue, smartCastDiagnostic.smartCastType, (receiverValue as? ExpressionReceiver)?.expression, context, call,
|
dataFlowValue, smartCastDiagnostic.smartCastType, (receiverValue as? ExpressionReceiver)?.expression, context, call,
|
||||||
recordExpressionType = true)
|
recordExpressionType = true
|
||||||
|
)
|
||||||
}
|
}
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
val resolvedCall = smartCastDiagnostic.kotlinCall?.psiKotlinCall?.psiCall?.getResolvedCall(trace.bindingContext) as? NewResolvedCallImpl<*>
|
val resolvedCall =
|
||||||
|
smartCastDiagnostic.kotlinCall?.psiKotlinCall?.psiCall?.getResolvedCall(trace.bindingContext) as? NewResolvedCallImpl<*>
|
||||||
if (resolvedCall != null && smartCastResult != null) {
|
if (resolvedCall != null && smartCastResult != null) {
|
||||||
if (resolvedCall.extensionReceiver == expressionArgument.receiver.receiverValue) {
|
if (resolvedCall.extensionReceiver == expressionArgument.receiver.receiverValue) {
|
||||||
resolvedCall.updateExtensionReceiverWithSmartCastIfNeeded(smartCastResult.resultType)
|
resolvedCall.updateExtensionReceiverWithSmartCastIfNeeded(smartCastResult.resultType)
|
||||||
@@ -218,7 +229,12 @@ class DiagnosticReporterByTrackingStrategy(
|
|||||||
val capturedError = diagnostic as CapturedTypeFromSubtyping
|
val capturedError = diagnostic as CapturedTypeFromSubtyping
|
||||||
(capturedError.position as? ArgumentConstraintPosition)?.let {
|
(capturedError.position as? ArgumentConstraintPosition)?.let {
|
||||||
val expression = it.argument.psiExpression ?: return
|
val expression = it.argument.psiExpression ?: return
|
||||||
trace.report(NEW_INFERENCE_ERROR.on(expression, "Capture type from subtyping ${capturedError.constraintType} for variable ${capturedError.typeVariable}"))
|
trace.report(
|
||||||
|
NEW_INFERENCE_ERROR.on(
|
||||||
|
expression,
|
||||||
|
"Capture type from subtyping ${capturedError.constraintType} for variable ${capturedError.typeVariable}"
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-15
@@ -185,8 +185,7 @@ class GenericCandidateResolver(
|
|||||||
val targetExpression = if (possibleQualifiedExpression is KtQualifiedExpression) {
|
val targetExpression = if (possibleQualifiedExpression is KtQualifiedExpression) {
|
||||||
if (possibleQualifiedExpression.selectorExpression != callExpression) return null
|
if (possibleQualifiedExpression.selectorExpression != callExpression) return null
|
||||||
possibleQualifiedExpression
|
possibleQualifiedExpression
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
callExpression
|
callExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,7 +267,8 @@ class GenericCandidateResolver(
|
|||||||
|
|
||||||
if (addConstraintForNestedCall(argumentExpression, constraintPosition, builder, newContext, effectiveExpectedType)) return
|
if (addConstraintForNestedCall(argumentExpression, constraintPosition, builder, newContext, effectiveExpectedType)) return
|
||||||
|
|
||||||
val type = updateResultTypeForSmartCasts(typeInfoForCall.type, argumentExpression, context.replaceDataFlowInfo(dataFlowInfoForArgument))
|
val type =
|
||||||
|
updateResultTypeForSmartCasts(typeInfoForCall.type, argumentExpression, context.replaceDataFlowInfo(dataFlowInfoForArgument))
|
||||||
|
|
||||||
if (argumentExpression is KtCallableReferenceExpression && type == null) return
|
if (argumentExpression is KtCallableReferenceExpression && type == null) return
|
||||||
|
|
||||||
@@ -345,7 +345,8 @@ class GenericCandidateResolver(
|
|||||||
// to inconsistency and errors in inference. See definition of `effectiveExpectedTypeInSystem` in `addConstraintForFunctionLiteralArgument`
|
// to inconsistency and errors in inference. See definition of `effectiveExpectedTypeInSystem` in `addConstraintForFunctionLiteralArgument`
|
||||||
val newContext = if (resolvedCall is VariableAsFunctionResolvedCall) {
|
val newContext = if (resolvedCall is VariableAsFunctionResolvedCall) {
|
||||||
CallCandidateResolutionContext.create(
|
CallCandidateResolutionContext.create(
|
||||||
resolvedCall, context, context.trace, context.tracing, resolvedCall.functionCall.call, context.candidateResolveMode)
|
resolvedCall, context, context.trace, context.tracing, resolvedCall.functionCall.call, context.candidateResolveMode
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
context
|
context
|
||||||
}
|
}
|
||||||
@@ -356,8 +357,10 @@ class GenericCandidateResolver(
|
|||||||
for (valueArgument in resolvedValueArgument.arguments) {
|
for (valueArgument in resolvedValueArgument.arguments) {
|
||||||
valueArgument.getArgumentExpression()?.let { argumentExpression ->
|
valueArgument.getArgumentExpression()?.let { argumentExpression ->
|
||||||
ArgumentTypeResolver.getFunctionLiteralArgumentIfAny(argumentExpression, newContext)?.let { functionLiteral ->
|
ArgumentTypeResolver.getFunctionLiteralArgumentIfAny(argumentExpression, newContext)?.let { functionLiteral ->
|
||||||
addConstraintForFunctionLiteralArgument(functionLiteral, valueArgument, valueParameterDescriptor, constraintSystem, newContext,
|
addConstraintForFunctionLiteralArgument(
|
||||||
resolvedCall.candidateDescriptor.returnType)
|
functionLiteral, valueArgument, valueParameterDescriptor, constraintSystem, newContext,
|
||||||
|
resolvedCall.candidateDescriptor.returnType
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// as inference for callable references depends on expected type,
|
// as inference for callable references depends on expected type,
|
||||||
@@ -367,10 +370,10 @@ class GenericCandidateResolver(
|
|||||||
// For example, type info for arguments is needed before call will be completed (See ControlStructureTypingVisitor.visitIfExpression)
|
// For example, type info for arguments is needed before call will be completed (See ControlStructureTypingVisitor.visitIfExpression)
|
||||||
val temporaryContextForCall = if (resolvedCall.candidateDescriptor.name in SPECIAL_FUNCTION_NAMES) {
|
val temporaryContextForCall = if (resolvedCall.candidateDescriptor.name in SPECIAL_FUNCTION_NAMES) {
|
||||||
newContext
|
newContext
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val temporaryBindingTrace = TemporaryBindingTrace.create(
|
val temporaryBindingTrace = TemporaryBindingTrace.create(
|
||||||
newContext.trace, "Trace to complete argument for call that might be not resulting call")
|
newContext.trace, "Trace to complete argument for call that might be not resulting call"
|
||||||
|
)
|
||||||
newContext.replaceBindingTrace(temporaryBindingTrace)
|
newContext.replaceBindingTrace(temporaryBindingTrace)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,7 +383,8 @@ class GenericCandidateResolver(
|
|||||||
valueArgument,
|
valueArgument,
|
||||||
valueParameterDescriptor,
|
valueParameterDescriptor,
|
||||||
constraintSystem,
|
constraintSystem,
|
||||||
temporaryContextForCall)
|
temporaryContextForCall
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -446,17 +450,20 @@ class GenericCandidateResolver(
|
|||||||
val position = VALUE_PARAMETER_POSITION.position(valueParameterDescriptor.index)
|
val position = VALUE_PARAMETER_POSITION.position(valueParameterDescriptor.index)
|
||||||
if (hasExpectedReturnType) {
|
if (hasExpectedReturnType) {
|
||||||
val temporaryToResolveFunctionLiteral = TemporaryTraceAndCache.create(
|
val temporaryToResolveFunctionLiteral = TemporaryTraceAndCache.create(
|
||||||
context, "trace to resolve function literal with expected return type", argumentExpression)
|
context, "trace to resolve function literal with expected return type", argumentExpression
|
||||||
|
)
|
||||||
|
|
||||||
val statementExpression = KtPsiUtil.getExpressionOrLastStatementInBlock(functionLiteral.bodyExpression) ?: return
|
val statementExpression = KtPsiUtil.getExpressionOrLastStatementInBlock(functionLiteral.bodyExpression) ?: return
|
||||||
val mismatch = BooleanArray(1)
|
val mismatch = BooleanArray(1)
|
||||||
val errorInterceptingTrace = ExpressionTypingUtils.makeTraceInterceptingTypeMismatch(
|
val errorInterceptingTrace = ExpressionTypingUtils.makeTraceInterceptingTypeMismatch(
|
||||||
temporaryToResolveFunctionLiteral.trace, statementExpression, mismatch)
|
temporaryToResolveFunctionLiteral.trace, statementExpression, mismatch
|
||||||
|
)
|
||||||
val newContext = context.replaceBindingTrace(errorInterceptingTrace).replaceExpectedType(expectedType)
|
val newContext = context.replaceBindingTrace(errorInterceptingTrace).replaceExpectedType(expectedType)
|
||||||
.replaceDataFlowInfo(dataFlowInfoForArgument).replaceResolutionResultsCache(temporaryToResolveFunctionLiteral.cache)
|
.replaceDataFlowInfo(dataFlowInfoForArgument).replaceResolutionResultsCache(temporaryToResolveFunctionLiteral.cache)
|
||||||
.replaceContextDependency(INDEPENDENT)
|
.replaceContextDependency(INDEPENDENT)
|
||||||
val type = argumentTypeResolver.getFunctionLiteralTypeInfo(
|
val type = argumentTypeResolver.getFunctionLiteralTypeInfo(
|
||||||
argumentExpression, functionLiteral, newContext, RESOLVE_FUNCTION_ARGUMENTS).type
|
argumentExpression, functionLiteral, newContext, RESOLVE_FUNCTION_ARGUMENTS
|
||||||
|
).type
|
||||||
if (!mismatch[0]) {
|
if (!mismatch[0]) {
|
||||||
constraintSystem.addSubtypeConstraint(type, effectiveExpectedTypeInSystem, position)
|
constraintSystem.addSubtypeConstraint(type, effectiveExpectedTypeInSystem, position)
|
||||||
temporaryToResolveFunctionLiteral.commit()
|
temporaryToResolveFunctionLiteral.commit()
|
||||||
@@ -467,7 +474,9 @@ class GenericCandidateResolver(
|
|||||||
val expectedTypeWithEstimatedReturnType = replaceReturnTypeForCallable(expectedType, estimatedReturnType)
|
val expectedTypeWithEstimatedReturnType = replaceReturnTypeForCallable(expectedType, estimatedReturnType)
|
||||||
val newContext = context.replaceExpectedType(expectedTypeWithEstimatedReturnType).replaceDataFlowInfo(dataFlowInfoForArgument)
|
val newContext = context.replaceExpectedType(expectedTypeWithEstimatedReturnType).replaceDataFlowInfo(dataFlowInfoForArgument)
|
||||||
.replaceContextDependency(INDEPENDENT)
|
.replaceContextDependency(INDEPENDENT)
|
||||||
val type = argumentTypeResolver.getFunctionLiteralTypeInfo(argumentExpression, functionLiteral, newContext, RESOLVE_FUNCTION_ARGUMENTS).type
|
val type =
|
||||||
|
argumentTypeResolver.getFunctionLiteralTypeInfo(argumentExpression, functionLiteral, newContext, RESOLVE_FUNCTION_ARGUMENTS)
|
||||||
|
.type
|
||||||
constraintSystem.addSubtypeConstraint(type, effectiveExpectedTypeInSystem, position)
|
constraintSystem.addSubtypeConstraint(type, effectiveExpectedTypeInSystem, position)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -515,7 +524,8 @@ class GenericCandidateResolver(
|
|||||||
valueArgument: ValueArgument
|
valueArgument: ValueArgument
|
||||||
): KotlinType? {
|
): KotlinType? {
|
||||||
val dataFlowInfoForArgument = context.candidateCall.dataFlowInfoForArguments.getInfo(valueArgument)
|
val dataFlowInfoForArgument = context.candidateCall.dataFlowInfoForArguments.getInfo(valueArgument)
|
||||||
val expectedTypeWithoutReturnType = if (!hasUnknownReturnType(expectedType)) replaceReturnTypeByUnknown(expectedType) else expectedType
|
val expectedTypeWithoutReturnType =
|
||||||
|
if (!hasUnknownReturnType(expectedType)) replaceReturnTypeByUnknown(expectedType) else expectedType
|
||||||
val newContext = context
|
val newContext = context
|
||||||
.replaceExpectedType(expectedTypeWithoutReturnType)
|
.replaceExpectedType(expectedTypeWithoutReturnType)
|
||||||
.replaceDataFlowInfo(dataFlowInfoForArgument)
|
.replaceDataFlowInfo(dataFlowInfoForArgument)
|
||||||
|
|||||||
+8
-3
@@ -32,11 +32,16 @@ class CallableReferenceCompatibilityChecker : CallChecker {
|
|||||||
for ((_, resolvedArgument) in resolvedCall.valueArguments) {
|
for ((_, resolvedArgument) in resolvedCall.valueArguments) {
|
||||||
inner@ for (argument in resolvedArgument.arguments) {
|
inner@ for (argument in resolvedArgument.arguments) {
|
||||||
val argumentExpression = argument.getArgumentExpression() as? KtCallableReferenceExpression ?: continue@inner
|
val argumentExpression = argument.getArgumentExpression() as? KtCallableReferenceExpression ?: continue@inner
|
||||||
val callableReferenceResolvedCall = argumentExpression.callableReference.getResolvedCall(context.trace.bindingContext) ?: continue@inner
|
val callableReferenceResolvedCall =
|
||||||
|
argumentExpression.callableReference.getResolvedCall(context.trace.bindingContext) ?: continue@inner
|
||||||
if (callableReferenceResolvedCall.call.isCallableReference() &&
|
if (callableReferenceResolvedCall.call.isCallableReference() &&
|
||||||
callableReferenceResolvedCall.candidateDescriptor.typeParameters.isNotEmpty()) {
|
callableReferenceResolvedCall.candidateDescriptor.typeParameters.isNotEmpty()) {
|
||||||
context.trace.report(Errors.UNSUPPORTED_FEATURE.on(argumentExpression,
|
context.trace.report(
|
||||||
typeInferenceForCallableReferencesFeature to context.languageVersionSettings))
|
Errors.UNSUPPORTED_FEATURE.on(
|
||||||
|
argumentExpression,
|
||||||
|
typeInferenceForCallableReferencesFeature to context.languageVersionSettings
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -58,8 +58,7 @@ object DeprecatedCallChecker : CallChecker {
|
|||||||
for (deprecation in deprecations) {
|
for (deprecation in deprecations) {
|
||||||
trace.report(createDeprecationDiagnostic(element, deprecation, languageVersionSettings))
|
trace.report(createDeprecationDiagnostic(element, deprecation, languageVersionSettings))
|
||||||
}
|
}
|
||||||
}
|
} else if (targetDescriptor is PropertyDescriptor && shouldCheckPropertyGetter(element)) {
|
||||||
else if (targetDescriptor is PropertyDescriptor && shouldCheckPropertyGetter(element)) {
|
|
||||||
targetDescriptor.getter?.let { check(it, trace, element, languageVersionSettings, deprecationResolver) }
|
targetDescriptor.getter?.let { check(it, trace, element, languageVersionSettings, deprecationResolver) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-4
@@ -49,9 +49,11 @@ class OperatorCallChecker : CallChecker {
|
|||||||
call is CallTransformer.CallForImplicitInvoke && call.itIsVariableAsFunctionCall) {
|
call is CallTransformer.CallForImplicitInvoke && call.itIsVariableAsFunctionCall) {
|
||||||
val outerCall = call.outerCall
|
val outerCall = call.outerCall
|
||||||
if (isConventionCall(outerCall) || isWrongCallWithExplicitTypeArguments(resolvedCall, outerCall)) {
|
if (isConventionCall(outerCall) || isWrongCallWithExplicitTypeArguments(resolvedCall, outerCall)) {
|
||||||
throw AssertionError("Illegal resolved call to variable with invoke for $outerCall. " +
|
throw AssertionError(
|
||||||
|
"Illegal resolved call to variable with invoke for $outerCall. " +
|
||||||
"Variable: ${resolvedCall.variableCall.resultingDescriptor}" +
|
"Variable: ${resolvedCall.variableCall.resultingDescriptor}" +
|
||||||
"Invoke: ${resolvedCall.functionCall.resultingDescriptor}")
|
"Invoke: ${resolvedCall.functionCall.resultingDescriptor}"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,8 +119,7 @@ private fun checkModConvention(
|
|||||||
if (shouldWarnAboutDeprecatedModFromBuiltIns(languageVersionSettings)) {
|
if (shouldWarnAboutDeprecatedModFromBuiltIns(languageVersionSettings)) {
|
||||||
addWarningAboutDeprecatedMod(descriptor, diagnosticHolder, modifier)
|
addWarningAboutDeprecatedMod(descriptor, diagnosticHolder, modifier)
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem)) {
|
if (languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem)) {
|
||||||
addWarningAboutDeprecatedMod(descriptor, diagnosticHolder, modifier)
|
addWarningAboutDeprecatedMod(descriptor, diagnosticHolder, modifier)
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-5
@@ -67,19 +67,32 @@ object CoroutineSuspendCallChecker : CallChecker {
|
|||||||
|
|
||||||
if (!InlineUtil.checkNonLocalReturnUsage(enclosingSuspendFunction, callElement, context.resolutionContext)) {
|
if (!InlineUtil.checkNonLocalReturnUsage(enclosingSuspendFunction, callElement, context.resolutionContext)) {
|
||||||
context.trace.report(Errors.NON_LOCAL_SUSPENSION_POINT.on(reportOn))
|
context.trace.report(Errors.NON_LOCAL_SUSPENSION_POINT.on(reportOn))
|
||||||
}
|
} else if (context.scope.parentsWithSelf.any { it.isScopeForDefaultParameterValuesOf(enclosingSuspendFunction) }) {
|
||||||
else if (context.scope.parentsWithSelf.any { it.isScopeForDefaultParameterValuesOf(enclosingSuspendFunction) }) {
|
|
||||||
context.trace.report(Errors.UNSUPPORTED.on(reportOn, "suspend function calls in a context of default parameter value"))
|
context.trace.report(Errors.UNSUPPORTED.on(reportOn, "suspend function calls in a context of default parameter value"))
|
||||||
}
|
}
|
||||||
|
|
||||||
context.trace.record(BindingContext.ENCLOSING_SUSPEND_FUNCTION_FOR_SUSPEND_FUNCTION_CALL, resolvedCall.call, enclosingSuspendFunction)
|
context.trace.record(
|
||||||
|
BindingContext.ENCLOSING_SUSPEND_FUNCTION_FOR_SUSPEND_FUNCTION_CALL,
|
||||||
|
resolvedCall.call,
|
||||||
|
enclosingSuspendFunction
|
||||||
|
)
|
||||||
|
|
||||||
checkRestrictsSuspension(enclosingSuspendFunction, resolvedCall, reportOn, context)
|
checkRestrictsSuspension(enclosingSuspendFunction, resolvedCall, reportOn, context)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
when (descriptor) {
|
when (descriptor) {
|
||||||
is FunctionDescriptor -> context.trace.report(Errors.ILLEGAL_SUSPEND_FUNCTION_CALL.on(reportOn, resolvedCall.candidateDescriptor))
|
is FunctionDescriptor -> context.trace.report(
|
||||||
is PropertyDescriptor -> context.trace.report(Errors.ILLEGAL_SUSPEND_PROPERTY_ACCESS.on(reportOn, resolvedCall.candidateDescriptor))
|
Errors.ILLEGAL_SUSPEND_FUNCTION_CALL.on(
|
||||||
|
reportOn,
|
||||||
|
resolvedCall.candidateDescriptor
|
||||||
|
)
|
||||||
|
)
|
||||||
|
is PropertyDescriptor -> context.trace.report(
|
||||||
|
Errors.ILLEGAL_SUSPEND_PROPERTY_ACCESS.on(
|
||||||
|
reportOn,
|
||||||
|
resolvedCall.candidateDescriptor
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-24
@@ -82,8 +82,7 @@ open class ConstraintSystemBuilderImpl(private val mode: Mode = ConstraintSystem
|
|||||||
typeParameters.map {
|
typeParameters.map {
|
||||||
TypeVariable(call, it, it, true)
|
TypeVariable(call, it, it, true)
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val freshTypeParameters = ArrayList<TypeParameterDescriptor>(typeParameters.size)
|
val freshTypeParameters = ArrayList<TypeParameterDescriptor>(typeParameters.size)
|
||||||
DescriptorSubstitutor.substituteTypeParameters(
|
DescriptorSubstitutor.substituteTypeParameters(
|
||||||
typeParameters.toList(), TypeSubstitution.EMPTY, typeParameters.first().containingDeclaration, freshTypeParameters
|
typeParameters.toList(), TypeSubstitution.EMPTY, typeParameters.first().containingDeclaration, freshTypeParameters
|
||||||
@@ -106,20 +105,29 @@ open class ConstraintSystemBuilderImpl(private val mode: Mode = ConstraintSystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return storeSubstitutor(call, TypeSubstitutor.create(TypeConstructorSubstitution.createByParametersMap(
|
return storeSubstitutor(
|
||||||
|
call, TypeSubstitutor.create(
|
||||||
|
TypeConstructorSubstitution.createByParametersMap(
|
||||||
typeParameters.zip(typeVariables.map { it.type }.defaultProjections()).toMap()
|
typeParameters.zip(typeVariables.map { it.type }.defaultProjections()).toMap()
|
||||||
)))
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KotlinType.isProper() = !TypeUtils.contains(this) {
|
private fun KotlinType.isProper() = !TypeUtils.contains(this) { type ->
|
||||||
type -> type.constructor.declarationDescriptor.let { it is TypeParameterDescriptor && isMyTypeVariable(it) }
|
type.constructor.declarationDescriptor.let { it is TypeParameterDescriptor && isMyTypeVariable(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun getNestedTypeVariables(type: KotlinType): List<TypeVariable> =
|
internal fun getNestedTypeVariables(type: KotlinType): List<TypeVariable> =
|
||||||
type.getNestedTypeParameters().mapNotNull { getMyTypeVariable(it) }
|
type.getNestedTypeParameters().mapNotNull { getMyTypeVariable(it) }
|
||||||
|
|
||||||
override fun addSubtypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType?, constraintPosition: ConstraintPosition) {
|
override fun addSubtypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType?, constraintPosition: ConstraintPosition) {
|
||||||
addConstraint(SUB_TYPE, constrainingType, subjectType, ConstraintContext(constraintPosition, initial = true, initialReduction = true))
|
addConstraint(
|
||||||
|
SUB_TYPE,
|
||||||
|
constrainingType,
|
||||||
|
subjectType,
|
||||||
|
ConstraintContext(constraintPosition, initial = true, initialReduction = true)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addConstraint(
|
fun addConstraint(
|
||||||
@@ -131,8 +139,10 @@ open class ConstraintSystemBuilderImpl(private val mode: Mode = ConstraintSystem
|
|||||||
val constraintPosition = constraintContext.position
|
val constraintPosition = constraintContext.position
|
||||||
|
|
||||||
// when processing nested constraints, `derivedFrom` information should be reset
|
// when processing nested constraints, `derivedFrom` information should be reset
|
||||||
val newConstraintContext = ConstraintContext(constraintContext.position, derivedFrom = null, initial = false,
|
val newConstraintContext = ConstraintContext(
|
||||||
initialReduction = constraintContext.initialReduction)
|
constraintContext.position, derivedFrom = null, initial = false,
|
||||||
|
initialReduction = constraintContext.initialReduction
|
||||||
|
)
|
||||||
val typeCheckingProcedure = TypeCheckingProcedure(object : TypeCheckingProcedureCallbacks {
|
val typeCheckingProcedure = TypeCheckingProcedure(object : TypeCheckingProcedureCallbacks {
|
||||||
private var depth = 0
|
private var depth = 0
|
||||||
|
|
||||||
@@ -212,8 +222,7 @@ open class ConstraintSystemBuilderImpl(private val mode: Mode = ConstraintSystem
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
createTypeForFunctionPlaceholder(subType, superType)
|
createTypeForFunctionPlaceholder(subType, superType)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
subType
|
subType
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,8 +239,7 @@ open class ConstraintSystemBuilderImpl(private val mode: Mode = ConstraintSystem
|
|||||||
val superType2 = simplifyType(superType, constraintContext.initial)
|
val superType2 = simplifyType(superType, constraintContext.initial)
|
||||||
val result = if (constraintKind == EQUAL) {
|
val result = if (constraintKind == EQUAL) {
|
||||||
typeCheckingProcedure.equalTypes(subType2, superType2)
|
typeCheckingProcedure.equalTypes(subType2, superType2)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
typeCheckingProcedure.isSubtypeOf(subType2, superType)
|
typeCheckingProcedure.isSubtypeOf(subType2, superType)
|
||||||
}
|
}
|
||||||
if (!result) errors.add(newTypeInferenceOrParameterConstraintError(constraintPosition))
|
if (!result) errors.add(newTypeInferenceOrParameterConstraintError(constraintPosition))
|
||||||
@@ -259,8 +267,10 @@ open class ConstraintSystemBuilderImpl(private val mode: Mode = ConstraintSystem
|
|||||||
kind: TypeBounds.BoundKind,
|
kind: TypeBounds.BoundKind,
|
||||||
constraintContext: ConstraintContext
|
constraintContext: ConstraintContext
|
||||||
) {
|
) {
|
||||||
val bound = Bound(typeVariable, constrainingType, kind, constraintContext.position,
|
val bound = Bound(
|
||||||
constrainingType.isProper(), constraintContext.derivedFrom ?: emptySet())
|
typeVariable, constrainingType, kind, constraintContext.position,
|
||||||
|
constrainingType.isProper(), constraintContext.derivedFrom ?: emptySet()
|
||||||
|
)
|
||||||
val typeBounds = getTypeBounds(typeVariable)
|
val typeBounds = getTypeBounds(typeVariable)
|
||||||
if (typeBounds.bounds.contains(bound)) return
|
if (typeBounds.bounds.contains(bound)) return
|
||||||
|
|
||||||
@@ -332,8 +342,7 @@ open class ConstraintSystemBuilderImpl(private val mode: Mode = ConstraintSystem
|
|||||||
}
|
}
|
||||||
val typeProjection = if (isTypeMarkedNullable) {
|
val typeProjection = if (isTypeMarkedNullable) {
|
||||||
TypeProjectionImpl(constrainingTypeProjection.projectionKind, TypeUtils.makeNotNullable(constrainingTypeProjection.type))
|
TypeProjectionImpl(constrainingTypeProjection.projectionKind, TypeUtils.makeNotNullable(constrainingTypeProjection.type))
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
constrainingTypeProjection
|
constrainingTypeProjection
|
||||||
}
|
}
|
||||||
val capturedType = createCapturedType(typeProjection)
|
val capturedType = createCapturedType(typeProjection)
|
||||||
@@ -341,8 +350,8 @@ open class ConstraintSystemBuilderImpl(private val mode: Mode = ConstraintSystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun getTypeBounds(variable: TypeVariable): TypeBoundsImpl {
|
internal fun getTypeBounds(variable: TypeVariable): TypeBoundsImpl {
|
||||||
return allTypeParameterBounds[variable] ?:
|
return allTypeParameterBounds[variable]
|
||||||
throw IllegalArgumentException("TypeParameterDescriptor is not a type variable for constraint system: $variable")
|
?: throw IllegalArgumentException("TypeParameterDescriptor is not a type variable for constraint system: $variable")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isMyTypeVariable(typeParameter: TypeParameterDescriptor) =
|
private fun isMyTypeVariable(typeParameter: TypeParameterDescriptor) =
|
||||||
@@ -358,7 +367,12 @@ open class ConstraintSystemBuilderImpl(private val mode: Mode = ConstraintSystem
|
|||||||
private fun getMyTypeVariable(typeParameter: TypeParameterDescriptor): TypeVariable? =
|
private fun getMyTypeVariable(typeParameter: TypeParameterDescriptor): TypeVariable? =
|
||||||
allTypeParameterBounds.keys.find { it.freshTypeParameter == typeParameter }
|
allTypeParameterBounds.keys.find { it.freshTypeParameter == typeParameter }
|
||||||
|
|
||||||
private fun storeInitialConstraint(constraintKind: ConstraintKind, subType: KotlinType, superType: KotlinType, position: ConstraintPosition) {
|
private fun storeInitialConstraint(
|
||||||
|
constraintKind: ConstraintKind,
|
||||||
|
subType: KotlinType,
|
||||||
|
superType: KotlinType,
|
||||||
|
position: ConstraintPosition
|
||||||
|
) {
|
||||||
initialConstraints.add(Constraint(constraintKind, subType, superType, position))
|
initialConstraints.add(Constraint(constraintKind, subType, superType, position))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,11 +459,12 @@ internal fun createTypeForFunctionPlaceholder(
|
|||||||
val result = arrayListOf<KotlinType>()
|
val result = arrayListOf<KotlinType>()
|
||||||
(1..functionArgumentsSize).forEach { result.add(DONT_CARE) }
|
(1..functionArgumentsSize).forEach { result.add(DONT_CARE) }
|
||||||
result
|
result
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
functionPlaceholderTypeConstructor.argumentTypes
|
functionPlaceholderTypeConstructor.argumentTypes
|
||||||
}
|
}
|
||||||
val receiverType = if (isExtension) DONT_CARE else null
|
val receiverType = if (isExtension) DONT_CARE else null
|
||||||
return createFunctionType(functionPlaceholder.builtIns, Annotations.EMPTY, receiverType, newArgumentTypes, null, DONT_CARE,
|
return createFunctionType(
|
||||||
suspendFunction = expectedType.isSuspendFunctionType)
|
functionPlaceholder.builtIns, Annotations.EMPTY, receiverType, newArgumentTypes, null, DONT_CARE,
|
||||||
|
suspendFunction = expectedType.isSuspendFunctionType
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-4
@@ -130,8 +130,8 @@ internal class ConstraintSystemImpl(
|
|||||||
get() = allTypeParameterBounds.keys
|
get() = allTypeParameterBounds.keys
|
||||||
|
|
||||||
override fun getTypeBounds(typeVariable: TypeVariable): TypeBoundsImpl {
|
override fun getTypeBounds(typeVariable: TypeVariable): TypeBoundsImpl {
|
||||||
return allTypeParameterBounds[typeVariable] ?:
|
return allTypeParameterBounds[typeVariable]
|
||||||
throw IllegalArgumentException("TypeParameterDescriptor is not a type variable for constraint system: $typeVariable")
|
?: throw IllegalArgumentException("TypeParameterDescriptor is not a type variable for constraint system: $typeVariable")
|
||||||
}
|
}
|
||||||
|
|
||||||
override val resultingSubstitutor: TypeSubstitutor
|
override val resultingSubstitutor: TypeSubstitutor
|
||||||
@@ -159,8 +159,7 @@ internal class ConstraintSystemImpl(
|
|||||||
val substitutor = getSubstitutor(substituteOriginal = false) { ErrorUtils.createUninferredParameterType(it.originalTypeParameter) }
|
val substitutor = getSubstitutor(substituteOriginal = false) { ErrorUtils.createUninferredParameterType(it.originalTypeParameter) }
|
||||||
fun KotlinType.substitute(): KotlinType? = substitutor.substitute(this, Variance.INVARIANT)
|
fun KotlinType.substitute(): KotlinType? = substitutor.substitute(this, Variance.INVARIANT)
|
||||||
|
|
||||||
return initialConstraints.all {
|
return initialConstraints.all { (kind, subtype, superType, position) ->
|
||||||
(kind, subtype, superType, position) ->
|
|
||||||
val resultSubType = subtype.substitute()?.let {
|
val resultSubType = subtype.substitute()?.let {
|
||||||
// the call might be done via safe access, so we check for notNullable receiver type;
|
// the call might be done via safe access, so we check for notNullable receiver type;
|
||||||
// 'unsafe call' error is reported otherwise later
|
// 'unsafe call' error is reported otherwise later
|
||||||
|
|||||||
+13
-7
@@ -155,13 +155,16 @@ class CoroutineInferenceSupport(
|
|||||||
val approximationSubstitutor = object : DelegatedTypeSubstitution(constraintSystem.currentSubstitutor.substitution) {
|
val approximationSubstitutor = object : DelegatedTypeSubstitution(constraintSystem.currentSubstitutor.substitution) {
|
||||||
override fun approximateContravariantCapturedTypes() = true
|
override fun approximateContravariantCapturedTypes() = true
|
||||||
}
|
}
|
||||||
val approximatedLambdaType = approximationSubstitutor.buildSubstitutor().substitute(lambdaExpectedType, Variance.IN_VARIANCE) ?: return
|
val approximatedLambdaType =
|
||||||
|
approximationSubstitutor.buildSubstitutor().substitute(lambdaExpectedType, Variance.IN_VARIANCE) ?: return
|
||||||
|
|
||||||
val newExpectedType = createFunctionType(newReceiverType.builtIns, approximatedLambdaType.annotations, newReceiverType,
|
val newExpectedType = createFunctionType(
|
||||||
|
newReceiverType.builtIns, approximatedLambdaType.annotations, newReceiverType,
|
||||||
approximatedLambdaType.getValueParameterTypesFromFunctionType().map(TypeProjection::getType),
|
approximatedLambdaType.getValueParameterTypesFromFunctionType().map(TypeProjection::getType),
|
||||||
parameterNames = null, // TODO: parameterNames
|
parameterNames = null, // TODO: parameterNames
|
||||||
returnType = approximatedLambdaType.getReturnTypeFromFunctionType(),
|
returnType = approximatedLambdaType.getReturnTypeFromFunctionType(),
|
||||||
suspendFunction = true)
|
suspendFunction = true
|
||||||
|
)
|
||||||
|
|
||||||
if (hasUnknownFunctionParameter(newExpectedType)) return
|
if (hasUnknownFunctionParameter(newExpectedType)) return
|
||||||
|
|
||||||
@@ -169,7 +172,8 @@ class CoroutineInferenceSupport(
|
|||||||
|
|
||||||
// this trace shouldn't be committed
|
// this trace shouldn't be committed
|
||||||
val temporaryForCoroutine = TemporaryTraceAndCache.create(
|
val temporaryForCoroutine = TemporaryTraceAndCache.create(
|
||||||
context, "trace for type argument inference for coroutine", functionLiteral)
|
context, "trace for type argument inference for coroutine", functionLiteral
|
||||||
|
)
|
||||||
|
|
||||||
val newContext = context.replaceExpectedType(newExpectedType)
|
val newContext = context.replaceExpectedType(newExpectedType)
|
||||||
.replaceDataFlowInfo(context.candidateCall.dataFlowInfoForArguments.getInfo(valueArgument))
|
.replaceDataFlowInfo(context.candidateCall.dataFlowInfoForArguments.getInfo(valueArgument))
|
||||||
@@ -197,8 +201,7 @@ class CoroutineInferenceSupport(
|
|||||||
inferenceData.badCallHappened()
|
inferenceData.badCallHappened()
|
||||||
}
|
}
|
||||||
|
|
||||||
forceInferenceForArguments(context) {
|
forceInferenceForArguments(context) { valueArgument: ValueArgument, kotlinType: KotlinType ->
|
||||||
valueArgument: ValueArgument, kotlinType: KotlinType ->
|
|
||||||
val argumentMatch = resultingCall.getArgumentMapping(valueArgument) as? ArgumentMatch
|
val argumentMatch = resultingCall.getArgumentMapping(valueArgument) as? ArgumentMatch
|
||||||
?: return@forceInferenceForArguments
|
?: return@forceInferenceForArguments
|
||||||
|
|
||||||
@@ -237,7 +240,10 @@ class CoroutineInferenceSupport(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun forceInferenceForArguments(context: CallResolutionContext<*>, callback: (argument: ValueArgument, argumentType: KotlinType) -> Unit) {
|
private fun forceInferenceForArguments(
|
||||||
|
context: CallResolutionContext<*>,
|
||||||
|
callback: (argument: ValueArgument, argumentType: KotlinType) -> Unit
|
||||||
|
) {
|
||||||
val infoForArguments = context.dataFlowInfoForArguments
|
val infoForArguments = context.dataFlowInfoForArguments
|
||||||
val call = context.call
|
val call = context.call
|
||||||
val baseContext = context.replaceContextDependency(ContextDependency.INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE)
|
val baseContext = context.replaceContextDependency(ContextDependency.INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE)
|
||||||
|
|||||||
+2
-1
@@ -36,7 +36,8 @@ data class ConstraintContext(
|
|||||||
// see TypeBounds.Bound.derivedFrom
|
// see TypeBounds.Bound.derivedFrom
|
||||||
val derivedFrom: Set<TypeVariable>? = null,
|
val derivedFrom: Set<TypeVariable>? = null,
|
||||||
val initial: Boolean = false,
|
val initial: Boolean = false,
|
||||||
val initialReduction: Boolean = false)
|
val initialReduction: Boolean = false
|
||||||
|
)
|
||||||
|
|
||||||
fun ConstraintSystemBuilderImpl.incorporateBound(newBound: Bound) {
|
fun ConstraintSystemBuilderImpl.incorporateBound(newBound: Bound) {
|
||||||
val typeVariable = newBound.typeVariable
|
val typeVariable = newBound.typeVariable
|
||||||
|
|||||||
@@ -64,5 +64,4 @@ class ArgumentMatchImpl(override val valueParameter: ValueParameterDescriptor):
|
|||||||
}
|
}
|
||||||
|
|
||||||
//TODO: temporary hack until status.isSuccess is not always correct
|
//TODO: temporary hack until status.isSuccess is not always correct
|
||||||
fun ResolvedCall<*>.isReallySuccess(): Boolean
|
fun ResolvedCall<*>.isReallySuccess(): Boolean = status.isSuccess && !ErrorUtils.isError(resultingDescriptor)
|
||||||
= status.isSuccess && !ErrorUtils.isError(resultingDescriptor)
|
|
||||||
|
|||||||
+4
-2
@@ -28,9 +28,11 @@ private val KotlinType.immanentNullability: Nullability
|
|||||||
* This class describes an arbitrary object which has some value in data flow analysis.
|
* This class describes an arbitrary object which has some value in data flow analysis.
|
||||||
* In general case it's some r-value.
|
* In general case it's some r-value.
|
||||||
*/
|
*/
|
||||||
class DataFlowValue(val identifierInfo: IdentifierInfo,
|
class DataFlowValue(
|
||||||
|
val identifierInfo: IdentifierInfo,
|
||||||
val type: KotlinType,
|
val type: KotlinType,
|
||||||
val immanentNullability: Nullability = type.immanentNullability) {
|
val immanentNullability: Nullability = type.immanentNullability
|
||||||
|
) {
|
||||||
|
|
||||||
val kind: Kind get() = identifierInfo.kind
|
val kind: Kind get() = identifierInfo.kind
|
||||||
|
|
||||||
|
|||||||
+45
-15
@@ -82,8 +82,7 @@ internal class DelegatingDataFlowInfo private constructor(
|
|||||||
private fun getNullability(key: DataFlowValue, stableOnly: Boolean) =
|
private fun getNullability(key: DataFlowValue, stableOnly: Boolean) =
|
||||||
if (stableOnly && !key.isStable) {
|
if (stableOnly && !key.isStable) {
|
||||||
key.immanentNullability
|
key.immanentNullability
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
nullabilityInfo[key] ?: parent?.getCollectedNullability(key) ?: key.immanentNullability
|
nullabilityInfo[key] ?: parent?.getCollectedNullability(key) ?: key.immanentNullability
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,8 +109,10 @@ internal class DelegatingDataFlowInfo private constructor(
|
|||||||
val receiverType = identifierInfo.receiverType
|
val receiverType = identifierInfo.receiverType
|
||||||
if (identifierInfo.safe && receiverType != null) {
|
if (identifierInfo.safe && receiverType != null) {
|
||||||
val receiverValue = DataFlowValue(identifierInfo.receiverInfo, receiverType)
|
val receiverValue = DataFlowValue(identifierInfo.receiverInfo, receiverType)
|
||||||
putNullabilityAndTypeInfo(map, receiverValue, nullability,
|
putNullabilityAndTypeInfo(
|
||||||
languageVersionSettings, typeInfo, recordUnstable = recordUnstable)
|
map, receiverValue, nullability,
|
||||||
|
languageVersionSettings, typeInfo, recordUnstable = recordUnstable
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is IdentifierInfo.SafeCast -> {
|
is IdentifierInfo.SafeCast -> {
|
||||||
@@ -121,16 +122,20 @@ internal class DelegatingDataFlowInfo private constructor(
|
|||||||
languageVersionSettings.supportsFeature(LanguageFeature.SafeCastCheckBoundSmartCasts)) {
|
languageVersionSettings.supportsFeature(LanguageFeature.SafeCastCheckBoundSmartCasts)) {
|
||||||
|
|
||||||
val subjectValue = DataFlowValue(identifierInfo.subjectInfo, subjectType)
|
val subjectValue = DataFlowValue(identifierInfo.subjectInfo, subjectType)
|
||||||
putNullabilityAndTypeInfo(map, subjectValue, nullability,
|
putNullabilityAndTypeInfo(
|
||||||
languageVersionSettings, typeInfo, recordUnstable = false)
|
map, subjectValue, nullability,
|
||||||
|
languageVersionSettings, typeInfo, recordUnstable = false
|
||||||
|
)
|
||||||
if (subjectValue.isStable) {
|
if (subjectValue.isStable) {
|
||||||
typeInfo?.put(subjectValue, targetType)
|
typeInfo?.put(subjectValue, targetType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is IdentifierInfo.Variable -> identifierInfo.bound?.let {
|
is IdentifierInfo.Variable -> identifierInfo.bound?.let {
|
||||||
putNullabilityAndTypeInfo(map, it, nullability,
|
putNullabilityAndTypeInfo(
|
||||||
languageVersionSettings, typeInfo, recordUnstable = recordUnstable)
|
map, it, nullability,
|
||||||
|
languageVersionSettings, typeInfo, recordUnstable = recordUnstable
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -182,6 +187,7 @@ internal class DelegatingDataFlowInfo private constructor(
|
|||||||
else
|
else
|
||||||
TypeUtils.makeNotNullable(this)
|
TypeUtils.makeNotNullable(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this function to clear all data flow information about
|
* Call this function to clear all data flow information about
|
||||||
* the given data flow value.
|
* the given data flow value.
|
||||||
@@ -222,8 +228,20 @@ internal class DelegatingDataFlowInfo private constructor(
|
|||||||
|
|
||||||
val newTypeInfo = newTypeInfo()
|
val newTypeInfo = newTypeInfo()
|
||||||
var changed =
|
var changed =
|
||||||
putNullabilityAndTypeInfo(resultNullabilityInfo, a, nullabilityOfA.refine(nullabilityOfB), languageVersionSettings, newTypeInfo) or
|
putNullabilityAndTypeInfo(
|
||||||
putNullabilityAndTypeInfo(resultNullabilityInfo, b, nullabilityOfB.refine(nullabilityOfA), languageVersionSettings, newTypeInfo)
|
resultNullabilityInfo,
|
||||||
|
a,
|
||||||
|
nullabilityOfA.refine(nullabilityOfB),
|
||||||
|
languageVersionSettings,
|
||||||
|
newTypeInfo
|
||||||
|
) or
|
||||||
|
putNullabilityAndTypeInfo(
|
||||||
|
resultNullabilityInfo,
|
||||||
|
b,
|
||||||
|
nullabilityOfB.refine(nullabilityOfA),
|
||||||
|
languageVersionSettings,
|
||||||
|
newTypeInfo
|
||||||
|
)
|
||||||
|
|
||||||
// NB: == has no guarantees of type equality, see KT-11280 for the example
|
// NB: == has no guarantees of type equality, see KT-11280 for the example
|
||||||
if (identityEquals || !nullabilityOfA.canBeNonNull() || !nullabilityOfB.canBeNonNull()) {
|
if (identityEquals || !nullabilityOfA.canBeNonNull() || !nullabilityOfB.canBeNonNull()) {
|
||||||
@@ -252,8 +270,7 @@ internal class DelegatingDataFlowInfo private constructor(
|
|||||||
if (current is DelegatingDataFlowInfo) {
|
if (current is DelegatingDataFlowInfo) {
|
||||||
types.addAll(current.typeInfo.get(value))
|
types.addAll(current.typeInfo.get(value))
|
||||||
current = if (value == current.valueWithGivenTypeInfo) null else current.parent
|
current = if (value == current.valueWithGivenTypeInfo) null else current.parent
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
types.addAll(current.getCollectedTypes(value, languageVersionSettings))
|
types.addAll(current.getCollectedTypes(value, languageVersionSettings))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -271,8 +288,20 @@ internal class DelegatingDataFlowInfo private constructor(
|
|||||||
|
|
||||||
val newTypeInfo = newTypeInfo()
|
val newTypeInfo = newTypeInfo()
|
||||||
val changed =
|
val changed =
|
||||||
putNullabilityAndTypeInfo(resultNullabilityInfo, a, nullabilityOfA.refine(nullabilityOfB.invert()), languageVersionSettings, newTypeInfo) or
|
putNullabilityAndTypeInfo(
|
||||||
putNullabilityAndTypeInfo(resultNullabilityInfo, b, nullabilityOfB.refine(nullabilityOfA.invert()), languageVersionSettings, newTypeInfo)
|
resultNullabilityInfo,
|
||||||
|
a,
|
||||||
|
nullabilityOfA.refine(nullabilityOfB.invert()),
|
||||||
|
languageVersionSettings,
|
||||||
|
newTypeInfo
|
||||||
|
) or
|
||||||
|
putNullabilityAndTypeInfo(
|
||||||
|
resultNullabilityInfo,
|
||||||
|
b,
|
||||||
|
nullabilityOfB.refine(nullabilityOfA.invert()),
|
||||||
|
languageVersionSettings,
|
||||||
|
newTypeInfo
|
||||||
|
)
|
||||||
|
|
||||||
return if (changed) create(this, resultNullabilityInfo, if (newTypeInfo.isEmpty) EMPTY_TYPE_INFO else newTypeInfo) else this
|
return if (changed) create(this, resultNullabilityInfo, if (newTypeInfo.isEmpty) EMPTY_TYPE_INFO else newTypeInfo) else this
|
||||||
|
|
||||||
@@ -362,7 +391,8 @@ internal class DelegatingDataFlowInfo private constructor(
|
|||||||
|
|
||||||
fun newTypeInfo(): SetMultimap<DataFlowValue, KotlinType> = LinkedHashMultimap.create<DataFlowValue, KotlinType>()
|
fun newTypeInfo(): SetMultimap<DataFlowValue, KotlinType> = LinkedHashMultimap.create<DataFlowValue, KotlinType>()
|
||||||
|
|
||||||
private fun create(parent: DataFlowInfo?,
|
private fun create(
|
||||||
|
parent: DataFlowInfo?,
|
||||||
nullabilityInfo: Map<DataFlowValue, Nullability>,
|
nullabilityInfo: Map<DataFlowValue, Nullability>,
|
||||||
// NB: typeInfo must be mutable here!
|
// NB: typeInfo must be mutable here!
|
||||||
typeInfo: SetMultimap<DataFlowValue, KotlinType>,
|
typeInfo: SetMultimap<DataFlowValue, KotlinType>,
|
||||||
|
|||||||
@@ -81,8 +81,7 @@ class DynamicCallableDescriptors(storageManager: StorageManager, builtIns: Kotli
|
|||||||
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> {
|
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> {
|
||||||
return if (call.valueArgumentList == null && call.valueArguments.isEmpty()) {
|
return if (call.valueArgumentList == null && call.valueArguments.isEmpty()) {
|
||||||
listOf(createDynamicProperty(owner, name, call))
|
listOf(createDynamicProperty(owner, name, call))
|
||||||
}
|
} else listOf()
|
||||||
else listOf()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,8 +143,8 @@ class DynamicCallableDescriptors(storageManager: StorageManager, builtIns: Kotli
|
|||||||
return ReceiverParameterDescriptorImpl(owner, TransientReceiver(dynamicType))
|
return ReceiverParameterDescriptorImpl(owner, TransientReceiver(dynamicType))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createTypeParameters(owner: DeclarationDescriptor, call: Call): List<TypeParameterDescriptor> = call.typeArguments.indices.map {
|
private fun createTypeParameters(owner: DeclarationDescriptor, call: Call): List<TypeParameterDescriptor> =
|
||||||
index
|
call.typeArguments.indices.map { index
|
||||||
->
|
->
|
||||||
TypeParameterDescriptorImpl.createWithDefaultBound(
|
TypeParameterDescriptorImpl.createWithDefaultBound(
|
||||||
owner,
|
owner,
|
||||||
@@ -163,7 +162,8 @@ class DynamicCallableDescriptors(storageManager: StorageManager, builtIns: Kotli
|
|||||||
fun addParameter(arg: ValueArgument, outType: KotlinType, varargElementType: KotlinType?) {
|
fun addParameter(arg: ValueArgument, outType: KotlinType, varargElementType: KotlinType?) {
|
||||||
val index = parameters.size
|
val index = parameters.size
|
||||||
|
|
||||||
parameters.add(ValueParameterDescriptorImpl(
|
parameters.add(
|
||||||
|
ValueParameterDescriptorImpl(
|
||||||
owner,
|
owner,
|
||||||
null,
|
null,
|
||||||
index,
|
index,
|
||||||
@@ -175,7 +175,8 @@ class DynamicCallableDescriptors(storageManager: StorageManager, builtIns: Kotli
|
|||||||
/* isNoinline = */ false,
|
/* isNoinline = */ false,
|
||||||
varargElementType,
|
varargElementType,
|
||||||
SourceElement.NO_SOURCE
|
SourceElement.NO_SOURCE
|
||||||
))
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFunctionType(funLiteralExpr: KtLambdaExpression): KotlinType {
|
fun getFunctionType(funLiteralExpr: KtLambdaExpression): KotlinType {
|
||||||
|
|||||||
+16
-11
@@ -85,19 +85,26 @@ class KotlinResolutionCallbacksImpl(
|
|||||||
val outerCallContext = psiCallArgument.outerCallContext
|
val outerCallContext = psiCallArgument.outerCallContext
|
||||||
|
|
||||||
fun createCallArgument(ktExpression: KtExpression, typeInfo: KotlinTypeInfo) =
|
fun createCallArgument(ktExpression: KtExpression, typeInfo: KotlinTypeInfo) =
|
||||||
createSimplePSICallArgument(trace.bindingContext, outerCallContext.statementFilter, outerCallContext.scope.ownerDescriptor,
|
createSimplePSICallArgument(
|
||||||
CallMaker.makeExternalValueArgument(ktExpression), DataFlowInfo.EMPTY, typeInfo, languageVersionSettings)
|
trace.bindingContext, outerCallContext.statementFilter, outerCallContext.scope.ownerDescriptor,
|
||||||
|
CallMaker.makeExternalValueArgument(ktExpression), DataFlowInfo.EMPTY, typeInfo, languageVersionSettings
|
||||||
|
)
|
||||||
|
|
||||||
val lambdaInfo = LambdaInfo(expectedReturnType ?: TypeUtils.NO_EXPECTED_TYPE,
|
val lambdaInfo = LambdaInfo(
|
||||||
if (expectedReturnType == null) ContextDependency.DEPENDENT else ContextDependency.INDEPENDENT)
|
expectedReturnType ?: TypeUtils.NO_EXPECTED_TYPE,
|
||||||
|
if (expectedReturnType == null) ContextDependency.DEPENDENT else ContextDependency.INDEPENDENT
|
||||||
|
)
|
||||||
|
|
||||||
trace.record(BindingContext.NEW_INFERENCE_LAMBDA_INFO, psiCallArgument.ktFunction, lambdaInfo)
|
trace.record(BindingContext.NEW_INFERENCE_LAMBDA_INFO, psiCallArgument.ktFunction, lambdaInfo)
|
||||||
|
|
||||||
val builtIns = outerCallContext.scope.ownerDescriptor.builtIns
|
val builtIns = outerCallContext.scope.ownerDescriptor.builtIns
|
||||||
val expectedType = createFunctionType(builtIns, Annotations.EMPTY, receiverType, parameters, null,
|
val expectedType = createFunctionType(
|
||||||
lambdaInfo.expectedType, isSuspend)
|
builtIns, Annotations.EMPTY, receiverType, parameters, null,
|
||||||
|
lambdaInfo.expectedType, isSuspend
|
||||||
|
)
|
||||||
|
|
||||||
val approximatesExpectedType = typeApproximator.approximateToSubType(expectedType, TypeApproximatorConfiguration.LocalDeclaration) ?: expectedType
|
val approximatesExpectedType =
|
||||||
|
typeApproximator.approximateToSubType(expectedType, TypeApproximatorConfiguration.LocalDeclaration) ?: expectedType
|
||||||
|
|
||||||
val actualContext = outerCallContext
|
val actualContext = outerCallContext
|
||||||
.replaceBindingTrace(trace)
|
.replaceBindingTrace(trace)
|
||||||
@@ -116,8 +123,7 @@ class KotlinResolutionCallbacksImpl(
|
|||||||
returnedExpression,
|
returnedExpression,
|
||||||
typeInfo ?: throw AssertionError("typeInfo should be non-null for return with expression")
|
typeInfo ?: throw AssertionError("typeInfo should be non-null for return with expression")
|
||||||
)
|
)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
hasReturnWithoutExpression = true
|
hasReturnWithoutExpression = true
|
||||||
EmptyLabeledReturn(expression, builtIns)
|
EmptyLabeledReturn(expression, builtIns)
|
||||||
}
|
}
|
||||||
@@ -141,8 +147,7 @@ class KotlinResolutionCallbacksImpl(
|
|||||||
val lastExpression: KtExpression?
|
val lastExpression: KtExpression?
|
||||||
if (psiCallArgument is LambdaKotlinCallArgumentImpl) {
|
if (psiCallArgument is LambdaKotlinCallArgumentImpl) {
|
||||||
lastExpression = psiCallArgument.ktLambdaExpression.bodyExpression?.statements?.lastOrNull()
|
lastExpression = psiCallArgument.ktLambdaExpression.bodyExpression?.statements?.lastOrNull()
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
lastExpression = (psiCallArgument as FunctionExpressionImpl).ktFunction.bodyExpression?.lastBlockStatementOrThis()
|
lastExpression = (psiCallArgument as FunctionExpressionImpl).ktFunction.bodyExpression?.lastBlockStatementOrThis()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+56
-19
@@ -86,7 +86,13 @@ class NewResolutionOldInference(
|
|||||||
scopeTower: ImplicitScopeTower, explicitReceiver: DetailedReceiver?, context: BasicCallResolutionContext
|
scopeTower: ImplicitScopeTower, explicitReceiver: DetailedReceiver?, context: BasicCallResolutionContext
|
||||||
): ScopeTowerProcessor<MyCandidate> {
|
): ScopeTowerProcessor<MyCandidate> {
|
||||||
val functionFactory = outer.CandidateFactoryImpl(name, context, tracing)
|
val functionFactory = outer.CandidateFactoryImpl(name, context, tracing)
|
||||||
return createFunctionProcessor(scopeTower, name, functionFactory, outer.CandidateFactoryProviderForInvokeImpl(functionFactory), explicitReceiver)
|
return createFunctionProcessor(
|
||||||
|
scopeTower,
|
||||||
|
name,
|
||||||
|
functionFactory,
|
||||||
|
outer.CandidateFactoryProviderForInvokeImpl(functionFactory),
|
||||||
|
explicitReceiver
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +131,12 @@ class NewResolutionOldInference(
|
|||||||
"Call should be CallForImplicitInvoke, but it is: ${context.call}"
|
"Call should be CallForImplicitInvoke, but it is: ${context.call}"
|
||||||
}
|
}
|
||||||
return createProcessorWithReceiverValueOrEmpty(explicitReceiver) {
|
return createProcessorWithReceiverValueOrEmpty(explicitReceiver) {
|
||||||
createCallTowerProcessorForExplicitInvoke(scopeTower, functionFactory, context.transformToReceiverWithSmartCastInfo(call.dispatchReceiver), it)
|
createCallTowerProcessorForExplicitInvoke(
|
||||||
|
scopeTower,
|
||||||
|
functionFactory,
|
||||||
|
context.transformToReceiverWithSmartCastInfo(call.dispatchReceiver),
|
||||||
|
it
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,8 +161,7 @@ class NewResolutionOldInference(
|
|||||||
val explicitReceiver = context.call.explicitReceiver
|
val explicitReceiver = context.call.explicitReceiver
|
||||||
val detailedReceiver = if (explicitReceiver is QualifierReceiver?) {
|
val detailedReceiver = if (explicitReceiver is QualifierReceiver?) {
|
||||||
explicitReceiver
|
explicitReceiver
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
context.transformToReceiverWithSmartCastInfo(explicitReceiver as ReceiverValue)
|
context.transformToReceiverWithSmartCastInfo(explicitReceiver as ReceiverValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,15 +181,22 @@ class NewResolutionOldInference(
|
|||||||
return allCandidatesResult(towerResolver.collectAllCandidates(scopeTower, processor, nameToResolve))
|
return allCandidatesResult(towerResolver.collectAllCandidates(scopeTower, processor, nameToResolve))
|
||||||
}
|
}
|
||||||
|
|
||||||
var candidates = towerResolver.runResolve(scopeTower, processor, useOrder = kind != ResolutionKind.CallableReference, name = nameToResolve)
|
var candidates =
|
||||||
|
towerResolver.runResolve(scopeTower, processor, useOrder = kind != ResolutionKind.CallableReference, name = nameToResolve)
|
||||||
|
|
||||||
// Temporary hack to resolve 'rem' as 'mod' if the first is do not present
|
// Temporary hack to resolve 'rem' as 'mod' if the first is do not present
|
||||||
val emptyOrInapplicableCandidates = candidates.isEmpty() ||
|
val emptyOrInapplicableCandidates = candidates.isEmpty() ||
|
||||||
candidates.all { it.resultingApplicability.isInapplicable }
|
candidates.all { it.resultingApplicability.isInapplicable }
|
||||||
if (isBinaryRemOperator && shouldUseOperatorRem && emptyOrInapplicableCandidates) {
|
if (isBinaryRemOperator && shouldUseOperatorRem && emptyOrInapplicableCandidates) {
|
||||||
val deprecatedName = OperatorConventions.REM_TO_MOD_OPERATION_NAMES[name]
|
val deprecatedName = OperatorConventions.REM_TO_MOD_OPERATION_NAMES[name]
|
||||||
val processorForDeprecatedName = kind.createTowerProcessor(this, deprecatedName!!, tracing, scopeTower, detailedReceiver, context)
|
val processorForDeprecatedName =
|
||||||
candidates = towerResolver.runResolve(scopeTower, processorForDeprecatedName, useOrder = kind != ResolutionKind.CallableReference, name = deprecatedName)
|
kind.createTowerProcessor(this, deprecatedName!!, tracing, scopeTower, detailedReceiver, context)
|
||||||
|
candidates = towerResolver.runResolve(
|
||||||
|
scopeTower,
|
||||||
|
processorForDeprecatedName,
|
||||||
|
useOrder = kind != ResolutionKind.CallableReference,
|
||||||
|
name = deprecatedName
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (candidates.isEmpty()) {
|
if (candidates.isEmpty()) {
|
||||||
@@ -219,19 +236,23 @@ class NewResolutionOldInference(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (basicCallContext.collectAllCandidates) {
|
if (basicCallContext.collectAllCandidates) {
|
||||||
val allCandidates = towerResolver.runWithEmptyTowerData(KnownResultProcessor(resolvedCandidates),
|
val allCandidates = towerResolver.runWithEmptyTowerData(
|
||||||
TowerResolver.AllCandidatesCollector(), useOrder = false)
|
KnownResultProcessor(resolvedCandidates),
|
||||||
|
TowerResolver.AllCandidatesCollector(), useOrder = false
|
||||||
|
)
|
||||||
return allCandidatesResult(allCandidates)
|
return allCandidatesResult(allCandidates)
|
||||||
}
|
}
|
||||||
|
|
||||||
val processedCandidates = towerResolver.runWithEmptyTowerData(KnownResultProcessor(resolvedCandidates),
|
val processedCandidates = towerResolver.runWithEmptyTowerData(
|
||||||
TowerResolver.SuccessfulResultCollector(), useOrder = true)
|
KnownResultProcessor(resolvedCandidates),
|
||||||
|
TowerResolver.SuccessfulResultCollector(), useOrder = true
|
||||||
|
)
|
||||||
|
|
||||||
return convertToOverloadResults(processedCandidates, tracing, basicCallContext, languageVersionSettings)
|
return convertToOverloadResults(processedCandidates, tracing, basicCallContext, languageVersionSettings)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <D: CallableDescriptor> allCandidatesResult(allCandidates: Collection<MyCandidate>)
|
private fun <D : CallableDescriptor> allCandidatesResult(allCandidates: Collection<MyCandidate>) =
|
||||||
= OverloadResolutionResultsImpl.nameNotFound<D>().apply {
|
OverloadResolutionResultsImpl.nameNotFound<D>().apply {
|
||||||
this.allCandidates = allCandidates.map { it.resolvedCall as MutableResolvedCall<D> }
|
this.allCandidates = allCandidates.map { it.resolvedCall as MutableResolvedCall<D> }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,8 +281,17 @@ class NewResolutionOldInference(
|
|||||||
if (resolvedCall.status.possibleTransformToSuccess()) {
|
if (resolvedCall.status.possibleTransformToSuccess()) {
|
||||||
for (error in diagnostics) {
|
for (error in diagnostics) {
|
||||||
when (error) {
|
when (error) {
|
||||||
is UnsupportedInnerClassCall -> resolvedCall.trace.report(Errors.UNSUPPORTED.on(resolvedCall.call.callElement, error.message))
|
is UnsupportedInnerClassCall -> resolvedCall.trace.report(
|
||||||
is NestedClassViaInstanceReference -> tracing.nestedClassAccessViaInstanceReference(resolvedCall.trace, error.classDescriptor, resolvedCall.explicitReceiverKind)
|
Errors.UNSUPPORTED.on(
|
||||||
|
resolvedCall.call.callElement,
|
||||||
|
error.message
|
||||||
|
)
|
||||||
|
)
|
||||||
|
is NestedClassViaInstanceReference -> tracing.nestedClassAccessViaInstanceReference(
|
||||||
|
resolvedCall.trace,
|
||||||
|
error.classDescriptor,
|
||||||
|
resolvedCall.explicitReceiverKind
|
||||||
|
)
|
||||||
is ErrorDescriptorDiagnostic -> {
|
is ErrorDescriptorDiagnostic -> {
|
||||||
// todo
|
// todo
|
||||||
// return@map null
|
// return@map null
|
||||||
@@ -445,7 +475,11 @@ class NewResolutionOldInference(
|
|||||||
val newCall = CallTransformer.stripCallArguments(functionContext.basicCallContext.call).let {
|
val newCall = CallTransformer.stripCallArguments(functionContext.basicCallContext.call).let {
|
||||||
if (stripExplicitReceiver) CallTransformer.stripReceiver(it) else it
|
if (stripExplicitReceiver) CallTransformer.stripReceiver(it) else it
|
||||||
}
|
}
|
||||||
return CandidateFactoryImpl(functionContext.name, functionContext.basicCallContext.replaceCall(newCall), functionContext.tracing)
|
return CandidateFactoryImpl(
|
||||||
|
functionContext.name,
|
||||||
|
functionContext.basicCallContext.replaceCall(newCall),
|
||||||
|
functionContext.tracing
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun factoryForInvoke(
|
override fun factoryForInvoke(
|
||||||
@@ -467,15 +501,18 @@ class NewResolutionOldInference(
|
|||||||
return null // todo: create special check that there is no invoke on variable
|
return null // todo: create special check that there is no invoke on variable
|
||||||
}
|
}
|
||||||
val basicCallContext = functionContext.basicCallContext
|
val basicCallContext = functionContext.basicCallContext
|
||||||
val variableReceiver = ExpressionReceiver.create(calleeExpression!!,
|
val variableReceiver = ExpressionReceiver.create(
|
||||||
|
calleeExpression!!,
|
||||||
variableType,
|
variableType,
|
||||||
basicCallContext.trace.bindingContext)
|
basicCallContext.trace.bindingContext
|
||||||
|
)
|
||||||
// used for smartCasts, see: DataFlowValueFactory.getIdForSimpleNameExpression
|
// used for smartCasts, see: DataFlowValueFactory.getIdForSimpleNameExpression
|
||||||
functionContext.tracing.bindReference(variable.resolvedCall.trace, variable.resolvedCall)
|
functionContext.tracing.bindReference(variable.resolvedCall.trace, variable.resolvedCall)
|
||||||
// todo hacks
|
// todo hacks
|
||||||
val functionCall = CallTransformer.CallForImplicitInvoke(
|
val functionCall = CallTransformer.CallForImplicitInvoke(
|
||||||
basicCallContext.call.explicitReceiver?.takeIf { useExplicitReceiver },
|
basicCallContext.call.explicitReceiver?.takeIf { useExplicitReceiver },
|
||||||
variableReceiver, basicCallContext.call, true)
|
variableReceiver, basicCallContext.call, true
|
||||||
|
)
|
||||||
val tracingForInvoke = TracingStrategyForInvoke(calleeExpression, functionCall, variableReceiver.type)
|
val tracingForInvoke = TracingStrategyForInvoke(calleeExpression, functionCall, variableReceiver.type)
|
||||||
val basicCallResolutionContext = basicCallContext.replaceBindingTrace(variable.resolvedCall.trace)
|
val basicCallResolutionContext = basicCallContext.replaceBindingTrace(variable.resolvedCall.trace)
|
||||||
.replaceCall(functionCall)
|
.replaceCall(functionCall)
|
||||||
|
|||||||
@@ -93,7 +93,8 @@ class PSICallResolver(
|
|||||||
|
|
||||||
val expectedType = calculateExpectedType(context)
|
val expectedType = calculateExpectedType(context)
|
||||||
var result = kotlinCallResolver.resolveCall(
|
var result = kotlinCallResolver.resolveCall(
|
||||||
scopeTower, resolutionCallbacks, kotlinCall, expectedType, factoryProviderForInvoke, context.collectAllCandidates)
|
scopeTower, resolutionCallbacks, kotlinCall, expectedType, factoryProviderForInvoke, context.collectAllCandidates
|
||||||
|
)
|
||||||
|
|
||||||
val shouldUseOperatorRem = languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem)
|
val shouldUseOperatorRem = languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem)
|
||||||
if (isBinaryRemOperator && shouldUseOperatorRem && (result.isEmpty() || result.areAllInapplicable())) {
|
if (isBinaryRemOperator && shouldUseOperatorRem && (result.isEmpty() || result.areAllInapplicable())) {
|
||||||
@@ -115,18 +116,22 @@ class PSICallResolver(
|
|||||||
): OverloadResolutionResults<D> {
|
): OverloadResolutionResults<D> {
|
||||||
val dispatchReceiver = resolutionCandidates.firstNotNullResult { it.dispatchReceiver }
|
val dispatchReceiver = resolutionCandidates.firstNotNullResult { it.dispatchReceiver }
|
||||||
|
|
||||||
val kotlinCall = toKotlinCall(context, KotlinCallKind.FUNCTION, context.call, GIVEN_CANDIDATES_NAME, tracingStrategy, dispatchReceiver)
|
val kotlinCall =
|
||||||
|
toKotlinCall(context, KotlinCallKind.FUNCTION, context.call, GIVEN_CANDIDATES_NAME, tracingStrategy, dispatchReceiver)
|
||||||
val scopeTower = ASTScopeTower(context)
|
val scopeTower = ASTScopeTower(context)
|
||||||
val resolutionCallbacks = createResolutionCallbacks(context)
|
val resolutionCallbacks = createResolutionCallbacks(context)
|
||||||
|
|
||||||
val givenCandidates = resolutionCandidates.map {
|
val givenCandidates = resolutionCandidates.map {
|
||||||
GivenCandidate(it.descriptor as FunctionDescriptor,
|
GivenCandidate(
|
||||||
|
it.descriptor as FunctionDescriptor,
|
||||||
it.dispatchReceiver?.let { context.transformToReceiverWithSmartCastInfo(it) },
|
it.dispatchReceiver?.let { context.transformToReceiverWithSmartCastInfo(it) },
|
||||||
it.knownTypeParametersResultingSubstitutor)
|
it.knownTypeParametersResultingSubstitutor
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = kotlinCallResolver.resolveGivenCandidates(
|
val result = kotlinCallResolver.resolveGivenCandidates(
|
||||||
scopeTower, resolutionCallbacks, kotlinCall, calculateExpectedType(context), givenCandidates, context.collectAllCandidates)
|
scopeTower, resolutionCallbacks, kotlinCall, calculateExpectedType(context), givenCandidates, context.collectAllCandidates
|
||||||
|
)
|
||||||
return convertToOverloadResolutionResults(context, result, tracingStrategy)
|
return convertToOverloadResolutionResults(context, result, tracingStrategy)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -143,8 +148,10 @@ class PSICallResolver(
|
|||||||
val deprecatedName = OperatorConventions.REM_TO_MOD_OPERATION_NAMES[remOperatorName]!!
|
val deprecatedName = OperatorConventions.REM_TO_MOD_OPERATION_NAMES[remOperatorName]!!
|
||||||
val callWithDeprecatedName = toKotlinCall(context, resolutionKind.kotlinCallKind, context.call, deprecatedName, tracingStrategy)
|
val callWithDeprecatedName = toKotlinCall(context, resolutionKind.kotlinCallKind, context.call, deprecatedName, tracingStrategy)
|
||||||
val refinedProviderForInvokeFactory = FactoryProviderForInvoke(context, scopeTower, callWithDeprecatedName)
|
val refinedProviderForInvokeFactory = FactoryProviderForInvoke(context, scopeTower, callWithDeprecatedName)
|
||||||
return kotlinCallResolver.resolveCall(scopeTower, resolutionCallbacks, callWithDeprecatedName, expectedType,
|
return kotlinCallResolver.resolveCall(
|
||||||
refinedProviderForInvokeFactory, context.collectAllCandidates)
|
scopeTower, resolutionCallbacks, callWithDeprecatedName, expectedType,
|
||||||
|
refinedProviderForInvokeFactory, context.collectAllCandidates
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refineNameForRemOperator(isBinaryRemOperator: Boolean, name: Name): Name {
|
private fun refineNameForRemOperator(isBinaryRemOperator: Boolean, name: Name): Name {
|
||||||
@@ -153,9 +160,11 @@ class PSICallResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createResolutionCallbacks(context: BasicCallResolutionContext) =
|
private fun createResolutionCallbacks(context: BasicCallResolutionContext) =
|
||||||
KotlinResolutionCallbacksImpl(context, expressionTypingServices, typeApproximator,
|
KotlinResolutionCallbacksImpl(
|
||||||
|
context, expressionTypingServices, typeApproximator,
|
||||||
argumentTypeResolver, languageVersionSettings, kotlinToResolvedCallTransformer,
|
argumentTypeResolver, languageVersionSettings, kotlinToResolvedCallTransformer,
|
||||||
constantExpressionEvaluator)
|
constantExpressionEvaluator
|
||||||
|
)
|
||||||
|
|
||||||
private fun calculateExpectedType(context: BasicCallResolutionContext): UnwrappedType? {
|
private fun calculateExpectedType(context: BasicCallResolutionContext): UnwrappedType? {
|
||||||
val expectedType = context.expectedType.unwrap()
|
val expectedType = context.expectedType.unwrap()
|
||||||
@@ -165,8 +174,7 @@ class PSICallResolver(
|
|||||||
"Should have no expected type, got: $expectedType"
|
"Should have no expected type, got: $expectedType"
|
||||||
}
|
}
|
||||||
null
|
null
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (expectedType.isError) TypeUtils.NO_EXPECTED_TYPE else expectedType
|
if (expectedType.isError) TypeUtils.NO_EXPECTED_TYPE else expectedType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,28 +205,26 @@ class PSICallResolver(
|
|||||||
if (it.candidates.areAllFailed()) {
|
if (it.candidates.areAllFailed()) {
|
||||||
tracingStrategy.noneApplicable(trace, resolvedCalls)
|
tracingStrategy.noneApplicable(trace, resolvedCalls)
|
||||||
tracingStrategy.recordAmbiguity(trace, resolvedCalls)
|
tracingStrategy.recordAmbiguity(trace, resolvedCalls)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
tracingStrategy.recordAmbiguity(trace, resolvedCalls)
|
tracingStrategy.recordAmbiguity(trace, resolvedCalls)
|
||||||
if (resolvedCalls.first().status == ResolutionStatus.INCOMPLETE_TYPE_INFERENCE) {
|
if (resolvedCalls.first().status == ResolutionStatus.INCOMPLETE_TYPE_INFERENCE) {
|
||||||
tracingStrategy.cannotCompleteResolve(trace, resolvedCalls)
|
tracingStrategy.cannotCompleteResolve(trace, resolvedCalls)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
tracingStrategy.ambiguity(trace, resolvedCalls)
|
tracingStrategy.ambiguity(trace, resolvedCalls)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ManyCandidates(resolvedCalls)
|
return ManyCandidates(resolvedCalls)
|
||||||
}
|
}
|
||||||
|
|
||||||
val isInapplicableReceiver = getResultApplicability(result.diagnostics) == ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER
|
val isInapplicableReceiver =
|
||||||
|
getResultApplicability(result.diagnostics) == ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER
|
||||||
|
|
||||||
val resolvedCall = if (isInapplicableReceiver) {
|
val resolvedCall = if (isInapplicableReceiver) {
|
||||||
val singleCandidate = result.resultCallAtom ?: error("Should be not null for result: $result")
|
val singleCandidate = result.resultCallAtom ?: error("Should be not null for result: $result")
|
||||||
kotlinToResolvedCallTransformer.onlyTransform<D>(singleCandidate, result.diagnostics).also {
|
kotlinToResolvedCallTransformer.onlyTransform<D>(singleCandidate, result.diagnostics).also {
|
||||||
tracingStrategy.unresolvedReferenceWrongReceiver(trace, listOf(it))
|
tracingStrategy.unresolvedReferenceWrongReceiver(trace, listOf(it))
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
kotlinToResolvedCallTransformer.transformAndReport<D>(result, context)
|
kotlinToResolvedCallTransformer.transformAndReport<D>(result, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,7 +291,14 @@ class PSICallResolver(
|
|||||||
for (candidate in errorCandidates) {
|
for (candidate in errorCandidates) {
|
||||||
if (candidate is ErrorCandidate.Classifier) {
|
if (candidate is ErrorCandidate.Classifier) {
|
||||||
context.trace.record(BindingContext.REFERENCE_TARGET, reference, candidate.descriptor)
|
context.trace.record(BindingContext.REFERENCE_TARGET, reference, candidate.descriptor)
|
||||||
context.trace.report(Errors.RESOLUTION_TO_CLASSIFIER.on(reference, candidate.descriptor, candidate.kind, candidate.errorMessage))
|
context.trace.report(
|
||||||
|
Errors.RESOLUTION_TO_CLASSIFIER.on(
|
||||||
|
reference,
|
||||||
|
candidate.descriptor,
|
||||||
|
candidate.kind,
|
||||||
|
candidate.errorMessage
|
||||||
|
)
|
||||||
|
)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -297,7 +310,8 @@ class PSICallResolver(
|
|||||||
val context: BasicCallResolutionContext
|
val context: BasicCallResolutionContext
|
||||||
) : ImplicitScopeTower {
|
) : ImplicitScopeTower {
|
||||||
// todo may be for invoke for case variable + invoke we should create separate dynamicScope(by newCall for invoke)
|
// todo may be for invoke for case variable + invoke we should create separate dynamicScope(by newCall for invoke)
|
||||||
override val dynamicScope: MemberScope = dynamicCallableDescriptors.createDynamicDescriptorScope(context.call, context.scope.ownerDescriptor)
|
override val dynamicScope: MemberScope =
|
||||||
|
dynamicCallableDescriptors.createDynamicDescriptorScope(context.call, context.scope.ownerDescriptor)
|
||||||
// same for location
|
// same for location
|
||||||
override val location: LookupLocation = context.call.createLookupLocation()
|
override val location: LookupLocation = context.call.createLookupLocation()
|
||||||
|
|
||||||
@@ -350,8 +364,7 @@ class PSICallResolver(
|
|||||||
val explicitReceiver = kotlinCall.explicitReceiver
|
val explicitReceiver = kotlinCall.explicitReceiver
|
||||||
val callForInvoke = if (useExplicitReceiver && explicitReceiver != null) {
|
val callForInvoke = if (useExplicitReceiver && explicitReceiver != null) {
|
||||||
PSIKotlinCallForInvoke(kotlinCall, variable, explicitReceiver, variableCallArgument)
|
PSIKotlinCallForInvoke(kotlinCall, variable, explicitReceiver, variableCallArgument)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
PSIKotlinCallForInvoke(kotlinCall, variable, variableCallArgument, null)
|
PSIKotlinCallForInvoke(kotlinCall, variable, variableCallArgument, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,22 +382,32 @@ class PSICallResolver(
|
|||||||
variable.forceResolution()
|
variable.forceResolution()
|
||||||
val variableReceiver = createReceiverValueWithSmartCastInfo(variable)
|
val variableReceiver = createReceiverValueWithSmartCastInfo(variable)
|
||||||
if (variableReceiver.possibleTypes.isNotEmpty()) {
|
if (variableReceiver.possibleTypes.isNotEmpty()) {
|
||||||
return ReceiverExpressionKotlinCallArgument(createReceiverValueWithSmartCastInfo(variable), isVariableReceiverForInvoke = true)
|
return ReceiverExpressionKotlinCallArgument(
|
||||||
|
createReceiverValueWithSmartCastInfo(variable),
|
||||||
|
isVariableReceiverForInvoke = true
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val psiKotlinCall = variable.resolvedCall.atom.psiKotlinCall
|
val psiKotlinCall = variable.resolvedCall.atom.psiKotlinCall
|
||||||
|
|
||||||
val variableResult = CallResolutionResult(CallResolutionResult.Type.PARTIAL, variable.resolvedCall, listOf(), variable.getSystem().asReadOnlyStorage())
|
val variableResult = CallResolutionResult(
|
||||||
return SubKotlinCallArgumentImpl(CallMaker.makeExternalValueArgument((variableReceiver.receiverValue as ExpressionReceiver).expression),
|
CallResolutionResult.Type.PARTIAL,
|
||||||
|
variable.resolvedCall,
|
||||||
|
listOf(),
|
||||||
|
variable.getSystem().asReadOnlyStorage()
|
||||||
|
)
|
||||||
|
return SubKotlinCallArgumentImpl(
|
||||||
|
CallMaker.makeExternalValueArgument((variableReceiver.receiverValue as ExpressionReceiver).expression),
|
||||||
psiKotlinCall.resultDataFlowInfo, psiKotlinCall.resultDataFlowInfo, variableReceiver,
|
psiKotlinCall.resultDataFlowInfo, psiKotlinCall.resultDataFlowInfo, variableReceiver,
|
||||||
variableResult)
|
variableResult
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: decrease hacks count
|
// todo: decrease hacks count
|
||||||
private fun createReceiverValueWithSmartCastInfo(variable: KotlinResolutionCandidate): ReceiverValueWithSmartCastInfo {
|
private fun createReceiverValueWithSmartCastInfo(variable: KotlinResolutionCandidate): ReceiverValueWithSmartCastInfo {
|
||||||
val callForVariable = variable.resolvedCall.atom as PSIKotlinCallForVariable
|
val callForVariable = variable.resolvedCall.atom as PSIKotlinCallForVariable
|
||||||
val calleeExpression = callForVariable.baseCall.psiCall.calleeExpression as? KtReferenceExpression ?:
|
val calleeExpression = callForVariable.baseCall.psiCall.calleeExpression as? KtReferenceExpression
|
||||||
error("Unexpected call : ${callForVariable.baseCall.psiCall}")
|
?: error("Unexpected call : ${callForVariable.baseCall.psiCall}")
|
||||||
|
|
||||||
val temporaryTrace = TemporaryBindingTrace.create(context.trace, "Context for resolve candidate")
|
val temporaryTrace = TemporaryBindingTrace.create(context.trace, "Context for resolve candidate")
|
||||||
|
|
||||||
@@ -392,7 +415,8 @@ class PSICallResolver(
|
|||||||
val variableReceiver = ExpressionReceiver.create(calleeExpression, type, temporaryTrace.bindingContext)
|
val variableReceiver = ExpressionReceiver.create(calleeExpression, type, temporaryTrace.bindingContext)
|
||||||
|
|
||||||
temporaryTrace.record(BindingContext.REFERENCE_TARGET, calleeExpression, variable.resolvedCall.candidateDescriptor)
|
temporaryTrace.record(BindingContext.REFERENCE_TARGET, calleeExpression, variable.resolvedCall.candidateDescriptor)
|
||||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(variableReceiver, temporaryTrace.bindingContext, context.scope.ownerDescriptor)
|
val dataFlowValue =
|
||||||
|
DataFlowValueFactory.createDataFlowValue(variableReceiver, temporaryTrace.bindingContext, context.scope.ownerDescriptor)
|
||||||
return ReceiverValueWithSmartCastInfo(
|
return ReceiverValueWithSmartCastInfo(
|
||||||
variableReceiver,
|
variableReceiver,
|
||||||
context.dataFlowInfo.getCollectedTypes(dataFlowValue, context.languageVersionSettings),
|
context.dataFlowInfo.getCollectedTypes(dataFlowValue, context.languageVersionSettings),
|
||||||
@@ -410,13 +434,13 @@ class PSICallResolver(
|
|||||||
tracingStrategy: TracingStrategy,
|
tracingStrategy: TracingStrategy,
|
||||||
forcedExplicitReceiver: Receiver? = null
|
forcedExplicitReceiver: Receiver? = null
|
||||||
): PSIKotlinCallImpl {
|
): PSIKotlinCallImpl {
|
||||||
val resolvedExplicitReceiver = resolveExplicitReceiver(context, forcedExplicitReceiver?: oldCall.explicitReceiver, oldCall.isSafeCall())
|
val resolvedExplicitReceiver =
|
||||||
|
resolveExplicitReceiver(context, forcedExplicitReceiver ?: oldCall.explicitReceiver, oldCall.isSafeCall())
|
||||||
val resolvedTypeArguments = resolveTypeArguments(context, oldCall.typeArguments)
|
val resolvedTypeArguments = resolveTypeArguments(context, oldCall.typeArguments)
|
||||||
|
|
||||||
val argumentsInParenthesis = if (oldCall.callType != Call.CallType.ARRAY_SET_METHOD && oldCall.functionLiteralArguments.isEmpty()) {
|
val argumentsInParenthesis = if (oldCall.callType != Call.CallType.ARRAY_SET_METHOD && oldCall.functionLiteralArguments.isEmpty()) {
|
||||||
oldCall.valueArguments
|
oldCall.valueArguments
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
oldCall.valueArguments.dropLast(1)
|
oldCall.valueArguments.dropLast(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,8 +452,7 @@ class PSICallResolver(
|
|||||||
"Unexpected lambda parameters for call $oldCall"
|
"Unexpected lambda parameters for call $oldCall"
|
||||||
}
|
}
|
||||||
oldCall.valueArguments.last()
|
oldCall.valueArguments.last()
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (externalLambdaArguments.size > 2) {
|
if (externalLambdaArguments.size > 2) {
|
||||||
externalLambdaArguments.drop(1).forEach {
|
externalLambdaArguments.drop(1).forEach {
|
||||||
context.trace.report(Errors.MANY_LAMBDA_EXPRESSION_ARGUMENTS.on(it.getLambdaExpression()))
|
context.trace.report(Errors.MANY_LAMBDA_EXPRESSION_ARGUMENTS.on(it.getLambdaExpression()))
|
||||||
@@ -451,11 +474,17 @@ class PSICallResolver(
|
|||||||
resolvedArgumentsInParenthesis.forEach { it.setResultDataFlowInfoIfRelevant(resultDataFlowInfo) }
|
resolvedArgumentsInParenthesis.forEach { it.setResultDataFlowInfoIfRelevant(resultDataFlowInfo) }
|
||||||
astExternalArgument?.setResultDataFlowInfoIfRelevant(resultDataFlowInfo)
|
astExternalArgument?.setResultDataFlowInfoIfRelevant(resultDataFlowInfo)
|
||||||
|
|
||||||
return PSIKotlinCallImpl(kotlinCallKind, oldCall, tracingStrategy, resolvedExplicitReceiver, name, resolvedTypeArguments, resolvedArgumentsInParenthesis,
|
return PSIKotlinCallImpl(
|
||||||
astExternalArgument, context.dataFlowInfo, resultDataFlowInfo, context.dataFlowInfoForArguments)
|
kotlinCallKind, oldCall, tracingStrategy, resolvedExplicitReceiver, name, resolvedTypeArguments, resolvedArgumentsInParenthesis,
|
||||||
|
astExternalArgument, context.dataFlowInfo, resultDataFlowInfo, context.dataFlowInfoForArguments
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveExplicitReceiver(context: BasicCallResolutionContext, oldReceiver: Receiver?, isSafeCall: Boolean): ReceiverKotlinCallArgument? =
|
private fun resolveExplicitReceiver(
|
||||||
|
context: BasicCallResolutionContext,
|
||||||
|
oldReceiver: Receiver?,
|
||||||
|
isSafeCall: Boolean
|
||||||
|
): ReceiverKotlinCallArgument? =
|
||||||
when (oldReceiver) {
|
when (oldReceiver) {
|
||||||
null -> null
|
null -> null
|
||||||
is QualifierReceiver -> QualifierReceiverKotlinCallArgument(oldReceiver) // todo report warning if isSafeCall
|
is QualifierReceiver -> QualifierReceiverKotlinCallArgument(oldReceiver) // todo report warning if isSafeCall
|
||||||
@@ -474,8 +503,10 @@ class PSICallResolver(
|
|||||||
bindingContext.get(BindingContext.ONLY_RESOLVED_CALL, it)
|
bindingContext.get(BindingContext.ONLY_RESOLVED_CALL, it)
|
||||||
}
|
}
|
||||||
if (onlyResolvedCall != null) {
|
if (onlyResolvedCall != null) {
|
||||||
subCallArgument = SubKotlinCallArgumentImpl(CallMaker.makeExternalValueArgument(oldReceiver.expression),
|
subCallArgument = SubKotlinCallArgumentImpl(
|
||||||
context.dataFlowInfo, context.dataFlowInfo, detailedReceiver, onlyResolvedCall)
|
CallMaker.makeExternalValueArgument(oldReceiver.expression),
|
||||||
|
context.dataFlowInfo, context.dataFlowInfo, detailedReceiver, onlyResolvedCall
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -500,7 +531,8 @@ class PSICallResolver(
|
|||||||
}
|
}
|
||||||
ModifierCheckerCore.check(projection, context.trace, null, languageVersionSettings)
|
ModifierCheckerCore.check(projection, context.trace, null, languageVersionSettings)
|
||||||
|
|
||||||
resolveType(context, projection.typeReference)?.let { SimpleTypeArgumentImpl(projection.typeReference!!, it) } ?: TypeArgumentPlaceholder
|
resolveType(context, projection.typeReference)?.let { SimpleTypeArgumentImpl(projection.typeReference!!, it) }
|
||||||
|
?: TypeArgumentPlaceholder
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveArgumentsInParenthesis(
|
private fun resolveArgumentsInParenthesis(
|
||||||
@@ -534,7 +566,8 @@ class PSICallResolver(
|
|||||||
|
|
||||||
if (ktExpression is KtCollectionLiteralExpression) {
|
if (ktExpression is KtCollectionLiteralExpression) {
|
||||||
return CollectionLiteralKotlinCallArgumentImpl(
|
return CollectionLiteralKotlinCallArgumentImpl(
|
||||||
valueArgument, argumentName, startDataFlowInfo, startDataFlowInfo, ktExpression, outerCallContext)
|
valueArgument, argumentName, startDataFlowInfo, startDataFlowInfo, ktExpression, outerCallContext
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val context = outerCallContext.replaceContextDependency(ContextDependency.DEPENDENT)
|
val context = outerCallContext.replaceContextDependency(ContextDependency.DEPENDENT)
|
||||||
@@ -544,7 +577,10 @@ class PSICallResolver(
|
|||||||
checkNoSpread(outerCallContext, valueArgument)
|
checkNoSpread(outerCallContext, valueArgument)
|
||||||
|
|
||||||
val expressionTypingContext = ExpressionTypingContext.newContext(context)
|
val expressionTypingContext = ExpressionTypingContext.newContext(context)
|
||||||
val lhsResult = if (ktExpression.isEmptyLHS) null else doubleColonExpressionResolver.resolveDoubleColonLHS(ktExpression, expressionTypingContext)
|
val lhsResult = if (ktExpression.isEmptyLHS) null else doubleColonExpressionResolver.resolveDoubleColonLHS(
|
||||||
|
ktExpression,
|
||||||
|
expressionTypingContext
|
||||||
|
)
|
||||||
val newDataFlowInfo = (lhsResult as? DoubleColonLHS.Expression)?.dataFlowInfo ?: startDataFlowInfo
|
val newDataFlowInfo = (lhsResult as? DoubleColonLHS.Expression)?.dataFlowInfo ?: startDataFlowInfo
|
||||||
val name = ktExpression.callableReference.getReferencedNameAsName()
|
val name = ktExpression.callableReference.getReferencedNameAsName()
|
||||||
|
|
||||||
@@ -556,12 +592,10 @@ class PSICallResolver(
|
|||||||
val calleeExpression = ktExpression.receiverExpression?.getCalleeExpressionIfAny()
|
val calleeExpression = ktExpression.receiverExpression?.getCalleeExpressionIfAny()
|
||||||
if (calleeExpression is KtSimpleNameExpression && classifier is ClassDescriptor) {
|
if (calleeExpression is KtSimpleNameExpression && classifier is ClassDescriptor) {
|
||||||
LHSResult.Object(ClassQualifier(calleeExpression, classifier))
|
LHSResult.Object(ClassQualifier(calleeExpression, classifier))
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
LHSResult.Error
|
LHSResult.Error
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val fakeArgument = FakeValueArgumentForLeftCallableReference(ktExpression)
|
val fakeArgument = FakeValueArgumentForLeftCallableReference(ktExpression)
|
||||||
|
|
||||||
val kotlinCallArgument = createSimplePSICallArgument(context, fakeArgument, lhsResult.typeInfo)
|
val kotlinCallArgument = createSimplePSICallArgument(context, fakeArgument, lhsResult.typeInfo)
|
||||||
@@ -573,15 +607,16 @@ class PSICallResolver(
|
|||||||
val qualifier = expressionTypingContext.trace.get(BindingContext.QUALIFIER, qualifiedExpression)
|
val qualifier = expressionTypingContext.trace.get(BindingContext.QUALIFIER, qualifiedExpression)
|
||||||
if (qualifier is ClassQualifier) {
|
if (qualifier is ClassQualifier) {
|
||||||
LHSResult.Type(qualifier, lhsResult.type.unwrap())
|
LHSResult.Type(qualifier, lhsResult.type.unwrap())
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
LHSResult.Error
|
LHSResult.Error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return CallableReferenceKotlinCallArgumentImpl(ASTScopeTower(context), valueArgument, startDataFlowInfo, newDataFlowInfo,
|
return CallableReferenceKotlinCallArgumentImpl(
|
||||||
ktExpression, argumentName, lhsNewResult, name)
|
ASTScopeTower(context), valueArgument, startDataFlowInfo, newDataFlowInfo,
|
||||||
|
ktExpression, argumentName, lhsNewResult, name
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// argumentExpression instead of ktExpression is hack -- type info should be stored also for parenthesized expression
|
// argumentExpression instead of ktExpression is hack -- type info should be stored also for parenthesized expression
|
||||||
@@ -602,17 +637,21 @@ class PSICallResolver(
|
|||||||
|
|
||||||
val lambdaArgument: PSIKotlinCallArgument? = when (postponedExpression) {
|
val lambdaArgument: PSIKotlinCallArgument? = when (postponedExpression) {
|
||||||
is KtLambdaExpression ->
|
is KtLambdaExpression ->
|
||||||
LambdaKotlinCallArgumentImpl(outerCallContext, valueArgument, startDataFlowInfo, argumentName, postponedExpression,
|
LambdaKotlinCallArgumentImpl(
|
||||||
argumentExpression, resolveParametersTypes(outerCallContext, postponedExpression.functionLiteral))
|
outerCallContext, valueArgument, startDataFlowInfo, argumentName, postponedExpression,
|
||||||
|
argumentExpression, resolveParametersTypes(outerCallContext, postponedExpression.functionLiteral)
|
||||||
|
)
|
||||||
|
|
||||||
is KtNamedFunction -> {
|
is KtNamedFunction -> {
|
||||||
val receiverType = resolveType(outerCallContext, postponedExpression.receiverTypeReference)
|
val receiverType = resolveType(outerCallContext, postponedExpression.receiverTypeReference)
|
||||||
val parametersTypes = resolveParametersTypes(outerCallContext, postponedExpression) ?: emptyArray()
|
val parametersTypes = resolveParametersTypes(outerCallContext, postponedExpression) ?: emptyArray()
|
||||||
val returnType = resolveType(outerCallContext, postponedExpression.typeReference) ?:
|
val returnType = resolveType(outerCallContext, postponedExpression.typeReference)
|
||||||
if (postponedExpression.hasBlockBody()) builtIns.unitType else null
|
?: if (postponedExpression.hasBlockBody()) builtIns.unitType else null
|
||||||
|
|
||||||
FunctionExpressionImpl(outerCallContext, valueArgument, startDataFlowInfo, argumentName,
|
FunctionExpressionImpl(
|
||||||
argumentExpression, postponedExpression, receiverType, parametersTypes, returnType)
|
outerCallContext, valueArgument, startDataFlowInfo, argumentName,
|
||||||
|
argumentExpression, postponedExpression, receiverType, parametersTypes, returnType
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> return null
|
else -> return null
|
||||||
|
|||||||
+38
-13
@@ -79,7 +79,12 @@ class ResolvedAtomCompleter(
|
|||||||
fun completeResolvedCall(resolvedCallAtom: ResolvedCallAtom, diagnostics: Collection<KotlinCallDiagnostic>): ResolvedCall<*>? {
|
fun completeResolvedCall(resolvedCallAtom: ResolvedCallAtom, diagnostics: Collection<KotlinCallDiagnostic>): ResolvedCall<*>? {
|
||||||
if (resolvedCallAtom.atom.psiKotlinCall is PSIKotlinCallForVariable) return null
|
if (resolvedCallAtom.atom.psiKotlinCall is PSIKotlinCallForVariable) return null
|
||||||
|
|
||||||
val resolvedCall = kotlinToResolvedCallTransformer.transformToResolvedCall<CallableDescriptor>(resolvedCallAtom, trace, resultSubstitutor, diagnostics)
|
val resolvedCall = kotlinToResolvedCallTransformer.transformToResolvedCall<CallableDescriptor>(
|
||||||
|
resolvedCallAtom,
|
||||||
|
trace,
|
||||||
|
resultSubstitutor,
|
||||||
|
diagnostics
|
||||||
|
)
|
||||||
kotlinToResolvedCallTransformer.bindAndReport(topLevelCallContext, trace, resolvedCall, diagnostics)
|
kotlinToResolvedCallTransformer.bindAndReport(topLevelCallContext, trace, resolvedCall, diagnostics)
|
||||||
kotlinToResolvedCallTransformer.runCallCheckers(resolvedCall, callCheckerContext)
|
kotlinToResolvedCallTransformer.runCallCheckers(resolvedCall, callCheckerContext)
|
||||||
|
|
||||||
@@ -123,8 +128,8 @@ class ResolvedAtomCompleter(
|
|||||||
else -> throw AssertionError("Unexpected psiCallArgument for resolved lambda argument: $psiCallArgument")
|
else -> throw AssertionError("Unexpected psiCallArgument for resolved lambda argument: $psiCallArgument")
|
||||||
}
|
}
|
||||||
|
|
||||||
val functionDescriptor = trace.bindingContext.get(BindingContext.FUNCTION, ktFunction) as? FunctionDescriptorImpl ?:
|
val functionDescriptor = trace.bindingContext.get(BindingContext.FUNCTION, ktFunction) as? FunctionDescriptorImpl
|
||||||
throw AssertionError("No function descriptor for resolved lambda argument")
|
?: throw AssertionError("No function descriptor for resolved lambda argument")
|
||||||
functionDescriptor.setReturnType(returnType)
|
functionDescriptor.setReturnType(returnType)
|
||||||
|
|
||||||
val existingLambdaType = trace.getType(ktArgumentExpression) ?: throw AssertionError("No type for resolved lambda argument")
|
val existingLambdaType = trace.getType(ktArgumentExpression) ?: throw AssertionError("No type for resolved lambda argument")
|
||||||
@@ -139,19 +144,24 @@ class ResolvedAtomCompleter(
|
|||||||
// todo report meanfull diagnostic here
|
// todo report meanfull diagnostic here
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val resultTypeParameters = callableCandidate.freshSubstitutor!!.freshVariables.map { resultSubstitutor.safeSubstitute(it.defaultType) }
|
val resultTypeParameters =
|
||||||
|
callableCandidate.freshSubstitutor!!.freshVariables.map { resultSubstitutor.safeSubstitute(it.defaultType) }
|
||||||
|
|
||||||
|
|
||||||
val psiCallArgument = resolvedAtom.atom.psiCallArgument as CallableReferenceKotlinCallArgumentImpl
|
val psiCallArgument = resolvedAtom.atom.psiCallArgument as CallableReferenceKotlinCallArgumentImpl
|
||||||
val callableReferenceExpression = psiCallArgument.ktCallableReferenceExpression
|
val callableReferenceExpression = psiCallArgument.ktCallableReferenceExpression
|
||||||
val resultSubstitutor = IndexedParametersSubstitution(callableCandidate.candidate.typeParameters, resultTypeParameters.map { it.asTypeProjection() }).buildSubstitutor()
|
val resultSubstitutor = IndexedParametersSubstitution(
|
||||||
|
callableCandidate.candidate.typeParameters,
|
||||||
|
resultTypeParameters.map { it.asTypeProjection() }).buildSubstitutor()
|
||||||
|
|
||||||
|
|
||||||
// write down type for callable reference expression
|
// write down type for callable reference expression
|
||||||
val resultType = resultSubstitutor.safeSubstitute(callableCandidate.reflectionCandidateType, Variance.INVARIANT)
|
val resultType = resultSubstitutor.safeSubstitute(callableCandidate.reflectionCandidateType, Variance.INVARIANT)
|
||||||
argumentTypeResolver.updateResultArgumentTypeIfNotDenotable(trace, expressionTypingServices.statementFilter,
|
argumentTypeResolver.updateResultArgumentTypeIfNotDenotable(
|
||||||
|
trace, expressionTypingServices.statementFilter,
|
||||||
resultType,
|
resultType,
|
||||||
callableReferenceExpression)
|
callableReferenceExpression
|
||||||
|
)
|
||||||
val reference = callableReferenceExpression.callableReference
|
val reference = callableReferenceExpression.callableReference
|
||||||
|
|
||||||
val explicitCallableReceiver = when (callableCandidate.explicitReceiverKind) {
|
val explicitCallableReceiver = when (callableCandidate.explicitReceiverKind) {
|
||||||
@@ -166,9 +176,11 @@ class ResolvedAtomCompleter(
|
|||||||
val tracing = TracingStrategyImpl.create(reference, psiCall)
|
val tracing = TracingStrategyImpl.create(reference, psiCall)
|
||||||
val temporaryTrace = TemporaryBindingTrace.create(trace, "callable reference fake call")
|
val temporaryTrace = TemporaryBindingTrace.create(trace, "callable reference fake call")
|
||||||
|
|
||||||
val resolvedCall = ResolvedCallImpl(psiCall, callableCandidate.candidate, callableCandidate.dispatchReceiver?.receiver?.receiverValue,
|
val resolvedCall = ResolvedCallImpl(
|
||||||
|
psiCall, callableCandidate.candidate, callableCandidate.dispatchReceiver?.receiver?.receiverValue,
|
||||||
callableCandidate.extensionReceiver?.receiver?.receiverValue, callableCandidate.explicitReceiverKind,
|
callableCandidate.extensionReceiver?.receiver?.receiverValue, callableCandidate.explicitReceiverKind,
|
||||||
null, temporaryTrace, tracing, MutableDataFlowInfoForArguments.WithoutArgumentsCheck(DataFlowInfo.EMPTY))
|
null, temporaryTrace, tracing, MutableDataFlowInfoForArguments.WithoutArgumentsCheck(DataFlowInfo.EMPTY)
|
||||||
|
)
|
||||||
resolvedCall.setResultingSubstitutor(resultSubstitutor)
|
resolvedCall.setResultingSubstitutor(resultSubstitutor)
|
||||||
|
|
||||||
tracing.bindCall(trace, psiCall)
|
tracing.bindCall(trace, psiCall)
|
||||||
@@ -179,22 +191,35 @@ class ResolvedAtomCompleter(
|
|||||||
resolvedCall.markCallAsCompleted()
|
resolvedCall.markCallAsCompleted()
|
||||||
|
|
||||||
when (callableCandidate.candidate) {
|
when (callableCandidate.candidate) {
|
||||||
is FunctionDescriptor -> doubleColonExpressionResolver.bindFunctionReference(callableReferenceExpression, resultType, topLevelCallContext)
|
is FunctionDescriptor -> doubleColonExpressionResolver.bindFunctionReference(
|
||||||
is PropertyDescriptor -> doubleColonExpressionResolver.bindPropertyReference(callableReferenceExpression, resultType, topLevelCallContext)
|
callableReferenceExpression,
|
||||||
|
resultType,
|
||||||
|
topLevelCallContext
|
||||||
|
)
|
||||||
|
is PropertyDescriptor -> doubleColonExpressionResolver.bindPropertyReference(
|
||||||
|
callableReferenceExpression,
|
||||||
|
resultType,
|
||||||
|
topLevelCallContext
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: probably we should also record key 'DATA_FLOW_INFO_BEFORE', see ExpressionTypingVisitorDispatcher.getTypeInfo
|
// TODO: probably we should also record key 'DATA_FLOW_INFO_BEFORE', see ExpressionTypingVisitorDispatcher.getTypeInfo
|
||||||
trace.recordType(callableReferenceExpression, resultType)
|
trace.recordType(callableReferenceExpression, resultType)
|
||||||
trace.record(BindingContext.PROCESSED, callableReferenceExpression)
|
trace.record(BindingContext.PROCESSED, callableReferenceExpression)
|
||||||
|
|
||||||
doubleColonExpressionResolver.checkReferenceIsToAllowedMember(callableCandidate.candidate, topLevelCallContext.trace, callableReferenceExpression)
|
doubleColonExpressionResolver.checkReferenceIsToAllowedMember(
|
||||||
|
callableCandidate.candidate,
|
||||||
|
topLevelCallContext.trace,
|
||||||
|
callableReferenceExpression
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun completeCollectionLiteralCalls(collectionLiteralArgument: ResolvedCollectionLiteralAtom) {
|
private fun completeCollectionLiteralCalls(collectionLiteralArgument: ResolvedCollectionLiteralAtom) {
|
||||||
val psiCallArgument = collectionLiteralArgument.atom.psiCallArgument as CollectionLiteralKotlinCallArgumentImpl
|
val psiCallArgument = collectionLiteralArgument.atom.psiCallArgument as CollectionLiteralKotlinCallArgumentImpl
|
||||||
val context = psiCallArgument.outerCallContext
|
val context = psiCallArgument.outerCallContext
|
||||||
|
|
||||||
val expectedType = collectionLiteralArgument.expectedType?.let { resultSubstitutor.safeSubstitute(it) } ?: TypeUtils.NO_EXPECTED_TYPE
|
val expectedType =
|
||||||
|
collectionLiteralArgument.expectedType?.let { resultSubstitutor.safeSubstitute(it) } ?: TypeUtils.NO_EXPECTED_TYPE
|
||||||
|
|
||||||
val actualContext = context
|
val actualContext = context
|
||||||
.replaceBindingTrace(trace)
|
.replaceBindingTrace(trace)
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ fun <D : CallableDescriptor> ResolvedCall<D>.hasUnmappedParameters(): Boolean {
|
|||||||
return !parameterToArgumentMap.keys.containsAll(resultingDescriptor.valueParameters)
|
return !parameterToArgumentMap.keys.containsAll(resultingDescriptor.valueParameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <D : CallableDescriptor> ResolvedCall<D>.allArgumentsMapped()
|
fun <D : CallableDescriptor> ResolvedCall<D>.allArgumentsMapped() =
|
||||||
= call.valueArguments.all { argument -> getArgumentMapping(argument) is ArgumentMatch }
|
call.valueArguments.all { argument -> getArgumentMapping(argument) is ArgumentMatch }
|
||||||
|
|
||||||
fun <D : CallableDescriptor> ResolvedCall<D>.hasTypeMismatchErrorOnParameter(parameter: ValueParameterDescriptor): Boolean {
|
fun <D : CallableDescriptor> ResolvedCall<D>.hasTypeMismatchErrorOnParameter(parameter: ValueParameterDescriptor): Boolean {
|
||||||
val resolvedValueArgument = valueArguments[parameter]
|
val resolvedValueArgument = valueArguments[parameter]
|
||||||
@@ -93,8 +93,7 @@ fun KtCallElement.getValueArgumentsInParentheses(): List<ValueArgument> = valueA
|
|||||||
fun Call.getValueArgumentListOrElement(): KtElement =
|
fun Call.getValueArgumentListOrElement(): KtElement =
|
||||||
if (this is CallTransformer.CallForImplicitInvoke) {
|
if (this is CallTransformer.CallForImplicitInvoke) {
|
||||||
outerCall.getValueArgumentListOrElement()
|
outerCall.getValueArgumentListOrElement()
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
valueArgumentList ?: calleeExpression ?: callElement
|
valueArgumentList ?: calleeExpression ?: callElement
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,6 +110,7 @@ fun Call.getValueArgumentForExpression(expression: KtExpression): ValueArgument?
|
|||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun KtElement.isParenthesizedExpression() = generateSequence(this) { it.deparenthesizeStructurally() }.any { it == expression }
|
fun KtElement.isParenthesizedExpression() = generateSequence(this) { it.deparenthesizeStructurally() }.any { it == expression }
|
||||||
return valueArguments.firstOrNull { it?.getArgumentExpression()?.isParenthesizedExpression() ?: false }
|
return valueArguments.firstOrNull { it?.getArgumentExpression()?.isParenthesizedExpression() ?: false }
|
||||||
}
|
}
|
||||||
@@ -157,7 +157,8 @@ fun KtElement.getCall(context: BindingContext): Call? {
|
|||||||
fun KtElement.getParentCall(context: BindingContext, strict: Boolean = true): Call? {
|
fun KtElement.getParentCall(context: BindingContext, strict: Boolean = true): Call? {
|
||||||
val callExpressionTypes = arrayOf<Class<out KtElement>?>(
|
val callExpressionTypes = arrayOf<Class<out KtElement>?>(
|
||||||
KtSimpleNameExpression::class.java, KtCallElement::class.java, KtBinaryExpression::class.java,
|
KtSimpleNameExpression::class.java, KtCallElement::class.java, KtBinaryExpression::class.java,
|
||||||
KtUnaryExpression::class.java, KtArrayAccessExpression::class.java)
|
KtUnaryExpression::class.java, KtArrayAccessExpression::class.java
|
||||||
|
)
|
||||||
|
|
||||||
val parent = if (strict) {
|
val parent = if (strict) {
|
||||||
PsiTreeUtil.getParentOfType(this, *callExpressionTypes)
|
PsiTreeUtil.getParentOfType(this, *callExpressionTypes)
|
||||||
@@ -263,5 +264,4 @@ fun ResolvedCall<*>.getFirstArgumentExpression(): KtExpression? =
|
|||||||
valueArgumentsByIndex?.run { get(0).arguments[0].getArgumentExpression() }
|
valueArgumentsByIndex?.run { get(0).arguments[0].getArgumentExpression() }
|
||||||
|
|
||||||
fun ResolvedCall<*>.getReceiverExpression(): KtExpression? =
|
fun ResolvedCall<*>.getReceiverExpression(): KtExpression? =
|
||||||
extensionReceiver.safeAs<ExpressionReceiver>()?.expression ?:
|
extensionReceiver.safeAs<ExpressionReceiver>()?.expression ?: dispatchReceiver.safeAs<ExpressionReceiver>()?.expression
|
||||||
dispatchReceiver.safeAs<ExpressionReceiver>()?.expression
|
|
||||||
@@ -47,9 +47,11 @@ object ConstModifierChecker : SimpleDeclarationChecker {
|
|||||||
fun canBeConst(declaration: KtDeclaration, constModifierPsiElement: PsiElement, descriptor: VariableDescriptor): Boolean =
|
fun canBeConst(declaration: KtDeclaration, constModifierPsiElement: PsiElement, descriptor: VariableDescriptor): Boolean =
|
||||||
checkCanBeConst(declaration, constModifierPsiElement, descriptor).canBeConst
|
checkCanBeConst(declaration, constModifierPsiElement, descriptor).canBeConst
|
||||||
|
|
||||||
private fun checkCanBeConst(declaration: KtDeclaration,
|
private fun checkCanBeConst(
|
||||||
|
declaration: KtDeclaration,
|
||||||
constModifierPsiElement: PsiElement,
|
constModifierPsiElement: PsiElement,
|
||||||
descriptor: VariableDescriptor): ConstApplicability {
|
descriptor: VariableDescriptor
|
||||||
|
): ConstApplicability {
|
||||||
if (descriptor.isVar) {
|
if (descriptor.isVar) {
|
||||||
return Errors.WRONG_MODIFIER_TARGET.on(constModifierPsiElement, KtTokens.CONST_KEYWORD, "vars").nonApplicable()
|
return Errors.WRONG_MODIFIER_TARGET.on(constModifierPsiElement, KtTokens.CONST_KEYWORD, "vars").nonApplicable()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,13 @@ class DelegationChecker : DeclarationChecker {
|
|||||||
|
|
||||||
if (nonAbstractReachable.isNotEmpty()) {
|
if (nonAbstractReachable.isNotEmpty()) {
|
||||||
/*In case of MANY_IMPL_MEMBER_NOT_IMPLEMENTED error there could be several elements otherwise only one*/
|
/*In case of MANY_IMPL_MEMBER_NOT_IMPLEMENTED error there could be several elements otherwise only one*/
|
||||||
diagnosticHolder.report(DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE.on(classDeclaration, delegatedDescriptor, nonAbstractReachable))
|
diagnosticHolder.report(
|
||||||
|
DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE.on(
|
||||||
|
classDeclaration,
|
||||||
|
delegatedDescriptor,
|
||||||
|
nonAbstractReachable
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-17
@@ -71,8 +71,7 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
|
|||||||
|
|
||||||
if (descriptor.isExpect) {
|
if (descriptor.isExpect) {
|
||||||
checkExpectedDeclarationHasActual(declaration, descriptor, diagnosticHolder, descriptor.module, expectActualTracker)
|
checkExpectedDeclarationHasActual(declaration, descriptor, diagnosticHolder, descriptor.module, expectActualTracker)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val checkActual = !languageVersionSettings.getFlag(AnalysisFlag.multiPlatformDoNotCheckActual)
|
val checkActual = !languageVersionSettings.getFlag(AnalysisFlag.multiPlatformDoNotCheckActual)
|
||||||
checkActualDeclarationHasExpected(declaration, descriptor, diagnosticHolder, checkActual)
|
checkActualDeclarationHasExpected(declaration, descriptor, diagnosticHolder, checkActual)
|
||||||
}
|
}
|
||||||
@@ -102,8 +101,7 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
|
|||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val incompatibility = compatibility as Map<Incompatible, Collection<MemberDescriptor>>
|
val incompatibility = compatibility as Map<Incompatible, Collection<MemberDescriptor>>
|
||||||
diagnosticHolder.report(Errors.NO_ACTUAL_FOR_EXPECT.on(reportOn, descriptor, platformModule, incompatibility))
|
diagnosticHolder.report(Errors.NO_ACTUAL_FOR_EXPECT.on(reportOn, descriptor, platformModule, incompatibility))
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val actualMembers = compatibility.asSequence()
|
val actualMembers = compatibility.asSequence()
|
||||||
.filter { (compatibility, _) ->
|
.filter { (compatibility, _) ->
|
||||||
compatibility is Compatible || (compatibility is Incompatible && compatibility.kind != Compatibility.IncompatibilityKind.STRONG)
|
compatibility is Compatible || (compatibility is Incompatible && compatibility.kind != Compatibility.IncompatibilityKind.STRONG)
|
||||||
@@ -132,7 +130,10 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
|
|||||||
fun Map<out Compatibility, Collection<MemberDescriptor>>.allStrongIncompatibilities(): Boolean =
|
fun Map<out Compatibility, Collection<MemberDescriptor>>.allStrongIncompatibilities(): Boolean =
|
||||||
this.keys.all { it is Incompatible && it.kind == Compatibility.IncompatibilityKind.STRONG }
|
this.keys.all { it is Incompatible && it.kind == Compatibility.IncompatibilityKind.STRONG }
|
||||||
|
|
||||||
private fun findActualForExpected(expected: MemberDescriptor, platformModule: ModuleDescriptor): Map<Compatibility, List<MemberDescriptor>>? {
|
private fun findActualForExpected(
|
||||||
|
expected: MemberDescriptor,
|
||||||
|
platformModule: ModuleDescriptor
|
||||||
|
): Map<Compatibility, List<MemberDescriptor>>? {
|
||||||
return when (expected) {
|
return when (expected) {
|
||||||
is CallableMemberDescriptor -> {
|
is CallableMemberDescriptor -> {
|
||||||
expected.findNamesakesFromModule(platformModule).filter { actual ->
|
expected.findNamesakesFromModule(platformModule).filter { actual ->
|
||||||
@@ -207,12 +208,13 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
|
|||||||
val classDescriptor =
|
val classDescriptor =
|
||||||
(descriptor as? TypeAliasDescriptor)?.expandedType?.constructor?.declarationDescriptor as? ClassDescriptor
|
(descriptor as? TypeAliasDescriptor)?.expandedType?.constructor?.declarationDescriptor as? ClassDescriptor
|
||||||
?: (descriptor as ClassDescriptor)
|
?: (descriptor as ClassDescriptor)
|
||||||
diagnosticHolder.report(Errors.NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS.on(
|
diagnosticHolder.report(
|
||||||
|
Errors.NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS.on(
|
||||||
reportOn, classDescriptor, nonTrivialUnfulfilled
|
reportOn, classDescriptor, nonTrivialUnfulfilled
|
||||||
))
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
} else if (Compatible !in compatibility) {
|
||||||
else if (Compatible !in compatibility) {
|
|
||||||
assert(compatibility.keys.all { it is Incompatible })
|
assert(compatibility.keys.all { it is Incompatible })
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val incompatibility = compatibility as Map<Incompatible, Collection<MemberDescriptor>>
|
val incompatibility = compatibility as Map<Incompatible, Collection<MemberDescriptor>>
|
||||||
@@ -229,14 +231,18 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
|
|||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findExpectedForActual(actual: MemberDescriptor, commonModule: ModuleDescriptor): Map<Compatibility, List<MemberDescriptor>>? {
|
private fun findExpectedForActual(
|
||||||
|
actual: MemberDescriptor,
|
||||||
|
commonModule: ModuleDescriptor
|
||||||
|
): Map<Compatibility, List<MemberDescriptor>>? {
|
||||||
return when (actual) {
|
return when (actual) {
|
||||||
is CallableMemberDescriptor -> {
|
is CallableMemberDescriptor -> {
|
||||||
val container = actual.containingDeclaration
|
val container = actual.containingDeclaration
|
||||||
val candidates = when (container) {
|
val candidates = when (container) {
|
||||||
is ClassDescriptor -> {
|
is ClassDescriptor -> {
|
||||||
// TODO: replace with 'singleOrNull' as soon as multi-module diagnostic tests are refactored
|
// TODO: replace with 'singleOrNull' as soon as multi-module diagnostic tests are refactored
|
||||||
val expectedClass = findExpectedForActual(container, commonModule)?.values?.firstOrNull()?.firstOrNull() as? ClassDescriptor
|
val expectedClass =
|
||||||
|
findExpectedForActual(container, commonModule)?.values?.firstOrNull()?.firstOrNull() as? ClassDescriptor
|
||||||
expectedClass?.getMembers(actual.name)?.filterIsInstance<CallableMemberDescriptor>().orEmpty()
|
expectedClass?.getMembers(actual.name)?.filterIsInstance<CallableMemberDescriptor>().orEmpty()
|
||||||
}
|
}
|
||||||
is PackageFragmentDescriptor -> actual.findNamesakesFromModule(commonModule)
|
is PackageFragmentDescriptor -> actual.findNamesakesFromModule(commonModule)
|
||||||
@@ -252,8 +258,7 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
|
|||||||
val expectedClass = declaration.containingDeclaration as ClassDescriptor
|
val expectedClass = declaration.containingDeclaration as ClassDescriptor
|
||||||
// TODO: this might not work for members of inner generic classes
|
// TODO: this might not work for members of inner generic classes
|
||||||
Substitutor(expectedClass.declaredTypeParameters, container.declaredTypeParameters)
|
Substitutor(expectedClass.declaredTypeParameters, container.declaredTypeParameters)
|
||||||
}
|
} else null
|
||||||
else null
|
|
||||||
areCompatibleCallables(declaration, actual, parentSubstitutor = substitutor)
|
areCompatibleCallables(declaration, actual, parentSubstitutor = substitutor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -350,13 +355,17 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
|
|||||||
|
|
||||||
object ValueParameterHasDefault : Incompatible("some parameters have default values")
|
object ValueParameterHasDefault : Incompatible("some parameters have default values")
|
||||||
object ValueParameterVararg : Incompatible("some value parameter is vararg in one declaration and non-vararg in the other")
|
object ValueParameterVararg : Incompatible("some value parameter is vararg in one declaration and non-vararg in the other")
|
||||||
object ValueParameterNoinline : Incompatible("some value parameter is noinline in one declaration and not noinline in the other")
|
object ValueParameterNoinline :
|
||||||
object ValueParameterCrossinline : Incompatible("some value parameter is crossinline in one declaration and not crossinline in the other")
|
Incompatible("some value parameter is noinline in one declaration and not noinline in the other")
|
||||||
|
|
||||||
|
object ValueParameterCrossinline :
|
||||||
|
Incompatible("some value parameter is crossinline in one declaration and not crossinline in the other")
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
|
|
||||||
object FunctionModifiersDifferent : Incompatible("modifiers are different (suspend)")
|
object FunctionModifiersDifferent : Incompatible("modifiers are different (suspend)")
|
||||||
object FunctionModifiersNotSubset : Incompatible("some modifiers on expected declaration are missing on the actual one (external, infix, inline, operator, tailrec)")
|
object FunctionModifiersNotSubset :
|
||||||
|
Incompatible("some modifiers on expected declaration are missing on the actual one (external, infix, inline, operator, tailrec)")
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
|
|
||||||
@@ -425,7 +434,11 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
|
|||||||
return Incompatible.ParameterTypes
|
return Incompatible.ParameterTypes
|
||||||
if (!areCompatibleTypes(substitutor(a.returnType), b.returnType, platformModule)) return Incompatible.ReturnType
|
if (!areCompatibleTypes(substitutor(a.returnType), b.returnType, platformModule)) return Incompatible.ReturnType
|
||||||
|
|
||||||
if (b.hasStableParameterNames() && !equalsBy(aParams, bParams, ValueParameterDescriptor::getName)) return Incompatible.ParameterNames
|
if (b.hasStableParameterNames() && !equalsBy(
|
||||||
|
aParams,
|
||||||
|
bParams,
|
||||||
|
ValueParameterDescriptor::getName
|
||||||
|
)) return Incompatible.ParameterNames
|
||||||
if (!equalsBy(aTypeParams, bTypeParams, TypeParameterDescriptor::getName)) return Incompatible.TypeParameterNames
|
if (!equalsBy(aTypeParams, bTypeParams, TypeParameterDescriptor::getName)) return Incompatible.TypeParameterNames
|
||||||
|
|
||||||
if (!areCompatibleModalities(a.modality, b.modality)) return Incompatible.Modality
|
if (!areCompatibleModalities(a.modality, b.modality)) return Incompatible.Modality
|
||||||
@@ -636,6 +649,7 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
|
|||||||
if (a.kind == ClassKind.ENUM_CLASS) {
|
if (a.kind == ClassKind.ENUM_CLASS) {
|
||||||
fun ClassDescriptor.enumEntries() =
|
fun ClassDescriptor.enumEntries() =
|
||||||
unsubstitutedMemberScope.getDescriptorsFiltered().filter(DescriptorUtils::isEnumEntry).map { it.name }
|
unsubstitutedMemberScope.getDescriptorsFiltered().filter(DescriptorUtils::isEnumEntry).map { it.name }
|
||||||
|
|
||||||
val aEntries = a.enumEntries()
|
val aEntries = a.enumEntries()
|
||||||
val bEntries = b.enumEntries()
|
val bEntries = b.enumEntries()
|
||||||
|
|
||||||
|
|||||||
+12
-2
@@ -29,7 +29,12 @@ import org.jetbrains.kotlin.types.typeUtil.contains
|
|||||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||||
|
|
||||||
object KClassWithIncorrectTypeArgumentChecker : SimpleDeclarationChecker {
|
object KClassWithIncorrectTypeArgumentChecker : SimpleDeclarationChecker {
|
||||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink, bindingContext: BindingContext) {
|
override fun check(
|
||||||
|
declaration: KtDeclaration,
|
||||||
|
descriptor: DeclarationDescriptor,
|
||||||
|
diagnosticHolder: DiagnosticSink,
|
||||||
|
bindingContext: BindingContext
|
||||||
|
) {
|
||||||
if (descriptor !is CallableMemberDescriptor || descriptor.visibility == Visibilities.LOCAL) return
|
if (descriptor !is CallableMemberDescriptor || descriptor.visibility == Visibilities.LOCAL) return
|
||||||
|
|
||||||
if (declaration !is KtCallableDeclaration || declaration.typeReference != null) return
|
if (declaration !is KtCallableDeclaration || declaration.typeReference != null) return
|
||||||
@@ -53,7 +58,12 @@ object KClassWithIncorrectTypeArgumentChecker : SimpleDeclarationChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeParameterWithoutNotNullableUpperBound != null) {
|
if (typeParameterWithoutNotNullableUpperBound != null) {
|
||||||
diagnosticHolder.report(Errors.KCLASS_WITH_NULLABLE_TYPE_PARAMETER_IN_SIGNATURE.on(declaration, typeParameterWithoutNotNullableUpperBound!!))
|
diagnosticHolder.report(
|
||||||
|
Errors.KCLASS_WITH_NULLABLE_TYPE_PARAMETER_IN_SIGNATURE.on(
|
||||||
|
declaration,
|
||||||
|
typeParameterWithoutNotNullableUpperBound!!
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+113
-60
@@ -107,8 +107,7 @@ class ConstantExpressionEvaluator(
|
|||||||
if (parameterDescriptor.declaresDefaultValue() && compileTimeConstants.isEmpty()) return null
|
if (parameterDescriptor.declaresDefaultValue() && compileTimeConstants.isEmpty()) return null
|
||||||
|
|
||||||
return constantValueFactory.createArrayValue(constants, parameterDescriptor.type)
|
return constantValueFactory.createArrayValue(constants, parameterDescriptor.type)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// we should actually get only one element, but just in case of getting many, we take the last one
|
// we should actually get only one element, but just in case of getting many, we take the last one
|
||||||
return constants.lastOrNull()
|
return constants.lastOrNull()
|
||||||
}
|
}
|
||||||
@@ -137,7 +136,12 @@ class ConstantExpressionEvaluator(
|
|||||||
getArgumentExpressionsForArrayCall(argumentExpression, trace)?.let { checkArgumentsAreCompileTimeConstants(it, trace) }
|
getArgumentExpressionsForArrayCall(argumentExpression, trace)?.let { checkArgumentsAreCompileTimeConstants(it, trace) }
|
||||||
}
|
}
|
||||||
if (argumentExpression is KtCollectionLiteralExpression) {
|
if (argumentExpression is KtCollectionLiteralExpression) {
|
||||||
getArgumentExpressionsForCollectionLiteralCall(argumentExpression, trace)?.let { checkArgumentsAreCompileTimeConstants(it, trace) }
|
getArgumentExpressionsForCollectionLiteralCall(argumentExpression, trace)?.let {
|
||||||
|
checkArgumentsAreCompileTimeConstants(
|
||||||
|
it,
|
||||||
|
trace
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val constant = ConstantExpressionEvaluator.getConstant(argumentExpression, trace.bindingContext)
|
val constant = ConstantExpressionEvaluator.getConstant(argumentExpression, trace.bindingContext)
|
||||||
@@ -162,16 +166,17 @@ class ConstantExpressionEvaluator(
|
|||||||
val descriptor = expressionType.constructor.declarationDescriptor
|
val descriptor = expressionType.constructor.declarationDescriptor
|
||||||
if (descriptor != null && DescriptorUtils.isEnumClass(descriptor)) {
|
if (descriptor != null && DescriptorUtils.isEnumClass(descriptor)) {
|
||||||
trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_ENUM_CONST.on(argumentExpression))
|
trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_ENUM_CONST.on(argumentExpression))
|
||||||
}
|
} else if (descriptor is ClassDescriptor && KotlinBuiltIns.isKClass(descriptor)) {
|
||||||
else if (descriptor is ClassDescriptor && KotlinBuiltIns.isKClass(descriptor)) {
|
|
||||||
trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL.on(argumentExpression))
|
trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL.on(argumentExpression))
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_CONST.on(argumentExpression))
|
trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_CONST.on(argumentExpression))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkArgumentsAreCompileTimeConstants(argumentsWithComponentType: Pair<List<KtExpression>, KotlinType?>, trace: BindingTrace) {
|
private fun checkArgumentsAreCompileTimeConstants(
|
||||||
|
argumentsWithComponentType: Pair<List<KtExpression>, KotlinType?>,
|
||||||
|
trace: BindingTrace
|
||||||
|
) {
|
||||||
val (arguments, componentType) = argumentsWithComponentType
|
val (arguments, componentType) = argumentsWithComponentType
|
||||||
for (expression in arguments) {
|
for (expression in arguments) {
|
||||||
checkCompileTimeConstant(expression, componentType!!, trace)
|
checkCompileTimeConstant(expression, componentType!!, trace)
|
||||||
@@ -188,7 +193,8 @@ class ConstantExpressionEvaluator(
|
|||||||
|
|
||||||
private fun getArgumentExpressionsForCollectionLiteralCall(
|
private fun getArgumentExpressionsForCollectionLiteralCall(
|
||||||
expression: KtCollectionLiteralExpression,
|
expression: KtCollectionLiteralExpression,
|
||||||
trace: BindingTrace): Pair<List<KtExpression>, KotlinType?>? {
|
trace: BindingTrace
|
||||||
|
): Pair<List<KtExpression>, KotlinType?>? {
|
||||||
val resolvedCall = trace[COLLECTION_LITERAL_CALL, expression] ?: return null
|
val resolvedCall = trace[COLLECTION_LITERAL_CALL, expression] ?: return null
|
||||||
return getArgumentExpressionsForArrayLikeCall(resolvedCall)
|
return getArgumentExpressionsForArrayLikeCall(resolvedCall)
|
||||||
}
|
}
|
||||||
@@ -222,7 +228,8 @@ class ConstantExpressionEvaluator(
|
|||||||
private fun resolveAnnotationValueArguments(
|
private fun resolveAnnotationValueArguments(
|
||||||
resolvedValueArgument: ResolvedValueArgument,
|
resolvedValueArgument: ResolvedValueArgument,
|
||||||
expectedType: KotlinType,
|
expectedType: KotlinType,
|
||||||
trace: BindingTrace): List<CompileTimeConstant<*>> {
|
trace: BindingTrace
|
||||||
|
): List<CompileTimeConstant<*>> {
|
||||||
val constants = ArrayList<CompileTimeConstant<*>>()
|
val constants = ArrayList<CompileTimeConstant<*>>()
|
||||||
for (argument in resolvedValueArgument.arguments) {
|
for (argument in resolvedValueArgument.arguments) {
|
||||||
val argumentExpression = argument.getArgumentExpression() ?: continue
|
val argumentExpression = argument.getArgumentExpression() ?: continue
|
||||||
@@ -260,7 +267,8 @@ class ConstantExpressionEvaluator(
|
|||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic fun getConstant(expression: KtExpression, bindingContext: BindingContext): CompileTimeConstant<*>? {
|
@JvmStatic
|
||||||
|
fun getConstant(expression: KtExpression, bindingContext: BindingContext): CompileTimeConstant<*>? {
|
||||||
val constant = getPossiblyErrorConstant(expression, bindingContext) ?: return null
|
val constant = getPossiblyErrorConstant(expression, bindingContext) ?: return null
|
||||||
return if (!constant.isError) constant else null
|
return if (!constant.isError) constant else null
|
||||||
}
|
}
|
||||||
@@ -315,7 +323,10 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
return entry.accept(this, null)
|
return entry.accept(this, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitStringTemplateEntryWithExpression(entry: KtStringTemplateEntryWithExpression, data: Nothing?): TypedCompileTimeConstant<String>? {
|
override fun visitStringTemplateEntryWithExpression(
|
||||||
|
entry: KtStringTemplateEntryWithExpression,
|
||||||
|
data: Nothing?
|
||||||
|
): TypedCompileTimeConstant<String>? {
|
||||||
val expression = entry.expression ?: return null
|
val expression = entry.expression ?: return null
|
||||||
|
|
||||||
return evaluate(expression, constantExpressionEvaluator.builtIns.stringType)?.let {
|
return evaluate(expression, constantExpressionEvaluator.builtIns.stringType)?.let {
|
||||||
@@ -323,9 +334,11 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitLiteralStringTemplateEntry(entry: KtLiteralStringTemplateEntry, data: Nothing?) = factory.createStringValue(entry.text).wrap()
|
override fun visitLiteralStringTemplateEntry(entry: KtLiteralStringTemplateEntry, data: Nothing?) =
|
||||||
|
factory.createStringValue(entry.text).wrap()
|
||||||
|
|
||||||
override fun visitEscapeStringTemplateEntry(entry: KtEscapeStringTemplateEntry, data: Nothing?) = factory.createStringValue(entry.unescapedValue).wrap()
|
override fun visitEscapeStringTemplateEntry(entry: KtEscapeStringTemplateEntry, data: Nothing?) =
|
||||||
|
factory.createStringValue(entry.unescapedValue).wrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitConstantExpression(expression: KtConstantExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
override fun visitConstantExpression(expression: KtConstantExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
||||||
@@ -360,7 +373,11 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val isLongWithSuffix = nodeElementType == KtNodeTypes.INTEGER_CONSTANT && hasLongSuffix(text)
|
val isLongWithSuffix = nodeElementType == KtNodeTypes.INTEGER_CONSTANT && hasLongSuffix(text)
|
||||||
return createConstant(result, expectedType, CompileTimeConstant.Parameters(true, !isLongWithSuffix, false, usesNonConstValAsConstant = false))
|
return createConstant(
|
||||||
|
result,
|
||||||
|
expectedType,
|
||||||
|
CompileTimeConstant.Parameters(true, !isLongWithSuffix, false, usesNonConstValAsConstant = false)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitParenthesizedExpression(expression: KtParenthesizedExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
override fun visitParenthesizedExpression(expression: KtParenthesizedExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
||||||
@@ -390,8 +407,7 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
if (constant == null) {
|
if (constant == null) {
|
||||||
interupted = true
|
interupted = true
|
||||||
break
|
break
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (!constant.canBeUsedInAnnotations) canBeUsedInAnnotation = false
|
if (!constant.canBeUsedInAnnotations) canBeUsedInAnnotation = false
|
||||||
if (constant.usesVariableAsConstant) usesVariableAsConstant = true
|
if (constant.usesVariableAsConstant) usesVariableAsConstant = true
|
||||||
if (constant.usesNonConstValAsConstant) usesNonConstantVariableAsConstant = true
|
if (constant.usesNonConstValAsConstant) usesNonConstantVariableAsConstant = true
|
||||||
@@ -416,7 +432,10 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
return ConstantExpressionEvaluator.getConstant(expression, trace.bindingContext)?.isStandaloneOnlyConstant() ?: return false
|
return ConstantExpressionEvaluator.getConstant(expression, trace.bindingContext)?.isStandaloneOnlyConstant() ?: return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitBinaryWithTypeRHSExpression(expression: KtBinaryExpressionWithTypeRHS, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
override fun visitBinaryWithTypeRHSExpression(
|
||||||
|
expression: KtBinaryExpressionWithTypeRHS,
|
||||||
|
expectedType: KotlinType?
|
||||||
|
): CompileTimeConstant<*>? {
|
||||||
val compileTimeConstant = evaluate(expression.left, expectedType)
|
val compileTimeConstant = evaluate(expression.left, expectedType)
|
||||||
if (compileTimeConstant != null) {
|
if (compileTimeConstant != null) {
|
||||||
if (expectedType != null && !TypeUtils.noExpectedType(expectedType)) {
|
if (expectedType != null && !TypeUtils.noExpectedType(expectedType)) {
|
||||||
@@ -467,18 +486,24 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
usesNonConstValAsConstant = leftConstant.usesNonConstValAsConstant || rightConstant.usesNonConstValAsConstant
|
usesNonConstValAsConstant = leftConstant.usesNonConstValAsConstant || rightConstant.usesNonConstValAsConstant
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return evaluateCall(expression.operationReference, leftExpression, expectedType)
|
return evaluateCall(expression.operationReference, leftExpression, expectedType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitCollectionLiteralExpression(expression: KtCollectionLiteralExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
override fun visitCollectionLiteralExpression(
|
||||||
|
expression: KtCollectionLiteralExpression,
|
||||||
|
expectedType: KotlinType?
|
||||||
|
): CompileTimeConstant<*>? {
|
||||||
val resolvedCall = trace.bindingContext[COLLECTION_LITERAL_CALL, expression] ?: return null
|
val resolvedCall = trace.bindingContext[COLLECTION_LITERAL_CALL, expression] ?: return null
|
||||||
return createConstantValueForArrayFunctionCall(resolvedCall)
|
return createConstantValueForArrayFunctionCall(resolvedCall)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun evaluateCall(callExpression: KtExpression, receiverExpression: KtExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
private fun evaluateCall(
|
||||||
|
callExpression: KtExpression,
|
||||||
|
receiverExpression: KtExpression,
|
||||||
|
expectedType: KotlinType?
|
||||||
|
): CompileTimeConstant<*>? {
|
||||||
val resolvedCall = callExpression.getResolvedCall(trace.bindingContext) ?: return null
|
val resolvedCall = callExpression.getResolvedCall(trace.bindingContext) ?: return null
|
||||||
if (!KotlinBuiltIns.isUnderKotlinPackage(resolvedCall.resultingDescriptor)) return null
|
if (!KotlinBuiltIns.isUnderKotlinPackage(resolvedCall.resultingDescriptor)) return null
|
||||||
|
|
||||||
@@ -504,10 +529,10 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
CompileTimeConstant.Parameters(
|
CompileTimeConstant.Parameters(
|
||||||
canBeUsedInAnnotation,
|
canBeUsedInAnnotation,
|
||||||
!isNumberConversionMethod && isArgumentPure,
|
!isNumberConversionMethod && isArgumentPure,
|
||||||
usesVariableAsConstant, usesNonConstValAsConstant)
|
usesVariableAsConstant, usesNonConstValAsConstant
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
else if (argumentsEntrySet.size == 1) {
|
} else if (argumentsEntrySet.size == 1) {
|
||||||
val (parameter, argument) = argumentsEntrySet.first()
|
val (parameter, argument) = argumentsEntrySet.first()
|
||||||
val argumentForParameter = createOperationArgumentForFirstParameter(argument, parameter) ?: return null
|
val argumentForParameter = createOperationArgumentForFirstParameter(argument, parameter) ?: return null
|
||||||
if (isStandaloneOnlyConstant(argumentForParameter.expression)) {
|
if (isStandaloneOnlyConstant(argumentForParameter.expression)) {
|
||||||
@@ -524,15 +549,23 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = evaluateBinaryAndCheck(argumentForReceiver, argumentForParameter, resultingDescriptorName.asString(), callExpression) ?: return null
|
val result =
|
||||||
|
evaluateBinaryAndCheck(argumentForReceiver, argumentForParameter, resultingDescriptorName.asString(), callExpression)
|
||||||
|
?: return null
|
||||||
|
|
||||||
val areArgumentsPure = isPureConstant(argumentForReceiver.expression) && isPureConstant(argumentForParameter.expression)
|
val areArgumentsPure = isPureConstant(argumentForReceiver.expression) && isPureConstant(argumentForParameter.expression)
|
||||||
val canBeUsedInAnnotation = canBeUsedInAnnotation(argumentForReceiver.expression) && canBeUsedInAnnotation(argumentForParameter.expression)
|
val canBeUsedInAnnotation =
|
||||||
val usesVariableAsConstant = usesVariableAsConstant(argumentForReceiver.expression) || usesVariableAsConstant(argumentForParameter.expression)
|
canBeUsedInAnnotation(argumentForReceiver.expression) && canBeUsedInAnnotation(argumentForParameter.expression)
|
||||||
val usesNonConstValAsConstant = usesNonConstValAsConstant(argumentForReceiver.expression) || usesNonConstValAsConstant(argumentForParameter.expression)
|
val usesVariableAsConstant =
|
||||||
val parameters = CompileTimeConstant.Parameters(canBeUsedInAnnotation, areArgumentsPure, usesVariableAsConstant, usesNonConstValAsConstant)
|
usesVariableAsConstant(argumentForReceiver.expression) || usesVariableAsConstant(argumentForParameter.expression)
|
||||||
|
val usesNonConstValAsConstant =
|
||||||
|
usesNonConstValAsConstant(argumentForReceiver.expression) || usesNonConstValAsConstant(argumentForParameter.expression)
|
||||||
|
val parameters =
|
||||||
|
CompileTimeConstant.Parameters(canBeUsedInAnnotation, areArgumentsPure, usesVariableAsConstant, usesNonConstValAsConstant)
|
||||||
return when (resultingDescriptorName) {
|
return when (resultingDescriptorName) {
|
||||||
OperatorNameConventions.COMPARE_TO -> createCompileTimeConstantForCompareTo(result, callExpression, factory)?.wrap(parameters)
|
OperatorNameConventions.COMPARE_TO -> createCompileTimeConstantForCompareTo(result, callExpression, factory)?.wrap(
|
||||||
|
parameters
|
||||||
|
)
|
||||||
OperatorNameConventions.EQUALS -> createCompileTimeConstantForEquals(result, callExpression, factory)?.wrap(parameters)
|
OperatorNameConventions.EQUALS -> createCompileTimeConstantForEquals(result, callExpression, factory)?.wrap(parameters)
|
||||||
else -> {
|
else -> {
|
||||||
createConstant(result, expectedType, parameters)
|
createConstant(result, expectedType, parameters)
|
||||||
@@ -543,13 +576,17 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun usesVariableAsConstant(expression: KtExpression) = ConstantExpressionEvaluator.getConstant(expression, trace.bindingContext)?.usesVariableAsConstant ?: false
|
private fun usesVariableAsConstant(expression: KtExpression) =
|
||||||
private fun usesNonConstValAsConstant(expression: KtExpression)
|
ConstantExpressionEvaluator.getConstant(expression, trace.bindingContext)?.usesVariableAsConstant ?: false
|
||||||
= ConstantExpressionEvaluator.getConstant(expression, trace.bindingContext)?.usesNonConstValAsConstant ?: false
|
|
||||||
|
|
||||||
private fun canBeUsedInAnnotation(expression: KtExpression) = ConstantExpressionEvaluator.getConstant(expression, trace.bindingContext)?.canBeUsedInAnnotations ?: false
|
private fun usesNonConstValAsConstant(expression: KtExpression) =
|
||||||
|
ConstantExpressionEvaluator.getConstant(expression, trace.bindingContext)?.usesNonConstValAsConstant ?: false
|
||||||
|
|
||||||
private fun isPureConstant(expression: KtExpression) = ConstantExpressionEvaluator.getConstant(expression, trace.bindingContext)?.isPure ?: false
|
private fun canBeUsedInAnnotation(expression: KtExpression) =
|
||||||
|
ConstantExpressionEvaluator.getConstant(expression, trace.bindingContext)?.canBeUsedInAnnotations ?: false
|
||||||
|
|
||||||
|
private fun isPureConstant(expression: KtExpression) =
|
||||||
|
ConstantExpressionEvaluator.getConstant(expression, trace.bindingContext)?.isPure ?: false
|
||||||
|
|
||||||
private fun evaluateUnaryAndCheck(receiver: OperationArgument, name: String, callExpression: KtExpression): Any? {
|
private fun evaluateUnaryAndCheck(receiver: OperationArgument, name: String, callExpression: KtExpression): Any? {
|
||||||
val functions = unaryOperations[UnaryOperationKey(receiver.ctcType, name)] ?: return null
|
val functions = unaryOperations[UnaryOperationKey(receiver.ctcType, name)] ?: return null
|
||||||
@@ -568,14 +605,18 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun evaluateBinaryAndCheck(receiver: OperationArgument, parameter: OperationArgument, name: String, callExpression: KtExpression): Any? {
|
private fun evaluateBinaryAndCheck(
|
||||||
|
receiver: OperationArgument,
|
||||||
|
parameter: OperationArgument,
|
||||||
|
name: String,
|
||||||
|
callExpression: KtExpression
|
||||||
|
): Any? {
|
||||||
val functions = getBinaryOperation(receiver, parameter, name) ?: return null
|
val functions = getBinaryOperation(receiver, parameter, name) ?: return null
|
||||||
|
|
||||||
val (function, checker) = functions
|
val (function, checker) = functions
|
||||||
val actualResult = try {
|
val actualResult = try {
|
||||||
function(receiver.value, parameter.value)
|
function(receiver.value, parameter.value)
|
||||||
}
|
} catch (e: Exception) {
|
||||||
catch (e: Exception) {
|
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
if (checker == emptyBinaryFun) {
|
if (checker == emptyBinaryFun) {
|
||||||
@@ -587,8 +628,7 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
|
|
||||||
val refinedChecker = if (name == OperatorNameConventions.MOD.asString()) {
|
val refinedChecker = if (name == OperatorNameConventions.MOD.asString()) {
|
||||||
getBinaryOperation(receiver, parameter, OperatorNameConventions.REM.asString())?.second ?: return null
|
getBinaryOperation(receiver, parameter, OperatorNameConventions.REM.asString())?.second ?: return null
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
checker
|
checker
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -769,7 +809,10 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
return createOperationArgument(expression, receiverExpressionType, receiverCompileTimeType)
|
return createOperationArgument(expression, receiverExpressionType, receiverCompileTimeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createOperationArgumentForFirstParameter(argument: ResolvedValueArgument, parameter: ValueParameterDescriptor): OperationArgument? {
|
private fun createOperationArgumentForFirstParameter(
|
||||||
|
argument: ResolvedValueArgument,
|
||||||
|
parameter: ValueParameterDescriptor
|
||||||
|
): OperationArgument? {
|
||||||
val argumentCompileTimeType = getCompileTimeType(parameter.type) ?: return null
|
val argumentCompileTimeType = getCompileTimeType(parameter.type) ?: return null
|
||||||
|
|
||||||
val arguments = argument.arguments
|
val arguments = argument.arguments
|
||||||
@@ -798,7 +841,11 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createOperationArgument(expression: KtExpression, parameterType: KotlinType, compileTimeType: CompileTimeType<*>): OperationArgument? {
|
private fun createOperationArgument(
|
||||||
|
expression: KtExpression,
|
||||||
|
parameterType: KotlinType,
|
||||||
|
compileTimeType: CompileTimeType<*>
|
||||||
|
): OperationArgument? {
|
||||||
val compileTimeConstant = constantExpressionEvaluator.evaluateExpression(expression, trace, parameterType) ?: return null
|
val compileTimeConstant = constantExpressionEvaluator.evaluateExpression(expression, trace, parameterType) ?: return null
|
||||||
if (compileTimeConstant is TypedCompileTimeConstant && !compileTimeConstant.type.isSubtypeOf(parameterType)) return null
|
if (compileTimeConstant is TypedCompileTimeConstant && !compileTimeConstant.type.isSubtypeOf(parameterType)) return null
|
||||||
val evaluationResult = compileTimeConstant.getValue(parameterType) ?: return null
|
val evaluationResult = compileTimeConstant.getValue(parameterType) ?: return null
|
||||||
@@ -812,8 +859,7 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
): CompileTimeConstant<*>? {
|
): CompileTimeConstant<*>? {
|
||||||
return if (parameters.isPure) {
|
return if (parameters.isPure) {
|
||||||
return createCompileTimeConstant(value, parameters, expectedType ?: TypeUtils.NO_EXPECTED_TYPE)
|
return createCompileTimeConstant(value, parameters, expectedType ?: TypeUtils.NO_EXPECTED_TYPE)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
factory.createConstantValue(value)?.wrap(parameters)
|
factory.createConstantValue(value)?.wrap(parameters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -847,16 +893,16 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
}.wrap(parameters)
|
}.wrap(parameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T> ConstantValue<T>.wrap(parameters: CompileTimeConstant.Parameters): TypedCompileTimeConstant<T>
|
private fun <T> ConstantValue<T>.wrap(parameters: CompileTimeConstant.Parameters): TypedCompileTimeConstant<T> =
|
||||||
= TypedCompileTimeConstant(this, parameters)
|
TypedCompileTimeConstant(this, parameters)
|
||||||
|
|
||||||
private fun <T> ConstantValue<T>.wrap(
|
private fun <T> ConstantValue<T>.wrap(
|
||||||
canBeUsedInAnnotation: Boolean = this !is NullValue,
|
canBeUsedInAnnotation: Boolean = this !is NullValue,
|
||||||
isPure: Boolean = false,
|
isPure: Boolean = false,
|
||||||
usesVariableAsConstant: Boolean = false,
|
usesVariableAsConstant: Boolean = false,
|
||||||
usesNonConstValAsConstant: Boolean = false
|
usesNonConstValAsConstant: Boolean = false
|
||||||
): TypedCompileTimeConstant<T>
|
): TypedCompileTimeConstant<T> =
|
||||||
= wrap(CompileTimeConstant.Parameters(canBeUsedInAnnotation, isPure, usesVariableAsConstant, usesNonConstValAsConstant))
|
wrap(CompileTimeConstant.Parameters(canBeUsedInAnnotation, isPure, usesVariableAsConstant, usesNonConstValAsConstant))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hasLongSuffix(text: String) = text.endsWith('l') || text.endsWith('L')
|
private fun hasLongSuffix(text: String) = text.endsWith('l') || text.endsWith('L')
|
||||||
@@ -877,8 +923,7 @@ private fun parseLong(text: String): Long? {
|
|||||||
|
|
||||||
val (number, radix) = extractRadix(text)
|
val (number, radix) = extractRadix(text)
|
||||||
return parseLong(number, radix)
|
return parseLong(number, radix)
|
||||||
}
|
} catch (e: NumberFormatException) {
|
||||||
catch (e: NumberFormatException) {
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -893,8 +938,7 @@ private fun parseFloatingLiteral(text: String): Any? {
|
|||||||
private fun parseDouble(text: String): Double? {
|
private fun parseDouble(text: String): Double? {
|
||||||
try {
|
try {
|
||||||
return java.lang.Double.parseDouble(text)
|
return java.lang.Double.parseDouble(text)
|
||||||
}
|
} catch (e: NumberFormatException) {
|
||||||
catch (e: NumberFormatException) {
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -902,8 +946,7 @@ private fun parseDouble(text: String): Double? {
|
|||||||
private fun parseFloat(text: String): Float? {
|
private fun parseFloat(text: String): Float? {
|
||||||
try {
|
try {
|
||||||
return java.lang.Float.parseFloat(text)
|
return java.lang.Float.parseFloat(text)
|
||||||
}
|
} catch (e: NumberFormatException) {
|
||||||
catch (e: NumberFormatException) {
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -911,8 +954,7 @@ private fun parseFloat(text: String): Float? {
|
|||||||
private fun parseBoolean(text: String): Boolean {
|
private fun parseBoolean(text: String): Boolean {
|
||||||
if ("true".equals(text)) {
|
if ("true".equals(text)) {
|
||||||
return true
|
return true
|
||||||
}
|
} else if ("false".equals(text)) {
|
||||||
else if ("false".equals(text)) {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -920,7 +962,11 @@ private fun parseBoolean(text: String): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun createCompileTimeConstantForEquals(result: Any?, operationReference: KtExpression, factory: ConstantValueFactory): ConstantValue<*>? {
|
private fun createCompileTimeConstantForEquals(
|
||||||
|
result: Any?,
|
||||||
|
operationReference: KtExpression,
|
||||||
|
factory: ConstantValueFactory
|
||||||
|
): ConstantValue<*>? {
|
||||||
if (result is Boolean) {
|
if (result is Boolean) {
|
||||||
assert(operationReference is KtSimpleNameExpression) { "This method should be called only for equals operations" }
|
assert(operationReference is KtSimpleNameExpression) { "This method should be called only for equals operations" }
|
||||||
val operationToken = (operationReference as KtSimpleNameExpression).getReferencedNameElementType()
|
val operationToken = (operationReference as KtSimpleNameExpression).getReferencedNameElementType()
|
||||||
@@ -938,7 +984,11 @@ private fun createCompileTimeConstantForEquals(result: Any?, operationReference:
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createCompileTimeConstantForCompareTo(result: Any?, operationReference: KtExpression, factory: ConstantValueFactory): ConstantValue<*>? {
|
private fun createCompileTimeConstantForCompareTo(
|
||||||
|
result: Any?,
|
||||||
|
operationReference: KtExpression,
|
||||||
|
factory: ConstantValueFactory
|
||||||
|
): ConstantValue<*>? {
|
||||||
if (result is Int) {
|
if (result is Int) {
|
||||||
assert(operationReference is KtSimpleNameExpression) { "This method should be called only for compareTo operations" }
|
assert(operationReference is KtSimpleNameExpression) { "This method should be called only for compareTo operations" }
|
||||||
val operationToken = (operationReference as KtSimpleNameExpression).getReferencedNameElementType()
|
val operationToken = (operationReference as KtSimpleNameExpression).getReferencedNameElementType()
|
||||||
@@ -991,7 +1041,10 @@ internal fun <A, B> binaryOperation(
|
|||||||
functionName: String,
|
functionName: String,
|
||||||
operation: Function2<A, B, Any>,
|
operation: Function2<A, B, Any>,
|
||||||
checker: Function2<BigInteger, BigInteger, BigInteger>
|
checker: Function2<BigInteger, BigInteger, BigInteger>
|
||||||
) = BinaryOperationKey(a, b, functionName) to Pair(operation, checker) as Pair<Function2<Any?, Any?, Any>, Function2<BigInteger, BigInteger, BigInteger>>
|
) = BinaryOperationKey(a, b, functionName) to Pair(
|
||||||
|
operation,
|
||||||
|
checker
|
||||||
|
) as Pair<Function2<Any?, Any?, Any>, Function2<BigInteger, BigInteger, BigInteger>>
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
internal fun <A> unaryOperation(
|
internal fun <A> unaryOperation(
|
||||||
|
|||||||
+4
-4
@@ -24,8 +24,8 @@ import java.util.HashMap
|
|||||||
internal val emptyBinaryFun: Function2<BigInteger, BigInteger, BigInteger> = { a, b -> BigInteger("0") }
|
internal val emptyBinaryFun: Function2<BigInteger, BigInteger, BigInteger> = { a, b -> BigInteger("0") }
|
||||||
internal val emptyUnaryFun: Function1<Long, Long> = { a -> 1.toLong() }
|
internal val emptyUnaryFun: Function1<Long, Long> = { a -> 1.toLong() }
|
||||||
|
|
||||||
internal val unaryOperations: HashMap<UnaryOperationKey<*>, Pair<Function1<Any?, Any>, Function1<Long, Long>>>
|
internal val unaryOperations: HashMap<UnaryOperationKey<*>, Pair<Function1<Any?, Any>, Function1<Long, Long>>> =
|
||||||
= hashMapOf<UnaryOperationKey<*>, Pair<Function1<Any?, Any>, Function1<Long, Long>>>(
|
hashMapOf<UnaryOperationKey<*>, Pair<Function1<Any?, Any>, Function1<Long, Long>>>(
|
||||||
unaryOperation(BOOLEAN, "not", { a -> a.not() }, emptyUnaryFun),
|
unaryOperation(BOOLEAN, "not", { a -> a.not() }, emptyUnaryFun),
|
||||||
unaryOperation(BOOLEAN, "toString", { a -> a.toString() }, emptyUnaryFun),
|
unaryOperation(BOOLEAN, "toString", { a -> a.toString() }, emptyUnaryFun),
|
||||||
unaryOperation(BYTE, "toByte", { a -> a.toByte() }, emptyUnaryFun),
|
unaryOperation(BYTE, "toByte", { a -> a.toByte() }, emptyUnaryFun),
|
||||||
@@ -102,8 +102,8 @@ internal val unaryOperations: HashMap<UnaryOperationKey<*>, Pair<Function1<Any?,
|
|||||||
unaryOperation(STRING, "toString", { a -> a.toString() }, emptyUnaryFun)
|
unaryOperation(STRING, "toString", { a -> a.toString() }, emptyUnaryFun)
|
||||||
)
|
)
|
||||||
|
|
||||||
internal val binaryOperations: HashMap<BinaryOperationKey<*, *>, Pair<Function2<Any?, Any?, Any>, Function2<BigInteger, BigInteger, BigInteger>>>
|
internal val binaryOperations: HashMap<BinaryOperationKey<*, *>, Pair<Function2<Any?, Any?, Any>, Function2<BigInteger, BigInteger, BigInteger>>> =
|
||||||
= hashMapOf<BinaryOperationKey<*, *>, Pair<Function2<Any?, Any?, Any>, Function2<BigInteger, BigInteger, BigInteger>>>(
|
hashMapOf<BinaryOperationKey<*, *>, Pair<Function2<Any?, Any?, Any>, Function2<BigInteger, BigInteger, BigInteger>>>(
|
||||||
binaryOperation(BOOLEAN, BOOLEAN, "and", { a, b -> a.and(b) }, emptyBinaryFun),
|
binaryOperation(BOOLEAN, BOOLEAN, "and", { a, b -> a.and(b) }, emptyBinaryFun),
|
||||||
binaryOperation(BOOLEAN, BOOLEAN, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun),
|
binaryOperation(BOOLEAN, BOOLEAN, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun),
|
||||||
binaryOperation(BOOLEAN, ANY, "equals", { a, b -> a.equals(b) }, emptyBinaryFun),
|
binaryOperation(BOOLEAN, ANY, "equals", { a, b -> a.equals(b) }, emptyBinaryFun),
|
||||||
|
|||||||
@@ -97,7 +97,8 @@ private data class DeprecatedByOverridden(private val deprecations: Collection<D
|
|||||||
return "${additionalMessage()}. $message"
|
return "${additionalMessage()}. $message"
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun additionalMessage() = "Overrides deprecated member in '${DescriptorUtils.getContainingClass(target)!!.fqNameSafe.asString()}'"
|
internal fun additionalMessage() =
|
||||||
|
"Overrides deprecated member in '${DescriptorUtils.getContainingClass(target)!!.fqNameSafe.asString()}'"
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class DeprecatedByVersionRequirement(
|
private data class DeprecatedByVersionRequirement(
|
||||||
@@ -123,8 +124,7 @@ private data class DeprecatedByVersionRequirement(
|
|||||||
if (errorCode != null) {
|
if (errorCode != null) {
|
||||||
append(" (error code $errorCode)")
|
append(" (error code $errorCode)")
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
append("Error code $errorCode")
|
append("Error code $errorCode")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,8 +155,10 @@ internal fun createDeprecationDiagnostic(
|
|||||||
WARNING -> Errors.VERSION_REQUIREMENT_DEPRECATION
|
WARNING -> Errors.VERSION_REQUIREMENT_DEPRECATION
|
||||||
ERROR, HIDDEN -> Errors.VERSION_REQUIREMENT_DEPRECATION_ERROR
|
ERROR, HIDDEN -> Errors.VERSION_REQUIREMENT_DEPRECATION_ERROR
|
||||||
}
|
}
|
||||||
factory.on(element, targetOriginal, deprecation.versionRequirement.version,
|
factory.on(
|
||||||
languageVersionSettings.languageVersion to deprecation.message)
|
element, targetOriginal, deprecation.versionRequirement.version,
|
||||||
|
languageVersionSettings.languageVersion to deprecation.message
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
is DeprecatedTypealiasByAnnotation -> {
|
is DeprecatedTypealiasByAnnotation -> {
|
||||||
@@ -311,7 +313,11 @@ class DeprecationResolver(
|
|||||||
|
|
||||||
fun addUseSiteTargetedDeprecationIfPresent(annotatedDescriptor: DeclarationDescriptor, useSiteTarget: AnnotationUseSiteTarget?) {
|
fun addUseSiteTargetedDeprecationIfPresent(annotatedDescriptor: DeclarationDescriptor, useSiteTarget: AnnotationUseSiteTarget?) {
|
||||||
if (useSiteTarget != null) {
|
if (useSiteTarget != null) {
|
||||||
val annotation = Annotations.findUseSiteTargetedAnnotation(annotatedDescriptor.annotations, useSiteTarget, KotlinBuiltIns.FQ_NAMES.deprecated)
|
val annotation = Annotations.findUseSiteTargetedAnnotation(
|
||||||
|
annotatedDescriptor.annotations,
|
||||||
|
useSiteTarget,
|
||||||
|
KotlinBuiltIns.FQ_NAMES.deprecated
|
||||||
|
)
|
||||||
?: Annotations.findUseSiteTargetedAnnotation(annotatedDescriptor.annotations, useSiteTarget, JAVA_DEPRECATED)
|
?: Annotations.findUseSiteTargetedAnnotation(annotatedDescriptor.annotations, useSiteTarget, JAVA_DEPRECATED)
|
||||||
if (annotation != null) {
|
if (annotation != null) {
|
||||||
result.add(DeprecatedByAnnotation(annotation, this))
|
result.add(DeprecatedByAnnotation(annotation, this))
|
||||||
|
|||||||
+22
-15
@@ -43,8 +43,7 @@ class InlineAnalyzerExtension(
|
|||||||
}
|
}
|
||||||
checkDefaults(descriptor, functionOrProperty as KtNamedFunction, trace)
|
checkDefaults(descriptor, functionOrProperty as KtNamedFunction, trace)
|
||||||
checkHasInlinableAndNullability(descriptor, functionOrProperty, trace)
|
checkHasInlinableAndNullability(descriptor, functionOrProperty, trace)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
assert(descriptor is PropertyDescriptor) {
|
assert(descriptor is PropertyDescriptor) {
|
||||||
"PropertyDescriptor expected, but was $descriptor"
|
"PropertyDescriptor expected, but was $descriptor"
|
||||||
}
|
}
|
||||||
@@ -59,7 +58,11 @@ class InlineAnalyzerExtension(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun notSupportedInInlineCheck(descriptor: CallableMemberDescriptor, functionOrProperty: KtCallableDeclaration, trace: BindingTrace) {
|
private fun notSupportedInInlineCheck(
|
||||||
|
descriptor: CallableMemberDescriptor,
|
||||||
|
functionOrProperty: KtCallableDeclaration,
|
||||||
|
trace: BindingTrace
|
||||||
|
) {
|
||||||
val visitor = object : KtVisitorVoid() {
|
val visitor = object : KtVisitorVoid() {
|
||||||
override fun visitKtElement(element: KtElement) {
|
override fun visitKtElement(element: KtElement) {
|
||||||
super.visitKtElement(element)
|
super.visitKtElement(element)
|
||||||
@@ -73,8 +76,7 @@ class InlineAnalyzerExtension(
|
|||||||
override fun visitNamedFunction(function: KtNamedFunction) {
|
override fun visitNamedFunction(function: KtNamedFunction) {
|
||||||
if (function.parent.parent is KtObjectDeclaration) {
|
if (function.parent.parent is KtObjectDeclaration) {
|
||||||
super.visitNamedFunction(function)
|
super.visitNamedFunction(function)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
trace.report(Errors.NOT_YET_SUPPORTED_IN_INLINE.on(function, "Local functions"))
|
trace.report(Errors.NOT_YET_SUPPORTED_IN_INLINE.on(function, "Local functions"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,7 +88,8 @@ class InlineAnalyzerExtension(
|
|||||||
private fun checkDefaults(
|
private fun checkDefaults(
|
||||||
functionDescriptor: FunctionDescriptor,
|
functionDescriptor: FunctionDescriptor,
|
||||||
function: KtFunction,
|
function: KtFunction,
|
||||||
trace: BindingTrace) {
|
trace: BindingTrace
|
||||||
|
) {
|
||||||
val ktParameters = function.valueParameters
|
val ktParameters = function.valueParameters
|
||||||
for (parameter in functionDescriptor.valueParameters) {
|
for (parameter in functionDescriptor.valueParameters) {
|
||||||
if (parameter.hasDefaultValue()) {
|
if (parameter.hasDefaultValue()) {
|
||||||
@@ -95,9 +98,13 @@ class InlineAnalyzerExtension(
|
|||||||
val inheritDefaultValues = !parameter.declaresDefaultValue()
|
val inheritDefaultValues = !parameter.declaresDefaultValue()
|
||||||
if (checkInlinableParameter(parameter, ktParameter, functionDescriptor, null) || inheritDefaultValues) {
|
if (checkInlinableParameter(parameter, ktParameter, functionDescriptor, null) || inheritDefaultValues) {
|
||||||
if (inheritDefaultValues || !languageVersionSettings.supportsFeature(LanguageFeature.InlineDefaultFunctionalParameters)) {
|
if (inheritDefaultValues || !languageVersionSettings.supportsFeature(LanguageFeature.InlineDefaultFunctionalParameters)) {
|
||||||
trace.report(Errors.NOT_YET_SUPPORTED_IN_INLINE.on(ktParameter, "Functional parameters with inherited default values"))
|
trace.report(
|
||||||
}
|
Errors.NOT_YET_SUPPORTED_IN_INLINE.on(
|
||||||
else {
|
ktParameter,
|
||||||
|
"Functional parameters with inherited default values"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
checkDefaultValue(trace, parameter, ktParameter)
|
checkDefaultValue(trace, parameter, ktParameter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,7 +123,8 @@ class InlineAnalyzerExtension(
|
|||||||
private fun checkModalityAndOverrides(
|
private fun checkModalityAndOverrides(
|
||||||
callableDescriptor: CallableMemberDescriptor,
|
callableDescriptor: CallableMemberDescriptor,
|
||||||
functionOrProperty: KtCallableDeclaration,
|
functionOrProperty: KtCallableDeclaration,
|
||||||
trace: BindingTrace) {
|
trace: BindingTrace
|
||||||
|
) {
|
||||||
if (callableDescriptor.containingDeclaration is PackageFragmentDescriptor) {
|
if (callableDescriptor.containingDeclaration is PackageFragmentDescriptor) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -155,8 +163,7 @@ class InlineAnalyzerExtension(
|
|||||||
|
|
||||||
private fun checkHasInlinableAndNullability(functionDescriptor: FunctionDescriptor, function: KtFunction, trace: BindingTrace) {
|
private fun checkHasInlinableAndNullability(functionDescriptor: FunctionDescriptor, function: KtFunction, trace: BindingTrace) {
|
||||||
var hasInlineArgs = false
|
var hasInlineArgs = false
|
||||||
function.valueParameters.zip(functionDescriptor.valueParameters).forEach {
|
function.valueParameters.zip(functionDescriptor.valueParameters).forEach { (parameter, descriptor) ->
|
||||||
(parameter, descriptor) ->
|
|
||||||
hasInlineArgs = hasInlineArgs or checkInlinableParameter(descriptor, parameter, functionDescriptor, trace)
|
hasInlineArgs = hasInlineArgs or checkInlinableParameter(descriptor, parameter, functionDescriptor, trace)
|
||||||
}
|
}
|
||||||
if (hasInlineArgs) return
|
if (hasInlineArgs) return
|
||||||
@@ -173,12 +180,12 @@ class InlineAnalyzerExtension(
|
|||||||
parameter: ParameterDescriptor,
|
parameter: ParameterDescriptor,
|
||||||
expression: KtElement,
|
expression: KtElement,
|
||||||
functionDescriptor: CallableDescriptor,
|
functionDescriptor: CallableDescriptor,
|
||||||
trace: BindingTrace?): Boolean {
|
trace: BindingTrace?
|
||||||
|
): Boolean {
|
||||||
if (InlineUtil.isInlineParameterExceptNullability(parameter)) {
|
if (InlineUtil.isInlineParameterExceptNullability(parameter)) {
|
||||||
if (parameter.type.isMarkedNullable) {
|
if (parameter.type.isMarkedNullable) {
|
||||||
trace?.report(Errors.NULLABLE_INLINE_PARAMETER.on(expression, expression, functionDescriptor))
|
trace?.report(Errors.NULLABLE_INLINE_PARAMETER.on(expression, expression, functionDescriptor))
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,8 +50,7 @@ class DefaultImportProvider(
|
|||||||
|
|
||||||
for (packageFqName in packages) {
|
for (packageFqName in packages) {
|
||||||
dependencyModuleDescriptor.packageFragmentProviderForContent.getPackageFragments(packageFqName)
|
dependencyModuleDescriptor.packageFragmentProviderForContent.getPackageFragments(packageFqName)
|
||||||
.flatMapTo(result) {
|
.flatMapTo(result) { packageFragmentDescriptor ->
|
||||||
packageFragmentDescriptor ->
|
|
||||||
packageFragmentDescriptor.getMemberScope()
|
packageFragmentDescriptor.getMemberScope()
|
||||||
.getContributedDescriptors(DescriptorKindFilter.TYPE_ALIASES)
|
.getContributedDescriptors(DescriptorKindFilter.TYPE_ALIASES)
|
||||||
.filterIsInstance<TypeAliasDescriptor>()
|
.filterIsInstance<TypeAliasDescriptor>()
|
||||||
|
|||||||
@@ -103,7 +103,8 @@ open class LazyDeclarationResolver @Deprecated("") constructor(
|
|||||||
getClassDescriptorIfAny(declaration, lookupLocationFor(declaration, declaration.isTopLevel()))
|
getClassDescriptorIfAny(declaration, lookupLocationFor(declaration, declaration.isTopLevel()))
|
||||||
|
|
||||||
override fun visitTypeParameter(parameter: KtTypeParameter, data: Nothing?): DeclarationDescriptor? {
|
override fun visitTypeParameter(parameter: KtTypeParameter, data: Nothing?): DeclarationDescriptor? {
|
||||||
val ownerElement = PsiTreeUtil.getParentOfType(parameter, KtTypeParameterListOwner::class.java) ?: error("Owner not found for type parameter: " + parameter.text)
|
val ownerElement = PsiTreeUtil.getParentOfType(parameter, KtTypeParameterListOwner::class.java)
|
||||||
|
?: error("Owner not found for type parameter: " + parameter.text)
|
||||||
val ownerDescriptor = resolveToDescriptor(ownerElement, /*track =*/false) ?: return null
|
val ownerDescriptor = resolveToDescriptor(ownerElement, /*track =*/false) ?: return null
|
||||||
|
|
||||||
val typeParameters: List<TypeParameterDescriptor>
|
val typeParameters: List<TypeParameterDescriptor>
|
||||||
@@ -136,7 +137,8 @@ open class LazyDeclarationResolver @Deprecated("") constructor(
|
|||||||
classDescriptor == null -> null
|
classDescriptor == null -> null
|
||||||
parameter.hasValOrVar() -> {
|
parameter.hasValOrVar() -> {
|
||||||
classDescriptor.defaultType.memberScope.getContributedVariables(
|
classDescriptor.defaultType.memberScope.getContributedVariables(
|
||||||
parameter.nameAsSafeName, lookupLocationFor(parameter, false))
|
parameter.nameAsSafeName, lookupLocationFor(parameter, false)
|
||||||
|
)
|
||||||
bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter)
|
bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
@@ -202,8 +204,10 @@ open class LazyDeclarationResolver @Deprecated("") constructor(
|
|||||||
getScriptDescriptor(script, lookupLocationFor(script, true))
|
getScriptDescriptor(script, lookupLocationFor(script, true))
|
||||||
|
|
||||||
override fun visitKtElement(element: KtElement, data: Nothing?): DeclarationDescriptor? {
|
override fun visitKtElement(element: KtElement, data: Nothing?): DeclarationDescriptor? {
|
||||||
throw IllegalArgumentException("Unsupported declaration type: " + element + " " +
|
throw IllegalArgumentException(
|
||||||
element.getElementTextWithContext())
|
"Unsupported declaration type: " + element + " " +
|
||||||
|
element.getElementTextWithContext()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}, null)
|
}, null)
|
||||||
}
|
}
|
||||||
@@ -218,13 +222,14 @@ open class LazyDeclarationResolver @Deprecated("") constructor(
|
|||||||
topLevelDescriptorProvider.assertValid()
|
topLevelDescriptorProvider.assertValid()
|
||||||
val packageDescriptor = topLevelDescriptorProvider.getPackageFragmentOrDiagnoseFailure(fqName, ktFile)
|
val packageDescriptor = topLevelDescriptorProvider.getPackageFragmentOrDiagnoseFailure(fqName, ktFile)
|
||||||
return packageDescriptor.getMemberScope()
|
return packageDescriptor.getMemberScope()
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return when (parentDeclaration) {
|
return when (parentDeclaration) {
|
||||||
is KtClassOrObject -> getClassDescriptor(parentDeclaration, location).unsubstitutedMemberScope
|
is KtClassOrObject -> getClassDescriptor(parentDeclaration, location).unsubstitutedMemberScope
|
||||||
is KtScript -> getScriptDescriptor(parentDeclaration, location).unsubstitutedMemberScope
|
is KtScript -> getScriptDescriptor(parentDeclaration, location).unsubstitutedMemberScope
|
||||||
else -> throw IllegalStateException("Don't call this method for local declarations: " + declaration + "\n" +
|
else -> throw IllegalStateException(
|
||||||
declaration.getElementTextWithContext())
|
"Don't call this method for local declarations: " + declaration + "\n" +
|
||||||
|
declaration.getElementTextWithContext()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -30,8 +30,8 @@ class CombinedPackageMemberDeclarationProvider(
|
|||||||
|
|
||||||
override fun containsFile(file: KtFile) = providers.any { it.containsFile(file) }
|
override fun containsFile(file: KtFile) = providers.any { it.containsFile(file) }
|
||||||
|
|
||||||
override fun getDeclarations(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean)
|
override fun getDeclarations(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean) =
|
||||||
= providers.flatMap { it.getDeclarations(kindFilter, nameFilter) }
|
providers.flatMap { it.getDeclarations(kindFilter, nameFilter) }
|
||||||
|
|
||||||
override fun getFunctionDeclarations(name: Name) = providers.flatMap { it.getFunctionDeclarations(name) }
|
override fun getFunctionDeclarations(name: Name) = providers.flatMap { it.getFunctionDeclarations(name) }
|
||||||
|
|
||||||
|
|||||||
+4
-3
@@ -37,7 +37,8 @@ abstract class DeclarationProviderFactoryService {
|
|||||||
): DeclarationProviderFactory
|
): DeclarationProviderFactory
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic fun createDeclarationProviderFactory(
|
@JvmStatic
|
||||||
|
fun createDeclarationProviderFactory(
|
||||||
project: Project,
|
project: Project,
|
||||||
storageManager: StorageManager,
|
storageManager: StorageManager,
|
||||||
syntheticFiles: Collection<KtFile>,
|
syntheticFiles: Collection<KtFile>,
|
||||||
@@ -57,8 +58,8 @@ abstract class DeclarationProviderFactoryService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class SyntheticFilesFilteringScope(syntheticFiles: Collection<KtFile>, baseScope: GlobalSearchScope)
|
private class SyntheticFilesFilteringScope(syntheticFiles: Collection<KtFile>, baseScope: GlobalSearchScope) :
|
||||||
: DelegatingGlobalSearchScope(baseScope) {
|
DelegatingGlobalSearchScope(baseScope) {
|
||||||
|
|
||||||
private val originals = syntheticFiles.mapNotNullTo(HashSet<VirtualFile>()) { it.originalFile.virtualFile }
|
private val originals = syntheticFiles.mapNotNullTo(HashSet<VirtualFile>()) { it.originalFile.virtualFile }
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -21,8 +21,8 @@ import org.jetbrains.kotlin.storage.StorageManager
|
|||||||
|
|
||||||
class PsiBasedClassMemberDeclarationProvider(
|
class PsiBasedClassMemberDeclarationProvider(
|
||||||
storageManager: StorageManager,
|
storageManager: StorageManager,
|
||||||
override val ownerInfo: KtClassLikeInfo)
|
override val ownerInfo: KtClassLikeInfo
|
||||||
: AbstractPsiBasedDeclarationProvider(storageManager), ClassMemberDeclarationProvider {
|
) : AbstractPsiBasedDeclarationProvider(storageManager), ClassMemberDeclarationProvider {
|
||||||
|
|
||||||
override fun doCreateIndex(index: AbstractPsiBasedDeclarationProvider.Index) {
|
override fun doCreateIndex(index: AbstractPsiBasedDeclarationProvider.Index) {
|
||||||
for (declaration in ownerInfo.declarations) {
|
for (declaration in ownerInfo.declarations) {
|
||||||
|
|||||||
+19
-9
@@ -45,10 +45,14 @@ protected constructor(
|
|||||||
) : MemberScopeImpl() {
|
) : MemberScopeImpl() {
|
||||||
|
|
||||||
protected val storageManager: StorageManager = c.storageManager
|
protected val storageManager: StorageManager = c.storageManager
|
||||||
private val classDescriptors: MemoizedFunctionToNotNull<Name, List<ClassDescriptor>> = storageManager.createMemoizedFunction { doGetClasses(it) }
|
private val classDescriptors: MemoizedFunctionToNotNull<Name, List<ClassDescriptor>> =
|
||||||
private val functionDescriptors: MemoizedFunctionToNotNull<Name, Collection<SimpleFunctionDescriptor>> = storageManager.createMemoizedFunction { doGetFunctions(it) }
|
storageManager.createMemoizedFunction { doGetClasses(it) }
|
||||||
private val propertyDescriptors: MemoizedFunctionToNotNull<Name, Collection<PropertyDescriptor>> = storageManager.createMemoizedFunction { doGetProperties(it) }
|
private val functionDescriptors: MemoizedFunctionToNotNull<Name, Collection<SimpleFunctionDescriptor>> =
|
||||||
private val typeAliasDescriptors: MemoizedFunctionToNotNull<Name, Collection<TypeAliasDescriptor>> = storageManager.createMemoizedFunction { doGetTypeAliases(it) }
|
storageManager.createMemoizedFunction { doGetFunctions(it) }
|
||||||
|
private val propertyDescriptors: MemoizedFunctionToNotNull<Name, Collection<PropertyDescriptor>> =
|
||||||
|
storageManager.createMemoizedFunction { doGetProperties(it) }
|
||||||
|
private val typeAliasDescriptors: MemoizedFunctionToNotNull<Name, Collection<TypeAliasDescriptor>> =
|
||||||
|
storageManager.createMemoizedFunction { doGetTypeAliases(it) }
|
||||||
|
|
||||||
private fun doGetClasses(name: Name): List<ClassDescriptor> {
|
private fun doGetClasses(name: Name): List<ClassDescriptor> {
|
||||||
val result = Sets.newLinkedHashSet<ClassDescriptor>()
|
val result = Sets.newLinkedHashSet<ClassDescriptor>()
|
||||||
@@ -92,12 +96,15 @@ protected constructor(
|
|||||||
|
|
||||||
val declarations = declarationProvider.getFunctionDeclarations(name)
|
val declarations = declarationProvider.getFunctionDeclarations(name)
|
||||||
for (functionDeclaration in declarations) {
|
for (functionDeclaration in declarations) {
|
||||||
result.add(c.functionDescriptorResolver.resolveFunctionDescriptor(
|
result.add(
|
||||||
|
c.functionDescriptorResolver.resolveFunctionDescriptor(
|
||||||
thisDescriptor,
|
thisDescriptor,
|
||||||
getScopeForMemberDeclarationResolution(functionDeclaration),
|
getScopeForMemberDeclarationResolution(functionDeclaration),
|
||||||
functionDeclaration,
|
functionDeclaration,
|
||||||
trace,
|
trace,
|
||||||
c.declarationScopeProvider.getOuterDataFlowInfoForDeclaration(functionDeclaration)))
|
c.declarationScopeProvider.getOuterDataFlowInfoForDeclaration(functionDeclaration)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
getNonDeclaredFunctions(name, result)
|
getNonDeclaredFunctions(name, result)
|
||||||
@@ -129,7 +136,8 @@ protected constructor(
|
|||||||
getScopeForInitializerResolution(propertyDeclaration),
|
getScopeForInitializerResolution(propertyDeclaration),
|
||||||
propertyDeclaration,
|
propertyDeclaration,
|
||||||
trace,
|
trace,
|
||||||
c.declarationScopeProvider.getOuterDataFlowInfoForDeclaration(propertyDeclaration))
|
c.declarationScopeProvider.getOuterDataFlowInfoForDeclaration(propertyDeclaration)
|
||||||
|
)
|
||||||
result.add(propertyDescriptor)
|
result.add(propertyDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +148,8 @@ protected constructor(
|
|||||||
getScopeForInitializerResolution(entry),
|
getScopeForInitializerResolution(entry),
|
||||||
entry,
|
entry,
|
||||||
trace,
|
trace,
|
||||||
c.declarationScopeProvider.getOuterDataFlowInfoForDeclaration(entry))
|
c.declarationScopeProvider.getOuterDataFlowInfoForDeclaration(entry)
|
||||||
|
)
|
||||||
result.add(propertyDescriptor)
|
result.add(propertyDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +171,8 @@ protected constructor(
|
|||||||
thisDescriptor,
|
thisDescriptor,
|
||||||
getScopeForMemberDeclarationResolution(ktTypeAlias),
|
getScopeForMemberDeclarationResolution(ktTypeAlias),
|
||||||
ktTypeAlias,
|
ktTypeAlias,
|
||||||
trace)
|
trace
|
||||||
|
)
|
||||||
}.toList()
|
}.toList()
|
||||||
|
|
||||||
protected fun computeDescriptorsFromDeclaredElements(
|
protected fun computeDescriptorsFromDeclaredElements(
|
||||||
|
|||||||
+2
-4
@@ -55,8 +55,7 @@ class LazyAnnotations(
|
|||||||
) : Annotations, LazyEntity {
|
) : Annotations, LazyEntity {
|
||||||
override fun isEmpty() = annotationEntries.isEmpty()
|
override fun isEmpty() = annotationEntries.isEmpty()
|
||||||
|
|
||||||
private val annotation = c.storageManager.createMemoizedFunction {
|
private val annotation = c.storageManager.createMemoizedFunction { entry: KtAnnotationEntry ->
|
||||||
entry: KtAnnotationEntry ->
|
|
||||||
|
|
||||||
val descriptor = LazyAnnotationDescriptor(c, entry)
|
val descriptor = LazyAnnotationDescriptor(c, entry)
|
||||||
val target = entry.useSiteTarget?.getAnnotationUseSiteTarget()
|
val target = entry.useSiteTarget?.getAnnotationUseSiteTarget()
|
||||||
@@ -105,8 +104,7 @@ class LazyAnnotationDescriptor(
|
|||||||
|
|
||||||
private val scope = if (c.scope.ownerDescriptor is PackageFragmentDescriptor) {
|
private val scope = if (c.scope.ownerDescriptor is PackageFragmentDescriptor) {
|
||||||
LexicalScope.Base(c.scope, FileDescriptorForVisibilityChecks(source, c.scope.ownerDescriptor))
|
LexicalScope.Base(c.scope, FileDescriptorForVisibilityChecks(source, c.scope.ownerDescriptor))
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
c.scope
|
c.scope
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+72
-23
@@ -52,14 +52,20 @@ open class LazyClassMemberScope(
|
|||||||
) : AbstractLazyMemberScope<ClassDescriptorWithResolutionScopes, ClassMemberDeclarationProvider>(c, declarationProvider, thisClass, trace) {
|
) : AbstractLazyMemberScope<ClassDescriptorWithResolutionScopes, ClassMemberDeclarationProvider>(c, declarationProvider, thisClass, trace) {
|
||||||
|
|
||||||
private val descriptorsFromDeclaredElements = storageManager.createLazyValue {
|
private val descriptorsFromDeclaredElements = storageManager.createLazyValue {
|
||||||
computeDescriptorsFromDeclaredElements(DescriptorKindFilter.ALL, MemberScope.ALL_NAME_FILTER, NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS)
|
computeDescriptorsFromDeclaredElements(
|
||||||
|
DescriptorKindFilter.ALL,
|
||||||
|
MemberScope.ALL_NAME_FILTER,
|
||||||
|
NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS
|
||||||
|
)
|
||||||
}
|
}
|
||||||
private val extraDescriptors: NotNullLazyValue<Collection<DeclarationDescriptor>> = storageManager.createLazyValue {
|
private val extraDescriptors: NotNullLazyValue<Collection<DeclarationDescriptor>> = storageManager.createLazyValue {
|
||||||
computeExtraDescriptors(NoLookupLocation.FOR_ALREADY_TRACKED)
|
computeExtraDescriptors(NoLookupLocation.FOR_ALREADY_TRACKED)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter,
|
override fun getContributedDescriptors(
|
||||||
nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> {
|
kindFilter: DescriptorKindFilter,
|
||||||
|
nameFilter: (Name) -> Boolean
|
||||||
|
): Collection<DeclarationDescriptor> {
|
||||||
val result = LinkedHashSet(descriptorsFromDeclaredElements())
|
val result = LinkedHashSet(descriptorsFromDeclaredElements())
|
||||||
result.addAll(extraDescriptors())
|
result.addAll(extraDescriptors())
|
||||||
return result
|
return result
|
||||||
@@ -71,8 +77,7 @@ open class LazyClassMemberScope(
|
|||||||
for (descriptor in supertype.memberScope.getContributedDescriptors()) {
|
for (descriptor in supertype.memberScope.getContributedDescriptors()) {
|
||||||
if (descriptor is FunctionDescriptor) {
|
if (descriptor is FunctionDescriptor) {
|
||||||
result.addAll(getContributedFunctions(descriptor.name, location))
|
result.addAll(getContributedFunctions(descriptor.name, location))
|
||||||
}
|
} else if (descriptor is PropertyDescriptor) {
|
||||||
else if (descriptor is PropertyDescriptor) {
|
|
||||||
result.addAll(getContributedVariables(descriptor.name, location))
|
result.addAll(getContributedVariables(descriptor.name, location))
|
||||||
}
|
}
|
||||||
// Nothing else is inherited
|
// Nothing else is inherited
|
||||||
@@ -123,8 +128,8 @@ open class LazyClassMemberScope(
|
|||||||
fun extract(extractFrom: KotlinType, name: Name): Collection<T>
|
fun extract(extractFrom: KotlinType, name: Name): Collection<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
private val primaryConstructor: NullableLazyValue<ClassConstructorDescriptor>
|
private val primaryConstructor: NullableLazyValue<ClassConstructorDescriptor> =
|
||||||
= c.storageManager.createNullableLazyValue { resolvePrimaryConstructor() }
|
c.storageManager.createNullableLazyValue { resolvePrimaryConstructor() }
|
||||||
|
|
||||||
override fun getScopeForMemberDeclarationResolution(declaration: KtDeclaration): LexicalScope =
|
override fun getScopeForMemberDeclarationResolution(declaration: KtDeclaration): LexicalScope =
|
||||||
thisDescriptor.scopeForMemberDeclarationResolution
|
thisDescriptor.scopeForMemberDeclarationResolution
|
||||||
@@ -132,21 +137,47 @@ open class LazyClassMemberScope(
|
|||||||
override fun getScopeForInitializerResolution(declaration: KtDeclaration): LexicalScope =
|
override fun getScopeForInitializerResolution(declaration: KtDeclaration): LexicalScope =
|
||||||
thisDescriptor.scopeForInitializerResolution
|
thisDescriptor.scopeForInitializerResolution
|
||||||
|
|
||||||
private fun <D : CallableMemberDescriptor> generateFakeOverrides(name: Name, fromSupertypes: Collection<D>, result: MutableCollection<D>, exactDescriptorClass: Class<out D>) {
|
private fun <D : CallableMemberDescriptor> generateFakeOverrides(
|
||||||
OverridingUtil.generateOverridesInFunctionGroup(name, fromSupertypes, ArrayList(result), thisDescriptor, object : OverridingStrategy() {
|
name: Name,
|
||||||
|
fromSupertypes: Collection<D>,
|
||||||
|
result: MutableCollection<D>,
|
||||||
|
exactDescriptorClass: Class<out D>
|
||||||
|
) {
|
||||||
|
OverridingUtil.generateOverridesInFunctionGroup(
|
||||||
|
name,
|
||||||
|
fromSupertypes,
|
||||||
|
ArrayList(result),
|
||||||
|
thisDescriptor,
|
||||||
|
object : OverridingStrategy() {
|
||||||
override fun addFakeOverride(fakeOverride: CallableMemberDescriptor) {
|
override fun addFakeOverride(fakeOverride: CallableMemberDescriptor) {
|
||||||
assert(exactDescriptorClass.isInstance(fakeOverride)) { "Wrong descriptor type in an override: " + fakeOverride + " while expecting " + exactDescriptorClass.simpleName }
|
assert(exactDescriptorClass.isInstance(fakeOverride)) { "Wrong descriptor type in an override: " + fakeOverride + " while expecting " + exactDescriptorClass.simpleName }
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
result.add(fakeOverride as D)
|
result.add(fakeOverride as D)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun overrideConflict(fromSuper: CallableMemberDescriptor, fromCurrent: CallableMemberDescriptor) {
|
override fun overrideConflict(
|
||||||
reportOnDeclarationOrFail(trace, fromCurrent) { Errors.CONFLICTING_OVERLOADS.on(it, listOf(fromCurrent, fromSuper)) }
|
fromSuper: CallableMemberDescriptor,
|
||||||
|
fromCurrent: CallableMemberDescriptor
|
||||||
|
) {
|
||||||
|
reportOnDeclarationOrFail(
|
||||||
|
trace,
|
||||||
|
fromCurrent
|
||||||
|
) { Errors.CONFLICTING_OVERLOADS.on(it, listOf(fromCurrent, fromSuper)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun inheritanceConflict(first: CallableMemberDescriptor, second: CallableMemberDescriptor) {
|
override fun inheritanceConflict(
|
||||||
reportOnDeclarationAs<KtClassOrObject>(trace, thisDescriptor) { ktClassOrObject ->
|
first: CallableMemberDescriptor,
|
||||||
Errors.CONFLICTING_INHERITED_MEMBERS.on(ktClassOrObject, thisDescriptor, listOf(first, second))
|
second: CallableMemberDescriptor
|
||||||
|
) {
|
||||||
|
reportOnDeclarationAs<KtClassOrObject>(
|
||||||
|
trace,
|
||||||
|
thisDescriptor
|
||||||
|
) { ktClassOrObject ->
|
||||||
|
Errors.CONFLICTING_INHERITED_MEMBERS.on(
|
||||||
|
ktClassOrObject,
|
||||||
|
thisDescriptor,
|
||||||
|
listOf(first, second)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -205,9 +236,11 @@ open class LazyClassMemberScope(
|
|||||||
++componentIndex
|
++componentIndex
|
||||||
|
|
||||||
if (name == DataClassDescriptorResolver.createComponentName(componentIndex)) {
|
if (name == DataClassDescriptorResolver.createComponentName(componentIndex)) {
|
||||||
result.add(DataClassDescriptorResolver.createComponentFunctionDescriptor(
|
result.add(
|
||||||
|
DataClassDescriptorResolver.createComponentFunctionDescriptor(
|
||||||
componentIndex, property, parameter, thisDescriptor, trace
|
componentIndex, property, parameter, thisDescriptor, trace
|
||||||
))
|
)
|
||||||
|
)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -253,11 +286,21 @@ open class LazyClassMemberScope(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addSyntheticFunctions(result: MutableCollection<DeclarationDescriptor>, location: LookupLocation) {
|
private fun addSyntheticFunctions(result: MutableCollection<DeclarationDescriptor>, location: LookupLocation) {
|
||||||
result.addAll(c.syntheticResolveExtension.getSyntheticFunctionNames(thisDescriptor).flatMap { getContributedFunctions(it, location) }.toList())
|
result.addAll(c.syntheticResolveExtension.getSyntheticFunctionNames(thisDescriptor).flatMap {
|
||||||
|
getContributedFunctions(
|
||||||
|
it,
|
||||||
|
location
|
||||||
|
)
|
||||||
|
}.toList())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addSyntheticNestedClasses(result: MutableCollection<DeclarationDescriptor>, location: LookupLocation) {
|
private fun addSyntheticNestedClasses(result: MutableCollection<DeclarationDescriptor>, location: LookupLocation) {
|
||||||
result.addAll(c.syntheticResolveExtension.getSyntheticNestedClassNames(thisDescriptor).mapNotNull { getContributedClassifier(it, location) }.toList())
|
result.addAll(c.syntheticResolveExtension.getSyntheticNestedClassNames(thisDescriptor).mapNotNull {
|
||||||
|
getContributedClassifier(
|
||||||
|
it,
|
||||||
|
location
|
||||||
|
)
|
||||||
|
}.toList())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateSyntheticCompanionObject(name: Name, result: MutableSet<ClassDescriptor>) {
|
private fun generateSyntheticCompanionObject(name: Name, result: MutableSet<ClassDescriptor>) {
|
||||||
@@ -316,13 +359,18 @@ open class LazyClassMemberScope(
|
|||||||
if (parameter.hasValOrVar()) {
|
if (parameter.hasValOrVar()) {
|
||||||
val propertyDescriptor = c.descriptorResolver.resolvePrimaryConstructorParameterToAProperty(
|
val propertyDescriptor = c.descriptorResolver.resolvePrimaryConstructorParameterToAProperty(
|
||||||
// TODO: can't test because we get types from cache for this case
|
// TODO: can't test because we get types from cache for this case
|
||||||
thisDescriptor, valueParameterDescriptor, thisDescriptor.scopeForConstructorHeaderResolution, parameter, trace)
|
thisDescriptor, valueParameterDescriptor, thisDescriptor.scopeForConstructorHeaderResolution, parameter, trace
|
||||||
|
)
|
||||||
result.add(propertyDescriptor)
|
result.add(propertyDescriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T : CallableMemberDescriptor> generateDelegatingDescriptors(name: Name, extractor: MemberExtractor<T>, existingDescriptors: Collection<CallableDescriptor>): Collection<T> {
|
private fun <T : CallableMemberDescriptor> generateDelegatingDescriptors(
|
||||||
|
name: Name,
|
||||||
|
extractor: MemberExtractor<T>,
|
||||||
|
existingDescriptors: Collection<CallableDescriptor>
|
||||||
|
): Collection<T> {
|
||||||
val classOrObject = declarationProvider.correspondingClassOrObject ?: return setOf()
|
val classOrObject = declarationProvider.correspondingClassOrObject ?: return setOf()
|
||||||
|
|
||||||
val lazyTypeResolver = object : DelegationResolver.TypeResolver {
|
val lazyTypeResolver = object : DelegationResolver.TypeResolver {
|
||||||
@@ -358,8 +406,8 @@ open class LazyClassMemberScope(
|
|||||||
result.addAll(getContributedFunctions(Name.identifier("copy"), location))
|
result.addAll(getContributedFunctions(Name.identifier("copy"), location))
|
||||||
}
|
}
|
||||||
|
|
||||||
private val secondaryConstructors: NotNullLazyValue<Collection<ClassConstructorDescriptor>>
|
private val secondaryConstructors: NotNullLazyValue<Collection<ClassConstructorDescriptor>> =
|
||||||
= c.storageManager.createLazyValue { resolveSecondaryConstructors() }
|
c.storageManager.createLazyValue { resolveSecondaryConstructors() }
|
||||||
|
|
||||||
fun getConstructors(): Collection<ClassConstructorDescriptor> {
|
fun getConstructors(): Collection<ClassConstructorDescriptor> {
|
||||||
val result = secondaryConstructors()
|
val result = secondaryConstructors()
|
||||||
@@ -380,7 +428,8 @@ open class LazyClassMemberScope(
|
|||||||
|
|
||||||
if (DescriptorUtils.canHaveDeclaredConstructors(thisDescriptor) || hasPrimaryConstructor) {
|
if (DescriptorUtils.canHaveDeclaredConstructors(thisDescriptor) || hasPrimaryConstructor) {
|
||||||
val constructor = c.functionDescriptorResolver.resolvePrimaryConstructorDescriptor(
|
val constructor = c.functionDescriptorResolver.resolvePrimaryConstructorDescriptor(
|
||||||
thisDescriptor.scopeForConstructorHeaderResolution, thisDescriptor, classOrObject, trace)
|
thisDescriptor.scopeForConstructorHeaderResolution, thisDescriptor, classOrObject, trace
|
||||||
|
)
|
||||||
constructor ?: return null
|
constructor ?: return null
|
||||||
setDeferredReturnType(constructor)
|
setDeferredReturnType(constructor)
|
||||||
return constructor
|
return constructor
|
||||||
|
|||||||
+11
-3
@@ -29,10 +29,18 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
|||||||
class LazyPackageMemberScope(
|
class LazyPackageMemberScope(
|
||||||
private val resolveSession: ResolveSession,
|
private val resolveSession: ResolveSession,
|
||||||
declarationProvider: PackageMemberDeclarationProvider,
|
declarationProvider: PackageMemberDeclarationProvider,
|
||||||
thisPackage: PackageFragmentDescriptor)
|
thisPackage: PackageFragmentDescriptor
|
||||||
: AbstractLazyMemberScope<PackageFragmentDescriptor, PackageMemberDeclarationProvider>(resolveSession, declarationProvider, thisPackage, resolveSession.trace) {
|
) : AbstractLazyMemberScope<PackageFragmentDescriptor, PackageMemberDeclarationProvider>(
|
||||||
|
resolveSession,
|
||||||
|
declarationProvider,
|
||||||
|
thisPackage,
|
||||||
|
resolveSession.trace
|
||||||
|
) {
|
||||||
|
|
||||||
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> {
|
override fun getContributedDescriptors(
|
||||||
|
kindFilter: DescriptorKindFilter,
|
||||||
|
nameFilter: (Name) -> Boolean
|
||||||
|
): Collection<DeclarationDescriptor> {
|
||||||
return computeDescriptorsFromDeclaredElements(kindFilter, nameFilter, NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS)
|
return computeDescriptorsFromDeclaredElements(kindFilter, nameFilter, NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-3
@@ -30,8 +30,8 @@ class LazyScriptClassMemberScope(
|
|||||||
resolveSession: ResolveSession,
|
resolveSession: ResolveSession,
|
||||||
declarationProvider: ClassMemberDeclarationProvider,
|
declarationProvider: ClassMemberDeclarationProvider,
|
||||||
private val scriptDescriptor: LazyScriptDescriptor,
|
private val scriptDescriptor: LazyScriptDescriptor,
|
||||||
trace: BindingTrace)
|
trace: BindingTrace
|
||||||
: LazyClassMemberScope(resolveSession, declarationProvider, scriptDescriptor, trace) {
|
) : LazyClassMemberScope(resolveSession, declarationProvider, scriptDescriptor, trace) {
|
||||||
|
|
||||||
override fun resolvePrimaryConstructor(): ClassConstructorDescriptor? {
|
override fun resolvePrimaryConstructor(): ClassConstructorDescriptor? {
|
||||||
val constructor = ClassConstructorDescriptorImpl.create(
|
val constructor = ClassConstructorDescriptorImpl.create(
|
||||||
@@ -49,7 +49,8 @@ class LazyScriptClassMemberScope(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createScriptParameters(constructor: ClassConstructorDescriptorImpl): List<ValueParameterDescriptor> {
|
private fun createScriptParameters(constructor: ClassConstructorDescriptorImpl): List<ValueParameterDescriptor> {
|
||||||
return ScriptHelper.getInstance().getScriptParameters(scriptDescriptor.scriptDefinition, scriptDescriptor).mapIndexed { index, (name, type) ->
|
return ScriptHelper.getInstance().getScriptParameters(scriptDescriptor.scriptDefinition, scriptDescriptor)
|
||||||
|
.mapIndexed { index, (name, type) ->
|
||||||
ValueParameterDescriptorImpl(
|
ValueParameterDescriptorImpl(
|
||||||
constructor, null, index, Annotations.EMPTY, name, type,
|
constructor, null, index, Annotations.EMPTY, name, type,
|
||||||
/* declaresDefaultValue = */ false,
|
/* declaresDefaultValue = */ false,
|
||||||
|
|||||||
+14
-5
@@ -67,19 +67,28 @@ abstract class AbstractLocalRedeclarationChecker(val overloadChecker: OverloadCh
|
|||||||
|
|
||||||
class ThrowingLocalRedeclarationChecker(overloadChecker: OverloadChecker) : AbstractLocalRedeclarationChecker(overloadChecker) {
|
class ThrowingLocalRedeclarationChecker(overloadChecker: OverloadChecker) : AbstractLocalRedeclarationChecker(overloadChecker) {
|
||||||
override fun handleRedeclaration(first: DeclarationDescriptor, second: DeclarationDescriptor) {
|
override fun handleRedeclaration(first: DeclarationDescriptor, second: DeclarationDescriptor) {
|
||||||
throw IllegalStateException(String.format("Redeclaration: %s (%s) and %s (%s) (no line info available)",
|
throw IllegalStateException(
|
||||||
|
String.format(
|
||||||
|
"Redeclaration: %s (%s) and %s (%s) (no line info available)",
|
||||||
DescriptorUtils.getFqName(first), first,
|
DescriptorUtils.getFqName(first), first,
|
||||||
DescriptorUtils.getFqName(second), second))
|
DescriptorUtils.getFqName(second), second
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handleConflictingOverloads(first: CallableMemberDescriptor, second: CallableMemberDescriptor) {
|
override fun handleConflictingOverloads(first: CallableMemberDescriptor, second: CallableMemberDescriptor) {
|
||||||
throw IllegalStateException(String.format("Conflicting overloads: %s (%s) and %s (%s) (no line info available)",
|
throw IllegalStateException(
|
||||||
|
String.format(
|
||||||
|
"Conflicting overloads: %s (%s) and %s (%s) (no line info available)",
|
||||||
DescriptorUtils.getFqName(first), first,
|
DescriptorUtils.getFqName(first), first,
|
||||||
DescriptorUtils.getFqName(second), second))
|
DescriptorUtils.getFqName(second), second
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TraceBasedLocalRedeclarationChecker(val trace: BindingTrace, overloadChecker: OverloadChecker): AbstractLocalRedeclarationChecker(overloadChecker) {
|
class TraceBasedLocalRedeclarationChecker(val trace: BindingTrace, overloadChecker: OverloadChecker) :
|
||||||
|
AbstractLocalRedeclarationChecker(overloadChecker) {
|
||||||
override fun handleRedeclaration(first: DeclarationDescriptor, second: DeclarationDescriptor) {
|
override fun handleRedeclaration(first: DeclarationDescriptor, second: DeclarationDescriptor) {
|
||||||
reportOnDeclarationOrFail(trace, first) { Errors.REDECLARATION.on(it, listOf(first, second)) }
|
reportOnDeclarationOrFail(trace, first) { Errors.REDECLARATION.on(it, listOf(first, second)) }
|
||||||
reportOnDeclarationOrFail(trace, second) { Errors.REDECLARATION.on(it, listOf(first, second)) }
|
reportOnDeclarationOrFail(trace, second) { Errors.REDECLARATION.on(it, listOf(first, second)) }
|
||||||
|
|||||||
+39
-28
@@ -107,8 +107,7 @@ class DoubleColonExpressionResolver(
|
|||||||
if (expression.isEmptyLHS) {
|
if (expression.isEmptyLHS) {
|
||||||
// "::class" will maybe mean "this::class", a class of "this" instance
|
// "::class" will maybe mean "this::class", a class of "this" instance
|
||||||
c.trace.report(UNSUPPORTED.on(expression, "Class literals with empty left hand side are not yet supported"))
|
c.trace.report(UNSUPPORTED.on(expression, "Class literals with empty left hand side are not yet supported"))
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val result = resolveDoubleColonLHS(expression, c)
|
val result = resolveDoubleColonLHS(expression, c)
|
||||||
if (result != null && !result.type.isError) {
|
if (result != null && !result.type.isError) {
|
||||||
val inherentType = result.type
|
val inherentType = result.type
|
||||||
@@ -158,8 +157,7 @@ class DoubleColonExpressionResolver(
|
|||||||
// Note that "T::class" is allowed for type parameter T without a non-null upper bound
|
// Note that "T::class" is allowed for type parameter T without a non-null upper bound
|
||||||
else if ((TypeUtils.isNullableType(type) && descriptor !is TypeParameterDescriptor) || expression.hasQuestionMarks) {
|
else if ((TypeUtils.isNullableType(type) && descriptor !is TypeParameterDescriptor) || expression.hasQuestionMarks) {
|
||||||
c.trace.report(NULLABLE_TYPE_IN_CLASS_LITERAL_LHS.on(expression))
|
c.trace.report(NULLABLE_TYPE_IN_CLASS_LITERAL_LHS.on(expression))
|
||||||
}
|
} else if (!result.possiblyBareType.isBare && !isAllowedInClassLiteral(type)) {
|
||||||
else if (!result.possiblyBareType.isBare && !isAllowedInClassLiteral(type)) {
|
|
||||||
c.trace.report(CLASS_LITERAL_LHS_NOT_A_CLASS.on(expression))
|
c.trace.report(CLASS_LITERAL_LHS_NOT_A_CLASS.on(expression))
|
||||||
}
|
}
|
||||||
for (additionalChecker in additionalCheckers) {
|
for (additionalChecker in additionalCheckers) {
|
||||||
@@ -205,7 +203,12 @@ class DoubleColonExpressionResolver(
|
|||||||
|
|
||||||
private fun reportUnsupportedIfNeeded(expression: KtDoubleColonExpression, c: ExpressionTypingContext) {
|
private fun reportUnsupportedIfNeeded(expression: KtDoubleColonExpression, c: ExpressionTypingContext) {
|
||||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.BoundCallableReferences)) {
|
if (!languageVersionSettings.supportsFeature(LanguageFeature.BoundCallableReferences)) {
|
||||||
c.trace.report(UNSUPPORTED_FEATURE.on(expression.receiverExpression!!, LanguageFeature.BoundCallableReferences to languageVersionSettings))
|
c.trace.report(
|
||||||
|
UNSUPPORTED_FEATURE.on(
|
||||||
|
expression.receiverExpression!!,
|
||||||
|
LanguageFeature.BoundCallableReferences to languageVersionSettings
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,8 +231,7 @@ class DoubleColonExpressionResolver(
|
|||||||
val receiver = finger.receiverExpression
|
val receiver = finger.receiverExpression
|
||||||
if (receiver is KtQualifiedExpression) {
|
if (receiver is KtQualifiedExpression) {
|
||||||
finger = receiver
|
finger = receiver
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
result.push(receiver)
|
result.push(receiver)
|
||||||
return result.toList()
|
return result.toList()
|
||||||
}
|
}
|
||||||
@@ -266,8 +268,7 @@ class DoubleColonExpressionResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveReservedExpressionOnLHS(expression: KtExpression, c: ExpressionTypingContext): DoubleColonLHS.Expression? {
|
private fun resolveReservedExpressionOnLHS(expression: KtExpression, c: ExpressionTypingContext): DoubleColonLHS.Expression? {
|
||||||
val doubleColonExpression = expression.parent as? KtDoubleColonExpression ?:
|
val doubleColonExpression = expression.parent as? KtDoubleColonExpression ?: return null // should assert here?
|
||||||
return null // should assert here?
|
|
||||||
|
|
||||||
if (expression is KtCallExpression && expression.typeArguments.isNotEmpty()) {
|
if (expression is KtCallExpression && expression.typeArguments.isNotEmpty()) {
|
||||||
val callee = expression.calleeExpression ?: return null
|
val callee = expression.calleeExpression ?: return null
|
||||||
@@ -279,11 +280,9 @@ class DoubleColonExpressionResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return calleeAsDoubleColonLHS
|
return calleeAsDoubleColonLHS
|
||||||
}
|
} else if (doubleColonExpression.hasQuestionMarks) {
|
||||||
else if (doubleColonExpression.hasQuestionMarks) {
|
|
||||||
return resolveExpressionOnLHS(expression, c)
|
return resolveExpressionOnLHS(expression, c)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -293,7 +292,8 @@ class DoubleColonExpressionResolver(
|
|||||||
|
|
||||||
val newExpression = expression.buildNewExpressionForReservedGenericPropertyCallChainResolution() ?: return null
|
val newExpression = expression.buildNewExpressionForReservedGenericPropertyCallChainResolution() ?: return null
|
||||||
|
|
||||||
val temporaryTraceAndCache = TemporaryTraceAndCache.create(c, "resolve reserved generic property call chain in '::' LHS", newExpression)
|
val temporaryTraceAndCache =
|
||||||
|
TemporaryTraceAndCache.create(c, "resolve reserved generic property call chain in '::' LHS", newExpression)
|
||||||
val contextForCallChainResolution =
|
val contextForCallChainResolution =
|
||||||
c.replaceTraceAndCache(temporaryTraceAndCache)
|
c.replaceTraceAndCache(temporaryTraceAndCache)
|
||||||
.replaceExpectedType(NO_EXPECTED_TYPE)
|
.replaceExpectedType(NO_EXPECTED_TYPE)
|
||||||
@@ -304,9 +304,11 @@ class DoubleColonExpressionResolver(
|
|||||||
|
|
||||||
private fun resolveReservedExpressionSyntaxOnDoubleColonLHS(doubleColonExpression: KtDoubleColonExpression, c: ExpressionTypingContext):
|
private fun resolveReservedExpressionSyntaxOnDoubleColonLHS(doubleColonExpression: KtDoubleColonExpression, c: ExpressionTypingContext):
|
||||||
Pair<Boolean, DoubleColonLHS?> {
|
Pair<Boolean, DoubleColonLHS?> {
|
||||||
val resultForReservedExpr = tryResolveLHS(doubleColonExpression, c,
|
val resultForReservedExpr = tryResolveLHS(
|
||||||
|
doubleColonExpression, c,
|
||||||
this::shouldTryResolveLHSAsReservedExpression,
|
this::shouldTryResolveLHSAsReservedExpression,
|
||||||
this::resolveReservedExpressionOnLHS)
|
this::resolveReservedExpressionOnLHS
|
||||||
|
)
|
||||||
if (resultForReservedExpr != null) {
|
if (resultForReservedExpr != null) {
|
||||||
val lhs = resultForReservedExpr.lhs
|
val lhs = resultForReservedExpr.lhs
|
||||||
if (lhs != null) {
|
if (lhs != null) {
|
||||||
@@ -315,9 +317,11 @@ class DoubleColonExpressionResolver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val resultForReservedCallChain = tryResolveLHS(doubleColonExpression, c,
|
val resultForReservedCallChain = tryResolveLHS(
|
||||||
|
doubleColonExpression, c,
|
||||||
this::shouldTryResolveLHSAsReservedCallChain,
|
this::shouldTryResolveLHSAsReservedCallChain,
|
||||||
this::resolveReservedCallChainOnLHS)
|
this::resolveReservedCallChainOnLHS
|
||||||
|
)
|
||||||
if (resultForReservedCallChain != null) {
|
if (resultForReservedCallChain != null) {
|
||||||
val lhs = resultForReservedCallChain.lhs
|
val lhs = resultForReservedCallChain.lhs
|
||||||
if (lhs != null) {
|
if (lhs != null) {
|
||||||
@@ -473,8 +477,7 @@ class DoubleColonExpressionResolver(
|
|||||||
Annotations.EMPTY, descriptor.typeConstructor, arguments,
|
Annotations.EMPTY, descriptor.typeConstructor, arguments,
|
||||||
possiblyBareType.isNullable || doubleColonExpression.hasQuestionMarks
|
possiblyBareType.isNullable || doubleColonExpression.hasQuestionMarks
|
||||||
)
|
)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val actualType = possiblyBareType.actualType
|
val actualType = possiblyBareType.actualType
|
||||||
if (doubleColonExpression.hasQuestionMarks) actualType.makeNullable() else actualType
|
if (doubleColonExpression.hasQuestionMarks) actualType.makeNullable() else actualType
|
||||||
}
|
}
|
||||||
@@ -526,8 +529,7 @@ class DoubleColonExpressionResolver(
|
|||||||
if (resolutionResults != null && !resolutionResults.isNothing) {
|
if (resolutionResults != null && !resolutionResults.isNothing) {
|
||||||
val resolvedCall = OverloadResolutionResultsUtil.getResultingCall(resolutionResults, context)
|
val resolvedCall = OverloadResolutionResultsUtil.getResultingCall(resolutionResults, context)
|
||||||
resolvedCall?.resultingDescriptor ?: return null
|
resolvedCall?.resultingDescriptor ?: return null
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (lhs != null || expression.isEmptyLHS) {
|
if (lhs != null || expression.isEmptyLHS) {
|
||||||
context.trace.report(UNRESOLVED_REFERENCE.on(expression.callableReference, expression.callableReference))
|
context.trace.report(UNRESOLVED_REFERENCE.on(expression.callableReference, expression.callableReference))
|
||||||
}
|
}
|
||||||
@@ -553,9 +555,11 @@ class DoubleColonExpressionResolver(
|
|||||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.CallableReferencesToClassMembersWithEmptyLHS)) {
|
if (!languageVersionSettings.supportsFeature(LanguageFeature.CallableReferencesToClassMembersWithEmptyLHS)) {
|
||||||
if (expression.isEmptyLHS &&
|
if (expression.isEmptyLHS &&
|
||||||
(descriptor.dispatchReceiverParameter != null || descriptor.extensionReceiverParameter != null)) {
|
(descriptor.dispatchReceiverParameter != null || descriptor.extensionReceiverParameter != null)) {
|
||||||
trace.report(UNSUPPORTED_FEATURE.on(
|
trace.report(
|
||||||
|
UNSUPPORTED_FEATURE.on(
|
||||||
simpleName, LanguageFeature.CallableReferencesToClassMembersWithEmptyLHS to languageVersionSettings
|
simpleName, LanguageFeature.CallableReferencesToClassMembersWithEmptyLHS to languageVersionSettings
|
||||||
))
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (descriptor is ConstructorDescriptor && DescriptorUtils.isAnnotationClass(descriptor.containingDeclaration)) {
|
if (descriptor is ConstructorDescriptor && DescriptorUtils.isAnnotationClass(descriptor.containingDeclaration)) {
|
||||||
@@ -594,7 +598,11 @@ class DoubleColonExpressionResolver(
|
|||||||
context.trace.record(BindingContext.FUNCTION, expression, functionDescriptor)
|
context.trace.record(BindingContext.FUNCTION, expression, functionDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun bindPropertyReference(expression: KtCallableReferenceExpression, referenceType: KotlinType, context: ResolutionContext<*>) {
|
internal fun bindPropertyReference(
|
||||||
|
expression: KtCallableReferenceExpression,
|
||||||
|
referenceType: KotlinType,
|
||||||
|
context: ResolutionContext<*>
|
||||||
|
) {
|
||||||
val localVariable = LocalVariableDescriptor(
|
val localVariable = LocalVariableDescriptor(
|
||||||
context.scope.ownerDescriptor, Annotations.EMPTY, Name.special("<anonymous>"), referenceType,
|
context.scope.ownerDescriptor, Annotations.EMPTY, Name.special("<anonymous>"), referenceType,
|
||||||
expression.toSourceElement()
|
expression.toSourceElement()
|
||||||
@@ -652,7 +660,8 @@ class DoubleColonExpressionResolver(
|
|||||||
): ResolutionResultsAndTraceCommitCallback? {
|
): ResolutionResultsAndTraceCommitCallback? {
|
||||||
// we should preserve information about `call` because callable references are analyzed two times,
|
// we should preserve information about `call` because callable references are analyzed two times,
|
||||||
// otherwise there will be not completed calls in trace
|
// otherwise there will be not completed calls in trace
|
||||||
val call = outerContext.trace[BindingContext.CALL, reference] ?: CallMaker.makeCall(reference, receiver, null, reference, emptyList())
|
val call =
|
||||||
|
outerContext.trace[BindingContext.CALL, reference] ?: CallMaker.makeCall(reference, receiver, null, reference, emptyList())
|
||||||
val temporaryTrace = TemporaryTraceAndCache.create(outerContext, traceTitle, reference)
|
val temporaryTrace = TemporaryTraceAndCache.create(outerContext, traceTitle, reference)
|
||||||
val newContext =
|
val newContext =
|
||||||
if (resolutionMode == ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS)
|
if (resolutionMode == ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS)
|
||||||
@@ -773,8 +782,10 @@ class DoubleColonExpressionResolver(
|
|||||||
val returnType = descriptor.returnType ?: return null
|
val returnType = descriptor.returnType ?: return null
|
||||||
val parametersTypes = descriptor.valueParameters.map { it.type }
|
val parametersTypes = descriptor.valueParameters.map { it.type }
|
||||||
val parametersNames = descriptor.valueParameters.map { it.name }
|
val parametersNames = descriptor.valueParameters.map { it.name }
|
||||||
return reflectionTypes.getKFunctionType(Annotations.EMPTY, receiverType,
|
return reflectionTypes.getKFunctionType(
|
||||||
parametersTypes, parametersNames, returnType, descriptor.builtIns)
|
Annotations.EMPTY, receiverType,
|
||||||
|
parametersTypes, parametersNames, returnType, descriptor.builtIns
|
||||||
|
)
|
||||||
}
|
}
|
||||||
is PropertyDescriptor -> {
|
is PropertyDescriptor -> {
|
||||||
val mutable = descriptor.isVar && run {
|
val mutable = descriptor.isVar && run {
|
||||||
|
|||||||
+60
-32
@@ -58,7 +58,11 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
|||||||
context.trace.record(BindingContext.DATAFLOW_INFO_AFTER_CONDITION, expression, newDataFlowInfo)
|
context.trace.record(BindingContext.DATAFLOW_INFO_AFTER_CONDITION, expression, newDataFlowInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
val resultTypeInfo = components.dataFlowAnalyzer.checkType(typeInfo.replaceType(components.builtIns.booleanType), expression, contextWithExpectedType)
|
val resultTypeInfo = components.dataFlowAnalyzer.checkType(
|
||||||
|
typeInfo.replaceType(components.builtIns.booleanType),
|
||||||
|
expression,
|
||||||
|
contextWithExpectedType
|
||||||
|
)
|
||||||
|
|
||||||
if (typeReference != null) {
|
if (typeReference != null) {
|
||||||
val rhsType = context.trace[BindingContext.TYPE, typeReference]
|
val rhsType = context.trace[BindingContext.TYPE, typeReference]
|
||||||
@@ -103,7 +107,8 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
|||||||
} ?: DataFlowValue.nullValue(components.builtIns)
|
} ?: DataFlowValue.nullValue(components.builtIns)
|
||||||
|
|
||||||
val possibleTypesForSubject = subjectTypeInfo?.dataFlowInfo?.getStableTypes(
|
val possibleTypesForSubject = subjectTypeInfo?.dataFlowInfo?.getStableTypes(
|
||||||
subjectDataFlowValue, components.languageVersionSettings) ?: emptySet()
|
subjectDataFlowValue, components.languageVersionSettings
|
||||||
|
) ?: emptySet()
|
||||||
checkSmartCastsInSubjectIfRequired(expression, contextBeforeSubject, subjectType, possibleTypesForSubject)
|
checkSmartCastsInSubjectIfRequired(expression, contextBeforeSubject, subjectType, possibleTypesForSubject)
|
||||||
|
|
||||||
val dataFlowInfoForEntries = analyzeConditionsInWhenEntries(expression, contextAfterSubject, subjectDataFlowValue, subjectType)
|
val dataFlowInfoForEntries = analyzeConditionsInWhenEntries(expression, contextAfterSubject, subjectDataFlowValue, subjectType)
|
||||||
@@ -120,8 +125,7 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
|||||||
// Without else expression in non-exhaustive when, we *must* take initial data flow info into account,
|
// Without else expression in non-exhaustive when, we *must* take initial data flow info into account,
|
||||||
// because data flow can bypass all when branches in this case
|
// because data flow can bypass all when branches in this case
|
||||||
branchesDataFlowInfo.or(contextAfterSubject.dataFlowInfo)
|
branchesDataFlowInfo.or(contextAfterSubject.dataFlowInfo)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
branchesDataFlowInfo
|
branchesDataFlowInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +151,8 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
|||||||
|
|
||||||
val wrappedArgumentExpressions = wrapWhenEntryExpressionsAsSpecialCallArguments(expression)
|
val wrappedArgumentExpressions = wrapWhenEntryExpressionsAsSpecialCallArguments(expression)
|
||||||
val callForWhen = createCallForSpecialConstruction(expression, expression, wrappedArgumentExpressions)
|
val callForWhen = createCallForSpecialConstruction(expression, expression, wrappedArgumentExpressions)
|
||||||
val dataFlowInfoForArguments = createDataFlowInfoForArgumentsOfWhenCall(callForWhen, contextAfterSubject.dataFlowInfo, dataFlowInfoForEntries)
|
val dataFlowInfoForArguments =
|
||||||
|
createDataFlowInfoForArgumentsOfWhenCall(callForWhen, contextAfterSubject.dataFlowInfo, dataFlowInfoForEntries)
|
||||||
|
|
||||||
val resolvedCall = components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
|
val resolvedCall = components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
|
||||||
callForWhen, ResolveConstruct.WHEN,
|
callForWhen, ResolveConstruct.WHEN,
|
||||||
@@ -156,7 +161,8 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
|||||||
override val size: Int get() = wrappedArgumentExpressions.size
|
override val size: Int get() = wrappedArgumentExpressions.size
|
||||||
},
|
},
|
||||||
Collections.nCopies(wrappedArgumentExpressions.size, false),
|
Collections.nCopies(wrappedArgumentExpressions.size, false),
|
||||||
contextWithExpectedType, dataFlowInfoForArguments)
|
contextWithExpectedType, dataFlowInfoForArguments
|
||||||
|
)
|
||||||
|
|
||||||
return resolvedCall.resultingDescriptor.returnType
|
return resolvedCall.resultingDescriptor.returnType
|
||||||
}
|
}
|
||||||
@@ -179,9 +185,11 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
|||||||
val argumentDataFlowInfos = ArrayList<DataFlowInfo>()
|
val argumentDataFlowInfos = ArrayList<DataFlowInfo>()
|
||||||
var inputDataFlowInfo = contextAfterSubject.dataFlowInfo
|
var inputDataFlowInfo = contextAfterSubject.dataFlowInfo
|
||||||
for (whenEntry in expression.entries) {
|
for (whenEntry in expression.entries) {
|
||||||
val conditionsInfo = analyzeWhenEntryConditions(whenEntry,
|
val conditionsInfo = analyzeWhenEntryConditions(
|
||||||
|
whenEntry,
|
||||||
contextAfterSubject.replaceDataFlowInfo(inputDataFlowInfo),
|
contextAfterSubject.replaceDataFlowInfo(inputDataFlowInfo),
|
||||||
subjectExpression, subjectType, subjectDataFlowValue)
|
subjectExpression, subjectType, subjectDataFlowValue
|
||||||
|
)
|
||||||
inputDataFlowInfo = inputDataFlowInfo.and(conditionsInfo.elseInfo)
|
inputDataFlowInfo = inputDataFlowInfo.and(conditionsInfo.elseInfo)
|
||||||
|
|
||||||
if (whenEntry.expression != null) {
|
if (whenEntry.expression != null) {
|
||||||
@@ -206,8 +214,7 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
|||||||
for (whenEntry in expression.entries) {
|
for (whenEntry in expression.entries) {
|
||||||
val entryExpression = whenEntry.expression ?: continue
|
val entryExpression = whenEntry.expression ?: continue
|
||||||
|
|
||||||
val entryTypeInfo = BindingContextUtils.getRecordedTypeInfo(entryExpression, bindingContext) ?:
|
val entryTypeInfo = BindingContextUtils.getRecordedTypeInfo(entryExpression, bindingContext) ?: continue
|
||||||
continue
|
|
||||||
val entryType = entryTypeInfo.type
|
val entryType = entryTypeInfo.type
|
||||||
if (entryType == null) {
|
if (entryType == null) {
|
||||||
errorTypeExistInBranch = true
|
errorTypeExistInBranch = true
|
||||||
@@ -217,8 +224,7 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
|||||||
if (whenResultValue != null && entryType != null) {
|
if (whenResultValue != null && entryType != null) {
|
||||||
val entryValue = DataFlowValueFactory.createDataFlowValue(entryExpression, entryType, contextAfterSubject)
|
val entryValue = DataFlowValueFactory.createDataFlowValue(entryExpression, entryType, contextAfterSubject)
|
||||||
entryTypeInfo.dataFlowInfo.assign(whenResultValue, entryValue, components.languageVersionSettings)
|
entryTypeInfo.dataFlowInfo.assign(whenResultValue, entryValue, components.languageVersionSettings)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
entryTypeInfo.dataFlowInfo
|
entryTypeInfo.dataFlowInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,8 +256,10 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
|||||||
for (possibleCastType in possibleTypesForSubject) {
|
for (possibleCastType in possibleTypesForSubject) {
|
||||||
val possibleCastClass = possibleCastType.constructor.declarationDescriptor as? ClassDescriptor ?: continue
|
val possibleCastClass = possibleCastType.constructor.declarationDescriptor as? ClassDescriptor ?: continue
|
||||||
if (possibleCastClass.kind == ClassKind.ENUM_CLASS || possibleCastClass.modality == Modality.SEALED) {
|
if (possibleCastClass.kind == ClassKind.ENUM_CLASS || possibleCastClass.modality == Modality.SEALED) {
|
||||||
if (checkSmartCastToExpectedTypeInSubject(contextBeforeSubject, subjectExpression, subjectType,
|
if (checkSmartCastToExpectedTypeInSubject(
|
||||||
possibleCastType)) {
|
contextBeforeSubject, subjectExpression, subjectType,
|
||||||
|
possibleCastType
|
||||||
|
)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -260,8 +268,10 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
|||||||
val bindingContext = contextBeforeSubject.trace.bindingContext
|
val bindingContext = contextBeforeSubject.trace.bindingContext
|
||||||
if (isNullableType && !WhenChecker.containsNullCase(expression, bindingContext)) {
|
if (isNullableType && !WhenChecker.containsNullCase(expression, bindingContext)) {
|
||||||
val notNullableType = TypeUtils.makeNotNullable(subjectType)
|
val notNullableType = TypeUtils.makeNotNullable(subjectType)
|
||||||
if (checkSmartCastToExpectedTypeInSubject(contextBeforeSubject, subjectExpression, subjectType,
|
if (checkSmartCastToExpectedTypeInSubject(
|
||||||
notNullableType)) {
|
contextBeforeSubject, subjectExpression, subjectType,
|
||||||
|
notNullableType
|
||||||
|
)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -276,7 +286,8 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
|||||||
val trace = TemporaryBindingTrace.create(contextBeforeSubject.trace, "Temporary trace for when subject nullability")
|
val trace = TemporaryBindingTrace.create(contextBeforeSubject.trace, "Temporary trace for when subject nullability")
|
||||||
val subjectContext = contextBeforeSubject.replaceExpectedType(expectedType).replaceBindingTrace(trace)
|
val subjectContext = contextBeforeSubject.replaceExpectedType(expectedType).replaceBindingTrace(trace)
|
||||||
val castResult = DataFlowAnalyzer.checkPossibleCast(
|
val castResult = DataFlowAnalyzer.checkPossibleCast(
|
||||||
subjectType, KtPsiUtil.safeDeparenthesize(subjectExpression), subjectContext)
|
subjectType, KtPsiUtil.safeDeparenthesize(subjectExpression), subjectContext
|
||||||
|
)
|
||||||
if (castResult != null && castResult.isCorrect) {
|
if (castResult != null && castResult.isCorrect) {
|
||||||
trace.commit()
|
trace.commit()
|
||||||
return true
|
return true
|
||||||
@@ -298,8 +309,10 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
|||||||
var entryInfo: ConditionalDataFlowInfo? = null
|
var entryInfo: ConditionalDataFlowInfo? = null
|
||||||
var contextForCondition = context
|
var contextForCondition = context
|
||||||
for (condition in whenEntry.conditions) {
|
for (condition in whenEntry.conditions) {
|
||||||
val conditionInfo = checkWhenCondition(subjectExpression, subjectType, condition,
|
val conditionInfo = checkWhenCondition(
|
||||||
contextForCondition, subjectDataFlowValue)
|
subjectExpression, subjectType, condition,
|
||||||
|
contextForCondition, subjectDataFlowValue
|
||||||
|
)
|
||||||
entryInfo = entryInfo?.let {
|
entryInfo = entryInfo?.let {
|
||||||
ConditionalDataFlowInfo(it.thenInfo.or(conditionInfo.thenInfo), it.elseInfo.and(conditionInfo.elseInfo))
|
ConditionalDataFlowInfo(it.thenInfo.or(conditionInfo.thenInfo), it.elseInfo.and(conditionInfo.elseInfo))
|
||||||
} ?: conditionInfo
|
} ?: conditionInfo
|
||||||
@@ -328,8 +341,10 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
val argumentForSubject = CallMaker.makeExternalValueArgument(subjectExpression)
|
val argumentForSubject = CallMaker.makeExternalValueArgument(subjectExpression)
|
||||||
val typeInfo = facade.checkInExpression(condition, condition.operationReference,
|
val typeInfo = facade.checkInExpression(
|
||||||
argumentForSubject, rangeExpression, context)
|
condition, condition.operationReference,
|
||||||
|
argumentForSubject, rangeExpression, context
|
||||||
|
)
|
||||||
val dataFlowInfo = typeInfo.dataFlowInfo
|
val dataFlowInfo = typeInfo.dataFlowInfo
|
||||||
newDataFlowInfo = ConditionalDataFlowInfo(dataFlowInfo)
|
newDataFlowInfo = ConditionalDataFlowInfo(dataFlowInfo)
|
||||||
val type = typeInfo.type
|
val type = typeInfo.type
|
||||||
@@ -347,8 +362,7 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
|||||||
val result = checkTypeForIs(context, condition, condition.isNegated, subjectType, typeReference, subjectDataFlowValue)
|
val result = checkTypeForIs(context, condition, condition.isNegated, subjectType, typeReference, subjectDataFlowValue)
|
||||||
newDataFlowInfo = if (condition.isNegated) {
|
newDataFlowInfo = if (condition.isNegated) {
|
||||||
ConditionalDataFlowInfo(result.elseInfo, result.thenInfo)
|
ConditionalDataFlowInfo(result.elseInfo, result.thenInfo)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
val rhsType = context.trace[BindingContext.TYPE, typeReference]
|
val rhsType = context.trace[BindingContext.TYPE, typeReference]
|
||||||
@@ -370,9 +384,11 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
|||||||
val expression = condition.expression
|
val expression = condition.expression
|
||||||
if (expression != null) {
|
if (expression != null) {
|
||||||
val basicDataFlowInfo = checkTypeForExpressionCondition(
|
val basicDataFlowInfo = checkTypeForExpressionCondition(
|
||||||
context, expression, subjectType, subjectExpression == null, subjectDataFlowValue)
|
context, expression, subjectType, subjectExpression == null, subjectDataFlowValue
|
||||||
|
)
|
||||||
val moduleDescriptor = DescriptorUtils.getContainingModule(context.scope.ownerDescriptor)
|
val moduleDescriptor = DescriptorUtils.getContainingModule(context.scope.ownerDescriptor)
|
||||||
val dataFlowInfoFromES = components.effectSystem.getDataFlowInfoWhenEquals(subjectExpression, expression, context.trace, moduleDescriptor)
|
val dataFlowInfoFromES =
|
||||||
|
components.effectSystem.getDataFlowInfoWhenEquals(subjectExpression, expression, context.trace, moduleDescriptor)
|
||||||
newDataFlowInfo = basicDataFlowInfo.and(dataFlowInfoFromES)
|
newDataFlowInfo = basicDataFlowInfo.and(dataFlowInfoFromES)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -409,12 +425,16 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
|||||||
val expressionDataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, newContext)
|
val expressionDataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, newContext)
|
||||||
val result = noChange(newContext)
|
val result = noChange(newContext)
|
||||||
return ConditionalDataFlowInfo(
|
return ConditionalDataFlowInfo(
|
||||||
result.thenInfo.equate(subjectDataFlowValue, expressionDataFlowValue,
|
result.thenInfo.equate(
|
||||||
|
subjectDataFlowValue, expressionDataFlowValue,
|
||||||
identityEquals = DataFlowAnalyzer.typeHasEqualsFromAny(subjectType, expression),
|
identityEquals = DataFlowAnalyzer.typeHasEqualsFromAny(subjectType, expression),
|
||||||
languageVersionSettings = components.languageVersionSettings),
|
languageVersionSettings = components.languageVersionSettings
|
||||||
result.elseInfo.disequate(subjectDataFlowValue,
|
),
|
||||||
|
result.elseInfo.disequate(
|
||||||
|
subjectDataFlowValue,
|
||||||
expressionDataFlowValue,
|
expressionDataFlowValue,
|
||||||
components.languageVersionSettings)
|
components.languageVersionSettings
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -426,9 +446,16 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
|||||||
typeReferenceAfterIs: KtTypeReference,
|
typeReferenceAfterIs: KtTypeReference,
|
||||||
subjectDataFlowValue: DataFlowValue
|
subjectDataFlowValue: DataFlowValue
|
||||||
): ConditionalDataFlowInfo {
|
): ConditionalDataFlowInfo {
|
||||||
val typeResolutionContext = TypeResolutionContext(context.scope, context.trace, true, /*allowBareTypes=*/ true, context.isDebuggerContext)
|
val typeResolutionContext =
|
||||||
|
TypeResolutionContext(context.scope, context.trace, true, /*allowBareTypes=*/ true, context.isDebuggerContext)
|
||||||
val possiblyBareTarget = components.typeResolver.resolvePossiblyBareType(typeResolutionContext, typeReferenceAfterIs)
|
val possiblyBareTarget = components.typeResolver.resolvePossiblyBareType(typeResolutionContext, typeReferenceAfterIs)
|
||||||
val targetType = TypeReconstructionUtil.reconstructBareType(typeReferenceAfterIs, possiblyBareTarget, subjectType, context.trace, components.builtIns)
|
val targetType = TypeReconstructionUtil.reconstructBareType(
|
||||||
|
typeReferenceAfterIs,
|
||||||
|
possiblyBareTarget,
|
||||||
|
subjectType,
|
||||||
|
context.trace,
|
||||||
|
components.builtIns
|
||||||
|
)
|
||||||
|
|
||||||
if (targetType.isDynamic()) {
|
if (targetType.isDynamic()) {
|
||||||
context.trace.report(DYNAMIC_NOT_ALLOWED.on(typeReferenceAfterIs))
|
context.trace.report(DYNAMIC_NOT_ALLOWED.on(typeReferenceAfterIs))
|
||||||
@@ -464,7 +491,8 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
|||||||
) {
|
) {
|
||||||
if (subjectType.containsError() || targetType.containsError()) return
|
if (subjectType.containsError() || targetType.containsError()) return
|
||||||
|
|
||||||
val possibleTypes = DataFlowAnalyzer.getAllPossibleTypes(subjectType, context, subjectDataFlowValue, context.languageVersionSettings)
|
val possibleTypes =
|
||||||
|
DataFlowAnalyzer.getAllPossibleTypes(subjectType, context, subjectDataFlowValue, context.languageVersionSettings)
|
||||||
if (CastDiagnosticsUtil.isRefinementUseless(possibleTypes, targetType, false)) {
|
if (CastDiagnosticsUtil.isRefinementUseless(possibleTypes, targetType, false)) {
|
||||||
context.trace.report(Errors.USELESS_IS_CHECK.on(isCheck, !negated))
|
context.trace.report(Errors.USELESS_IS_CHECK.on(isCheck, !negated))
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-2
@@ -53,8 +53,10 @@ class PreliminaryDeclarationVisitor(
|
|||||||
fun createForDeclaration(declaration: KtDeclaration, trace: BindingTrace, languageVersionSettings: LanguageVersionSettings) {
|
fun createForDeclaration(declaration: KtDeclaration, trace: BindingTrace, languageVersionSettings: LanguageVersionSettings) {
|
||||||
val visitorOwner = topMostNonClassDeclaration(declaration)
|
val visitorOwner = topMostNonClassDeclaration(declaration)
|
||||||
if (trace.get(BindingContext.PRELIMINARY_VISITOR, visitorOwner) != null) return
|
if (trace.get(BindingContext.PRELIMINARY_VISITOR, visitorOwner) != null) return
|
||||||
trace.record(BindingContext.PRELIMINARY_VISITOR, visitorOwner,
|
trace.record(
|
||||||
PreliminaryDeclarationVisitor(visitorOwner, languageVersionSettings))
|
BindingContext.PRELIMINARY_VISITOR, visitorOwner,
|
||||||
|
PreliminaryDeclarationVisitor(visitorOwner, languageVersionSettings)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getVisitorByVariable(variableDescriptor: VariableDescriptor, bindingContext: BindingContext): PreliminaryDeclarationVisitor? {
|
fun getVisitorByVariable(variableDescriptor: VariableDescriptor, bindingContext: BindingContext): PreliminaryDeclarationVisitor? {
|
||||||
|
|||||||
@@ -33,8 +33,7 @@ protected constructor(
|
|||||||
val (app, extensions) = cached
|
val (app, extensions) = cached
|
||||||
return if (app == ApplicationManager.getApplication()) {
|
return if (app == ApplicationManager.getApplication()) {
|
||||||
extensions
|
extensions
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -50,6 +49,7 @@ protected constructor(
|
|||||||
|
|
||||||
class ExtensionProvider<T>(epName: ExtensionPointName<T>) : MappedExtensionProvider<T, List<T>>(epName, { it }) {
|
class ExtensionProvider<T>(epName: ExtensionPointName<T>) : MappedExtensionProvider<T, List<T>>(epName, { it }) {
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic fun <T> create(epName: ExtensionPointName<T>): ExtensionProvider<T> = ExtensionProvider(epName)
|
@JvmStatic
|
||||||
|
fun <T> create(epName: ExtensionPointName<T>): ExtensionProvider<T> = ExtensionProvider(epName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ abstract class PerformanceCounter protected constructor(val name: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmOverloads fun create(name: String, reenterable: Boolean = false): PerformanceCounter {
|
@JvmOverloads
|
||||||
|
fun create(name: String, reenterable: Boolean = false): PerformanceCounter {
|
||||||
return if (reenterable)
|
return if (reenterable)
|
||||||
ReenterableCounter(name)
|
ReenterableCounter(name)
|
||||||
else
|
else
|
||||||
@@ -92,8 +93,7 @@ abstract class PerformanceCounter protected constructor(val name: String) {
|
|||||||
excludedFrom.forEach { it.enterExcludedMethod() }
|
excludedFrom.forEach { it.enterExcludedMethod() }
|
||||||
try {
|
try {
|
||||||
return countTime(block)
|
return countTime(block)
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
excludedFrom.forEach { it.exitExcludedMethod() }
|
excludedFrom.forEach { it.exitExcludedMethod() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,8 +112,7 @@ abstract class PerformanceCounter protected constructor(val name: String) {
|
|||||||
fun report(consumer: (String) -> Unit) {
|
fun report(consumer: (String) -> Unit) {
|
||||||
if (totalTimeNanos == 0L) {
|
if (totalTimeNanos == 0L) {
|
||||||
consumer("$name performed $count times")
|
consumer("$name performed $count times")
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val millis = TimeUnit.NANOSECONDS.toMillis(totalTimeNanos)
|
val millis = TimeUnit.NANOSECONDS.toMillis(totalTimeNanos)
|
||||||
consumer("$name performed $count times, total time $millis ms")
|
consumer("$name performed $count times, total time $millis ms")
|
||||||
}
|
}
|
||||||
@@ -125,8 +124,7 @@ private class SimpleCounter(name: String): PerformanceCounter(name) {
|
|||||||
val startTime = PerformanceCounter.currentTime()
|
val startTime = PerformanceCounter.currentTime()
|
||||||
try {
|
try {
|
||||||
return block()
|
return block()
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
incrementTime(PerformanceCounter.currentTime() - startTime)
|
incrementTime(PerformanceCounter.currentTime() - startTime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -148,8 +146,7 @@ private class ReenterableCounter(name: String): PerformanceCounter(name) {
|
|||||||
val needTime = enterCounter(this)
|
val needTime = enterCounter(this)
|
||||||
try {
|
try {
|
||||||
return block()
|
return block()
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
if (needTime) {
|
if (needTime) {
|
||||||
incrementTime(PerformanceCounter.currentTime() - startTime)
|
incrementTime(PerformanceCounter.currentTime() - startTime)
|
||||||
leaveCounter(this)
|
leaveCounter(this)
|
||||||
@@ -168,8 +165,8 @@ internal class CounterWithExclude(name: String, vararg excludedCounters: Perform
|
|||||||
companion object {
|
companion object {
|
||||||
private val counterToCallStackMapThreadLocal = ThreadLocal<MutableMap<CounterWithExclude, CallStackWithTime>>()
|
private val counterToCallStackMapThreadLocal = ThreadLocal<MutableMap<CounterWithExclude, CallStackWithTime>>()
|
||||||
|
|
||||||
private fun getCallStack(counter: CounterWithExclude)
|
private fun getCallStack(counter: CounterWithExclude) =
|
||||||
= PerformanceCounter.getOrPut(counterToCallStackMapThreadLocal) { HashMap() }.getOrPut(counter) { CallStackWithTime() }
|
PerformanceCounter.getOrPut(counterToCallStackMapThreadLocal) { HashMap() }.getOrPut(counter) { CallStackWithTime() }
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -183,8 +180,7 @@ internal class CounterWithExclude(name: String, vararg excludedCounters: Perform
|
|||||||
incrementTime(callStack.push(true))
|
incrementTime(callStack.push(true))
|
||||||
try {
|
try {
|
||||||
return block()
|
return block()
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
incrementTime(callStack.pop(true))
|
incrementTime(callStack.pop(true))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ fun getExceptionMessage(
|
|||||||
|
|
||||||
if (location != null) {
|
if (location != null) {
|
||||||
result.append("File being compiled at position: ").append(location).append("\n")
|
result.append("File being compiled at position: ").append(location).append("\n")
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
result.append("Element is unknown")
|
result.append("Element is unknown")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user