summaryrefslogtreecommitdiff
path: root/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin')
-rw-r--r--plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesSupport.kt16
-rw-r--r--plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/AddElseBranchFix.kt92
-rw-r--r--plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/AddWhenElseBranchFix.kt37
-rw-r--r--plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/RemoveWhenBranchFix.kt9
-rw-r--r--plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/references/ReadWriteAccessChecker.kt38
-rw-r--r--plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/search/KotlinSearchSupport.kt27
-rw-r--r--plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinTargetElementEvaluator.kt81
-rw-r--r--plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/util/editorUtils.kt13
8 files changed, 253 insertions, 60 deletions
diff --git a/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesSupport.kt b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesSupport.kt
index f05150b9bd4d..2f456b737469 100644
--- a/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesSupport.kt
+++ b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesSupport.kt
@@ -3,6 +3,7 @@
package org.jetbrains.kotlin.idea.findUsages
import com.intellij.openapi.project.Project
+import com.intellij.psi.PsiConstructorCall
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiReference
import com.intellij.psi.search.GlobalSearchScope
@@ -12,6 +13,7 @@ import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtObjectDeclaration
import org.jetbrains.kotlin.psi.KtParameter
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
interface KotlinFindUsagesSupport {
@@ -33,8 +35,14 @@ interface KotlinFindUsagesSupport {
fun tryRenderDeclarationCompactStyle(declaration: KtDeclaration): String? =
getInstance(declaration.project).tryRenderDeclarationCompactStyle(declaration)
- fun PsiReference.isConstructorUsage(ktClassOrObject: KtClassOrObject): Boolean =
- getInstance(ktClassOrObject.project).isConstructorUsage(this, ktClassOrObject)
+ fun PsiReference.isConstructorUsage(ktClassOrObject: KtClassOrObject): Boolean {
+ fun isJavaConstructorUsage(): Boolean {
+ val call = element.getNonStrictParentOfType<PsiConstructorCall>()
+ return call == element.parent && call?.resolveConstructor()?.containingClass?.navigationElement == ktClassOrObject
+ }
+
+ return isJavaConstructorUsage() || getInstance(ktClassOrObject.project).isKotlinConstructorUsage(this, ktClassOrObject)
+ }
fun getSuperMethods(declaration: KtDeclaration, ignore: Collection<PsiElement>?) : List<PsiElement> =
getInstance(declaration.project).getSuperMethods(declaration, ignore)
@@ -51,9 +59,9 @@ interface KotlinFindUsagesSupport {
fun tryRenderDeclarationCompactStyle(declaration: KtDeclaration): String?
- fun isConstructorUsage(psiReference: PsiReference, ktClassOrObject: KtClassOrObject): Boolean
+ fun isKotlinConstructorUsage(psiReference: PsiReference, ktClassOrObject: KtClassOrObject): Boolean
fun getSuperMethods(declaration: KtDeclaration, ignore: Collection<PsiElement>?) : List<PsiElement>
fun sourcesAndLibraries(delegate: GlobalSearchScope, project: Project): GlobalSearchScope
-} \ No newline at end of file
+}
diff --git a/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/AddElseBranchFix.kt b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/AddElseBranchFix.kt
new file mode 100644
index 000000000000..addcad5b933d
--- /dev/null
+++ b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/AddElseBranchFix.kt
@@ -0,0 +1,92 @@
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+
+package org.jetbrains.kotlin.idea.quickfix
+
+import com.intellij.codeInsight.CodeInsightUtilCore
+import com.intellij.codeInsight.intention.IntentionAction
+import com.intellij.openapi.editor.Editor
+import com.intellij.openapi.project.Project
+import com.intellij.psi.PsiDocumentManager
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiErrorElement
+import com.intellij.psi.util.elementType
+import org.jetbrains.kotlin.KtNodeTypes
+import org.jetbrains.kotlin.idea.KotlinBundle
+import org.jetbrains.kotlin.idea.util.executeEnterHandler
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.endOffset
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+import org.jetbrains.kotlin.utils.addToStdlib.safeAs
+
+sealed class AddElseBranchFix<T : KtExpression>(element: T) : KotlinPsiOnlyQuickFixAction<T>(element) {
+ override fun getFamilyName() = KotlinBundle.message("fix.add.else.branch.when")
+ override fun getText() = familyName
+
+ abstract override fun isAvailable(project: Project, editor: Editor?, file: KtFile): Boolean
+
+ abstract override fun invoke(project: Project, editor: Editor?, file: KtFile)
+}
+
+class AddWhenElseBranchFix(element: KtWhenExpression) : AddElseBranchFix<KtWhenExpression>(element) {
+ override fun isAvailable(project: Project, editor: Editor?, file: KtFile): Boolean = element?.closeBrace != null
+
+ override fun invoke(project: Project, editor: Editor?, file: KtFile) {
+ val element = element ?: return
+ val whenCloseBrace = element.closeBrace ?: return
+ val entry = KtPsiFactory(file).createWhenEntry("else -> {}")
+ CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(element.addBefore(entry, whenCloseBrace))?.endOffset?.let { offset ->
+ editor?.caretModel?.moveToOffset(offset - 1)
+ }
+ }
+
+ companion object : QuickFixesPsiBasedFactory<PsiElement>(PsiElement::class, PsiElementSuitabilityCheckers.ALWAYS_SUITABLE) {
+ override fun doCreateQuickFix(psiElement: PsiElement): List<IntentionAction> {
+ return listOfNotNull(psiElement.getNonStrictParentOfType<KtWhenExpression>()?.let(::AddWhenElseBranchFix))
+ }
+ }
+}
+
+class AddIfElseBranchFix(element: KtIfExpression) : AddElseBranchFix<KtIfExpression>(element) {
+ override fun isAvailable(project: Project, editor: Editor?, file: KtFile): Boolean {
+ val ktIfExpression = element ?: return false
+ return ktIfExpression.`else` == null &&
+ ktIfExpression.condition != null &&
+ ktIfExpression.children.firstOrNull { it.elementType == KtNodeTypes.THEN }?.firstChild !is PsiErrorElement
+ }
+
+ override fun invoke(project: Project, editor: Editor?, file: KtFile) {
+ val element = element ?: return
+ val withBraces = element.then is KtBlockExpression
+ val psiFactory = KtPsiFactory(file)
+ val newIf = psiFactory.createExpression(
+ if (withBraces) {
+ "if (true) {} else {}"
+ } else {
+ "if (true) 2 else TODO()"
+ }
+ ) as KtIfExpression
+
+ element.addRange(newIf.then?.parent?.nextSibling, newIf.`else`?.parent)
+ editor?.caretModel?.currentCaret?.let { caret ->
+ if (withBraces) {
+ caret.moveToOffset(element.endOffset - 1)
+ val documentManager = PsiDocumentManager.getInstance(project)
+ documentManager.getDocument(element.containingFile)?.let { doc ->
+ documentManager.doPostponedOperationsAndUnblockDocument(doc)
+ editor.executeEnterHandler()
+ }
+ } else {
+ element.`else`?.textRange?.let {
+ caret.moveToOffset(it.startOffset)
+ caret.setSelection(it.startOffset, it.endOffset)
+ }
+ }
+ }
+ }
+
+ companion object : QuickFixesPsiBasedFactory<PsiElement>(PsiElement::class, PsiElementSuitabilityCheckers.ALWAYS_SUITABLE) {
+ override fun doCreateQuickFix(psiElement: PsiElement): List<IntentionAction> {
+ return listOfNotNull(psiElement.parent?.safeAs<KtIfExpression>()?.let(::AddIfElseBranchFix))
+ }
+ }
+}
diff --git a/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/AddWhenElseBranchFix.kt b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/AddWhenElseBranchFix.kt
deleted file mode 100644
index fb297eaef6c0..000000000000
--- a/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/AddWhenElseBranchFix.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-// 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.quickfix
-
-import com.intellij.codeInsight.CodeInsightUtilCore
-import com.intellij.codeInsight.intention.IntentionAction
-import com.intellij.openapi.editor.Editor
-import com.intellij.openapi.project.Project
-import com.intellij.psi.PsiElement
-import org.jetbrains.kotlin.idea.KotlinBundle
-import org.jetbrains.kotlin.psi.KtFile
-import org.jetbrains.kotlin.psi.KtPsiFactory
-import org.jetbrains.kotlin.psi.KtWhenExpression
-import org.jetbrains.kotlin.psi.psiUtil.endOffset
-import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
-
-class AddWhenElseBranchFix(element: KtWhenExpression) : KotlinPsiOnlyQuickFixAction<KtWhenExpression>(element) {
- override fun getFamilyName() = KotlinBundle.message("fix.add.else.branch.when")
- override fun getText() = familyName
-
- override fun isAvailable(project: Project, editor: Editor?, file: KtFile): Boolean = element?.closeBrace != null
-
- override fun invoke(project: Project, editor: Editor?, file: KtFile) {
- val element = element ?: return
- val whenCloseBrace = element.closeBrace ?: return
- val entry = KtPsiFactory(file).createWhenEntry("else -> {}")
- CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(element.addBefore(entry, whenCloseBrace))?.endOffset?.let { offset ->
- editor?.caretModel?.moveToOffset(offset - 1)
- }
- }
-
- companion object : QuickFixesPsiBasedFactory<PsiElement>(PsiElement::class, PsiElementSuitabilityCheckers.ALWAYS_SUITABLE) {
- override fun doCreateQuickFix(psiElement: PsiElement): List<IntentionAction> {
- return listOfNotNull(psiElement.getNonStrictParentOfType<KtWhenExpression>()?.let(::AddWhenElseBranchFix))
- }
- }
-}
diff --git a/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/RemoveWhenBranchFix.kt b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/RemoveWhenBranchFix.kt
index 1690b5aa73ef..e2fe00d0735f 100644
--- a/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/RemoveWhenBranchFix.kt
+++ b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/quickfix/RemoveWhenBranchFix.kt
@@ -9,9 +9,7 @@ import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
-import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.idea.KotlinBundle
-import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtWhenEntry
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
@@ -33,10 +31,11 @@ class RemoveWhenBranchFix(
companion object : QuickFixesPsiBasedFactory<PsiElement>(PsiElement::class, PsiElementSuitabilityCheckers.ALWAYS_SUITABLE) {
override fun doCreateQuickFix(psiElement: PsiElement): List<IntentionAction> {
val whenEntry = psiElement.getParentOfType<KtWhenEntry>(strict = false)
- ?.takeIf { it.conditions.size == 1 }
- ?: return emptyList()
+ if (whenEntry != null && (whenEntry.isElse || whenEntry.conditions.size == 1)) {
+ return listOf(RemoveWhenBranchFix(whenEntry))
+ }
- return listOfNotNull(RemoveWhenBranchFix(whenEntry))
+ return emptyList()
}
}
} \ No newline at end of file
diff --git a/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/references/ReadWriteAccessChecker.kt b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/references/ReadWriteAccessChecker.kt
index ccd20a5b3eb3..72f964c3f80d 100644
--- a/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/references/ReadWriteAccessChecker.kt
+++ b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/references/ReadWriteAccessChecker.kt
@@ -3,22 +3,46 @@
package org.jetbrains.kotlin.idea.references
import com.intellij.openapi.components.service
-import org.jetbrains.kotlin.psi.KtBinaryExpression
-import org.jetbrains.kotlin.psi.KtExpression
+import org.jetbrains.kotlin.lexer.KtTokens
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.getAssignmentByLHS
+import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis
import org.jetbrains.kotlin.resolve.references.ReferenceAccess
+import org.jetbrains.kotlin.utils.addToStdlib.constant
interface ReadWriteAccessChecker {
fun readWriteAccessWithFullExpressionByResolve(assignment: KtBinaryExpression): Pair<ReferenceAccess, KtExpression>?
- @Suppress("DEPRECATION")
fun readWriteAccessWithFullExpression(
targetExpression: KtExpression,
useResolveForReadWrite: Boolean
- ): Pair<ReferenceAccess, KtExpression> =
- if (useResolveForReadWrite)
- targetExpression.readWriteAccessWithFullExpressionWithPossibleResolve(::readWriteAccessWithFullExpressionByResolve)
+ ): Pair<ReferenceAccess, KtExpression> {
+ var expression = targetExpression.getQualifiedExpressionForSelectorOrThis()
+ loop@ while (true) {
+ when (val parent = expression.parent) {
+ is KtParenthesizedExpression, is KtAnnotatedExpression, is KtLabeledExpression -> expression = parent as KtExpression
+ else -> break@loop
+ }
+ }
+
+ val assignment = expression.getAssignmentByLHS()
+ if (assignment != null) {
+ return when (assignment.operationToken) {
+ KtTokens.EQ -> ReferenceAccess.WRITE to assignment
+
+ else -> {
+ (if (useResolveForReadWrite) readWriteAccessWithFullExpressionByResolve(assignment) else null)
+ ?: (ReferenceAccess.READ_WRITE to assignment)
+ }
+ }
+ }
+
+ val unaryExpression = expression.parent as? KtUnaryExpression
+ return if (unaryExpression != null && unaryExpression.operationToken in constant { setOf(KtTokens.PLUSPLUS, KtTokens.MINUSMINUS) })
+ ReferenceAccess.READ_WRITE to unaryExpression
else
- targetExpression.readWriteAccessWithFullExpressionWithPossibleResolve(readWriteAccessWithFullExpressionByResolve = { null })
+ ReferenceAccess.READ to expression
+ }
companion object {
fun getInstance(): ReadWriteAccessChecker = service()
diff --git a/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/search/KotlinSearchSupport.kt b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/search/KotlinSearchSupport.kt
index dff3b26b24f4..80558e011c53 100644
--- a/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/search/KotlinSearchSupport.kt
+++ b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/search/KotlinSearchSupport.kt
@@ -8,10 +8,13 @@ import com.intellij.openapi.util.NlsSafe
import com.intellij.psi.*
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.SearchScope
+import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions
import org.jetbrains.kotlin.idea.util.application.getServiceSafe
import org.jetbrains.kotlin.idea.util.application.runReadAction
+import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.resolve.DataClassResolver
import org.jetbrains.kotlin.resolve.ImportPath
interface KotlinSearchUsagesSupport {
@@ -32,10 +35,22 @@ interface KotlinSearchUsagesSupport {
val PsiClass.isSamInterface: Boolean
get() = getInstance(project).isSamInterface(this)
- fun <T : PsiNamedElement> List<T>.filterDataClassComponentsIfDisabled(kotlinOptions: KotlinReferencesSearchOptions): List<T> =
- firstOrNull()?.let {
- getInstance(it.project).filterDataClassComponentsIfDisabled(this, kotlinOptions)
- } ?: this
+ fun <T : PsiNamedElement> List<T>.filterDataClassComponentsIfDisabled(kotlinOptions: KotlinReferencesSearchOptions): List<T> {
+ fun PsiNamedElement.isComponentElement(): Boolean {
+ if (this !is PsiMethod) return false
+
+ val dataClassParent = ((parent as? KtLightClass)?.kotlinOrigin as? KtClass)?.isData() == true
+ if (!dataClassParent) return false
+
+ if (!Name.isValidIdentifier(name)) return false
+ val nameIdentifier = Name.identifier(name)
+ if (!DataClassResolver.isComponentLike(nameIdentifier)) return false
+
+ return true
+ }
+
+ return if (kotlinOptions.searchForComponentConventions) this else filter { !it.isComponentElement() }
+ }
fun PsiReference.isCallableOverrideUsage(declaration: KtNamedDeclaration): Boolean =
getInstance(declaration.project).isCallableOverrideUsage(this, declaration)
@@ -121,8 +136,6 @@ interface KotlinSearchUsagesSupport {
fun isSamInterface(psiClass: PsiClass): Boolean
- fun <T : PsiNamedElement> filterDataClassComponentsIfDisabled(elements: List<T>, kotlinOptions: KotlinReferencesSearchOptions): List<T>
-
fun isCallableOverrideUsage(reference: PsiReference, declaration: KtNamedDeclaration): Boolean
fun isUsageInContainingDeclaration(reference: PsiReference, declaration: KtNamedDeclaration): Boolean
@@ -176,4 +189,4 @@ interface KotlinSearchUsagesSupport {
fun createConstructorHandle(ktDeclaration: KtDeclaration): ConstructorCallHandle
fun createConstructorHandle(psiMethod: PsiMethod): ConstructorCallHandle
-} \ No newline at end of file
+}
diff --git a/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinTargetElementEvaluator.kt b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinTargetElementEvaluator.kt
new file mode 100644
index 000000000000..9cb96071066a
--- /dev/null
+++ b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinTargetElementEvaluator.kt
@@ -0,0 +1,81 @@
+// 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.search.ideaExtensions
+
+import com.intellij.codeInsight.JavaTargetElementEvaluator
+import com.intellij.codeInsight.TargetElementEvaluatorEx
+import com.intellij.codeInsight.TargetElementUtil
+import com.intellij.codeInsight.TargetElementUtilExtender
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiFile
+import com.intellij.psi.PsiReference
+import com.intellij.util.BitUtil
+import org.jetbrains.kotlin.idea.references.KtDestructuringDeclarationReference
+import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
+import org.jetbrains.kotlin.idea.references.mainReference
+import org.jetbrains.kotlin.lexer.KtTokens
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.*
+
+abstract class KotlinTargetElementEvaluator : TargetElementEvaluatorEx, TargetElementUtilExtender {
+ companion object {
+ const val DO_NOT_UNWRAP_LABELED_EXPRESSION = 0x100
+ const val BYPASS_IMPORT_ALIAS = 0x200
+ }
+
+ // Place caret after the open curly brace in lambda for generated 'it'
+ abstract fun findLambdaOpenLBraceForGeneratedIt(ref: PsiReference): PsiElement?
+
+ // Navigate to receiver element for this in extension declaration
+ abstract fun findReceiverForThisInExtensionFunction(ref: PsiReference): PsiElement?
+
+ override fun getAdditionalDefinitionSearchFlags() = 0
+
+ override fun getAdditionalReferenceSearchFlags() = DO_NOT_UNWRAP_LABELED_EXPRESSION or BYPASS_IMPORT_ALIAS
+
+ override fun getAllAdditionalFlags() = additionalDefinitionSearchFlags + additionalReferenceSearchFlags
+
+ override fun includeSelfInGotoImplementation(element: PsiElement): Boolean = !(element is KtClass && element.isAbstract())
+
+ override fun getElementByReference(ref: PsiReference, flags: Int): PsiElement? {
+ if (ref is KtSimpleNameReference && ref.expression is KtLabelReferenceExpression) {
+ val refTarget = ref.resolve() as? KtExpression ?: return null
+ if (!BitUtil.isSet(flags, DO_NOT_UNWRAP_LABELED_EXPRESSION)) {
+ return refTarget.getLabeledParent(ref.expression.getReferencedName()) ?: refTarget
+ }
+ return refTarget
+ }
+
+ if (!BitUtil.isSet(flags, BYPASS_IMPORT_ALIAS)) {
+ (ref.element as? KtSimpleNameExpression)?.mainReference?.getImportAlias()?.let { return it }
+ }
+
+ // prefer destructing declaration entry to its target if element name is accepted
+ if (ref is KtDestructuringDeclarationReference && BitUtil.isSet(flags, TargetElementUtil.ELEMENT_NAME_ACCEPTED)) {
+ return ref.element
+ }
+
+ val refExpression = ref.element as? KtSimpleNameExpression
+ val calleeExpression = refExpression?.getParentOfTypeAndBranch<KtCallElement> { calleeExpression }
+ if (calleeExpression != null) {
+ (ref.resolve() as? KtConstructor<*>)?.let {
+ return if (flags and JavaTargetElementEvaluator().additionalReferenceSearchFlags != 0) it else it.containingClassOrObject
+ }
+ }
+
+ if (BitUtil.isSet(flags, TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED)) {
+ return findLambdaOpenLBraceForGeneratedIt(ref)
+ ?: findReceiverForThisInExtensionFunction(ref)
+ }
+
+ return null
+ }
+
+ override fun isIdentifierPart(file: PsiFile, text: CharSequence, offset: Int): Boolean {
+ val elementAtCaret = file.findElementAt(offset)
+
+ if (elementAtCaret?.node?.elementType == KtTokens.IDENTIFIER) return true
+ // '(' is considered identifier part if it belongs to primary constructor without 'constructor' keyword
+ return elementAtCaret?.getNonStrictParentOfType<KtPrimaryConstructor>()?.textOffset == offset
+ }
+}
diff --git a/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/util/editorUtils.kt b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/util/editorUtils.kt
new file mode 100644
index 000000000000..a304a606bcf8
--- /dev/null
+++ b/plugins/kotlin/frontend-independent/src/org/jetbrains/kotlin/idea/util/editorUtils.kt
@@ -0,0 +1,13 @@
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package org.jetbrains.kotlin.idea.util
+
+import com.intellij.ide.DataManager
+import com.intellij.openapi.actionSystem.IdeActions
+import com.intellij.openapi.editor.Editor
+import com.intellij.openapi.editor.actionSystem.EditorActionManager
+
+fun Editor.executeEnterHandler() {
+ EditorActionManager.getInstance()
+ .getActionHandler(IdeActions.ACTION_EDITOR_ENTER)
+ .execute(/* editor = */ this, /* contextCaret = */ null, /* dataContext = */ DataManager.getInstance().getDataContext(component))
+}