summaryrefslogtreecommitdiff
path: root/plugins/kotlin/fir/src
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/kotlin/fir/src')
-rw-r--r--plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirIconProvider.kt13
-rw-r--r--plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCallableCompletionContributor.kt14
-rw-r--r--plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCompletionContributorBase.kt52
-rw-r--r--plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesSupportFirImpl.kt41
-rw-r--r--plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/HiglightingFactory.kt22
-rw-r--r--plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/KotlinHighLevelDiagnosticHighlightingPass.kt2
-rw-r--r--plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/beforeResolve/AbstractBeforeResolveHiglightingVisitory.kt16
-rw-r--r--plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/beforeResolve/AnnotationEntryHighlightingVisitor.kt35
-rw-r--r--plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/beforeResolve/DeclarationHighlightingVisitor.kt (renamed from plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/DeclarationHighlightingVisitor.kt)20
-rw-r--r--plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/FirAfterResolveHighlightingVisitor.kt7
-rw-r--r--plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/TypeHighlightingVisitor.kt16
-rw-r--r--plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/VariableReferenceHighlightingVisitor.kt33
-rw-r--r--plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/parameterInfo/KotlinHighLevelFunctionParameterInfoHandler.kt36
-rw-r--r--plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/parameterInfo/KotlinHighLevelTypeArgumentInfoHandler.kt2
-rw-r--r--plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/parameterInfo/utils.kt67
-rw-r--r--plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/SpecifySuperTypeFixFactory.kt6
-rw-r--r--plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/search/KotlinSearchUsagesSupportFirImpl.kt31
-rw-r--r--plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/search/ideaExtensions/FirKotlinTargetElementEvaluator.kt21
-rw-r--r--plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/util/findUsagesUtils.kt14
19 files changed, 303 insertions, 145 deletions
diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirIconProvider.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirIconProvider.kt
index 64383763fa21..c7f58156ada0 100644
--- a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirIconProvider.kt
+++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirIconProvider.kt
@@ -2,15 +2,23 @@
package org.jetbrains.kotlin.idea.completion
+import com.intellij.psi.PsiElement
import com.intellij.util.PlatformIcons
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.idea.KotlinIcons
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.api.symbols.markers.*
+import org.jetbrains.kotlin.psi.KtElement
import javax.swing.Icon
internal object KotlinFirIconProvider {
fun getIconFor(symbol: KtSymbol): Icon? {
+ symbol.psi?.let { referencedPsi ->
+ if (referencedPsi !is KtElement) {
+ return getIconForJavaDeclaration(referencedPsi)
+ }
+ }
+
if (symbol is KtFunctionSymbol) {
val isAbstract = symbol.modality == Modality.ABSTRACT
@@ -52,4 +60,9 @@ internal object KotlinFirIconProvider {
return null
}
+
+ private fun getIconForJavaDeclaration(declaration: PsiElement): Icon? {
+ val defaultIconFlags = 0
+ return declaration.getIcon(defaultIconFlags)
+ }
} \ No newline at end of file
diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCallableCompletionContributor.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCallableCompletionContributor.kt
index f795bea614a4..518cffc2f143 100644
--- a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCallableCompletionContributor.kt
+++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCallableCompletionContributor.kt
@@ -161,7 +161,8 @@ internal open class FirCallableCompletionContributor(
val symbol = explicitReceiver.reference()?.resolveToSymbol()
when {
symbol is KtPackageSymbol -> collectDotCompletionForPackageReceiver(symbol, context, visibilityChecker)
- symbol is KtNamedClassOrObjectSymbol && symbol.classKind == KtClassKind.ENUM_CLASS -> {
+
+ symbol is KtNamedClassOrObjectSymbol && symbol.hasImportantStaticMemberScope -> {
collectNonExtensions(symbol.getStaticMemberScope(), visibilityChecker, scopeNameFilter).forEach { memberSymbol ->
addCallableSymbolToCompletion(
context,
@@ -170,15 +171,24 @@ internal open class FirCallableCompletionContributor(
)
}
}
- symbol is KtNamedClassOrObjectSymbol && !symbol.classKind.isObject && symbol.companionObject == null -> {
+
+ symbol is KtNamedClassOrObjectSymbol && !symbol.canBeUsedAsReceiver -> {
// symbol cannot be used as callable receiver
}
+
else -> {
collectDotCompletionForCallableReceiver(implicitScopes, explicitReceiver, context, extensionChecker, visibilityChecker)
}
}
}
+ private val KtNamedClassOrObjectSymbol.hasImportantStaticMemberScope: Boolean
+ get() = classKind == KtClassKind.ENUM_CLASS ||
+ origin == KtSymbolOrigin.JAVA
+
+ private val KtNamedClassOrObjectSymbol.canBeUsedAsReceiver: Boolean
+ get() = classKind.isObject || companionObject != null
+
private fun KtAnalysisSession.collectDotCompletionForPackageReceiver(
packageSymbol: KtPackageSymbol,
context: WeighingContext,
diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCompletionContributorBase.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCompletionContributorBase.kt
index 0c5fa4fdae72..3cf5d82eca7a 100644
--- a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCompletionContributorBase.kt
+++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCompletionContributorBase.kt
@@ -132,32 +132,34 @@ internal abstract class FirCompletionContributorBase<C : FirRawPositionCompletio
}
}
- // Make the text gray and insert type cast if the receiver type does not match.
- is CallableMetadataProvider.CallableKind.ReceiverCastRequired -> object : LookupElementDecorator<LookupElement>(this) {
- override fun renderElement(presentation: LookupElementPresentation) {
- super.renderElement(presentation)
- presentation.itemTextForeground = LookupElementFactory.CAST_REQUIRED_COLOR
- // gray all tail fragments too:
- val fragments = presentation.tailFragments
- presentation.clearTail()
- for (fragment in fragments) {
- presentation.appendTailText(fragment.text, true)
- }
- }
+ // TODO this code should be uncommented when KTIJ-20913 is fixed
+ //// Make the text gray and insert type cast if the receiver type does not match.
+ //is CallableMetadataProvider.CallableKind.ReceiverCastRequired -> object : LookupElementDecorator<LookupElement>(this) {
+ // override fun renderElement(presentation: LookupElementPresentation) {
+ // super.renderElement(presentation)
+ // presentation.itemTextForeground = LookupElementFactory.CAST_REQUIRED_COLOR
+ // // gray all tail fragments too:
+ // val fragments = presentation.tailFragments
+ // presentation.clearTail()
+ // for (fragment in fragments) {
+ // presentation.appendTailText(fragment.text, true)
+ // }
+ // }
+ //
+ // override fun handleInsert(context: InsertionContext) {
+ // super.handleInsert(context)
+ // if (explicitReceiverRange == null || explicitReceiverText == null) return
+ // val castType = explicitReceiverTypeHint ?: kind.fullyQualifiedCastType
+ // val newReceiver = "(${explicitReceiverText} as $castType)"
+ // context.document.replaceString(explicitReceiverRange.startOffset, explicitReceiverRange.endOffset, newReceiver)
+ // context.commitDocument()
+ // shortenReferencesInRange(
+ // context.file as KtFile,
+ // explicitReceiverRange.grown(newReceiver.length)
+ // )
+ // }
+ //}
- override fun handleInsert(context: InsertionContext) {
- super.handleInsert(context)
- if (explicitReceiverRange == null || explicitReceiverText == null) return
- val castType = explicitReceiverTypeHint ?: kind.fullyQualifiedCastType
- val newReceiver = "(${explicitReceiverText} as $castType)"
- context.document.replaceString(explicitReceiverRange.startOffset, explicitReceiverRange.endOffset, newReceiver)
- context.commitDocument()
- shortenReferencesInRange(
- context.file as KtFile,
- explicitReceiverRange.grown(newReceiver.length)
- )
- }
- }
else -> this
}
}
diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesSupportFirImpl.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesSupportFirImpl.kt
index a412d09b2aec..d35b732402e0 100644
--- a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesSupportFirImpl.kt
+++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesSupportFirImpl.kt
@@ -12,11 +12,7 @@ import com.intellij.psi.search.GlobalSearchScope
import com.intellij.util.Processor
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.analyseInModalWindow
-import org.jetbrains.kotlin.analysis.api.analyseWithReadAction
-import org.jetbrains.kotlin.analysis.api.calls.KtCall
-import org.jetbrains.kotlin.analysis.api.calls.KtCallableMemberCall
-import org.jetbrains.kotlin.analysis.api.calls.KtImplicitReceiverValue
-import org.jetbrains.kotlin.analysis.api.calls.calls
+import org.jetbrains.kotlin.analysis.api.calls.*
import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtNamedSymbol
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithKind
@@ -25,11 +21,13 @@ import org.jetbrains.kotlin.idea.core.util.showYesNoCancelDialog
import org.jetbrains.kotlin.idea.refactoring.CHECK_SUPER_METHODS_YES_NO_DIALOG
import org.jetbrains.kotlin.idea.refactoring.formatPsiClass
import org.jetbrains.kotlin.idea.references.KtInvokeFunctionReference
+import org.jetbrains.kotlin.idea.util.withResolvedCall
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
class KotlinFindUsagesSupportFirImpl : KotlinFindUsagesSupport {
@@ -40,10 +38,9 @@ class KotlinFindUsagesSupportFirImpl : KotlinFindUsagesSupport {
val klass = companionObject.getStrictParentOfType<KtClass>() ?: return true
return !klass.anyDescendantOfType(fun(element: KtElement): Boolean {
if (element == companionObject) return false
- var result = false
- forResolvedCall(element) { call ->
+ return withResolvedCall(element) { call ->
if (callReceiverRefersToCompanionObject(call, companionObject)) {
- result = element.references.any {
+ element.references.any {
// We get both a simple named reference and an invoke function
// reference for all function calls. We want the named reference.
//
@@ -53,18 +50,13 @@ class KotlinFindUsagesSupportFirImpl : KotlinFindUsagesSupport {
// We should make FIR references behave the same.
it !is KtInvokeFunctionReference && !referenceProcessor.process(it)
}
+ } else {
+ false
}
- }
- return result
+ } ?: false
})
}
- private fun forResolvedCall(element: KtElement, block: KtAnalysisSession.(KtCall) -> Unit) {
- analyseWithReadAction(element) {
- element.resolveCall()?.calls?.singleOrNull()?.let { block(it) }
- }
- }
-
private fun KtAnalysisSession.callReceiverRefersToCompanionObject(call: KtCall, companionObject: KtObjectDeclaration): Boolean {
if (call !is KtCallableMemberCall<*, *>) return false
val dispatchReceiver = call.partiallyAppliedSymbol.dispatchReceiver
@@ -89,9 +81,20 @@ class KotlinFindUsagesSupportFirImpl : KotlinFindUsagesSupport {
return (declaration as? KtNamedDeclaration)?.name ?: "SUPPORT FOR FIR"
}
- override fun isConstructorUsage(psiReference: PsiReference, ktClassOrObject: KtClassOrObject): Boolean {
- // TODO: implement this
- return false
+ override fun isKotlinConstructorUsage(psiReference: PsiReference, ktClassOrObject: KtClassOrObject): Boolean {
+ val element = psiReference.element
+ if (element !is KtElement) return false
+
+ val constructorCalleeExpression = element.getNonStrictParentOfType<KtConstructorCalleeExpression>() ?: return false
+ return withResolvedCall(constructorCalleeExpression) { call ->
+ when (call) {
+ is KtDelegatedConstructorCall -> {
+ val constructedClassSymbol = call.symbol.containingClassIdIfNonLocal?.getCorrespondingToplevelClassOrObjectSymbol()
+ constructedClassSymbol == ktClassOrObject.getClassOrObjectSymbol()
+ }
+ else -> false
+ }
+ } ?: false
}
override fun getSuperMethods(declaration: KtDeclaration, ignore: Collection<PsiElement>?): List<PsiElement> {
diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/HiglightingFactory.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/HiglightingFactory.kt
new file mode 100644
index 000000000000..5f15fb41d8e6
--- /dev/null
+++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/HiglightingFactory.kt
@@ -0,0 +1,22 @@
+// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package org.jetbrains.kotlin.idea.fir.highlighter
+
+import com.intellij.lang.annotation.AnnotationHolder
+import com.intellij.lang.annotation.HighlightSeverity
+import com.intellij.openapi.editor.colors.TextAttributesKey
+import com.intellij.openapi.util.TextRange
+import com.intellij.util.applyIf
+
+internal object HiglightingFactory {
+ fun createInfoAnnotation(holder: AnnotationHolder, textRange: TextRange, message: String?, textAttributes: TextAttributesKey?) {
+ val builder =
+ if (message == null) holder.newSilentAnnotation(HighlightSeverity.INFORMATION)
+ else holder.newAnnotation(HighlightSeverity.INFORMATION, message)
+ builder
+ .range(textRange)
+ .applyIf(textAttributes != null) {
+ textAttributes(textAttributes!!)
+ }
+ .create()
+ }
+} \ No newline at end of file
diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/KotlinHighLevelDiagnosticHighlightingPass.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/KotlinHighLevelDiagnosticHighlightingPass.kt
index aa9b17b3b6da..a75759b77c01 100644
--- a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/KotlinHighLevelDiagnosticHighlightingPass.kt
+++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/KotlinHighLevelDiagnosticHighlightingPass.kt
@@ -37,7 +37,7 @@ class KotlinHighLevelDiagnosticHighlightingPass(
) : TextEditorHighlightingPass(ktFile.project, document) {
@Suppress("UnstableApiUsage")
- val annotationHolder = AnnotationHolderImpl(AnnotationSession(ktFile))
+ val annotationHolder = AnnotationHolderImpl(AnnotationSession(ktFile), false)
override fun doCollectInformation(progress: ProgressIndicator) {
analyse(ktFile) {
diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/beforeResolve/AbstractBeforeResolveHiglightingVisitory.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/beforeResolve/AbstractBeforeResolveHiglightingVisitory.kt
new file mode 100644
index 000000000000..e1215b2c51b1
--- /dev/null
+++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/beforeResolve/AbstractBeforeResolveHiglightingVisitory.kt
@@ -0,0 +1,16 @@
+// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package org.jetbrains.kotlin.idea.fir.highlighter.beforeResolve
+
+import com.intellij.lang.annotation.AnnotationHolder
+import com.intellij.lang.annotation.HighlightSeverity
+import com.intellij.openapi.editor.colors.TextAttributesKey
+import com.intellij.openapi.util.TextRange
+import com.intellij.util.applyIf
+import org.jetbrains.kotlin.idea.fir.highlighter.HiglightingFactory
+import org.jetbrains.kotlin.idea.highlighter.AbstractHighlightingVisitor
+
+abstract class AbstractBeforeResolveHiglightingVisitory(protected val holder: AnnotationHolder): AbstractHighlightingVisitor() {
+ override fun createInfoAnnotation(textRange: TextRange, message: String?, textAttributes: TextAttributesKey?) {
+ HiglightingFactory.createInfoAnnotation(holder, textRange, message, textAttributes)
+ }
+} \ No newline at end of file
diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/beforeResolve/AnnotationEntryHighlightingVisitor.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/beforeResolve/AnnotationEntryHighlightingVisitor.kt
new file mode 100644
index 000000000000..0fa128b53c8f
--- /dev/null
+++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/beforeResolve/AnnotationEntryHighlightingVisitor.kt
@@ -0,0 +1,35 @@
+// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+
+package org.jetbrains.kotlin.idea.fir.highlighter.beforeResolve
+
+import com.intellij.lang.annotation.AnnotationHolder
+import com.intellij.openapi.util.TextRange
+import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
+import org.jetbrains.kotlin.idea.highlighter.AbstractHighlightingVisitor
+import org.jetbrains.kotlin.idea.highlighter.BeforeResolveHighlightingExtension
+import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors
+import org.jetbrains.kotlin.idea.highlighter.NameHighlighter
+import org.jetbrains.kotlin.psi.KtAnnotationEntry
+import org.jetbrains.kotlin.psi.psiUtil.endOffset
+import org.jetbrains.kotlin.psi.psiUtil.startOffset
+
+internal class AnnotationEntryHighlightingVisitor(
+ holder: AnnotationHolder
+) : AbstractBeforeResolveHiglightingVisitory(holder) {
+ override fun visitAnnotationEntry(annotationEntry: KtAnnotationEntry) {
+ if (!NameHighlighter.namesHighlightingEnabled) return
+ val range = annotationEntry.getTextRangeToHiglight() ?: return
+ createInfoAnnotation(range, textAttributes = KotlinHighlightingColors.ANNOTATION)
+ }
+
+ private fun KtAnnotationEntry.getTextRangeToHiglight(): TextRange? {
+ val atSymbol = atSymbol ?: return null
+ val typeReference = typeReference ?: return null
+ return TextRange(atSymbol.startOffset, typeReference.endOffset)
+ }
+}
+
+class AnnotationsHighlightingExtension : BeforeResolveHighlightingExtension {
+ override fun createVisitor(holder: AnnotationHolder): AbstractHighlightingVisitor =
+ AnnotationEntryHighlightingVisitor(holder)
+} \ No newline at end of file
diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/DeclarationHighlightingVisitor.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/beforeResolve/DeclarationHighlightingVisitor.kt
index d28c062c6474..e25006a87395 100644
--- a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/DeclarationHighlightingVisitor.kt
+++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/beforeResolve/DeclarationHighlightingVisitor.kt
@@ -3,7 +3,7 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
-package org.jetbrains.kotlin.idea.fir.highlighter.visitors
+package org.jetbrains.kotlin.idea.fir.highlighter.beforeResolve
import com.intellij.lang.annotation.AnnotationHolder
import com.intellij.lang.annotation.HighlightSeverity
@@ -16,7 +16,7 @@ import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors as Colors
-internal class DeclarationHighlightingVisitor(private val holder: AnnotationHolder) : AbstractHighlightingVisitor() {
+internal class DeclarationHighlightingVisitor(holder: AnnotationHolder) : AbstractBeforeResolveHiglightingVisitory(holder) {
override fun visitTypeAlias(typeAlias: KtTypeAlias) {
highlightNamedDeclaration(typeAlias, Colors.TYPE_ALIAS)
super.visitTypeAlias(typeAlias)
@@ -27,22 +27,6 @@ internal class DeclarationHighlightingVisitor(private val holder: AnnotationHold
super.visitObjectDeclaration(declaration)
}
- override fun createInfoAnnotation(
- textRange: com.intellij.openapi.util.TextRange,
- message: kotlin.String?,
- textAttributes: com.intellij.openapi.editor.colors.TextAttributesKey?
- ) {
- return (message?.let { holder.newAnnotation(HighlightSeverity.INFORMATION, it) }
- ?: holder.newSilentAnnotation(HighlightSeverity.INFORMATION))
- .range(textRange)
- .also { builder ->
- textAttributes?.let {
- builder.textAttributes(it)
- }
- }
- .create()
- }
-
override fun visitClass(klass: KtClass) {
highlightNamedDeclaration(klass, textAttributesForClass(klass))
super.visitClass(klass)
diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/FirAfterResolveHighlightingVisitor.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/FirAfterResolveHighlightingVisitor.kt
index b7d71d9d4720..ff64768728bb 100644
--- a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/FirAfterResolveHighlightingVisitor.kt
+++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/FirAfterResolveHighlightingVisitor.kt
@@ -3,9 +3,12 @@
package org.jetbrains.kotlin.idea.fir.highlighter.visitors
import com.intellij.lang.annotation.AnnotationHolder
+import com.intellij.lang.annotation.HighlightSeverity
import com.intellij.openapi.editor.colors.TextAttributesKey
import com.intellij.openapi.util.TextRange
+import com.intellij.util.applyIf
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
+import org.jetbrains.kotlin.idea.fir.highlighter.HiglightingFactory
import org.jetbrains.kotlin.idea.highlighter.AbstractHighlightingVisitor
abstract class FirAfterResolveHighlightingVisitor(
@@ -14,9 +17,7 @@ abstract class FirAfterResolveHighlightingVisitor(
) : AbstractHighlightingVisitor() {
override fun createInfoAnnotation(textRange: TextRange, message: String?, textAttributes: TextAttributesKey?) {
- // TODO: Temporary use deprecated for FIR plugin as it is supposes to be rewritten fully
- holder.createInfoAnnotation(textRange, message)
- .also { annotation -> textAttributes?.let { annotation.textAttributes = textAttributes } }
+ HiglightingFactory.createInfoAnnotation(holder, textRange, message, textAttributes)
}
companion object {
diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/TypeHighlightingVisitor.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/TypeHighlightingVisitor.kt
index bce0c124f88e..2726ea372076 100644
--- a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/TypeHighlightingVisitor.kt
+++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/TypeHighlightingVisitor.kt
@@ -28,29 +28,29 @@ internal class TypeHighlightingVisitor(
return
}
val target = expression.mainReference.resolve() ?: return
+ if (isAnnotationCall(expression, target)) {
+ // higlighted by AnnotationEntryHiglightingVisitor
+ return
+ }
textAttributesKeyForTypeDeclaration(target)?.let { key ->
if (expression.isConstructorCallReference() && key != Colors.ANNOTATION) {
// Do not highlight constructor call as class reference
return@let
}
- highlightName(computeHighlightingRangeForUsage(expression, target), key)
+ highlightName(expression.textRange, key)
}
}
-
- private fun computeHighlightingRangeForUsage(expression: KtSimpleNameExpression, target: PsiElement): TextRange {
+ private fun isAnnotationCall(expression: KtSimpleNameExpression, target: PsiElement): Boolean {
val expressionRange = expression.textRange
val isKotlinAnnotation = target is KtPrimaryConstructor && target.parent.isAnnotationClass()
- if (!isKotlinAnnotation && !target.isAnnotationClass()) return expressionRange
+ if (!isKotlinAnnotation && !target.isAnnotationClass()) return false
- // include '@' symbol if the reference is the first segment of KtAnnotationEntry
- // if "Deprecated" is highlighted then '@' should be highlighted too in "@Deprecated"
val annotationEntry = PsiTreeUtil.getParentOfType(
expression, KtAnnotationEntry::class.java, /* strict = */false, KtValueArgumentList::class.java
)
- val atSymbol = annotationEntry?.atSymbol ?: return expressionRange
- return TextRange(atSymbol.textRange.startOffset, expression.textRange.endOffset)
+ return annotationEntry?.atSymbol != null
}
}
diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/VariableReferenceHighlightingVisitor.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/VariableReferenceHighlightingVisitor.kt
index 08d1776f9a5d..81aeb2abcf0e 100644
--- a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/VariableReferenceHighlightingVisitor.kt
+++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/fir/highlighter/visitors/VariableReferenceHighlightingVisitor.kt
@@ -3,21 +3,20 @@
package org.jetbrains.kotlin.idea.fir.highlighter.visitors
import com.intellij.lang.annotation.AnnotationHolder
-import com.intellij.psi.PsiElement
-import com.intellij.psi.PsiMethod
-import com.intellij.psi.PsiModifier
-import com.intellij.psi.PsiVariable
-import com.intellij.psi.util.PsiUtilCore
-import com.intellij.psi.util.parentOfType
-import org.jetbrains.kotlin.idea.KotlinIdeaAnalysisBundle
-import org.jetbrains.kotlin.idea.highlighter.textAttributesKeyForPropertyDeclaration
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.symbols.KtBackingFieldSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
+import org.jetbrains.kotlin.analysis.api.symbols.KtSyntheticJavaPropertySymbol
+import org.jetbrains.kotlin.analysis.api.symbols.KtVariableSymbol
+import org.jetbrains.kotlin.idea.KotlinIdeaAnalysisBundle
import org.jetbrains.kotlin.idea.highlighter.NameHighlighter
+import org.jetbrains.kotlin.idea.highlighter.textAttributesKeyForPropertyDeclaration
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.lexer.KtTokens
-import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.KtInstanceExpressionWithLabel
+import org.jetbrains.kotlin.psi.KtOperationReferenceExpression
+import org.jetbrains.kotlin.psi.KtSimpleNameExpression
+import org.jetbrains.kotlin.psi.KtValueArgumentName
import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors as Colors
internal class VariableReferenceHighlightingVisitor(
@@ -41,15 +40,17 @@ internal class VariableReferenceHighlightingVisitor(
with(analysisSession) {
val targetSymbol = expression.mainReference.resolveToSymbol()
- val target = expression.mainReference.resolve()
+ val targetPsi = targetSymbol?.psi
when {
targetSymbol is KtBackingFieldSymbol -> Colors.BACKING_FIELD_VARIABLE
- target is PsiMethod -> Colors.SYNTHETIC_EXTENSION_PROPERTY
- target != null -> textAttributesKeyForPropertyDeclaration(target)
+ targetSymbol is KtSyntheticJavaPropertySymbol -> Colors.SYNTHETIC_EXTENSION_PROPERTY
+ targetPsi != null -> textAttributesKeyForPropertyDeclaration(targetPsi)
else -> null
}?.let { attribute ->
highlightName(expression, attribute)
- if (target?.isMutableVariable() == true || targetSymbol != null && isBackingFieldReferencingMutableVariable(targetSymbol)) {
+ if (isMutableVariable(targetSymbol) == true
+ || targetSymbol != null && isBackingFieldReferencingMutableVariable(targetSymbol)
+ ) {
highlightName(expression, Colors.MUTABLE_VARIABLE)
}
}
@@ -71,9 +72,9 @@ internal class VariableReferenceHighlightingVisitor(
}
}
-private fun PsiElement.isMutableVariable() = when {
- this is KtValVarKeywordOwner && PsiUtilCore.getElementType(valOrVarKeyword) == KtTokens.VAR_KEYWORD -> true
- this is PsiVariable && !hasModifierProperty(PsiModifier.FINAL) -> true
+@Suppress("unused")
+private fun KtAnalysisSession.isMutableVariable(symbol: KtSymbol?): Boolean = when (symbol) {
+ is KtVariableSymbol -> !symbol.isVal
else -> false
}
diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/parameterInfo/KotlinHighLevelFunctionParameterInfoHandler.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/parameterInfo/KotlinHighLevelFunctionParameterInfoHandler.kt
index c5203435ecdf..bdd68250f040 100644
--- a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/parameterInfo/KotlinHighLevelFunctionParameterInfoHandler.kt
+++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/parameterInfo/KotlinHighLevelFunctionParameterInfoHandler.kt
@@ -12,6 +12,7 @@ import com.intellij.ui.JBColor
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.analyse
import org.jetbrains.kotlin.analysis.api.annotations.annotations
+import org.jetbrains.kotlin.analysis.api.calls.KtApplicableCallCandidateInfo
import org.jetbrains.kotlin.analysis.api.components.KtTypeRendererOptions
import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtVariableLikeSignature
@@ -115,7 +116,9 @@ abstract class KotlinHighLevelParameterInfoWithCallHandlerBase<TArgumentList : K
// `context.itemsToShow` array which becomes `context.objectsToView` array in updateParameterInfo(). Unfortunately
// `objectsToView` is read-only so we can't change the size of the array. So we have to store an array here of the correct size,
// which does mean we have to resolve here to know the number of candidates.
- val candidatesWithMapping = resolveCallCandidates(callElement)
+ val candidatesWithMapping = collectCallCandidates(callElement)
+
+ // TODO: Filter shadowed candidates. See use of ShadowedDeclarationsFilter in KotlinFunctionParameterInfoHandler.kt.
context.itemsToShow = Array(candidatesWithMapping.size) { CandidateInfo() }
argumentList
@@ -145,7 +148,8 @@ abstract class KotlinHighLevelParameterInfoWithCallHandlerBase<TArgumentList : K
is KtArrayAccessExpression -> Pair(null, callElement.indexExpressions)
else -> return@analyse
}
- val candidatesWithMapping = resolveCallCandidates(callElement)
+ val candidatesWithMapping = collectCallCandidates(callElement)
+ val hasMultipleApplicableBestCandidates = candidatesWithMapping.count { it.isApplicableBestCandidate } > 1
for ((index, objectToView) in context.objectsToView.withIndex()) {
val candidateInfo = objectToView as? CandidateInfo ?: continue
@@ -154,7 +158,7 @@ abstract class KotlinHighLevelParameterInfoWithCallHandlerBase<TArgumentList : K
// Number of candidates somehow changed while UI is shown, which should NOT be possible. Bail out to be safe.
return
}
- val (candidateSignature, argumentMapping) = candidatesWithMapping[index]
+ val (candidateSignature, argumentMapping, isApplicableBestCandidate) = candidatesWithMapping[index]
// For array set calls, we only want the index arguments in brackets, which are all except the last (the value to set).
val isArraySetCall = candidateSignature.symbol.callableIdIfNonLocal?.let {
@@ -205,8 +209,10 @@ abstract class KotlinHighLevelParameterInfoWithCallHandlerBase<TArgumentList : K
setValueParameter
)
- // TODO: This should be changed when there are multiple candidates available; need to know which one the call is resolved to
- val isCallResolvedToCandidate = candidatesWithMapping.size == 1
+ // We want to highlight the candidate green if it is the only best/final candidate selected and is applicable.
+ // However, if there is only one candidate available, we want to highlight it green regardless of its applicability.
+ val shouldHighlightGreen = (isApplicableBestCandidate && !hasMultipleApplicableBestCandidates)
+ || candidatesWithMapping.size == 1
candidateInfo.callInfo = CallInfo(
callElement,
@@ -215,10 +221,10 @@ abstract class KotlinHighLevelParameterInfoWithCallHandlerBase<TArgumentList : K
argumentToParameterIndex,
valueParameters.size,
parameterIndexToText,
- isCallResolvedToCandidate,
+ shouldHighlightGreen,
hasTypeMismatchBeforeCurrent,
highlightParameterIndex,
- candidateSignature.symbol.deprecationStatus != null,
+ isDeprecated = candidateSignature.symbol.deprecationStatus != null,
)
}
}
@@ -251,7 +257,7 @@ abstract class KotlinHighLevelParameterInfoWithCallHandlerBase<TArgumentList : K
}
if (includeName) {
- append(parameter.symbol.name)
+ append(parameter.name)
append(": ")
}
@@ -388,9 +394,10 @@ abstract class KotlinHighLevelParameterInfoWithCallHandlerBase<TArgumentList : K
var isDisabledBeforeHighlight = false
var hasUnmappedArgument = false
var hasUnmappedArgumentBeforeCurrent = false
+ var lastMappedArgumentIndex = -1
+ var namedMode = false
val usedParameterIndices = HashSet<Int>()
val text = buildString {
- var namedMode = false
var argumentIndex = 0
fun appendParameter(
@@ -452,6 +459,7 @@ abstract class KotlinHighLevelParameterInfoWithCallHandlerBase<TArgumentList : K
argumentIndex++
continue
}
+ lastMappedArgumentIndex = argumentIndex
if (!usedParameterIndices.add(parameterIndex)) continue
val shouldHighlight = parameterIndex == highlightParameterIndex
@@ -463,12 +471,13 @@ abstract class KotlinHighLevelParameterInfoWithCallHandlerBase<TArgumentList : K
val parameterIndex = argumentToParameterIndex[argument]
if (parameterIndex == null) {
hasUnmappedArgument = true
- if (argumentIndex <= currentArgumentIndex) {
+ if (argumentIndex < currentArgumentIndex) {
hasUnmappedArgumentBeforeCurrent = true
}
argumentIndex++
continue
}
+ lastMappedArgumentIndex = argumentIndex
if (!usedParameterIndices.add(parameterIndex)) continue
val shouldHighlight = parameterIndex == highlightParameterIndex
@@ -493,14 +502,15 @@ abstract class KotlinHighLevelParameterInfoWithCallHandlerBase<TArgumentList : K
}
}
- val backgroundColor = if (isCallResolvedToCandidate) GREEN_BACKGROUND else context.defaultParameterColor
+ val backgroundColor = if (shouldHighlightGreen) GREEN_BACKGROUND else context.defaultParameterColor
// Disabled when there are too many arguments.
val allParametersUsed = usedParameterIndices.size == valueParameterCount
val supportsTrailingCommas = callElement.languageVersionSettings.supportsFeature(LanguageFeature.TrailingCommas)
val afterTrailingComma = arguments.isNotEmpty() && currentArgumentIndex == arguments.size
val isInPositionToEnterArgument = !supportsTrailingCommas && afterTrailingComma
- val tooManyArgs = allParametersUsed && (isInPositionToEnterArgument || hasUnmappedArgument)
+ val isAfterMappedArgs = currentArgumentIndex > lastMappedArgumentIndex
+ val tooManyArgs = allParametersUsed && (isInPositionToEnterArgument || hasUnmappedArgument) && (isAfterMappedArgs || namedMode)
val isDisabled = tooManyArgs || hasTypeMismatchBeforeCurrent || hasUnmappedArgumentBeforeCurrent
@@ -525,7 +535,7 @@ abstract class KotlinHighLevelParameterInfoWithCallHandlerBase<TArgumentList : K
val argumentToParameterIndex: LinkedHashMap<KtExpression, Int>,
val valueParameterCount: Int,
val parameterIndexToText: Map<Int, String>,
- val isCallResolvedToCandidate: Boolean,
+ val shouldHighlightGreen: Boolean,
val hasTypeMismatchBeforeCurrent: Boolean,
val highlightParameterIndex: Int?,
val isDeprecated: Boolean,
diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/parameterInfo/KotlinHighLevelTypeArgumentInfoHandler.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/parameterInfo/KotlinHighLevelTypeArgumentInfoHandler.kt
index b39699a0f0c5..14c502dadae3 100644
--- a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/parameterInfo/KotlinHighLevelTypeArgumentInfoHandler.kt
+++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/parameterInfo/KotlinHighLevelTypeArgumentInfoHandler.kt
@@ -51,7 +51,7 @@ class KotlinHighLevelFunctionTypeArgumentInfoHandler : KotlinHighLevelTypeArgume
// will NOT return a KtCall because there is no FirFunctionCall there. We find the symbols using the callee name instead.
val reference = callElement.calleeExpression?.references?.singleOrNull() as? KtSimpleNameReference ?: return null
val parent = callElement.parent
- val receiver = if (parent is KtDotQualifiedExpression && parent.selectorExpression == callElement) {
+ val receiver = if (parent is KtQualifiedExpression && parent.selectorExpression == callElement) {
parent.receiverExpression
} else null
val fileSymbol = callElement.containingKtFile.getFileSymbol()
diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/parameterInfo/utils.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/parameterInfo/utils.kt
index 73f93f18a729..7671b35b42e0 100644
--- a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/parameterInfo/utils.kt
+++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/parameterInfo/utils.kt
@@ -2,39 +2,51 @@
package org.jetbrains.kotlin.idea.parameterInfo
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
-import org.jetbrains.kotlin.analysis.api.calls.KtFunctionCall
-import org.jetbrains.kotlin.analysis.api.calls.calls
-import org.jetbrains.kotlin.analysis.api.calls.symbol
+import org.jetbrains.kotlin.analysis.api.calls.*
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithVisibility
+import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
import org.jetbrains.kotlin.psi.*
// Analogous to Call.resolveCandidates() in plugins/kotlin/core/src/org/jetbrains/kotlin/idea/core/Utils.kt
-internal fun KtAnalysisSession.resolveCallCandidates(callElement: KtElement): List<CandidateWithMapping> {
- // TODO: FE 1.0 plugin collects all candidates (i.e., all overloads), even if arguments do not match. Not just resolved call.
- // See Call.resolveCandidates() in core/src/org/jetbrains/kotlin/idea/core/Utils.kt. Note `replaceCollectAllCandidates(true)`.
-
- val (resolvedCall, receiver) = when (callElement) {
+internal fun KtAnalysisSession.collectCallCandidates(callElement: KtElement): List<CandidateWithMapping> {
+ val (candidates, receiver) = when (callElement) {
is KtCallElement -> {
val parent = callElement.parent
- val receiver = if (parent is KtDotQualifiedExpression && parent.selectorExpression == callElement) {
+ val receiver = if (parent is KtQualifiedExpression && parent.selectorExpression == callElement) {
parent.receiverExpression
} else null
- Pair(callElement.resolveCall(), receiver)
+ callElement.collectCallCandidates() to receiver
}
- is KtArrayAccessExpression -> Pair(callElement.resolveCall(), callElement.arrayExpression)
+ is KtArrayAccessExpression -> callElement.collectCallCandidates() to callElement.arrayExpression
else -> return emptyList()
}
+ if (candidates.isEmpty()) return emptyList()
val fileSymbol = callElement.containingKtFile.getFileSymbol()
- return resolvedCall.calls.filterIsInstance<KtFunctionCall<*>>()
- .filter { filterCandidate(it.symbol, callElement, fileSymbol, receiver) }
- .map {
- CandidateWithMapping(
- it.partiallyAppliedSymbol.signature,
- it.argumentMapping,
- )
- }
+
+ return candidates.filter {
+ filterCandidate(it, callElement, fileSymbol, receiver)
+ }.map {
+ val functionCall = it.candidate as KtFunctionCall<*>
+ CandidateWithMapping(
+ functionCall.partiallyAppliedSymbol.signature,
+ functionCall.argumentMapping,
+ isApplicableBestCandidate = it is KtApplicableCallCandidateInfo && it.isInBestCandidates
+ )
+ }
+}
+
+private fun KtAnalysisSession.filterCandidate(
+ candidateInfo: KtCallCandidateInfo,
+ callElement: KtElement,
+ fileSymbol: KtFileSymbol,
+ receiver: KtExpression?
+): Boolean {
+ val candidateCall = candidateInfo.candidate
+ if (candidateCall !is KtFunctionCall<*>) return false
+ val candidateSymbol = candidateCall.partiallyAppliedSymbol.signature.symbol
+ return filterCandidate(candidateSymbol, callElement, fileSymbol, receiver)
}
internal fun KtAnalysisSession.filterCandidate(
@@ -54,8 +66,20 @@ internal fun KtAnalysisSession.filterCandidate(
}
if (receiver != null && candidateSymbol is KtCallableSymbol) {
- // Filter out candidates with wrong receiver
- val receiverType = receiver.getKtType() ?: error("Receiver should have a KtType")
+ // We want only the candidates that match the receiver type. E.g., if you have code like this:
+ // ```
+ // fun String.foo() {}
+ // fun Int.foo() {}
+ // fun call(i: Int?) {
+ // <expr>i?.foo()</expr>
+ // }
+ // ```
+ // The available candidates are `String.foo()` and `Int.foo()`. When checking the receiver types for safe calls, we want to compare
+ // the non-nullable receiver type against the candidate receiver type. E.g., that `Int` (and not the type of `i` which is `Int?`)
+ // is subtype of `Int` (the candidate receiver type).
+ val isSafeCall = receiver.parent is KtSafeQualifiedExpression
+ val receiverType = receiver.getKtType()?.let { if (isSafeCall) it.withNullability(KtTypeNullability.NON_NULLABLE) else it }
+ ?: error("Receiver should have a KtType")
val candidateReceiverType = candidateSymbol.receiverType
if (candidateReceiverType != null && receiverType.isNotSubTypeOf(candidateReceiverType)) return false
}
@@ -69,4 +93,5 @@ internal fun KtAnalysisSession.filterCandidate(
internal data class CandidateWithMapping(
val candidate: KtFunctionLikeSignature<KtFunctionLikeSymbol>,
val argumentMapping: LinkedHashMap<KtExpression, KtVariableLikeSignature<KtValueParameterSymbol>>,
+ val isApplicableBestCandidate: Boolean,
) \ No newline at end of file
diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/SpecifySuperTypeFixFactory.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/SpecifySuperTypeFixFactory.kt
index 380f8c484b88..caa7ec11a4d2 100644
--- a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/SpecifySuperTypeFixFactory.kt
+++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/SpecifySuperTypeFixFactory.kt
@@ -32,7 +32,7 @@ object SpecifySuperTypeFixFactory {
class Input(val superTypes: List<TypeStringWithoutArgs>) : HLApplicatorInput
val applicator = applicator<KtSuperExpression, Input> {
- familyAndActionName(KotlinBundle.lazyMessage("specify.super.type"))
+ familyAndActionName(KotlinBundle.lazyMessage("intention.name.specify.supertype"))
applyToWithEditorRequired { psi, input, project, editor ->
when (input.superTypes.size) {
0 -> return@applyToWithEditorRequired
@@ -46,7 +46,7 @@ object SpecifySuperTypeFixFactory {
}
private fun KtSuperExpression.specifySuperType(superType: TypeStringWithoutArgs) {
- project.executeWriteCommand(KotlinBundle.getMessage("specify.super.type")) {
+ project.executeWriteCommand(KotlinBundle.message("intention.name.specify.supertype")) {
val label = this.labelQualifier?.text ?: ""
val replaced =
replace(KtPsiFactory(this).createExpression("super<${superType.longTypeRepresentation}>$label")) as KtSuperExpression
@@ -55,7 +55,7 @@ object SpecifySuperTypeFixFactory {
}
private fun createListPopupStep(superExpression: KtSuperExpression, superTypes: List<TypeStringWithoutArgs>): ListPopupStep<*> {
- return object : BaseListPopupStep<TypeStringWithoutArgs>(KotlinBundle.getMessage("choose.super.type"), superTypes) {
+ return object : BaseListPopupStep<TypeStringWithoutArgs>(KotlinBundle.getMessage("popup.title.choose.supertype"), superTypes) {
override fun isAutoSelectionEnabled() = false
override fun onChosen(selectedValue: TypeStringWithoutArgs, finalChoice: Boolean): PopupStep<*>? {
diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/search/KotlinSearchUsagesSupportFirImpl.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/search/KotlinSearchUsagesSupportFirImpl.kt
index 26a162e2a8c3..696c6b80ee38 100644
--- a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/search/KotlinSearchUsagesSupportFirImpl.kt
+++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/search/KotlinSearchUsagesSupportFirImpl.kt
@@ -11,27 +11,30 @@ import com.intellij.psi.search.SearchScope
import com.intellij.psi.search.searches.DefinitionsScopedSearch
import com.intellij.psi.search.searches.OverridingMethodsSearch
import com.intellij.util.Processor
-import org.jetbrains.kotlin.asJava.classes.KtFakeLightMethod
-import org.jetbrains.kotlin.asJava.unwrapped
-import org.jetbrains.kotlin.descriptors.Modality
-import org.jetbrains.kotlin.idea.core.isInheritable
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.analyse
import org.jetbrains.kotlin.analysis.api.analyseWithReadAction
+import org.jetbrains.kotlin.analysis.api.calls.KtDelegatedConstructorCall
+import org.jetbrains.kotlin.analysis.api.calls.symbol
import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithModality
import org.jetbrains.kotlin.analysis.api.tokens.HackToForceAllowRunningAnalyzeOnEDT
import org.jetbrains.kotlin.analysis.api.tokens.hackyAllowRunningOnEdt
+import org.jetbrains.kotlin.asJava.classes.KtFakeLightMethod
+import org.jetbrains.kotlin.asJava.unwrapped
+import org.jetbrains.kotlin.descriptors.Modality
+import org.jetbrains.kotlin.idea.core.isInheritable
import org.jetbrains.kotlin.idea.search.declarationsSearch.toPossiblyFakeLightMethods
-import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions
import org.jetbrains.kotlin.idea.search.usagesSearch.getDefaultImports
import org.jetbrains.kotlin.idea.stubindex.KotlinTypeAliasShortNameIndex
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
+import org.jetbrains.kotlin.idea.util.withResolvedCall
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.resolve.ImportPath
class KotlinSearchUsagesSupportFirImpl : KotlinSearchUsagesSupport {
@@ -51,13 +54,6 @@ class KotlinSearchUsagesSupportFirImpl : KotlinSearchUsagesSupport {
return false
}
- override fun <T : PsiNamedElement> filterDataClassComponentsIfDisabled(
- elements: List<T>,
- kotlinOptions: KotlinReferencesSearchOptions
- ): List<T> {
- return emptyList()
- }
-
override fun isCallableOverrideUsage(reference: PsiReference, declaration: KtNamedDeclaration): Boolean {
return false
}
@@ -242,10 +238,15 @@ class KotlinSearchUsagesSupportFirImpl : KotlinSearchUsagesSupport {
}
override fun createConstructorHandle(ktDeclaration: KtDeclaration): KotlinSearchUsagesSupport.ConstructorCallHandle {
- //TODO FIR: This is the stub. Need to implement
return object : KotlinSearchUsagesSupport.ConstructorCallHandle {
override fun referencedTo(element: KtElement): Boolean {
- return false
+ val callExpression = element.getNonStrictParentOfType<KtCallElement>() ?: return false
+ return withResolvedCall(callExpression) { call ->
+ when (call) {
+ is KtDelegatedConstructorCall -> call.symbol == ktDeclaration.getSymbol()
+ else -> false
+ }
+ } ?: false
}
}
}
@@ -258,4 +259,4 @@ class KotlinSearchUsagesSupportFirImpl : KotlinSearchUsagesSupport {
}
}
}
-} \ No newline at end of file
+}
diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/search/ideaExtensions/FirKotlinTargetElementEvaluator.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/search/ideaExtensions/FirKotlinTargetElementEvaluator.kt
new file mode 100644
index 000000000000..8d4a9d4e13de
--- /dev/null
+++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/search/ideaExtensions/FirKotlinTargetElementEvaluator.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.idea.search.ideaExtensions
+
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiReference
+
+class FirKotlinTargetElementEvaluator : KotlinTargetElementEvaluator() {
+ override fun findLambdaOpenLBraceForGeneratedIt(ref: PsiReference): PsiElement? {
+ // TODO: implement
+ return null
+ }
+
+ override fun findReceiverForThisInExtensionFunction(ref: PsiReference): PsiElement? {
+ // TODO: implement
+ return null
+ }
+}
diff --git a/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/util/findUsagesUtils.kt b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/util/findUsagesUtils.kt
new file mode 100644
index 000000000000..df59b5bed1a4
--- /dev/null
+++ b/plugins/kotlin/fir/src/org/jetbrains/kotlin/idea/util/findUsagesUtils.kt
@@ -0,0 +1,14 @@
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package org.jetbrains.kotlin.idea.util
+
+import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
+import org.jetbrains.kotlin.analysis.api.analyseWithReadAction
+import org.jetbrains.kotlin.analysis.api.calls.KtCall
+import org.jetbrains.kotlin.analysis.api.calls.calls
+import org.jetbrains.kotlin.psi.KtElement
+
+inline fun <R> withResolvedCall(element: KtElement, crossinline block: KtAnalysisSession.(KtCall) -> R): R? {
+ return analyseWithReadAction(element) {
+ element.resolveCall()?.calls?.singleOrNull()?.let { block(it) }
+ }
+}