From 418903e9ef086d8a74f249ea31134fdd92edc367 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Thu, 7 May 2020 21:25:08 +0300 Subject: [PATCH] FIR IDE: Make KtReference class descriptors frontend independent * The new idea-frontend-independent module created * Moved KtReference and it inheritors to that module & implement them in idea-analysis module by using descriptors frontend --- .../jetbrains/kotlin/resolve/ArrayFqNames.kt | 24 ++ .../resolve/CollectionLiteralResolver.kt | 36 +- .../org/jetbrains/kotlin/utils/addToStdlib.kt | 26 +- .../kotlin/idea/kdoc/KDocReference.kt | 22 +- .../references/FirReferenceResolveHelper.kt | 164 +++++++++ ...ationMethodImplicitReferenceContributor.kt | 18 +- .../references/KotlinReferenceContributor.kt | 43 +-- .../KtArrayAccessReferenceDescriptorsImpl.kt | 41 +++ ...llectionLiteralReferenceDescriptorsImpl.kt | 23 ++ .../KtConstructorDelegationReference.java | 51 --- ...uctorDelegationReferenceDescriptorsImpl.kt | 20 ++ ...ingDeclarationReferenceDescriptorsImpl.kt} | 22 +- ...=> KtForLoopInReferenceDescriptorsImpl.kt} | 25 +- ...tInvokeFunctionReferenceDescriptorsImpl.kt | 38 +++ .../KtPropertyDelegationMethodsReference.kt | 56 --- ...legationMethodsReferenceDescriptorsImpl.kt | 31 ++ .../kotlin/idea/references/KtReference.kt | 323 ++++-------------- .../idea/references/KtSimpleNameReference.kt | 30 +- .../ReadWriteAccessCheckerDescriptorsImpl.kt | 23 ++ .../SyntheticPropertyAccessorReference.kt | 38 +-- .../kotlin/idea/references/referenceUtil.kt | 52 +-- idea/idea-core/build.gradle.kts | 1 + .../org/jetbrains/kotlin/idea/core/Utils.kt | 4 +- .../kotlin/idea/core/psiModificationUtils.kt | 10 +- .../build.gradle.kts | 37 ++ .../idea/core/frontendIndependentPsiUtils.kt | 24 ++ .../idea/references/KtArrayAccessReference.kt | 31 +- .../KtCollectionLiteralReference.kt | 16 +- .../KtConstructorDelegationReference.kt | 26 ++ .../KtDestructuringDeclarationReference.kt | 34 ++ .../idea/references/KtForLoopInReference.kt | 31 ++ .../KtIdeReferenceProviderService.kt | 25 +- .../references/KtInvokeFunctionReference.kt | 44 +-- .../KtPropertyDelegationMethodsReference.kt | 29 ++ .../kotlin/idea/references/KtReference.kt | 47 +++ .../idea/references/KtSimpleNameReference.kt | 97 ++++++ .../idea/references/ReadWriteAccessChecker.kt | 66 ++++ .../SyntheticPropertyAccessorReference.kt | 42 +++ .../SimpleNameReferenceExtension.kt | 2 +- .../idea/injection/KotlinLanguageInjector.kt | 3 +- idea/resources/META-INF/plugin-common.xml | 6 + .../idea/imports/KotlinImportOptimizer.kt | 7 +- .../jetbrains/kotlin/idea/intentions/Utils.kt | 21 +- ...hArrayOfWithSpreadOperatorInFunctionFix.kt | 7 +- .../changeSignature/KotlinParameterInfo.kt | 3 +- .../pullUp/pullUpConflictsUtils.kt | 16 +- .../pushDown/pushDownConflictsUtils.kt | 3 +- .../KotlinAwareJavaGetterRenameProcessor.kt | 8 +- ...KotlinOverridingMethodReferenceSearcher.kt | 17 +- .../conversions/ArrayInitializerConversion.kt | 10 +- prepare/idea-plugin/build.gradle.kts | 1 + settings.gradle | 1 + 52 files changed, 1045 insertions(+), 730 deletions(-) create mode 100644 compiler/frontend.common/src/org/jetbrains/kotlin/resolve/ArrayFqNames.kt create mode 100644 idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt create mode 100644 idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtArrayAccessReferenceDescriptorsImpl.kt create mode 100644 idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtCollectionLiteralReferenceDescriptorsImpl.kt delete mode 100644 idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtConstructorDelegationReference.java create mode 100644 idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtConstructorDelegationReferenceDescriptorsImpl.kt rename idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/{KtDestructuringDeclarationReference.kt => KtDestructuringDeclarationReferenceDescriptorsImpl.kt} (64%) rename idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/{KtForLoopInReference.kt => KtForLoopInReferenceDescriptorsImpl.kt} (60%) create mode 100644 idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtInvokeFunctionReferenceDescriptorsImpl.kt delete mode 100644 idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtPropertyDelegationMethodsReference.kt create mode 100644 idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtPropertyDelegationMethodsReferenceDescriptorsImpl.kt create mode 100644 idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/ReadWriteAccessCheckerDescriptorsImpl.kt create mode 100644 idea/idea-frontend-independent/build.gradle.kts create mode 100644 idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/core/frontendIndependentPsiUtils.kt rename idea/{idea-analysis => idea-frontend-independent}/src/org/jetbrains/kotlin/idea/references/KtArrayAccessReference.kt (65%) rename idea/{idea-analysis => idea-frontend-independent}/src/org/jetbrains/kotlin/idea/references/KtCollectionLiteralReference.kt (56%) create mode 100644 idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtConstructorDelegationReference.kt create mode 100644 idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtDestructuringDeclarationReference.kt create mode 100644 idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtForLoopInReference.kt rename idea/{idea-analysis => idea-frontend-independent}/src/org/jetbrains/kotlin/idea/references/KtIdeReferenceProviderService.kt (83%) rename idea/{idea-analysis => idea-frontend-independent}/src/org/jetbrains/kotlin/idea/references/KtInvokeFunctionReference.kt (63%) create mode 100644 idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtPropertyDelegationMethodsReference.kt create mode 100644 idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtReference.kt create mode 100644 idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtSimpleNameReference.kt create mode 100644 idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/ReadWriteAccessChecker.kt create mode 100644 idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/SyntheticPropertyAccessorReference.kt rename idea/{idea-analysis => idea-frontend-independent}/src/org/jetbrains/kotlin/plugin/references/SimpleNameReferenceExtension.kt (92%) diff --git a/compiler/frontend.common/src/org/jetbrains/kotlin/resolve/ArrayFqNames.kt b/compiler/frontend.common/src/org/jetbrains/kotlin/resolve/ArrayFqNames.kt new file mode 100644 index 00000000000..f5387e1dbbe --- /dev/null +++ b/compiler/frontend.common/src/org/jetbrains/kotlin/resolve/ArrayFqNames.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2020 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.resolve + +import org.jetbrains.kotlin.builtins.PrimitiveType +import org.jetbrains.kotlin.name.Name + +object ArrayFqNames { + val PRIMITIVE_TYPE_TO_ARRAY: Map = hashMapOf( + PrimitiveType.BOOLEAN to Name.identifier("booleanArrayOf"), + PrimitiveType.CHAR to Name.identifier("charArrayOf"), + PrimitiveType.INT to Name.identifier("intArrayOf"), + PrimitiveType.BYTE to Name.identifier("byteArrayOf"), + PrimitiveType.SHORT to Name.identifier("shortArrayOf"), + PrimitiveType.FLOAT to Name.identifier("floatArrayOf"), + PrimitiveType.LONG to Name.identifier("longArrayOf"), + PrimitiveType.DOUBLE to Name.identifier("doubleArrayOf") + ) + + val ARRAY_OF_FUNCTION = Name.identifier("arrayOf") +} \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/CollectionLiteralResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/CollectionLiteralResolver.kt index 232bc6d8780..a5ee84e5001 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/CollectionLiteralResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/CollectionLiteralResolver.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2010-2020 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.resolve @@ -44,21 +33,6 @@ class CollectionLiteralResolver( val callResolver: CallResolver, val languageVersionSettings: LanguageVersionSettings ) { - companion object { - val PRIMITIVE_TYPE_TO_ARRAY: Map = hashMapOf( - PrimitiveType.BOOLEAN to Name.identifier("booleanArrayOf"), - PrimitiveType.CHAR to Name.identifier("charArrayOf"), - PrimitiveType.INT to Name.identifier("intArrayOf"), - PrimitiveType.BYTE to Name.identifier("byteArrayOf"), - PrimitiveType.SHORT to Name.identifier("shortArrayOf"), - PrimitiveType.FLOAT to Name.identifier("floatArrayOf"), - PrimitiveType.LONG to Name.identifier("longArrayOf"), - PrimitiveType.DOUBLE to Name.identifier("doubleArrayOf") - ) - - val ARRAY_OF_FUNCTION = Name.identifier("arrayOf") - } - fun resolveCollectionLiteral( collectionLiteralExpression: KtCollectionLiteralExpression, context: ExpressionTypingContext @@ -120,11 +94,11 @@ class CollectionLiteralResolver( private fun getArrayFunctionCallName(expectedType: KotlinType): Name { if (NO_EXPECTED_TYPE === expectedType || !KotlinBuiltIns.isPrimitiveArray(expectedType)) { - return ARRAY_OF_FUNCTION + return ArrayFqNames.ARRAY_OF_FUNCTION } - val descriptor = expectedType.constructor.declarationDescriptor ?: return ARRAY_OF_FUNCTION + val descriptor = expectedType.constructor.declarationDescriptor ?: return ArrayFqNames.ARRAY_OF_FUNCTION - return PRIMITIVE_TYPE_TO_ARRAY[KotlinBuiltIns.getPrimitiveArrayType(descriptor)] ?: ARRAY_OF_FUNCTION + return ArrayFqNames.PRIMITIVE_TYPE_TO_ARRAY[KotlinBuiltIns.getPrimitiveArrayType(descriptor)] ?: ArrayFqNames.ARRAY_OF_FUNCTION } } diff --git a/core/util.runtime/src/org/jetbrains/kotlin/utils/addToStdlib.kt b/core/util.runtime/src/org/jetbrains/kotlin/utils/addToStdlib.kt index 9e4cb3636be..5843594a12a 100644 --- a/core/util.runtime/src/org/jetbrains/kotlin/utils/addToStdlib.kt +++ b/core/util.runtime/src/org/jetbrains/kotlin/utils/addToStdlib.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2010-2020 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.utils.addToStdlib @@ -50,6 +39,17 @@ inline fun Array<*>.firstIsInstance(): T { throw NoSuchElementException("No element of given type found") } +inline fun Iterable<*>.filterIsInstanceWithChecker(additionalChecker: (T) -> Boolean): List { + val result = arrayListOf() + for (element in this) { + if (element is T && additionalChecker(element)) { + result += element + } + } + return result +} + + inline fun Iterable<*>.lastIsInstanceOrNull(): T? { when (this) { is List<*> -> { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/kdoc/KDocReference.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/kdoc/KDocReference.kt index 8182f28b3a5..e94e1a695f9 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/kdoc/KDocReference.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/kdoc/KDocReference.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2010-2020 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.kdoc @@ -20,6 +9,7 @@ import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade +import org.jetbrains.kotlin.idea.references.KtDescriptorsBasedReference import org.jetbrains.kotlin.idea.references.KtMultiReference import org.jetbrains.kotlin.kdoc.psi.impl.KDocLink import org.jetbrains.kotlin.kdoc.psi.impl.KDocName @@ -28,7 +18,11 @@ import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -class KDocReference(element: KDocName) : KtMultiReference(element) { +//TODO move to frontend-independent module +class KDocReference(element: KDocName) : KtMultiReference(element), KtDescriptorsBasedReference { + override fun isReferenceTo(element: PsiElement): Boolean = + super.isReferenceTo(element) + override fun getTargetDescriptors(context: BindingContext): Collection { val declaration = element.getContainingDoc().getOwner() ?: return arrayListOf() val resolutionFacade = element.getResolutionFacade() diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt new file mode 100644 index 00000000000..ec81c482fbe --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt @@ -0,0 +1,164 @@ +/* + * Copyright 2010-2020 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.references + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.expressions.* +import org.jetbrains.kotlin.fir.psi +import org.jetbrains.kotlin.fir.references.* +import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.toSymbol +import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol +import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl +import org.jetbrains.kotlin.fir.types.ConeLookupTagBasedType +import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef +import org.jetbrains.kotlin.idea.fir.firResolveState +import org.jetbrains.kotlin.idea.fir.getOrBuildFir +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.psi.KtDotQualifiedExpression +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtPackageDirective +import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType + +object FirReferenceResolveHelper { + fun FirResolvedTypeRef.toTargetPsi(session: FirSession): PsiElement? { + val type = type as? ConeLookupTagBasedType ?: return null + return (type.lookupTag.toSymbol(session) as? AbstractFirBasedSymbol<*>)?.fir?.psi + } + + fun ClassId.toTargetPsi(session: FirSession, calleeReference: FirReference? = null): PsiElement? { + val classLikeDeclaration = ConeClassLikeLookupTagImpl(this).toSymbol(session)?.fir + if (classLikeDeclaration is FirRegularClass) { + if (calleeReference is FirResolvedNamedReference) { + val callee = calleeReference.resolvedSymbol.fir as? FirCallableMemberDeclaration + // TODO: check callee owner directly? + if (callee !is FirConstructor && callee?.isStatic != true) { + classLikeDeclaration.companionObject?.let { return it.psi } + } + } + } + return classLikeDeclaration?.psi + } + + fun FirReference.toTargetPsi(session: FirSession): PsiElement? { + return when (this) { + is FirResolvedNamedReference -> { + resolvedSymbol.fir.psi + } + is FirResolvedCallableReference -> { + resolvedSymbol.fir.psi + } + is FirThisReference -> { + boundSymbol?.fir?.psi + } + is FirSuperReference -> { + (superTypeRef as? FirResolvedTypeRef)?.toTargetPsi(session) + } + else -> { + null + } + } + } + + fun resolveToPsiElements(ref: AbstractKtReference): Collection { + val expression = ref.expression + val state = expression.firResolveState() + val session = state.getSession(expression) + when (val fir = expression.getOrBuildFir(state)) { + is FirResolvable -> { + return listOfNotNull(fir.calleeReference.toTargetPsi(session)) + } + is FirResolvedTypeRef -> { + return listOfNotNull(fir.toTargetPsi(session)) + } + is FirResolvedQualifier -> { + val classId = fir.classId ?: return emptyList() + // Distinguish A.foo() from A(.Companion).foo() + // Make expression.parent as? KtDotQualifiedExpression local function + var parent = expression.parent as? KtDotQualifiedExpression + while (parent != null) { + val selectorExpression = parent.selectorExpression ?: break + if (selectorExpression === expression) { + parent = parent.parent as? KtDotQualifiedExpression + continue + } + val parentFir = selectorExpression.getOrBuildFir(state) + if (parentFir is FirQualifiedAccess) { + return listOfNotNull(classId.toTargetPsi(session, parentFir.calleeReference)) + } + parent = parent.parent as? KtDotQualifiedExpression + } + return listOfNotNull(classId.toTargetPsi(session)) + } + is FirAnnotationCall -> { + val type = fir.typeRef as? FirResolvedTypeRef ?: return emptyList() + return listOfNotNull(type.toTargetPsi(session)) + } + is FirResolvedImport -> { + var parent = expression.parent + while (parent is KtDotQualifiedExpression) { + if (parent.selectorExpression !== expression) { + // Special: package reference in the middle of import directive + // import a.b.c.SomeClass + // TODO: return reference to PsiPackage + return listOf(expression) + } + parent = parent.parent + } + val classId = fir.resolvedClassId + if (classId != null) { + return listOfNotNull(classId.toTargetPsi(session)) + } + val name = fir.importedName ?: return emptyList() + val symbolProvider = session.firSymbolProvider + return symbolProvider.getTopLevelCallableSymbols(fir.packageFqName, name).mapNotNull { it.fir.psi } + + listOfNotNull(symbolProvider.getClassLikeSymbolByFqName(ClassId(fir.packageFqName, name))?.fir?.psi) + } + is FirFile -> { + if (expression.getNonStrictParentOfType() != null) { + // Special: package reference in the middle of package directive + return listOf(expression) + } + return listOfNotNull(fir.psi) + } + is FirArrayOfCall -> { + // We can't yet find PsiElement for arrayOf, intArrayOf, etc. + return emptyList() + } + is FirErrorNamedReference -> { + return emptyList() + } + else -> { + // Handle situation when we're in the middle/beginning of qualifier + // A.B.C.foo() or A.B.C.foo() + // NB: in this case we get some parent FIR, like FirBlock, FirProperty, FirFunction or the like + var parent = expression.parent as? KtDotQualifiedExpression + var unresolvedCounter = 1 + while (parent != null) { + val selectorExpression = parent.selectorExpression ?: break + if (selectorExpression === expression) { + parent = parent.parent as? KtDotQualifiedExpression + continue + } + val parentFir = selectorExpression.getOrBuildFir(state) + if (parentFir is FirResolvedQualifier) { + var classId = parentFir.classId + while (unresolvedCounter > 0) { + unresolvedCounter-- + classId = classId?.outerClassId + } + return listOfNotNull(classId?.toTargetPsi(session)) + } + parent = parent.parent as? KtDotQualifiedExpression + unresolvedCounter++ + } + return emptyList() + } + } + } +} diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KotlinDefaultAnnotationMethodImplicitReferenceContributor.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KotlinDefaultAnnotationMethodImplicitReferenceContributor.kt index 8e5115058ab..ac38d2f06c2 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KotlinDefaultAnnotationMethodImplicitReferenceContributor.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KotlinDefaultAnnotationMethodImplicitReferenceContributor.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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. */ @@ -66,14 +66,10 @@ class ReferenceImpl(private val argument: KtValueArgument) : PsiReference { override fun isSoft() = false } -internal class KotlinDefaultAnnotationMethodImplicitReferenceContributor : KotlinReferenceProviderContributor { - override fun registerReferenceProviders(registrar: KotlinPsiReferenceRegistrar) { - registrar.registerProvider { - if (it.isNamed()) return@registerProvider null - val annotationEntry = it.getParentOfTypeAndBranch { valueArgumentList } ?: return@registerProvider null - if (annotationEntry.valueArguments.size != 1) return@registerProvider null +internal val KotlinDefaultAnnotationMethodImplicitReferenceProvider = provider@{ element: KtValueArgument -> + if (element.isNamed()) return@provider null + val annotationEntry = element.getParentOfTypeAndBranch { valueArgumentList } ?: return@provider null + if (annotationEntry.valueArguments.size != 1) return@provider null - ReferenceImpl(it) - } - } -} + ReferenceImpl(element) +} \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KotlinReferenceContributor.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KotlinReferenceContributor.kt index 4a0a505b436..cbf7e8e823a 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KotlinReferenceContributor.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KotlinReferenceContributor.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2010-2020 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.references @@ -24,10 +13,10 @@ import org.jetbrains.kotlin.psi.KtPackageDirective import org.jetbrains.kotlin.psi.KtUserType import org.jetbrains.kotlin.psi.psiUtil.parents -internal class KotlinReferenceContributor : KotlinReferenceProviderContributor { +class KotlinReferenceContributor : KotlinReferenceProviderContributor { override fun registerReferenceProviders(registrar: KotlinPsiReferenceRegistrar) { with(registrar) { - registerProvider(factory = ::KtSimpleNameReference) + registerProvider(factory = ::KtSimpleNameReferenceDescriptorsImpl) registerMultiProvider { nameReferenceExpression -> if (nameReferenceExpression.getReferencedNameElementType() != KtTokens.IDENTIFIER) return@registerMultiProvider emptyArray() @@ -37,32 +26,34 @@ internal class KotlinReferenceContributor : KotlinReferenceProviderContributor { when (nameReferenceExpression.readWriteAccess(useResolveForReadWrite = false)) { ReferenceAccess.READ -> - arrayOf(SyntheticPropertyAccessorReference.Getter(nameReferenceExpression)) + arrayOf(SyntheticPropertyAccessorReferenceDescriptorImpl(nameReferenceExpression, getter = true)) ReferenceAccess.WRITE -> - arrayOf(SyntheticPropertyAccessorReference.Setter(nameReferenceExpression)) + arrayOf(SyntheticPropertyAccessorReferenceDescriptorImpl(nameReferenceExpression, getter = false)) ReferenceAccess.READ_WRITE -> arrayOf( - SyntheticPropertyAccessorReference.Getter(nameReferenceExpression), - SyntheticPropertyAccessorReference.Setter(nameReferenceExpression) + SyntheticPropertyAccessorReferenceDescriptorImpl(nameReferenceExpression, getter = true), + SyntheticPropertyAccessorReferenceDescriptorImpl(nameReferenceExpression, getter = false) ) } } - registerProvider(factory = ::KtConstructorDelegationReference) + registerProvider(factory = ::KtConstructorDelegationReferenceDescriptorsImpl) - registerProvider(factory = ::KtInvokeFunctionReference) + registerProvider(factory = ::KtInvokeFunctionReferenceDescriptorsImpl) - registerProvider(factory = ::KtArrayAccessReference) + registerProvider(factory = ::KtArrayAccessReferenceDescriptorsImpl) - registerProvider(factory = ::KtCollectionLiteralReference) + registerProvider(factory = ::KtCollectionLiteralReferenceDescriptorsImpl) - registerProvider(factory = ::KtForLoopInReference) + registerProvider(factory = ::KtForLoopInReferenceDescriptorsImpl) - registerProvider(factory = ::KtPropertyDelegationMethodsReference) + registerProvider(factory = ::KtPropertyDelegationMethodsReferenceDescriptorsImpl) - registerProvider(factory = ::KtDestructuringDeclarationReference) + registerProvider(factory = ::KtDestructuringDeclarationReferenceDescriptorsImpl) registerProvider(factory = ::KDocReference) + + registerProvider(KotlinDefaultAnnotationMethodImplicitReferenceProvider) } } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtArrayAccessReferenceDescriptorsImpl.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtArrayAccessReferenceDescriptorsImpl.kt new file mode 100644 index 00000000000..192671426c6 --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtArrayAccessReferenceDescriptorsImpl.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2020 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.references + +import com.intellij.psi.MultiRangeReference +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.idea.core.canMoveLambdaOutsideParentheses +import org.jetbrains.kotlin.idea.core.moveFunctionLiteralOutsideParentheses +import org.jetbrains.kotlin.psi.KtArrayAccessExpression +import org.jetbrains.kotlin.psi.KtCallExpression +import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_GET +import org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_SET + +internal class KtArrayAccessReferenceDescriptorsImpl( + expression: KtArrayAccessExpression +) : KtArrayAccessReference(expression), KtDescriptorsBasedReference { + override fun isReferenceTo(element: PsiElement): Boolean = + super.isReferenceTo(element) + + override fun moveFunctionLiteralOutsideParentheses(callExpression: KtCallExpression) { + callExpression.moveFunctionLiteralOutsideParentheses() + } + + override fun canMoveLambdaOutsideParentheses(callExpression: KtCallExpression): Boolean = + callExpression.canMoveLambdaOutsideParentheses() + + override fun doRenameImplicitConventionalCall(newName: String?): KtExpression = + renameImplicitConventionalCall(newName) + + override fun getTargetDescriptors(context: BindingContext): Collection { + val getFunctionDescriptor = context[INDEXED_LVALUE_GET, expression]?.candidateDescriptor + val setFunctionDescriptor = context[INDEXED_LVALUE_SET, expression]?.candidateDescriptor + return listOfNotNull(getFunctionDescriptor, setFunctionDescriptor) + } +} diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtCollectionLiteralReferenceDescriptorsImpl.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtCollectionLiteralReferenceDescriptorsImpl.kt new file mode 100644 index 00000000000..7a484605115 --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtCollectionLiteralReferenceDescriptorsImpl.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2020 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.references + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.psi.KtCollectionLiteralExpression +import org.jetbrains.kotlin.resolve.BindingContext + +class KtCollectionLiteralReferenceDescriptorsImpl( + expression: KtCollectionLiteralExpression +) : KtCollectionLiteralReference(expression), KtDescriptorsBasedReference { + override fun isReferenceTo(element: PsiElement): Boolean = + super.isReferenceTo(element) + + override fun getTargetDescriptors(context: BindingContext): Collection { + val resolvedCall = context[BindingContext.COLLECTION_LITERAL_CALL, element] + return listOfNotNull(resolvedCall?.resultingDescriptor) + } +} diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtConstructorDelegationReference.java b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtConstructorDelegationReference.java deleted file mode 100644 index 9acde94aba0..00000000000 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtConstructorDelegationReference.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.idea.references; - -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.name.Name; -import org.jetbrains.kotlin.psi.KtConstructorDelegationReferenceExpression; - -import java.util.Collection; -import java.util.Collections; - -public class KtConstructorDelegationReference extends KtSimpleReference { - public KtConstructorDelegationReference(KtConstructorDelegationReferenceExpression expression) { - super(expression); - } - - @Override - public TextRange getRangeInElement() { - return new TextRange(0, getElement().getTextLength()); - } - - @NotNull - @Override - public Collection getResolvesByNames() { - return Collections.emptyList(); - } - - @Nullable - @Override - public PsiElement handleElementRename(@Nullable String newElementName) { - // Class rename never affects this reference, so there is no need to fail with exception - return getExpression(); - } -} diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtConstructorDelegationReferenceDescriptorsImpl.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtConstructorDelegationReferenceDescriptorsImpl.kt new file mode 100644 index 00000000000..fba4183cfdd --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtConstructorDelegationReferenceDescriptorsImpl.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2020 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.references + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.psi.KtConstructorDelegationReferenceExpression +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets + +class KtConstructorDelegationReferenceDescriptorsImpl( + expression: KtConstructorDelegationReferenceExpression +) : KtConstructorDelegationReference(expression), KtDescriptorsBasedReference { + + override fun isReferenceTo(element: PsiElement): Boolean = + super.isReferenceTo(element) + + override fun getTargetDescriptors(context: BindingContext) = expression.getReferenceTargets(context) +} \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtDestructuringDeclarationReference.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtDestructuringDeclarationReferenceDescriptorsImpl.kt similarity index 64% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtDestructuringDeclarationReference.kt rename to idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtDestructuringDeclarationReferenceDescriptorsImpl.kt index d9eb1100ce4..972db896a5e 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtDestructuringDeclarationReference.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtDestructuringDeclarationReferenceDescriptorsImpl.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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. */ @@ -16,8 +16,12 @@ import org.jetbrains.kotlin.psi.KtDestructuringDeclaration import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry import org.jetbrains.kotlin.resolve.BindingContext -class KtDestructuringDeclarationReference(element: KtDestructuringDeclarationEntry) : - AbstractKtReference(element) { +class KtDestructuringDeclarationReferenceDescriptorsImpl( + element: KtDestructuringDeclarationEntry +) : KtDestructuringDeclarationReference(element), KtDescriptorsBasedReference { + override fun isReferenceTo(element: PsiElement): Boolean = + super.isReferenceTo(element) + override fun getTargetDescriptors(context: BindingContext): Collection { return listOfNotNull(context[BindingContext.COMPONENT_RESOLVED_CALL, element]?.candidateDescriptor) } @@ -30,16 +34,4 @@ class KtDestructuringDeclarationReference(element: KtDestructuringDeclarationEnt it is CallableMemberDescriptor && it.kind == CallableMemberDescriptor.Kind.SYNTHESIZED } } - - override fun handleElementRename(newElementName: String): PsiElement? { - if (canRename()) return expression - throw IncorrectOperationException() - } - - override val resolvesByNames: Collection - get() { - val destructuringParent = element.parent as? KtDestructuringDeclaration ?: return emptyList() - val componentIndex = destructuringParent.entries.indexOf(element) + 1 - return listOf(Name.identifier("component$componentIndex")) - } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtForLoopInReference.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtForLoopInReferenceDescriptorsImpl.kt similarity index 60% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtForLoopInReference.kt rename to idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtForLoopInReferenceDescriptorsImpl.kt index d4c856f99da..a90378c3f58 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtForLoopInReference.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtForLoopInReferenceDescriptorsImpl.kt @@ -1,45 +1,34 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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.references import com.intellij.openapi.util.TextRange +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.util.OperatorNameConventions -class KtForLoopInReference(element: KtForExpression) : KtMultiReference(element) { - - override fun getRangeInElement(): TextRange { - val inKeyword = expression.inKeyword ?: return TextRange.EMPTY_RANGE - - val offset = inKeyword.startOffsetInParent - return TextRange(offset, offset + inKeyword.textLength) - } +class KtForLoopInReferenceDescriptorsImpl( + element: KtForExpression +) : KtForLoopInReference(element), KtDescriptorsBasedReference { + override fun isReferenceTo(element: PsiElement): Boolean = + super.isReferenceTo(element) override fun getTargetDescriptors(context: BindingContext): Collection { val loopRange = expression.loopRange ?: return emptyList() return LOOP_RANGE_KEYS.mapNotNull { key -> context.get(key, loopRange)?.candidateDescriptor } } - override val resolvesByNames: Collection - get() = NAMES - companion object { private val LOOP_RANGE_KEYS = arrayOf( BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL, BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL, BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL ) - - private val NAMES = listOf( - OperatorNameConventions.ITERATOR, - OperatorNameConventions.NEXT, - OperatorNameConventions.HAS_NEXT - ) } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtInvokeFunctionReferenceDescriptorsImpl.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtInvokeFunctionReferenceDescriptorsImpl.kt new file mode 100644 index 00000000000..7729cce012e --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtInvokeFunctionReferenceDescriptorsImpl.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2020 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.references + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.psi.Call +import org.jetbrains.kotlin.psi.KtCallExpression +import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.calls.callUtil.getCall +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall +import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall + +class KtInvokeFunctionReferenceDescriptorsImpl(expression: KtCallExpression) : KtInvokeFunctionReference(expression), KtDescriptorsBasedReference { + override fun isReferenceTo(element: PsiElement): Boolean = + super.isReferenceTo(element) + + + override fun getTargetDescriptors(context: BindingContext): Collection { + val call = element.getCall(context) + val resolvedCall = call.getResolvedCall(context) + return when { + resolvedCall is VariableAsFunctionResolvedCall -> + setOf((resolvedCall as VariableAsFunctionResolvedCall).functionCall.candidateDescriptor) + call != null && resolvedCall != null && call.callType == Call.CallType.INVOKE -> + setOf(resolvedCall.candidateDescriptor) + else -> + emptyList() + } + } + + override fun doRenameImplicitConventionalCall(newName: String?): KtExpression = + renameImplicitConventionalCall(newName) +} diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtPropertyDelegationMethodsReference.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtPropertyDelegationMethodsReference.kt deleted file mode 100644 index 616a36ca4fe..00000000000 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtPropertyDelegationMethodsReference.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.idea.references - -import com.intellij.openapi.util.TextRange -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors -import org.jetbrains.kotlin.descriptors.accessors -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.psi.KtProperty -import org.jetbrains.kotlin.psi.KtPropertyDelegate -import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.util.OperatorNameConventions - -class KtPropertyDelegationMethodsReference(element: KtPropertyDelegate) : KtMultiReference(element) { - - override fun getRangeInElement(): TextRange { - val byKeywordNode = expression.byKeywordNode - val offset = byKeywordNode.psi!!.startOffsetInParent - return TextRange(offset, offset + byKeywordNode.textLength) - } - - override fun getTargetDescriptors(context: BindingContext): Collection { - val property = expression.getStrictParentOfType() ?: return emptyList() - val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, property] as? VariableDescriptorWithAccessors - ?: return emptyList() - return (descriptor.accessors.mapNotNull { accessor -> - context.get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, accessor)?.candidateDescriptor - } + listOfNotNull(context.get(BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, descriptor)?.candidateDescriptor)) - } - - override val resolvesByNames: Collection get() = NAMES - - companion object { - private val NAMES = listOf( - OperatorNameConventions.GET_VALUE, - OperatorNameConventions.SET_VALUE, - OperatorNameConventions.PROVIDE_DELEGATE - ) - } -} diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtPropertyDelegationMethodsReferenceDescriptorsImpl.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtPropertyDelegationMethodsReferenceDescriptorsImpl.kt new file mode 100644 index 00000000000..125c0f6e1bb --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtPropertyDelegationMethodsReferenceDescriptorsImpl.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2020 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.references + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors +import org.jetbrains.kotlin.descriptors.accessors +import org.jetbrains.kotlin.psi.KtProperty +import org.jetbrains.kotlin.psi.KtPropertyDelegate +import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType +import org.jetbrains.kotlin.resolve.BindingContext + +class KtPropertyDelegationMethodsReferenceDescriptorsImpl( + element: KtPropertyDelegate +) : KtPropertyDelegationMethodsReference(element), KtDescriptorsBasedReference { + override fun isReferenceTo(element: PsiElement): Boolean = + super.isReferenceTo(element) + + override fun getTargetDescriptors(context: BindingContext): Collection { + val property = expression.getStrictParentOfType() ?: return emptyList() + val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, property] as? VariableDescriptorWithAccessors + ?: return emptyList() + return descriptor.accessors.mapNotNull { accessor -> + context.get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, accessor)?.candidateDescriptor + } + listOfNotNull(context.get(BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, descriptor)?.candidateDescriptor) + } +} diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtReference.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtReference.kt index 674573b7f00..8de59d86da6 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtReference.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtReference.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2010-2020 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.references @@ -51,251 +40,83 @@ import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import java.util.* -interface KtReference : PsiPolyVariantReference { - fun resolveToDescriptors(bindingContext: BindingContext): Collection +interface KtDescriptorsBasedReference : KtReference { + override val resolver get() = KotlinDescriptorsBasedReferenceResolver - override fun getElement(): KtElement - - val resolvesByNames: Collection -} - -abstract class AbstractKtReference(element: T) : PsiPolyVariantReferenceBase(element), KtReference { - val expression: T - get() = element - - override fun multiResolve(incompleteCode: Boolean): Array { - @Suppress("UNCHECKED_CAST") - val kotlinResolver = KOTLIN_RESOLVER as ResolveCache.PolyVariantResolver> - return ResolveCache.getInstance(expression.project).resolveWithCaching(this, kotlinResolver, false, incompleteCode) + fun resolveToDescriptors(bindingContext: BindingContext): Collection { + return getTargetDescriptors(bindingContext) } + fun getTargetDescriptors(context: BindingContext): Collection + override fun isReferenceTo(element: PsiElement): Boolean { return matchesTarget(element) } - - override fun getCanonicalText(): String = "" - - open fun canRename(): Boolean = false - override fun handleElementRename(newElementName: String): PsiElement? = throw IncorrectOperationException() - - override fun bindToElement(element: PsiElement): PsiElement = throw IncorrectOperationException() - - @Suppress("UNCHECKED_CAST") - override fun getVariants(): Array = PsiReference.EMPTY_ARRAY as Array - - override fun isSoft(): Boolean = false - - override fun resolveToDescriptors(bindingContext: BindingContext): Collection { - return getTargetDescriptors(bindingContext) - } - - protected abstract fun getTargetDescriptors(context: BindingContext): Collection - - override fun toString() = this::class.java.simpleName + ": " + expression.text - - companion object { - private object FirReferenceResolveHelper { - fun FirResolvedTypeRef.toTargetPsi(session: FirSession): PsiElement? { - val type = type as? ConeLookupTagBasedType ?: return null - return (type.lookupTag.toSymbol(session) as? AbstractFirBasedSymbol<*>)?.fir?.psi - } - - fun ClassId.toTargetPsi(session: FirSession, calleeReference: FirReference? = null): PsiElement? { - val classLikeDeclaration = ConeClassLikeLookupTagImpl(this).toSymbol(session)?.fir - if (classLikeDeclaration is FirRegularClass) { - if (calleeReference is FirResolvedNamedReference) { - val callee = calleeReference.resolvedSymbol.fir as? FirCallableMemberDeclaration - // TODO: check callee owner directly? - if (callee !is FirConstructor && callee?.isStatic != true) { - classLikeDeclaration.companionObject?.let { return it.psi } - } - } - } - return classLikeDeclaration?.psi - } - - fun FirReference.toTargetPsi(session: FirSession): PsiElement? { - return when (this) { - is FirResolvedNamedReference -> { - resolvedSymbol.fir.psi - } - is FirResolvedCallableReference -> { - resolvedSymbol.fir.psi - } - is FirThisReference -> { - boundSymbol?.fir?.psi - } - is FirSuperReference -> { - (superTypeRef as? FirResolvedTypeRef)?.toTargetPsi(session) - } - else -> { - null - } - } - } - - fun resolveToPsiElements(ref: AbstractKtReference): Collection { - val expression = ref.expression - val state = expression.firResolveState() - val session = state.getSession(expression) - when (val fir = expression.getOrBuildFir(state)) { - is FirResolvable -> { - return listOfNotNull(fir.calleeReference.toTargetPsi(session)) - } - is FirResolvedTypeRef -> { - return listOfNotNull(fir.toTargetPsi(session)) - } - is FirResolvedQualifier -> { - val classId = fir.classId ?: return emptyList() - // Distinguish A.foo() from A(.Companion).foo() - // Make expression.parent as? KtDotQualifiedExpression local function - var parent = expression.parent as? KtDotQualifiedExpression - while (parent != null) { - val selectorExpression = parent.selectorExpression ?: break - if (selectorExpression === expression) { - parent = parent.parent as? KtDotQualifiedExpression - continue - } - val parentFir = selectorExpression.getOrBuildFir(state) - if (parentFir is FirQualifiedAccess) { - return listOfNotNull(classId.toTargetPsi(session, parentFir.calleeReference)) - } - parent = parent.parent as? KtDotQualifiedExpression - } - return listOfNotNull(classId.toTargetPsi(session)) - } - is FirAnnotationCall -> { - val type = fir.typeRef as? FirResolvedTypeRef ?: return emptyList() - return listOfNotNull(type.toTargetPsi(session)) - } - is FirResolvedImport -> { - var parent = expression.parent - while (parent is KtDotQualifiedExpression) { - if (parent.selectorExpression !== expression) { - // Special: package reference in the middle of import directive - // import a.b.c.SomeClass - // TODO: return reference to PsiPackage - return listOf(expression) - } - parent = parent.parent - } - val classId = fir.resolvedClassId - if (classId != null) { - return listOfNotNull(classId.toTargetPsi(session)) - } - val name = fir.importedName ?: return emptyList() - val symbolProvider = session.firSymbolProvider - return symbolProvider.getTopLevelCallableSymbols(fir.packageFqName, name).mapNotNull { it.fir.psi } + - listOfNotNull(symbolProvider.getClassLikeSymbolByFqName(ClassId(fir.packageFqName, name))?.fir?.psi) - } - is FirFile -> { - if (expression.getNonStrictParentOfType() != null) { - // Special: package reference in the middle of package directive - return listOf(expression) - } - return listOfNotNull(fir.psi) - } - is FirArrayOfCall -> { - // We can't yet find PsiElement for arrayOf, intArrayOf, etc. - return emptyList() - } - is FirErrorNamedReference -> { - return emptyList() - } - else -> { - // Handle situation when we're in the middle/beginning of qualifier - // A.B.C.foo() or A.B.C.foo() - // NB: in this case we get some parent FIR, like FirBlock, FirProperty, FirFunction or the like - var parent = expression.parent as? KtDotQualifiedExpression - var unresolvedCounter = 1 - while (parent != null) { - val selectorExpression = parent.selectorExpression ?: break - if (selectorExpression === expression) { - parent = parent.parent as? KtDotQualifiedExpression - continue - } - val parentFir = selectorExpression.getOrBuildFir(state) - if (parentFir is FirResolvedQualifier) { - var classId = parentFir.classId - while (unresolvedCounter > 0) { - unresolvedCounter-- - classId = classId?.outerClassId - } - return listOfNotNull(classId?.toTargetPsi(session)) - } - parent = parent.parent as? KtDotQualifiedExpression - unresolvedCounter++ - } - return emptyList() - } - } - } - } - - class KotlinReferenceResolver : ResolveCache.PolyVariantResolver> { - class KotlinResolveResult(element: PsiElement) : PsiElementResolveResult(element) - - private fun resolveToPsiElements(ref: AbstractKtReference): Collection { - if (FirResolution.enabled) { - return FirReferenceResolveHelper.resolveToPsiElements(ref) - } - val bindingContext = ref.expression.analyze(BodyResolveMode.PARTIAL) - return resolveToPsiElements(ref, bindingContext, ref.getTargetDescriptors(bindingContext)) - } - - private fun resolveToPsiElements( - ref: AbstractKtReference, - context: BindingContext, - targetDescriptors: Collection - ): Collection { - if (targetDescriptors.isNotEmpty()) { - return targetDescriptors.flatMap { target -> resolveToPsiElements(ref, target) }.toSet() - } - - val labelTargets = getLabelTargets(ref, context) - if (labelTargets != null) { - return labelTargets - } - - return Collections.emptySet() - } - - private fun resolveToPsiElements( - ref: AbstractKtReference, - targetDescriptor: DeclarationDescriptor - ): Collection { - return if (targetDescriptor is PackageViewDescriptor) { - val psiFacade = JavaPsiFacade.getInstance(ref.expression.project) - val fqName = targetDescriptor.fqName.asString() - listOfNotNull(psiFacade.findPackage(fqName)) - } else { - DescriptorToSourceUtilsIde.getAllDeclarations(ref.expression.project, targetDescriptor, ref.expression.resolveScope) - } - } - - private fun getLabelTargets(ref: AbstractKtReference, context: BindingContext): Collection? { - val reference = ref.expression as? KtReferenceExpression ?: return null - val labelTarget = context[BindingContext.LABEL_TARGET, reference] - if (labelTarget != null) { - return listOf(labelTarget) - } - return context[BindingContext.AMBIGUOUS_LABEL_TARGET, reference] - } - - override fun resolve(ref: AbstractKtReference, incompleteCode: Boolean): Array { - return runWithCancellationCheck { - val resolveToPsiElements = resolveToPsiElements(ref) - resolveToPsiElements.map { KotlinResolveResult(it) }.toTypedArray() - } - } - } - - val KOTLIN_RESOLVER = KotlinReferenceResolver() - } } -abstract class KtSimpleReference(expression: T) : AbstractKtReference(expression) { - override fun getTargetDescriptors(context: BindingContext) = expression.getReferenceTargets(context) +fun KtReference.resolveToDescriptors(bindingContext: BindingContext): Collection { + if (this !is KtDescriptorsBasedReference) { + error("Reference $this should be KtDescriptorsBasedReference but was ${this::class}") + } + return resolveToDescriptors(bindingContext) } -abstract class KtMultiReference(expression: T) : AbstractKtReference(expression) + +object KotlinDescriptorsBasedReferenceResolver : ResolveCache.PolyVariantResolver { + class KotlinResolveResult(element: PsiElement) : PsiElementResolveResult(element) + + private fun resolveToPsiElements(ref: KtDescriptorsBasedReference): Collection { + if (FirResolution.enabled) { + @Suppress("UNCHECKED_CAST") + return FirReferenceResolveHelper.resolveToPsiElements(ref as AbstractKtReference) + } + val bindingContext = ref.element.analyze(BodyResolveMode.PARTIAL) + return resolveToPsiElements(ref, bindingContext, ref.getTargetDescriptors(bindingContext)) + } + + private fun resolveToPsiElements( + ref: KtDescriptorsBasedReference, + context: BindingContext, + targetDescriptors: Collection + ): Collection { + if (targetDescriptors.isNotEmpty()) { + return targetDescriptors.flatMap { target -> resolveToPsiElements(ref, target) }.toSet() + } + + val labelTargets = getLabelTargets(ref, context) + if (labelTargets != null) { + return labelTargets + } + + return Collections.emptySet() + } + + private fun resolveToPsiElements( + ref: KtDescriptorsBasedReference, + targetDescriptor: DeclarationDescriptor + ): Collection { + return if (targetDescriptor is PackageViewDescriptor) { + val psiFacade = JavaPsiFacade.getInstance(ref.element.project) + val fqName = targetDescriptor.fqName.asString() + listOfNotNull(psiFacade.findPackage(fqName)) + } else { + DescriptorToSourceUtilsIde.getAllDeclarations(ref.element.project, targetDescriptor, ref.element.resolveScope) + } + } + + private fun getLabelTargets(ref: KtDescriptorsBasedReference, context: BindingContext): Collection? { + val reference = ref.element as? KtReferenceExpression ?: return null + val labelTarget = context[BindingContext.LABEL_TARGET, reference] + if (labelTarget != null) { + return listOf(labelTarget) + } + return context[BindingContext.AMBIGUOUS_LABEL_TARGET, reference] + } + + override fun resolve(ref: KtReference, incompleteCode: Boolean): Array { + return runWithCancellationCheck { + val resolveToPsiElements = resolveToPsiElements(ref as KtDescriptorsBasedReference) + resolveToPsiElements.map { KotlinResolveResult(it) }.toTypedArray() + } + } +} \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtSimpleNameReference.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtSimpleNameReference.kt index a9943d37dfd..8170053fc13 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtSimpleNameReference.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtSimpleNameReference.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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. */ @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.references import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiElement +import com.intellij.psi.PsiReference import com.intellij.psi.util.PsiTreeUtil import com.intellij.util.IncorrectOperationException import com.intellij.util.SmartList @@ -33,15 +34,21 @@ import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DataClassDescriptorResolver import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor +import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.types.expressions.OperatorConventions -class KtSimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleReference(expression) { +class KtSimpleNameReferenceDescriptorsImpl( + expression: KtSimpleNameExpression +) : KtSimpleNameReference(expression), KtDescriptorsBasedReference { + override fun doCanBeReferenceTo(candidateTarget: PsiElement): Boolean = + canBeReferenceTo(candidateTarget) + override fun getTargetDescriptors(context: BindingContext): Collection { return SmartList().apply { // Replace Java property with its accessor(s) - for (descriptor in super.getTargetDescriptors(context)) { + for (descriptor in expression.getReferenceTargets(context)) { val sizeBefore = size if (descriptor !is JavaPropertyDescriptor) { @@ -71,7 +78,7 @@ class KtSimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleRefere if (extension.isReferenceTo(this, element)) return true } - return super.isReferenceTo(element) + return super.isReferenceTo(element) } override fun getRangeInElement(): TextRange { @@ -141,23 +148,18 @@ class KtSimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleRefere return expression } - enum class ShorteningMode { - NO_SHORTENING, - DELAYED_SHORTENING, - FORCED_SHORTENING - } // By default reference binding is delayed override fun bindToElement(element: PsiElement): PsiElement = bindToElement(element, ShorteningMode.DELAYED_SHORTENING) - fun bindToElement(element: PsiElement, shorteningMode: ShorteningMode): PsiElement = + override fun bindToElement(element: PsiElement, shorteningMode: ShorteningMode): PsiElement = element.getKotlinFqName()?.let { fqName -> bindToFqName(fqName, shorteningMode, element) } ?: expression - fun bindToFqName( + override fun bindToFqName( fqName: FqName, - shorteningMode: ShorteningMode = ShorteningMode.DELAYED_SHORTENING, - targetElement: PsiElement? = null + shorteningMode: ShorteningMode, + targetElement: PsiElement? ): PsiElement { val expression = expression if (fqName.isRoot) return expression @@ -289,7 +291,7 @@ class KtSimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleRefere return listOf(element.getReferencedNameAsName()) } - fun getImportAlias(): KtImportAlias? { + override fun getImportAlias(): KtImportAlias? { fun DeclarationDescriptor.unwrap() = if (this is ImportedFromObjectCallableDescriptor<*>) callableFromObject else this val element = element diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/ReadWriteAccessCheckerDescriptorsImpl.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/ReadWriteAccessCheckerDescriptorsImpl.kt new file mode 100644 index 00000000000..0a524cfc0fd --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/ReadWriteAccessCheckerDescriptorsImpl.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2020 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.references + +import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall +import org.jetbrains.kotlin.psi.KtBinaryExpression +import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess +import org.jetbrains.kotlin.types.expressions.OperatorConventions + +class ReadWriteAccessCheckerDescriptorsImpl : ReadWriteAccessChecker { + override fun readWriteAccessWithFullExpressionByResolve(assignment: KtBinaryExpression): Pair { + val resolvedCall = assignment.resolveToCall() ?: return ReferenceAccess.READ_WRITE to assignment + if (!resolvedCall.isReallySuccess()) return ReferenceAccess.READ_WRITE to assignment + return if (resolvedCall.resultingDescriptor.name in OperatorConventions.ASSIGNMENT_OPERATIONS.values) + ReferenceAccess.READ to assignment + else + ReferenceAccess.READ_WRITE to assignment + } +} \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/SyntheticPropertyAccessorReference.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/SyntheticPropertyAccessorReference.kt index 7116ed7eb17..0a0198cb1e3 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/SyntheticPropertyAccessorReference.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/SyntheticPropertyAccessorReference.kt @@ -1,13 +1,11 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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.references -import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiElement -import com.intellij.psi.PsiMethod import com.intellij.util.SmartList import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor @@ -22,14 +20,22 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.utils.addIfNotNull -sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpression, private val getter: Boolean) : - KtSimpleReference(expression) { +class SyntheticPropertyAccessorReferenceDescriptorImpl( + expression: KtNameReferenceExpression, + getter: Boolean +) : SyntheticPropertyAccessorReference(expression, getter), KtDescriptorsBasedReference { + override fun isReferenceTo(element: PsiElement): Boolean = + super.isReferenceTo(element) + + override fun additionalIsReferenceToChecker(element: PsiElement): Boolean = matchesTarget(element) + override fun getTargetDescriptors(context: BindingContext): Collection { - val descriptors = super.getTargetDescriptors(context) + val descriptors = expression.getReferenceTargets(context) if (descriptors.none { it is SyntheticJavaPropertyDescriptor }) return emptyList() val result = SmartList() @@ -45,23 +51,6 @@ sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpre return result } - override fun isReferenceTo(element: PsiElement): Boolean { - if (element !is PsiMethod || !isAccessorName(element.name)) return false - if (!getter && expression.readWriteAccess(true) == ReferenceAccess.READ) return false - return super.isReferenceTo(element) - } - - private fun isAccessorName(name: String): Boolean { - if (getter) { - return name.startsWith("get") || name.startsWith("is") - } - return name.startsWith("set") - } - - override fun getRangeInElement() = TextRange(0, expression.textLength) - - override fun canRename() = true - private fun renameByPropertyName(newName: String): PsiElement? { val nameIdentifier = KtPsiFactory(expression).createNameIdentifier(newName) expression.getReferencedNameElement().replace(nameIdentifier) @@ -183,7 +172,4 @@ sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpre override val resolvesByNames: Collection get() = listOf(element.getReferencedNameAsName()) - - class Getter(expression: KtNameReferenceExpression) : SyntheticPropertyAccessorReference(expression, true) - class Setter(expression: KtNameReferenceExpression) : SyntheticPropertyAccessorReference(expression, false) } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/referenceUtil.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/referenceUtil.kt index 187167e3229..d9b1e5dc797 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/referenceUtil.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/referenceUtil.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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. */ @@ -221,20 +221,20 @@ fun AbstractKtReference.renameImplicitConventionalCall(newName return newExpression } -val KtSimpleNameExpression.mainReference: KtSimpleNameReference +val KtSimpleNameExpression.mainReference: KtSimpleNameReferenceDescriptorsImpl get() = references.firstIsInstance() -val KtReferenceExpression.mainReference: KtReference - get() = if (this is KtSimpleNameExpression) mainReference else references.firstIsInstance() +val KtReferenceExpression.mainReference: KtDescriptorsBasedReference + get() = if (this is KtSimpleNameExpression) mainReference else references.firstIsInstance() val KDocName.mainReference: KDocReference get() = references.firstIsInstance() -val KtElement.mainReference: KtReference? +val KtElement.mainReference: KtDescriptorsBasedReference? get() = when (this) { is KtReferenceExpression -> mainReference is KDocName -> mainReference - else -> references.firstIsInstanceOrNull() + else -> references.firstIsInstanceOrNull() } fun KtElement.resolveMainReferenceToDescriptors(): Collection { @@ -248,46 +248,6 @@ fun PsiReference.getImportAlias(): KtImportAlias? { // ----------- Read/write access ----------------------------------------------------------------------------------------------------------------------- -enum class ReferenceAccess(val isRead: Boolean, val isWrite: Boolean) { - READ(true, false), WRITE(false, true), READ_WRITE(true, true) -} - -fun KtExpression.readWriteAccess(useResolveForReadWrite: Boolean) = readWriteAccessWithFullExpression(useResolveForReadWrite).first - -fun KtExpression.readWriteAccessWithFullExpression(useResolveForReadWrite: Boolean): Pair { - var expression = 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) { - when (assignment.operationToken) { - KtTokens.EQ -> return ReferenceAccess.WRITE to assignment - - else -> { - if (!useResolveForReadWrite) return ReferenceAccess.READ_WRITE to assignment - - val resolvedCall = assignment.resolveToCall() ?: return ReferenceAccess.READ_WRITE to assignment - if (!resolvedCall.isReallySuccess()) return ReferenceAccess.READ_WRITE to assignment - return if (resolvedCall.resultingDescriptor.name in OperatorConventions.ASSIGNMENT_OPERATIONS.values) - ReferenceAccess.READ to assignment - else - 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 - ReferenceAccess.READ to expression -} - fun KtReference.canBeResolvedViaImport(target: DeclarationDescriptor, bindingContext: BindingContext): Boolean { if (this is KDocReference) { val qualifier = element.getQualifier() ?: return true diff --git a/idea/idea-core/build.gradle.kts b/idea/idea-core/build.gradle.kts index 4ce1268fdb8..ca419c0cd0f 100644 --- a/idea/idea-core/build.gradle.kts +++ b/idea/idea-core/build.gradle.kts @@ -16,6 +16,7 @@ dependencies { compile(project(":compiler:util")) compile(project(":idea:ide-common")) compile(project(":idea:idea-jps-common")) + compile(project(":idea:idea-frontend-independent")) compile(project(":kotlin-util-klib-metadata")) compile(project(":plugins:android-extensions-compiler")) compile(project(":kotlin-scripting-compiler-impl")) diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/Utils.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/Utils.kt index aa90b79afd9..c4fa4a8d46a 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/Utils.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/Utils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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. */ @@ -158,8 +158,6 @@ fun KtCallableDeclaration.canOmitDeclaredType(initializerOrBodyExpression: KtExp return canChangeTypeToSubtype && expressionType.isSubtypeOf(declaredType) } -fun String.unquote(): String = KtPsiUtil.unquoteIdentifier(this) - fun FqName.quoteSegmentsIfNeeded(): String { return pathSegments().joinToString(".") { it.asString().quoteIfNeeded() } } diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt index ef37361d85f..6317d4ea5ad 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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. */ @@ -45,14 +45,6 @@ import org.jetbrains.kotlin.types.typeUtil.isTypeParameter import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments import org.jetbrains.kotlin.utils.SmartList -inline fun PsiElement.replaced(newElement: T): T { - val result = replace(newElement) - return result as? T ?: (result as KtParenthesizedExpression).expression as T -} - -@Suppress("UNCHECKED_CAST") -fun T.copied(): T = copy() as T - fun KtLambdaArgument.moveInsideParentheses(bindingContext: BindingContext): KtCallExpression { val ktExpression = this.getArgumentExpression() ?: throw KotlinExceptionWithAttachments("no argument expression for $this") diff --git a/idea/idea-frontend-independent/build.gradle.kts b/idea/idea-frontend-independent/build.gradle.kts new file mode 100644 index 00000000000..655ac891f35 --- /dev/null +++ b/idea/idea-frontend-independent/build.gradle.kts @@ -0,0 +1,37 @@ +plugins { + kotlin("jvm") + id("jps-compatible") +} + +dependencies { + /* + This module should not depend on compiler scpecific functionality + No dependencies on descriptors (for now we still have transitive one by psi module), fir and similar modules, + but may be dependencies on frontend independent one like psi & type-system + This module is needed for smooth migration from descriptor frontend based IJ plugin to interlayer based one + */ + compileOnly(project(":compiler:psi")) + compileOnly(project(":kotlin-reflect-api")) + compileOnly(intellijCoreDep()) + compileOnly(intellijDep()) + + Platform[191].orLower { + compileOnly(intellijDep()) { includeJars("java-api", "java-impl") } + } + + Platform[192].orHigher { + compileOnly(intellijPluginDep("java")) { includeJars("java-api", "java-impl") } + } +} + +sourceSets { + "main" { projectDefault() } + "test" { projectDefault() } +} + +testsJar() + +projectTest { + dependsOn(":dist") + workingDir = rootDir +} diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/core/frontendIndependentPsiUtils.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/core/frontendIndependentPsiUtils.kt new file mode 100644 index 00000000000..3fb19ea4f33 --- /dev/null +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/core/frontendIndependentPsiUtils.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.core + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.psi.KtParenthesizedExpression +import org.jetbrains.kotlin.psi.KtPsiUtil + +inline fun PsiElement.replaced(newElement: T): T { + val result = replace(newElement) + return result as? T ?: (result as KtParenthesizedExpression).expression as T +} + +//todo make inline +@Suppress("UNCHECKED_CAST") +fun T.copied(): T = copy() as T + +fun String.unquote(): String = KtPsiUtil.unquoteIdentifier(this) + + + diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtArrayAccessReference.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtArrayAccessReference.kt similarity index 65% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtArrayAccessReference.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtArrayAccessReference.kt index 0627b742d1d..7df923157c3 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtArrayAccessReference.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtArrayAccessReference.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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. */ @@ -8,24 +8,15 @@ package org.jetbrains.kotlin.idea.references import com.google.common.collect.Lists import com.intellij.psi.MultiRangeReference import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.idea.core.canMoveLambdaOutsideParentheses -import org.jetbrains.kotlin.idea.core.moveFunctionLiteralOutsideParentheses import org.jetbrains.kotlin.idea.core.replaced import org.jetbrains.kotlin.lexer.KtToken import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.psi.KtArrayAccessExpression -import org.jetbrains.kotlin.psi.KtPsiFactory -import org.jetbrains.kotlin.psi.KtQualifiedExpression -import org.jetbrains.kotlin.psi.buildExpression +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getPossiblyQualifiedCallExpression -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_GET -import org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_SET import org.jetbrains.kotlin.util.OperatorNameConventions -class KtArrayAccessReference( +abstract class KtArrayAccessReference( expression: KtArrayAccessExpression ) : KtSimpleReference(expression), MultiRangeReference { override val resolvesByNames: Collection @@ -33,12 +24,6 @@ class KtArrayAccessReference( override fun getRangeInElement() = element.textRange.shiftRight(-element.textOffset) - override fun getTargetDescriptors(context: BindingContext): Collection { - val getFunctionDescriptor = context[INDEXED_LVALUE_GET, expression]?.candidateDescriptor - val setFunctionDescriptor = context[INDEXED_LVALUE_SET, expression]?.candidateDescriptor - return listOfNotNull(getFunctionDescriptor, setFunctionDescriptor) - } - private fun getBracketRange(bracketToken: KtToken) = expression.indicesNode.node.findChildByType(bracketToken)?.textRange?.shiftRight(-expression.textOffset) @@ -65,15 +50,19 @@ class KtArrayAccessReference( } val fullCallExpression = arrayAccessExpression.replaced(replacement) val callExpression = fullCallExpression.getPossiblyQualifiedCallExpression() - if (callExpression != null && callExpression.canMoveLambdaOutsideParentheses()) { - callExpression.moveFunctionLiteralOutsideParentheses() + if (callExpression != null && canMoveLambdaOutsideParentheses(callExpression)) { + moveFunctionLiteralOutsideParentheses(callExpression) } return fullCallExpression } - return this.renameImplicitConventionalCall(newElementName) + return doRenameImplicitConventionalCall(newElementName) } + protected abstract fun moveFunctionLiteralOutsideParentheses(callExpression: KtCallExpression) + protected abstract fun canMoveLambdaOutsideParentheses(callExpression: KtCallExpression): Boolean + protected abstract fun doRenameImplicitConventionalCall(newName: String?): KtExpression + companion object { private val NAMES = Lists.newArrayList(OperatorNameConventions.GET, OperatorNameConventions.SET) } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtCollectionLiteralReference.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtCollectionLiteralReference.kt similarity index 56% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtCollectionLiteralReference.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtCollectionLiteralReference.kt index 60696d190b0..ec5564081fa 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtCollectionLiteralReference.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtCollectionLiteralReference.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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. */ @@ -8,26 +8,18 @@ package org.jetbrains.kotlin.idea.references import com.intellij.openapi.util.TextRange import com.intellij.psi.MultiRangeReference import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtCollectionLiteralExpression -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.CollectionLiteralResolver +import org.jetbrains.kotlin.resolve.ArrayFqNames -class KtCollectionLiteralReference(expression: KtCollectionLiteralExpression) : +abstract class KtCollectionLiteralReference(expression: KtCollectionLiteralExpression) : KtSimpleReference(expression), MultiRangeReference { companion object { - private val COLLECTION_LITERAL_CALL_NAMES = - CollectionLiteralResolver.PRIMITIVE_TYPE_TO_ARRAY.values + CollectionLiteralResolver.ARRAY_OF_FUNCTION + private val COLLECTION_LITERAL_CALL_NAMES = ArrayFqNames.PRIMITIVE_TYPE_TO_ARRAY.values + ArrayFqNames.ARRAY_OF_FUNCTION } override fun getRangeInElement(): TextRange = element.normalizeRange() - override fun getTargetDescriptors(context: BindingContext): Collection { - val resolvedCall = context[BindingContext.COLLECTION_LITERAL_CALL, element] - return listOfNotNull(resolvedCall?.resultingDescriptor) - } - override fun getRanges(): List { return listOfNotNull(element.leftBracket?.normalizeRange(), element.rightBracket?.normalizeRange()) } diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtConstructorDelegationReference.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtConstructorDelegationReference.kt new file mode 100644 index 00000000000..0ae63287e55 --- /dev/null +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtConstructorDelegationReference.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2020 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.references + +import com.intellij.openapi.util.TextRange +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtConstructorDelegationReferenceExpression + +abstract class KtConstructorDelegationReference( + expression: KtConstructorDelegationReferenceExpression +) : KtSimpleReference(expression) { + override fun getRangeInElement(): TextRange { + return TextRange(0, element.textLength) + } + + override val resolvesByNames: Collection + get() = emptyList() + + override fun handleElementRename(newElementName: String): PsiElement? { + // Class rename never affects this reference, so there is no need to fail with exception + return expression + } +} \ No newline at end of file diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtDestructuringDeclarationReference.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtDestructuringDeclarationReference.kt new file mode 100644 index 00000000000..70498d514f9 --- /dev/null +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtDestructuringDeclarationReference.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2020 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.references + +import com.intellij.openapi.util.TextRange +import com.intellij.psi.PsiElement +import com.intellij.util.IncorrectOperationException +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtDestructuringDeclaration +import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry + +abstract class KtDestructuringDeclarationReference( + element: KtDestructuringDeclarationEntry +) : AbstractKtReference(element) { + + override fun getRangeInElement() = TextRange(0, element.textLength) + + abstract override fun canRename(): Boolean + + override fun handleElementRename(newElementName: String): PsiElement? { + if (canRename()) return expression + throw IncorrectOperationException() + } + + override val resolvesByNames: Collection + get() { + val destructuringParent = element.parent as? KtDestructuringDeclaration ?: return emptyList() + val componentIndex = destructuringParent.entries.indexOf(element) + 1 + return listOf(Name.identifier("component$componentIndex")) + } +} diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtForLoopInReference.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtForLoopInReference.kt new file mode 100644 index 00000000000..1c6e82cc294 --- /dev/null +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtForLoopInReference.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2020 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.references + +import com.intellij.openapi.util.TextRange +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtForExpression +import org.jetbrains.kotlin.util.OperatorNameConventions + +abstract class KtForLoopInReference(element: KtForExpression) : KtMultiReference(element) { + override fun getRangeInElement(): TextRange { + val inKeyword = expression.inKeyword ?: return TextRange.EMPTY_RANGE + + val offset = inKeyword.startOffsetInParent + return TextRange(offset, offset + inKeyword.textLength) + } + + override val resolvesByNames: Collection + get() = NAMES + + companion object { + private val NAMES = listOf( + OperatorNameConventions.ITERATOR, + OperatorNameConventions.NEXT, + OperatorNameConventions.HAS_NEXT + ) + } +} diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtIdeReferenceProviderService.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtIdeReferenceProviderService.kt similarity index 83% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtIdeReferenceProviderService.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtIdeReferenceProviderService.kt index 7cb850980d0..f6246fe9ad6 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtIdeReferenceProviderService.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtIdeReferenceProviderService.kt @@ -1,10 +1,11 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. + * Copyright 2010-2020 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.references +import com.intellij.openapi.components.service import com.intellij.openapi.project.IndexNotReadyException import com.intellij.psi.ContributedReferenceHost import com.intellij.psi.PsiElement @@ -21,15 +22,20 @@ import org.jetbrains.kotlin.psi.KotlinReferenceProvidersService import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.utils.SmartList -internal interface KotlinPsiReferenceProvider { +interface KotlinPsiReferenceProvider { fun getReferencesByElement(element: PsiElement): Array } -internal interface KotlinReferenceProviderContributor { +interface KotlinReferenceProviderContributor { fun registerReferenceProviders(registrar: KotlinPsiReferenceRegistrar) + + companion object { + fun getInstance(): KotlinReferenceProviderContributor = service() + } } -internal class KotlinPsiReferenceRegistrar { + +class KotlinPsiReferenceRegistrar { val providers: MultiMap, KotlinPsiReferenceProvider> = MultiMap.create() inline fun registerProvider(crossinline factory: (E) -> PsiReference?) { @@ -38,10 +44,9 @@ internal class KotlinPsiReferenceRegistrar { } } - inline fun registerMultiProvider(crossinline factory: (E) -> Array) { + inline fun registerMultiProvider(crossinline factory: (E) -> Array) { val provider: KotlinPsiReferenceProvider = object : KotlinPsiReferenceProvider { override fun getReferencesByElement(element: PsiElement): Array { - @Suppress("UNCHECKED_CAST") return factory(element as E) } } @@ -58,15 +63,13 @@ class KtIdeReferenceProviderService : KotlinReferenceProvidersService() { private val originalProvidersBinding: MultiMap, KotlinPsiReferenceProvider> private val providersBindingCache: Map, List> - private val referenceContributors = listOf(KotlinReferenceContributor(), KotlinDefaultAnnotationMethodImplicitReferenceContributor()) - init { val registrar = KotlinPsiReferenceRegistrar() - referenceContributors.forEach { it.registerReferenceProviders(registrar) } + KotlinReferenceProviderContributor.getInstance().registerReferenceProviders(registrar) originalProvidersBinding = registrar.providers providersBindingCache = ConcurrentFactoryMap.createMap, List> { klass -> - val result = ContainerUtil.newSmartList() + val result = SmartList() for (bindingClass in originalProvidersBinding.keySet()) { if (bindingClass.isAssignableFrom(klass)) { result.addAll(originalProvidersBinding.get(bindingClass)) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtInvokeFunctionReference.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtInvokeFunctionReference.kt similarity index 63% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtInvokeFunctionReference.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtInvokeFunctionReference.kt index 3763d61b973..12141910b19 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtInvokeFunctionReference.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtInvokeFunctionReference.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2010-2020 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.references @@ -20,40 +9,20 @@ import com.intellij.lang.ASTNode import com.intellij.openapi.util.TextRange import com.intellij.psi.MultiRangeReference import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.calls.callUtil.getCall -import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall -import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall import org.jetbrains.kotlin.util.OperatorNameConventions import java.util.* -class KtInvokeFunctionReference(expression: KtCallExpression) : KtSimpleReference(expression), MultiRangeReference { - - override val resolvesByNames: Collection - get() = NAMES +abstract class KtInvokeFunctionReference(expression: KtCallExpression) : KtSimpleReference(expression), MultiRangeReference { + override val resolvesByNames: Collection get() = NAMES override fun getRangeInElement(): TextRange { return element.textRange.shiftRight(-element.textOffset) } - override fun getTargetDescriptors(context: BindingContext): Collection { - val call = element.getCall(context) - val resolvedCall = call.getResolvedCall(context) - return when { - resolvedCall is VariableAsFunctionResolvedCall -> - setOf((resolvedCall as VariableAsFunctionResolvedCall).functionCall.candidateDescriptor) - call != null && resolvedCall != null && call.callType == Call.CallType.INVOKE -> - setOf(resolvedCall.candidateDescriptor) - else -> - emptyList() - } - } - override fun getRanges(): List { val list = ArrayList() val valueArgumentList = expression.valueArgumentList @@ -111,11 +80,12 @@ class KtInvokeFunctionReference(expression: KtCallExpression) : KtSimpleReferenc return fullCallExpression.replace(arrayAccessExpression) } - return renameImplicitConventionalCall(newElementName) + return doRenameImplicitConventionalCall(newElementName) } - companion object { + protected abstract fun doRenameImplicitConventionalCall(newName: String?): KtExpression + companion object { private val NAMES = listOf(OperatorNameConventions.INVOKE) } } diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtPropertyDelegationMethodsReference.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtPropertyDelegationMethodsReference.kt new file mode 100644 index 00000000000..15a776e69b2 --- /dev/null +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtPropertyDelegationMethodsReference.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2020 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.references + +import com.intellij.openapi.util.TextRange +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtPropertyDelegate +import org.jetbrains.kotlin.util.OperatorNameConventions + +abstract class KtPropertyDelegationMethodsReference(element: KtPropertyDelegate) : KtMultiReference(element) { + override fun getRangeInElement(): TextRange { + val byKeywordNode = expression.byKeywordNode + val offset = byKeywordNode.psi!!.startOffsetInParent + return TextRange(offset, offset + byKeywordNode.textLength) + } + + override val resolvesByNames: Collection get() = NAMES + + companion object { + private val NAMES = listOf( + OperatorNameConventions.GET_VALUE, + OperatorNameConventions.SET_VALUE, + OperatorNameConventions.PROVIDE_DELEGATE + ) + } +} diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtReference.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtReference.kt new file mode 100644 index 00000000000..453152179f8 --- /dev/null +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtReference.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2020 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.references + +import com.intellij.psi.* +import com.intellij.psi.impl.source.resolve.ResolveCache +import com.intellij.util.IncorrectOperationException +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtReferenceExpression + +interface KtReference : PsiPolyVariantReference { + val resolver: ResolveCache.PolyVariantResolver + + override fun getElement(): KtElement + + val resolvesByNames: Collection +} + +abstract class AbstractKtReference(element: T) : PsiPolyVariantReferenceBase(element), KtReference { + val expression: T + get() = element + + override fun multiResolve(incompleteCode: Boolean): Array = + ResolveCache.getInstance(expression.project).resolveWithCaching(this, resolver, false, incompleteCode) + + override fun getCanonicalText(): String = "" + + open fun canRename(): Boolean = false + override fun handleElementRename(newElementName: String): PsiElement? = throw IncorrectOperationException() + + override fun bindToElement(element: PsiElement): PsiElement = throw IncorrectOperationException() + + @Suppress("UNCHECKED_CAST") + override fun getVariants(): Array = PsiReference.EMPTY_ARRAY as Array + + override fun isSoft(): Boolean = false + + override fun toString() = this::class.java.simpleName + ": " + expression.text +} + +abstract class KtSimpleReference(expression: T) : AbstractKtReference(expression) + +abstract class KtMultiReference(expression: T) : AbstractKtReference(expression) \ No newline at end of file diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtSimpleNameReference.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtSimpleNameReference.kt new file mode 100644 index 00000000000..39cc4c7ab6e --- /dev/null +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/KtSimpleNameReference.kt @@ -0,0 +1,97 @@ +/* + * Copyright 2010-2020 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.references + +import com.intellij.openapi.extensions.Extensions +import com.intellij.openapi.util.TextRange +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiReference +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.plugin.references.SimpleNameReferenceExtension +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch +import org.jetbrains.kotlin.psi.psiUtil.startOffset +import org.jetbrains.kotlin.types.expressions.OperatorConventions + +abstract class KtSimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleReference(expression) { + override fun isReferenceTo(element: PsiElement): Boolean { + if (!doCanBeReferenceTo(element)) return false + + + @Suppress("DEPRECATION") // compatibility with 191 + for (extension in Extensions.getArea(element.project).getExtensionPoint(SimpleNameReferenceExtension.EP_NAME).extensions) { + if (extension.isReferenceTo(this, element)) return true + } + + return super.isReferenceTo(element) + } + + protected abstract fun doCanBeReferenceTo(candidateTarget: PsiElement): Boolean + + override fun getRangeInElement(): TextRange { + val element = element.getReferencedNameElement() + val startOffset = getElement().startOffset + return element.textRange.shiftRight(-startOffset) + } + + override fun canRename(): Boolean { + if (expression.getParentOfTypeAndBranch(strict = true) { operationReference } != null) return false + + val elementType = expression.getReferencedNameElementType() + if (elementType == KtTokens.PLUSPLUS || elementType == KtTokens.MINUSMINUS) return false + + return true + } + + abstract override fun handleElementRename(newElementName: String): PsiElement? + + enum class ShorteningMode { + NO_SHORTENING, + DELAYED_SHORTENING, + FORCED_SHORTENING + } + + // By default reference binding is delayed + override fun bindToElement(element: PsiElement): PsiElement = + bindToElement(element, ShorteningMode.DELAYED_SHORTENING) + + abstract fun bindToElement(element: PsiElement, shorteningMode: ShorteningMode): PsiElement + + abstract fun bindToFqName( + fqName: FqName, + shorteningMode: ShorteningMode = ShorteningMode.DELAYED_SHORTENING, + targetElement: PsiElement? = null + ): PsiElement + + override fun getCanonicalText(): String = expression.text + + override val resolvesByNames: Collection + get() { + val element = element + + if (element is KtOperationReferenceExpression) { + val tokenType = element.operationSignTokenType + if (tokenType != null) { + val name = OperatorConventions.getNameForOperationSymbol( + tokenType, element.parent is KtUnaryExpression, element.parent is KtBinaryExpression + ) ?: return emptyList() + val counterpart = OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS[tokenType] + return if (counterpart != null) { + val counterpartName = OperatorConventions.getNameForOperationSymbol(counterpart, false, true)!! + listOf(name, counterpartName) + } else { + listOf(name) + } + } + } + + return listOf(element.getReferencedNameAsName()) + } + + abstract fun getImportAlias(): KtImportAlias? +} diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/ReadWriteAccessChecker.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/ReadWriteAccessChecker.kt new file mode 100644 index 00000000000..3cae8380091 --- /dev/null +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/ReadWriteAccessChecker.kt @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2020 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.references + +import com.intellij.openapi.components.service +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.utils.addToStdlib.constant + +interface ReadWriteAccessChecker { + fun readWriteAccessWithFullExpressionByResolve(assignment: KtBinaryExpression): Pair? = null + + fun readWriteAccessWithFullExpression( + targetExpression: KtExpression, + useResolveForReadWrite: Boolean + ): Pair { + 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) { + when (assignment.operationToken) { + KtTokens.EQ -> return ReferenceAccess.WRITE to assignment + + else -> { + return ( + 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 + ReferenceAccess.READ to expression + } + + companion object { + fun getInstance(): ReadWriteAccessChecker = service() + } +} + +enum class ReferenceAccess(val isRead: Boolean, val isWrite: Boolean) { + READ(true, false), WRITE(false, true), READ_WRITE(true, true) +} + +fun KtExpression.readWriteAccess(useResolveForReadWrite: Boolean) = + readWriteAccessWithFullExpression(useResolveForReadWrite).first + +fun KtExpression.readWriteAccessWithFullExpression(useResolveForReadWrite: Boolean): Pair = + ReadWriteAccessChecker.getInstance().readWriteAccessWithFullExpression(this, useResolveForReadWrite) + + diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/SyntheticPropertyAccessorReference.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/SyntheticPropertyAccessorReference.kt new file mode 100644 index 00000000000..aef23d4b77b --- /dev/null +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/references/SyntheticPropertyAccessorReference.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2020 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.references + +import com.intellij.openapi.util.TextRange +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiMethod +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtNameReferenceExpression + +abstract class SyntheticPropertyAccessorReference( + expression: KtNameReferenceExpression, + val getter: Boolean +) : KtSimpleReference(expression) { + + override fun isReferenceTo(element: PsiElement): Boolean { + if (element !is PsiMethod || !isAccessorName(element.name)) return false + if (!getter && expression.readWriteAccess(true) == ReferenceAccess.READ) return false + return additionalIsReferenceToChecker(element) + } + + protected abstract fun additionalIsReferenceToChecker(element: PsiElement): Boolean + + private fun isAccessorName(name: String): Boolean { + if (getter) { + return name.startsWith("get") || name.startsWith("is") + } + return name.startsWith("set") + } + + override fun getRangeInElement() = TextRange(0, expression.textLength) + + override fun canRename() = true + + abstract override fun handleElementRename(newElementName: String): PsiElement? + + override val resolvesByNames: Collection + get() = listOf(element.getReferencedNameAsName()) +} diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/plugin/references/SimpleNameReferenceExtension.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/plugin/references/SimpleNameReferenceExtension.kt similarity index 92% rename from idea/idea-analysis/src/org/jetbrains/kotlin/plugin/references/SimpleNameReferenceExtension.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/plugin/references/SimpleNameReferenceExtension.kt index 3cd47fd97f1..d02b8d11f10 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/plugin/references/SimpleNameReferenceExtension.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/plugin/references/SimpleNameReferenceExtension.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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. */ diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt index 6e223869d22..37ff5c7ae59 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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. */ @@ -39,6 +39,7 @@ import org.jetbrains.kotlin.idea.core.util.runInReadActionWithWriteActionPriorit import org.jetbrains.kotlin.idea.patterns.KotlinFunctionPattern import org.jetbrains.kotlin.idea.references.KtReference import org.jetbrains.kotlin.idea.references.mainReference +import org.jetbrains.kotlin.idea.references.resolveToDescriptors import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor import org.jetbrains.kotlin.idea.util.ProjectRootsUtil import org.jetbrains.kotlin.lexer.KtTokens diff --git a/idea/resources/META-INF/plugin-common.xml b/idea/resources/META-INF/plugin-common.xml index ffcdcb1c536..ce5ef47ad94 100644 --- a/idea/resources/META-INF/plugin-common.xml +++ b/idea/resources/META-INF/plugin-common.xml @@ -171,6 +171,12 @@ + + + + () + .filterIsInstanceWithChecker { !it.getter } } .ifEmpty { return getterReferences } return ArrayList(getterReferences.size + setterReferences.size).apply { addAll(getterReferences) - setterReferences.mapTo(this) { SyntheticPropertyAccessorReference.Getter(it.expression) } + setterReferences.mapTo(this) { SyntheticPropertyAccessorReferenceDescriptorImpl(it.expression, getter = true) } } } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinOverridingMethodReferenceSearcher.kt b/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinOverridingMethodReferenceSearcher.kt index ddf344032f2..641afe43534 100644 --- a/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinOverridingMethodReferenceSearcher.kt +++ b/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinOverridingMethodReferenceSearcher.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2010-2020 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 @@ -94,7 +83,7 @@ class KotlinOverridingMethodReferenceSearcher : MethodUsagesSearcher() { return readWriteAccess.isRead != isGetter && readWriteAccess.isWrite == isGetter } if (ref is SyntheticPropertyAccessorReference) { - return (ref is SyntheticPropertyAccessorReference.Getter) != isGetter + return ref.getter != isGetter } return false } diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ArrayInitializerConversion.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ArrayInitializerConversion.kt index 2f7561f802b..51ac3293df3 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ArrayInitializerConversion.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ArrayInitializerConversion.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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. */ @@ -12,9 +12,7 @@ import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext import org.jetbrains.kotlin.nj2k.toArgumentList import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.types.* - -import org.jetbrains.kotlin.resolve.CollectionLiteralResolver - +import org.jetbrains.kotlin.resolve.ArrayFqNames class ArrayInitializerConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) { override fun applyToElement(element: JKTreeElement): JKTreeElement { @@ -23,9 +21,9 @@ class ArrayInitializerConversion(context: NewJ2kConverterContext) : RecursiveApp val primitiveArrayType = element.type.type as? JKJavaPrimitiveType val arrayConstructorName = if (primitiveArrayType != null) - CollectionLiteralResolver.PRIMITIVE_TYPE_TO_ARRAY[PrimitiveType.valueOf(primitiveArrayType.jvmPrimitiveType.name)]!!.asString() + ArrayFqNames.PRIMITIVE_TYPE_TO_ARRAY[PrimitiveType.valueOf(primitiveArrayType.jvmPrimitiveType.name)]!!.asString() else - CollectionLiteralResolver.ARRAY_OF_FUNCTION.asString() + ArrayFqNames.ARRAY_OF_FUNCTION.asString() val typeArguments = if (primitiveArrayType == null) JKTypeArgumentList(listOf(element::type.detached())) else JKTypeArgumentList() diff --git a/prepare/idea-plugin/build.gradle.kts b/prepare/idea-plugin/build.gradle.kts index 0b7e2df0b1c..7685b1fb785 100644 --- a/prepare/idea-plugin/build.gradle.kts +++ b/prepare/idea-plugin/build.gradle.kts @@ -93,6 +93,7 @@ val projectsToShadow by extra(listOf( ":idea:idea-jvm", ":idea:idea-git", ":idea:idea-jps-common", + ":idea:idea-frontend-independent", *if (Ide.IJ()) arrayOf( ":idea:idea-maven", diff --git a/settings.gradle b/settings.gradle index 8c3ca5ac1f3..d82c4aa9ca7 100644 --- a/settings.gradle +++ b/settings.gradle @@ -183,6 +183,7 @@ include ":kotlin-build-common", ":idea:jvm-debugger:jvm-debugger-coroutine", ":idea:jvm-debugger:jvm-debugger-test", ":idea:scripting-support", + ":idea:idea-frontend-independent", ":libraries:tools:new-project-wizard", ":idea:idea-new-project-wizard", ":libraries:tools:new-project-wizard:new-project-wizard-cli",