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
This commit is contained in:
Ilya Kirillov
2020-05-07 21:25:08 +03:00
parent 6adad1055b
commit 418903e9ef
52 changed files with 1045 additions and 730 deletions
@@ -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<PrimitiveType, Name> = 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")
}
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* 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.resolve package org.jetbrains.kotlin.resolve
@@ -44,21 +33,6 @@ class CollectionLiteralResolver(
val callResolver: CallResolver, val callResolver: CallResolver,
val languageVersionSettings: LanguageVersionSettings val languageVersionSettings: LanguageVersionSettings
) { ) {
companion object {
val PRIMITIVE_TYPE_TO_ARRAY: Map<PrimitiveType, Name> = 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( fun resolveCollectionLiteral(
collectionLiteralExpression: KtCollectionLiteralExpression, collectionLiteralExpression: KtCollectionLiteralExpression,
context: ExpressionTypingContext context: ExpressionTypingContext
@@ -120,11 +94,11 @@ class CollectionLiteralResolver(
private fun getArrayFunctionCallName(expectedType: KotlinType): Name { private fun getArrayFunctionCallName(expectedType: KotlinType): Name {
if (NO_EXPECTED_TYPE === expectedType || !KotlinBuiltIns.isPrimitiveArray(expectedType)) { 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
} }
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* 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.utils.addToStdlib package org.jetbrains.kotlin.utils.addToStdlib
@@ -50,6 +39,17 @@ inline fun <reified T> Array<*>.firstIsInstance(): T {
throw NoSuchElementException("No element of given type found") throw NoSuchElementException("No element of given type found")
} }
inline fun <reified T> Iterable<*>.filterIsInstanceWithChecker(additionalChecker: (T) -> Boolean): List<T> {
val result = arrayListOf<T>()
for (element in this) {
if (element is T && additionalChecker(element)) {
result += element
}
}
return result
}
inline fun <reified T : Any> Iterable<*>.lastIsInstanceOrNull(): T? { inline fun <reified T : Any> Iterable<*>.lastIsInstanceOrNull(): T? {
when (this) { when (this) {
is List<*> -> { is List<*> -> {
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* 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.kdoc package org.jetbrains.kotlin.idea.kdoc
@@ -20,6 +9,7 @@ import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade 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.idea.references.KtMultiReference
import org.jetbrains.kotlin.kdoc.psi.impl.KDocLink import org.jetbrains.kotlin.kdoc.psi.impl.KDocLink
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName 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.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
class KDocReference(element: KDocName) : KtMultiReference<KDocName>(element) { //TODO move to frontend-independent module
class KDocReference(element: KDocName) : KtMultiReference<KDocName>(element), KtDescriptorsBasedReference {
override fun isReferenceTo(element: PsiElement): Boolean =
super<KtDescriptorsBasedReference>.isReferenceTo(element)
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> { override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
val declaration = element.getContainingDoc().getOwner() ?: return arrayListOf() val declaration = element.getContainingDoc().getOwner() ?: return arrayListOf()
val resolutionFacade = element.getResolutionFacade() val resolutionFacade = element.getResolutionFacade()
@@ -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<KtElement>): Collection<PsiElement> {
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.<caret>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<KtPackageDirective>() != 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
// <caret>A.B.C.foo() or A.<caret>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()
}
}
}
}
@@ -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. * 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 override fun isSoft() = false
} }
internal class KotlinDefaultAnnotationMethodImplicitReferenceContributor : KotlinReferenceProviderContributor { internal val KotlinDefaultAnnotationMethodImplicitReferenceProvider = provider@{ element: KtValueArgument ->
override fun registerReferenceProviders(registrar: KotlinPsiReferenceRegistrar) { if (element.isNamed()) return@provider null
registrar.registerProvider<KtValueArgument> { val annotationEntry = element.getParentOfTypeAndBranch<KtAnnotationEntry> { valueArgumentList } ?: return@provider null
if (it.isNamed()) return@registerProvider null if (annotationEntry.valueArguments.size != 1) return@provider null
val annotationEntry = it.getParentOfTypeAndBranch<KtAnnotationEntry> { valueArgumentList } ?: return@registerProvider null
if (annotationEntry.valueArguments.size != 1) return@registerProvider null
ReferenceImpl(it) ReferenceImpl(element)
} }
}
}
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* 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 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.KtUserType
import org.jetbrains.kotlin.psi.psiUtil.parents import org.jetbrains.kotlin.psi.psiUtil.parents
internal class KotlinReferenceContributor : KotlinReferenceProviderContributor { class KotlinReferenceContributor : KotlinReferenceProviderContributor {
override fun registerReferenceProviders(registrar: KotlinPsiReferenceRegistrar) { override fun registerReferenceProviders(registrar: KotlinPsiReferenceRegistrar) {
with(registrar) { with(registrar) {
registerProvider(factory = ::KtSimpleNameReference) registerProvider(factory = ::KtSimpleNameReferenceDescriptorsImpl)
registerMultiProvider<KtNameReferenceExpression> { nameReferenceExpression -> registerMultiProvider<KtNameReferenceExpression> { nameReferenceExpression ->
if (nameReferenceExpression.getReferencedNameElementType() != KtTokens.IDENTIFIER) return@registerMultiProvider emptyArray() if (nameReferenceExpression.getReferencedNameElementType() != KtTokens.IDENTIFIER) return@registerMultiProvider emptyArray()
@@ -37,32 +26,34 @@ internal class KotlinReferenceContributor : KotlinReferenceProviderContributor {
when (nameReferenceExpression.readWriteAccess(useResolveForReadWrite = false)) { when (nameReferenceExpression.readWriteAccess(useResolveForReadWrite = false)) {
ReferenceAccess.READ -> ReferenceAccess.READ ->
arrayOf(SyntheticPropertyAccessorReference.Getter(nameReferenceExpression)) arrayOf(SyntheticPropertyAccessorReferenceDescriptorImpl(nameReferenceExpression, getter = true))
ReferenceAccess.WRITE -> ReferenceAccess.WRITE ->
arrayOf(SyntheticPropertyAccessorReference.Setter(nameReferenceExpression)) arrayOf(SyntheticPropertyAccessorReferenceDescriptorImpl(nameReferenceExpression, getter = false))
ReferenceAccess.READ_WRITE -> ReferenceAccess.READ_WRITE ->
arrayOf( arrayOf(
SyntheticPropertyAccessorReference.Getter(nameReferenceExpression), SyntheticPropertyAccessorReferenceDescriptorImpl(nameReferenceExpression, getter = true),
SyntheticPropertyAccessorReference.Setter(nameReferenceExpression) 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(factory = ::KDocReference)
registerProvider(KotlinDefaultAnnotationMethodImplicitReferenceProvider)
} }
} }
} }
@@ -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<KtDescriptorsBasedReference>.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<DeclarationDescriptor> {
val getFunctionDescriptor = context[INDEXED_LVALUE_GET, expression]?.candidateDescriptor
val setFunctionDescriptor = context[INDEXED_LVALUE_SET, expression]?.candidateDescriptor
return listOfNotNull(getFunctionDescriptor, setFunctionDescriptor)
}
}
@@ -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<KtDescriptorsBasedReference>.isReferenceTo(element)
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
val resolvedCall = context[BindingContext.COLLECTION_LITERAL_CALL, element]
return listOfNotNull(resolvedCall?.resultingDescriptor)
}
}
@@ -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<KtConstructorDelegationReferenceExpression> {
public KtConstructorDelegationReference(KtConstructorDelegationReferenceExpression expression) {
super(expression);
}
@Override
public TextRange getRangeInElement() {
return new TextRange(0, getElement().getTextLength());
}
@NotNull
@Override
public Collection<Name> 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();
}
}
@@ -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<KtDescriptorsBasedReference>.isReferenceTo(element)
override fun getTargetDescriptors(context: BindingContext) = expression.getReferenceTargets(context)
}
@@ -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. * 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.psi.KtDestructuringDeclarationEntry
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
class KtDestructuringDeclarationReference(element: KtDestructuringDeclarationEntry) : class KtDestructuringDeclarationReferenceDescriptorsImpl(
AbstractKtReference<KtDestructuringDeclarationEntry>(element) { element: KtDestructuringDeclarationEntry
) : KtDestructuringDeclarationReference(element), KtDescriptorsBasedReference {
override fun isReferenceTo(element: PsiElement): Boolean =
super<KtDescriptorsBasedReference>.isReferenceTo(element)
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> { override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
return listOfNotNull(context[BindingContext.COMPONENT_RESOLVED_CALL, element]?.candidateDescriptor) 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 it is CallableMemberDescriptor && it.kind == CallableMemberDescriptor.Kind.SYNTHESIZED
} }
} }
override fun handleElementRename(newElementName: String): PsiElement? {
if (canRename()) return expression
throw IncorrectOperationException()
}
override val resolvesByNames: Collection<Name>
get() {
val destructuringParent = element.parent as? KtDestructuringDeclaration ?: return emptyList()
val componentIndex = destructuringParent.entries.indexOf(element) + 1
return listOf(Name.identifier("component$componentIndex"))
}
} }
@@ -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. * 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 package org.jetbrains.kotlin.idea.references
import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
class KtForLoopInReference(element: KtForExpression) : KtMultiReference<KtForExpression>(element) { class KtForLoopInReferenceDescriptorsImpl(
element: KtForExpression
override fun getRangeInElement(): TextRange { ) : KtForLoopInReference(element), KtDescriptorsBasedReference {
val inKeyword = expression.inKeyword ?: return TextRange.EMPTY_RANGE override fun isReferenceTo(element: PsiElement): Boolean =
super<KtDescriptorsBasedReference>.isReferenceTo(element)
val offset = inKeyword.startOffsetInParent
return TextRange(offset, offset + inKeyword.textLength)
}
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> { override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
val loopRange = expression.loopRange ?: return emptyList() val loopRange = expression.loopRange ?: return emptyList()
return LOOP_RANGE_KEYS.mapNotNull { key -> context.get(key, loopRange)?.candidateDescriptor } return LOOP_RANGE_KEYS.mapNotNull { key -> context.get(key, loopRange)?.candidateDescriptor }
} }
override val resolvesByNames: Collection<Name>
get() = NAMES
companion object { companion object {
private val LOOP_RANGE_KEYS = arrayOf( private val LOOP_RANGE_KEYS = arrayOf(
BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL, BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL,
BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL, BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL,
BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL
) )
private val NAMES = listOf(
OperatorNameConventions.ITERATOR,
OperatorNameConventions.NEXT,
OperatorNameConventions.HAS_NEXT
)
} }
} }
@@ -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<KtDescriptorsBasedReference>.isReferenceTo(element)
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
val call = element.getCall(context)
val resolvedCall = call.getResolvedCall(context)
return when {
resolvedCall is VariableAsFunctionResolvedCall ->
setOf<DeclarationDescriptor>((resolvedCall as VariableAsFunctionResolvedCall).functionCall.candidateDescriptor)
call != null && resolvedCall != null && call.callType == Call.CallType.INVOKE ->
setOf<DeclarationDescriptor>(resolvedCall.candidateDescriptor)
else ->
emptyList()
}
}
override fun doRenameImplicitConventionalCall(newName: String?): KtExpression =
renameImplicitConventionalCall(newName)
}
@@ -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<KtPropertyDelegate>(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<DeclarationDescriptor> {
val property = expression.getStrictParentOfType<KtProperty>() ?: 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<Name> get() = NAMES
companion object {
private val NAMES = listOf(
OperatorNameConventions.GET_VALUE,
OperatorNameConventions.SET_VALUE,
OperatorNameConventions.PROVIDE_DELEGATE
)
}
}
@@ -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<KtDescriptorsBasedReference>.isReferenceTo(element)
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
val property = expression.getStrictParentOfType<KtProperty>() ?: 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)
}
}
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* 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 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 org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import java.util.* import java.util.*
interface KtReference : PsiPolyVariantReference { interface KtDescriptorsBasedReference : KtReference {
fun resolveToDescriptors(bindingContext: BindingContext): Collection<DeclarationDescriptor> override val resolver get() = KotlinDescriptorsBasedReferenceResolver
override fun getElement(): KtElement fun resolveToDescriptors(bindingContext: BindingContext): Collection<DeclarationDescriptor> {
return getTargetDescriptors(bindingContext)
val resolvesByNames: Collection<Name>
}
abstract class AbstractKtReference<T : KtElement>(element: T) : PsiPolyVariantReferenceBase<T>(element), KtReference {
val expression: T
get() = element
override fun multiResolve(incompleteCode: Boolean): Array<ResolveResult> {
@Suppress("UNCHECKED_CAST")
val kotlinResolver = KOTLIN_RESOLVER as ResolveCache.PolyVariantResolver<AbstractKtReference<T>>
return ResolveCache.getInstance(expression.project).resolveWithCaching(this, kotlinResolver, false, incompleteCode)
} }
fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor>
override fun isReferenceTo(element: PsiElement): Boolean { override fun isReferenceTo(element: PsiElement): Boolean {
return matchesTarget(element) return matchesTarget(element)
} }
override fun getCanonicalText(): String = "<TBD>"
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<Any> = PsiReference.EMPTY_ARRAY as Array<Any>
override fun isSoft(): Boolean = false
override fun resolveToDescriptors(bindingContext: BindingContext): Collection<DeclarationDescriptor> {
return getTargetDescriptors(bindingContext)
}
protected abstract fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor>
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<KtElement>): Collection<PsiElement> {
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.<caret>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<KtPackageDirective>() != 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
// <caret>A.B.C.foo() or A.<caret>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<AbstractKtReference<KtElement>> {
class KotlinResolveResult(element: PsiElement) : PsiElementResolveResult(element)
private fun resolveToPsiElements(ref: AbstractKtReference<KtElement>): Collection<PsiElement> {
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<KtElement>,
context: BindingContext,
targetDescriptors: Collection<DeclarationDescriptor>
): Collection<PsiElement> {
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<KtElement>,
targetDescriptor: DeclarationDescriptor
): Collection<PsiElement> {
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<KtElement>, context: BindingContext): Collection<PsiElement>? {
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<KtElement>, incompleteCode: Boolean): Array<ResolveResult> {
return runWithCancellationCheck {
val resolveToPsiElements = resolveToPsiElements(ref)
resolveToPsiElements.map { KotlinResolveResult(it) }.toTypedArray()
}
}
}
val KOTLIN_RESOLVER = KotlinReferenceResolver()
}
} }
abstract class KtSimpleReference<T : KtReferenceExpression>(expression: T) : AbstractKtReference<T>(expression) { fun KtReference.resolveToDescriptors(bindingContext: BindingContext): Collection<DeclarationDescriptor> {
override fun getTargetDescriptors(context: BindingContext) = expression.getReferenceTargets(context) if (this !is KtDescriptorsBasedReference) {
error("Reference $this should be KtDescriptorsBasedReference but was ${this::class}")
}
return resolveToDescriptors(bindingContext)
} }
abstract class KtMultiReference<T : KtElement>(expression: T) : AbstractKtReference<T>(expression)
object KotlinDescriptorsBasedReferenceResolver : ResolveCache.PolyVariantResolver<KtReference> {
class KotlinResolveResult(element: PsiElement) : PsiElementResolveResult(element)
private fun resolveToPsiElements(ref: KtDescriptorsBasedReference): Collection<PsiElement> {
if (FirResolution.enabled) {
@Suppress("UNCHECKED_CAST")
return FirReferenceResolveHelper.resolveToPsiElements(ref as AbstractKtReference<KtElement>)
}
val bindingContext = ref.element.analyze(BodyResolveMode.PARTIAL)
return resolveToPsiElements(ref, bindingContext, ref.getTargetDescriptors(bindingContext))
}
private fun resolveToPsiElements(
ref: KtDescriptorsBasedReference,
context: BindingContext,
targetDescriptors: Collection<DeclarationDescriptor>
): Collection<PsiElement> {
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<PsiElement> {
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<PsiElement>? {
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<ResolveResult> {
return runWithCancellationCheck {
val resolveToPsiElements = resolveToPsiElements(ref as KtDescriptorsBasedReference)
resolveToPsiElements.map { KotlinResolveResult(it) }.toTypedArray()
}
}
}
@@ -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. * 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.extensions.Extensions
import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiReference
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import com.intellij.util.IncorrectOperationException import com.intellij.util.IncorrectOperationException
import com.intellij.util.SmartList 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.BindingContext
import org.jetbrains.kotlin.resolve.DataClassDescriptorResolver import org.jetbrains.kotlin.resolve.DataClassDescriptorResolver
import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor 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.descriptorUtil.getImportableDescriptor
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.types.expressions.OperatorConventions
class KtSimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleReference<KtSimpleNameExpression>(expression) { class KtSimpleNameReferenceDescriptorsImpl(
expression: KtSimpleNameExpression
) : KtSimpleNameReference(expression), KtDescriptorsBasedReference {
override fun doCanBeReferenceTo(candidateTarget: PsiElement): Boolean =
canBeReferenceTo(candidateTarget)
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> { override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
return SmartList<DeclarationDescriptor>().apply { return SmartList<DeclarationDescriptor>().apply {
// Replace Java property with its accessor(s) // Replace Java property with its accessor(s)
for (descriptor in super.getTargetDescriptors(context)) { for (descriptor in expression.getReferenceTargets(context)) {
val sizeBefore = size val sizeBefore = size
if (descriptor !is JavaPropertyDescriptor) { if (descriptor !is JavaPropertyDescriptor) {
@@ -71,7 +78,7 @@ class KtSimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleRefere
if (extension.isReferenceTo(this, element)) return true if (extension.isReferenceTo(this, element)) return true
} }
return super.isReferenceTo(element) return super<KtDescriptorsBasedReference>.isReferenceTo(element)
} }
override fun getRangeInElement(): TextRange { override fun getRangeInElement(): TextRange {
@@ -141,23 +148,18 @@ class KtSimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleRefere
return expression return expression
} }
enum class ShorteningMode {
NO_SHORTENING,
DELAYED_SHORTENING,
FORCED_SHORTENING
}
// By default reference binding is delayed // By default reference binding is delayed
override fun bindToElement(element: PsiElement): PsiElement = override fun bindToElement(element: PsiElement): PsiElement =
bindToElement(element, ShorteningMode.DELAYED_SHORTENING) 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 element.getKotlinFqName()?.let { fqName -> bindToFqName(fqName, shorteningMode, element) } ?: expression
fun bindToFqName( override fun bindToFqName(
fqName: FqName, fqName: FqName,
shorteningMode: ShorteningMode = ShorteningMode.DELAYED_SHORTENING, shorteningMode: ShorteningMode,
targetElement: PsiElement? = null targetElement: PsiElement?
): PsiElement { ): PsiElement {
val expression = expression val expression = expression
if (fqName.isRoot) return expression if (fqName.isRoot) return expression
@@ -289,7 +291,7 @@ class KtSimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleRefere
return listOf(element.getReferencedNameAsName()) return listOf(element.getReferencedNameAsName())
} }
fun getImportAlias(): KtImportAlias? { override fun getImportAlias(): KtImportAlias? {
fun DeclarationDescriptor.unwrap() = if (this is ImportedFromObjectCallableDescriptor<*>) callableFromObject else this fun DeclarationDescriptor.unwrap() = if (this is ImportedFromObjectCallableDescriptor<*>) callableFromObject else this
val element = element val element = element
@@ -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<ReferenceAccess, KtExpression> {
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
}
}
@@ -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. * 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 package org.jetbrains.kotlin.idea.references
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.util.SmartList import com.intellij.util.SmartList
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor 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.*
import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpression, private val getter: Boolean) : class SyntheticPropertyAccessorReferenceDescriptorImpl(
KtSimpleReference<KtNameReferenceExpression>(expression) { expression: KtNameReferenceExpression,
getter: Boolean
) : SyntheticPropertyAccessorReference(expression, getter), KtDescriptorsBasedReference {
override fun isReferenceTo(element: PsiElement): Boolean =
super<SyntheticPropertyAccessorReference>.isReferenceTo(element)
override fun additionalIsReferenceToChecker(element: PsiElement): Boolean = matchesTarget(element)
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> { override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
val descriptors = super.getTargetDescriptors(context) val descriptors = expression.getReferenceTargets(context)
if (descriptors.none { it is SyntheticJavaPropertyDescriptor }) return emptyList() if (descriptors.none { it is SyntheticJavaPropertyDescriptor }) return emptyList()
val result = SmartList<FunctionDescriptor>() val result = SmartList<FunctionDescriptor>()
@@ -45,23 +51,6 @@ sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpre
return result 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? { private fun renameByPropertyName(newName: String): PsiElement? {
val nameIdentifier = KtPsiFactory(expression).createNameIdentifier(newName) val nameIdentifier = KtPsiFactory(expression).createNameIdentifier(newName)
expression.getReferencedNameElement().replace(nameIdentifier) expression.getReferencedNameElement().replace(nameIdentifier)
@@ -183,7 +172,4 @@ sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpre
override val resolvesByNames: Collection<Name> override val resolvesByNames: Collection<Name>
get() = listOf(element.getReferencedNameAsName()) get() = listOf(element.getReferencedNameAsName())
class Getter(expression: KtNameReferenceExpression) : SyntheticPropertyAccessorReference(expression, true)
class Setter(expression: KtNameReferenceExpression) : SyntheticPropertyAccessorReference(expression, false)
} }
@@ -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. * 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<out KtExpression>.renameImplicitConventionalCall(newName
return newExpression return newExpression
} }
val KtSimpleNameExpression.mainReference: KtSimpleNameReference val KtSimpleNameExpression.mainReference: KtSimpleNameReferenceDescriptorsImpl
get() = references.firstIsInstance() get() = references.firstIsInstance()
val KtReferenceExpression.mainReference: KtReference val KtReferenceExpression.mainReference: KtDescriptorsBasedReference
get() = if (this is KtSimpleNameExpression) mainReference else references.firstIsInstance<KtReference>() get() = if (this is KtSimpleNameExpression) mainReference else references.firstIsInstance<KtDescriptorsBasedReference>()
val KDocName.mainReference: KDocReference val KDocName.mainReference: KDocReference
get() = references.firstIsInstance() get() = references.firstIsInstance()
val KtElement.mainReference: KtReference? val KtElement.mainReference: KtDescriptorsBasedReference?
get() = when (this) { get() = when (this) {
is KtReferenceExpression -> mainReference is KtReferenceExpression -> mainReference
is KDocName -> mainReference is KDocName -> mainReference
else -> references.firstIsInstanceOrNull<KtReference>() else -> references.firstIsInstanceOrNull<KtDescriptorsBasedReference>()
} }
fun KtElement.resolveMainReferenceToDescriptors(): Collection<DeclarationDescriptor> { fun KtElement.resolveMainReferenceToDescriptors(): Collection<DeclarationDescriptor> {
@@ -248,46 +248,6 @@ fun PsiReference.getImportAlias(): KtImportAlias? {
// ----------- Read/write access ----------------------------------------------------------------------------------------------------------------------- // ----------- 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<ReferenceAccess, KtExpression> {
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 { fun KtReference.canBeResolvedViaImport(target: DeclarationDescriptor, bindingContext: BindingContext): Boolean {
if (this is KDocReference) { if (this is KDocReference) {
val qualifier = element.getQualifier() ?: return true val qualifier = element.getQualifier() ?: return true
+1
View File
@@ -16,6 +16,7 @@ dependencies {
compile(project(":compiler:util")) compile(project(":compiler:util"))
compile(project(":idea:ide-common")) compile(project(":idea:ide-common"))
compile(project(":idea:idea-jps-common")) compile(project(":idea:idea-jps-common"))
compile(project(":idea:idea-frontend-independent"))
compile(project(":kotlin-util-klib-metadata")) compile(project(":kotlin-util-klib-metadata"))
compile(project(":plugins:android-extensions-compiler")) compile(project(":plugins:android-extensions-compiler"))
compile(project(":kotlin-scripting-compiler-impl")) compile(project(":kotlin-scripting-compiler-impl"))
@@ -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. * 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) return canChangeTypeToSubtype && expressionType.isSubtypeOf(declaredType)
} }
fun String.unquote(): String = KtPsiUtil.unquoteIdentifier(this)
fun FqName.quoteSegmentsIfNeeded(): String { fun FqName.quoteSegmentsIfNeeded(): String {
return pathSegments().joinToString(".") { it.asString().quoteIfNeeded() } return pathSegments().joinToString(".") { it.asString().quoteIfNeeded() }
} }
@@ -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. * 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.KotlinExceptionWithAttachments
import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.SmartList
inline fun <reified T : PsiElement> PsiElement.replaced(newElement: T): T {
val result = replace(newElement)
return result as? T ?: (result as KtParenthesizedExpression).expression as T
}
@Suppress("UNCHECKED_CAST")
fun <T : PsiElement> T.copied(): T = copy() as T
fun KtLambdaArgument.moveInsideParentheses(bindingContext: BindingContext): KtCallExpression { fun KtLambdaArgument.moveInsideParentheses(bindingContext: BindingContext): KtCallExpression {
val ktExpression = this.getArgumentExpression() val ktExpression = this.getArgumentExpression()
?: throw KotlinExceptionWithAttachments("no argument expression for $this") ?: throw KotlinExceptionWithAttachments("no argument expression for $this")
@@ -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
}
@@ -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 <reified T : PsiElement> 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 : PsiElement> T.copied(): T = copy() as T
fun String.unquote(): String = KtPsiUtil.unquoteIdentifier(this)
@@ -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. * 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.google.common.collect.Lists
import com.intellij.psi.MultiRangeReference import com.intellij.psi.MultiRangeReference
import com.intellij.psi.PsiElement 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.idea.core.replaced
import org.jetbrains.kotlin.lexer.KtToken import org.jetbrains.kotlin.lexer.KtToken
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtArrayAccessExpression import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.KtQualifiedExpression
import org.jetbrains.kotlin.psi.buildExpression
import org.jetbrains.kotlin.psi.psiUtil.getPossiblyQualifiedCallExpression 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 import org.jetbrains.kotlin.util.OperatorNameConventions
class KtArrayAccessReference( abstract class KtArrayAccessReference(
expression: KtArrayAccessExpression expression: KtArrayAccessExpression
) : KtSimpleReference<KtArrayAccessExpression>(expression), MultiRangeReference { ) : KtSimpleReference<KtArrayAccessExpression>(expression), MultiRangeReference {
override val resolvesByNames: Collection<Name> override val resolvesByNames: Collection<Name>
@@ -33,12 +24,6 @@ class KtArrayAccessReference(
override fun getRangeInElement() = element.textRange.shiftRight(-element.textOffset) override fun getRangeInElement() = element.textRange.shiftRight(-element.textOffset)
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
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) = private fun getBracketRange(bracketToken: KtToken) =
expression.indicesNode.node.findChildByType(bracketToken)?.textRange?.shiftRight(-expression.textOffset) expression.indicesNode.node.findChildByType(bracketToken)?.textRange?.shiftRight(-expression.textOffset)
@@ -65,15 +50,19 @@ class KtArrayAccessReference(
} }
val fullCallExpression = arrayAccessExpression.replaced(replacement) val fullCallExpression = arrayAccessExpression.replaced(replacement)
val callExpression = fullCallExpression.getPossiblyQualifiedCallExpression() val callExpression = fullCallExpression.getPossiblyQualifiedCallExpression()
if (callExpression != null && callExpression.canMoveLambdaOutsideParentheses()) { if (callExpression != null && canMoveLambdaOutsideParentheses(callExpression)) {
callExpression.moveFunctionLiteralOutsideParentheses() moveFunctionLiteralOutsideParentheses(callExpression)
} }
return fullCallExpression 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 { companion object {
private val NAMES = Lists.newArrayList(OperatorNameConventions.GET, OperatorNameConventions.SET) private val NAMES = Lists.newArrayList(OperatorNameConventions.GET, OperatorNameConventions.SET)
} }
@@ -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. * 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.openapi.util.TextRange
import com.intellij.psi.MultiRangeReference import com.intellij.psi.MultiRangeReference
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtCollectionLiteralExpression import org.jetbrains.kotlin.psi.KtCollectionLiteralExpression
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.ArrayFqNames
import org.jetbrains.kotlin.resolve.CollectionLiteralResolver
class KtCollectionLiteralReference(expression: KtCollectionLiteralExpression) : abstract class KtCollectionLiteralReference(expression: KtCollectionLiteralExpression) :
KtSimpleReference<KtCollectionLiteralExpression>(expression), MultiRangeReference { KtSimpleReference<KtCollectionLiteralExpression>(expression), MultiRangeReference {
companion object { companion object {
private val COLLECTION_LITERAL_CALL_NAMES = private val COLLECTION_LITERAL_CALL_NAMES = ArrayFqNames.PRIMITIVE_TYPE_TO_ARRAY.values + ArrayFqNames.ARRAY_OF_FUNCTION
CollectionLiteralResolver.PRIMITIVE_TYPE_TO_ARRAY.values + CollectionLiteralResolver.ARRAY_OF_FUNCTION
} }
override fun getRangeInElement(): TextRange = element.normalizeRange() override fun getRangeInElement(): TextRange = element.normalizeRange()
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
val resolvedCall = context[BindingContext.COLLECTION_LITERAL_CALL, element]
return listOfNotNull(resolvedCall?.resultingDescriptor)
}
override fun getRanges(): List<TextRange> { override fun getRanges(): List<TextRange> {
return listOfNotNull(element.leftBracket?.normalizeRange(), element.rightBracket?.normalizeRange()) return listOfNotNull(element.leftBracket?.normalizeRange(), element.rightBracket?.normalizeRange())
} }
@@ -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<KtConstructorDelegationReferenceExpression>(expression) {
override fun getRangeInElement(): TextRange {
return TextRange(0, element.textLength)
}
override val resolvesByNames: Collection<Name>
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
}
}
@@ -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<KtDestructuringDeclarationEntry>(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<Name>
get() {
val destructuringParent = element.parent as? KtDestructuringDeclaration ?: return emptyList()
val componentIndex = destructuringParent.entries.indexOf(element) + 1
return listOf(Name.identifier("component$componentIndex"))
}
}
@@ -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<KtForExpression>(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<Name>
get() = NAMES
companion object {
private val NAMES = listOf(
OperatorNameConventions.ITERATOR,
OperatorNameConventions.NEXT,
OperatorNameConventions.HAS_NEXT
)
}
}
@@ -1,10 +1,11 @@
/* /*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* that can be found in the license/LICENSE.txt file. * 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 package org.jetbrains.kotlin.idea.references
import com.intellij.openapi.components.service
import com.intellij.openapi.project.IndexNotReadyException import com.intellij.openapi.project.IndexNotReadyException
import com.intellij.psi.ContributedReferenceHost import com.intellij.psi.ContributedReferenceHost
import com.intellij.psi.PsiElement 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.psi.KtElement
import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.SmartList
internal interface KotlinPsiReferenceProvider { interface KotlinPsiReferenceProvider {
fun getReferencesByElement(element: PsiElement): Array<PsiReference> fun getReferencesByElement(element: PsiElement): Array<PsiReference>
} }
internal interface KotlinReferenceProviderContributor { interface KotlinReferenceProviderContributor {
fun registerReferenceProviders(registrar: KotlinPsiReferenceRegistrar) fun registerReferenceProviders(registrar: KotlinPsiReferenceRegistrar)
companion object {
fun getInstance(): KotlinReferenceProviderContributor = service()
}
} }
internal class KotlinPsiReferenceRegistrar {
class KotlinPsiReferenceRegistrar {
val providers: MultiMap<Class<out PsiElement>, KotlinPsiReferenceProvider> = MultiMap.create() val providers: MultiMap<Class<out PsiElement>, KotlinPsiReferenceProvider> = MultiMap.create()
inline fun <reified E : KtElement> registerProvider(crossinline factory: (E) -> PsiReference?) { inline fun <reified E : KtElement> registerProvider(crossinline factory: (E) -> PsiReference?) {
@@ -38,10 +44,9 @@ internal class KotlinPsiReferenceRegistrar {
} }
} }
inline fun <reified E : KtElement> registerMultiProvider(crossinline factory: (E) -> Array<PsiReference>) { inline fun <reified E : KtElement> registerMultiProvider(crossinline factory: (E) -> Array<PsiReference>) {
val provider: KotlinPsiReferenceProvider = object : KotlinPsiReferenceProvider { val provider: KotlinPsiReferenceProvider = object : KotlinPsiReferenceProvider {
override fun getReferencesByElement(element: PsiElement): Array<PsiReference> { override fun getReferencesByElement(element: PsiElement): Array<PsiReference> {
@Suppress("UNCHECKED_CAST")
return factory(element as E) return factory(element as E)
} }
} }
@@ -58,15 +63,13 @@ class KtIdeReferenceProviderService : KotlinReferenceProvidersService() {
private val originalProvidersBinding: MultiMap<Class<out PsiElement>, KotlinPsiReferenceProvider> private val originalProvidersBinding: MultiMap<Class<out PsiElement>, KotlinPsiReferenceProvider>
private val providersBindingCache: Map<Class<out PsiElement>, List<KotlinPsiReferenceProvider>> private val providersBindingCache: Map<Class<out PsiElement>, List<KotlinPsiReferenceProvider>>
private val referenceContributors = listOf(KotlinReferenceContributor(), KotlinDefaultAnnotationMethodImplicitReferenceContributor())
init { init {
val registrar = KotlinPsiReferenceRegistrar() val registrar = KotlinPsiReferenceRegistrar()
referenceContributors.forEach { it.registerReferenceProviders(registrar) } KotlinReferenceProviderContributor.getInstance().registerReferenceProviders(registrar)
originalProvidersBinding = registrar.providers originalProvidersBinding = registrar.providers
providersBindingCache = ConcurrentFactoryMap.createMap<Class<out PsiElement>, List<KotlinPsiReferenceProvider>> { klass -> providersBindingCache = ConcurrentFactoryMap.createMap<Class<out PsiElement>, List<KotlinPsiReferenceProvider>> { klass ->
val result = ContainerUtil.newSmartList<KotlinPsiReferenceProvider>() val result = SmartList<KotlinPsiReferenceProvider>()
for (bindingClass in originalProvidersBinding.keySet()) { for (bindingClass in originalProvidersBinding.keySet()) {
if (bindingClass.isAssignableFrom(klass)) { if (bindingClass.isAssignableFrom(klass)) {
result.addAll(originalProvidersBinding.get(bindingClass)) result.addAll(originalProvidersBinding.get(bindingClass))
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* 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 package org.jetbrains.kotlin.idea.references
@@ -20,40 +9,20 @@ import com.intellij.lang.ASTNode
import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.TextRange
import com.intellij.psi.MultiRangeReference import com.intellij.psi.MultiRangeReference
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis 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 org.jetbrains.kotlin.util.OperatorNameConventions
import java.util.* import java.util.*
class KtInvokeFunctionReference(expression: KtCallExpression) : KtSimpleReference<KtCallExpression>(expression), MultiRangeReference { abstract class KtInvokeFunctionReference(expression: KtCallExpression) : KtSimpleReference<KtCallExpression>(expression), MultiRangeReference {
override val resolvesByNames: Collection<Name> get() = NAMES
override val resolvesByNames: Collection<Name>
get() = NAMES
override fun getRangeInElement(): TextRange { override fun getRangeInElement(): TextRange {
return element.textRange.shiftRight(-element.textOffset) return element.textRange.shiftRight(-element.textOffset)
} }
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
val call = element.getCall(context)
val resolvedCall = call.getResolvedCall(context)
return when {
resolvedCall is VariableAsFunctionResolvedCall ->
setOf<DeclarationDescriptor>((resolvedCall as VariableAsFunctionResolvedCall).functionCall.candidateDescriptor)
call != null && resolvedCall != null && call.callType == Call.CallType.INVOKE ->
setOf<DeclarationDescriptor>(resolvedCall.candidateDescriptor)
else ->
emptyList()
}
}
override fun getRanges(): List<TextRange> { override fun getRanges(): List<TextRange> {
val list = ArrayList<TextRange>() val list = ArrayList<TextRange>()
val valueArgumentList = expression.valueArgumentList val valueArgumentList = expression.valueArgumentList
@@ -111,11 +80,12 @@ class KtInvokeFunctionReference(expression: KtCallExpression) : KtSimpleReferenc
return fullCallExpression.replace(arrayAccessExpression) 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) private val NAMES = listOf(OperatorNameConventions.INVOKE)
} }
} }
@@ -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<KtPropertyDelegate>(element) {
override fun getRangeInElement(): TextRange {
val byKeywordNode = expression.byKeywordNode
val offset = byKeywordNode.psi!!.startOffsetInParent
return TextRange(offset, offset + byKeywordNode.textLength)
}
override val resolvesByNames: Collection<Name> get() = NAMES
companion object {
private val NAMES = listOf(
OperatorNameConventions.GET_VALUE,
OperatorNameConventions.SET_VALUE,
OperatorNameConventions.PROVIDE_DELEGATE
)
}
}
@@ -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<KtReference>
override fun getElement(): KtElement
val resolvesByNames: Collection<Name>
}
abstract class AbstractKtReference<T : KtElement>(element: T) : PsiPolyVariantReferenceBase<T>(element), KtReference {
val expression: T
get() = element
override fun multiResolve(incompleteCode: Boolean): Array<ResolveResult> =
ResolveCache.getInstance(expression.project).resolveWithCaching(this, resolver, false, incompleteCode)
override fun getCanonicalText(): String = "<TBD>"
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<Any> = PsiReference.EMPTY_ARRAY as Array<Any>
override fun isSoft(): Boolean = false
override fun toString() = this::class.java.simpleName + ": " + expression.text
}
abstract class KtSimpleReference<T : KtReferenceExpression>(expression: T) : AbstractKtReference<T>(expression)
abstract class KtMultiReference<T : KtElement>(expression: T) : AbstractKtReference<T>(expression)
@@ -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<KtSimpleNameExpression>(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<KtWhenConditionInRange>(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<Name>
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?
}
@@ -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<ReferenceAccess, KtExpression>? = null
fun readWriteAccessWithFullExpression(
targetExpression: KtExpression,
useResolveForReadWrite: Boolean
): Pair<ReferenceAccess, KtExpression> {
var expression = targetExpression.getQualifiedExpressionForSelectorOrThis()
loop@ while (true) {
when (val parent = expression.parent) {
is KtParenthesizedExpression, is KtAnnotatedExpression, is KtLabeledExpression -> expression = parent as KtExpression
else -> break@loop
}
}
val assignment = expression.getAssignmentByLHS()
if (assignment != null) {
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<ReferenceAccess, KtExpression> =
ReadWriteAccessChecker.getInstance().readWriteAccessWithFullExpression(this, useResolveForReadWrite)
@@ -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<KtNameReferenceExpression>(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<Name>
get() = listOf(element.getReferencedNameAsName())
}
@@ -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. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@@ -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. * 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.patterns.KotlinFunctionPattern
import org.jetbrains.kotlin.idea.references.KtReference import org.jetbrains.kotlin.idea.references.KtReference
import org.jetbrains.kotlin.idea.references.mainReference 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.search.usagesSearch.descriptor
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
@@ -171,6 +171,12 @@
<applicationService serviceInterface="org.jetbrains.kotlin.idea.caches.FileAttributeService" <applicationService serviceInterface="org.jetbrains.kotlin.idea.caches.FileAttributeService"
serviceImplementation="org.jetbrains.kotlin.idea.caches.FileAttributeServiceImpl"/> serviceImplementation="org.jetbrains.kotlin.idea.caches.FileAttributeServiceImpl"/>
<applicationService serviceInterface="org.jetbrains.kotlin.idea.references.ReadWriteAccessChecker"
serviceImplementation="org.jetbrains.kotlin.idea.references.ReadWriteAccessCheckerDescriptorsImpl"/>
<applicationService serviceInterface="org.jetbrains.kotlin.idea.references.KotlinReferenceProviderContributor"
serviceImplementation="org.jetbrains.kotlin.idea.references.KotlinReferenceContributor"/>
<applicationService serviceImplementation="org.jetbrains.kotlin.idea.KotlinPluginUpdater"/> <applicationService serviceImplementation="org.jetbrains.kotlin.idea.KotlinPluginUpdater"/>
<applicationService serviceInterface="org.jetbrains.kotlin.psi.KotlinDeclarationNavigationPolicy" <applicationService serviceInterface="org.jetbrains.kotlin.psi.KotlinDeclarationNavigationPolicy"
@@ -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. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@@ -20,10 +20,7 @@ import org.jetbrains.kotlin.idea.caches.project.getNullableModuleInfo
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings
import org.jetbrains.kotlin.idea.references.KtInvokeFunctionReference import org.jetbrains.kotlin.idea.references.*
import org.jetbrains.kotlin.idea.references.KtReference
import org.jetbrains.kotlin.idea.references.canBeResolvedViaImport
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.util.getResolutionScope import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* 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.intentions package org.jetbrains.kotlin.idea.intentions
@@ -35,8 +24,8 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClass import org.jetbrains.kotlin.psi.psiUtil.containingClass
import org.jetbrains.kotlin.psi.psiUtil.getCallNameExpression import org.jetbrains.kotlin.psi.psiUtil.getCallNameExpression
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.ArrayFqNames
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.CollectionLiteralResolver
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
@@ -294,8 +283,8 @@ fun KtDotQualifiedExpression.deleteFirstReceiver(): KtExpression {
return this return this
} }
private val ARRAY_OF_METHODS = setOf(CollectionLiteralResolver.ARRAY_OF_FUNCTION) + private val ARRAY_OF_METHODS = setOf(ArrayFqNames.ARRAY_OF_FUNCTION) +
CollectionLiteralResolver.PRIMITIVE_TYPE_TO_ARRAY.values.toSet() + ArrayFqNames.PRIMITIVE_TYPE_TO_ARRAY.values.toSet() +
Name.identifier("emptyArray") Name.identifier("emptyArray")
fun KtCallExpression.isArrayOfMethod(): Boolean { fun KtCallExpression.isArrayOfMethod(): Boolean {
@@ -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. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@@ -14,8 +14,7 @@ import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.resolve.CollectionLiteralResolver.Companion.ARRAY_OF_FUNCTION import org.jetbrains.kotlin.resolve.ArrayFqNames
import org.jetbrains.kotlin.resolve.CollectionLiteralResolver.Companion.PRIMITIVE_TYPE_TO_ARRAY
class SurroundWithArrayOfWithSpreadOperatorInFunctionFix( class SurroundWithArrayOfWithSpreadOperatorInFunctionFix(
val wrapper: Name, val wrapper: Name,
@@ -52,7 +51,7 @@ class SurroundWithArrayOfWithSpreadOperatorInFunctionFix(
val parameterType = actualDiagnostic.a val parameterType = actualDiagnostic.a
val wrapper = PRIMITIVE_TYPE_TO_ARRAY[KotlinBuiltIns.getPrimitiveArrayElementType(parameterType)] ?: ARRAY_OF_FUNCTION val wrapper = ArrayFqNames.PRIMITIVE_TYPE_TO_ARRAY[KotlinBuiltIns.getPrimitiveArrayElementType(parameterType)] ?: ArrayFqNames.ARRAY_OF_FUNCTION
return SurroundWithArrayOfWithSpreadOperatorInFunctionFix(wrapper, actualDiagnostic.psiElement) return SurroundWithArrayOfWithSpreadOperatorInFunctionFix(wrapper, actualDiagnostic.psiElement)
} }
} }
@@ -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. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.idea.core.setDefaultValue
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.KotlinCallableDefinitionUsage import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.KotlinCallableDefinitionUsage
import org.jetbrains.kotlin.idea.references.KtReference import org.jetbrains.kotlin.idea.references.KtReference
import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.references.resolveToDescriptors
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.addRemoveModifier.setModifierList import org.jetbrains.kotlin.psi.addRemoveModifier.setModifierList
import org.jetbrains.kotlin.psi.psiUtil.quoteIfNeeded import org.jetbrains.kotlin.psi.psiUtil.quoteIfNeeded
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* 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.refactoring.pullUp package org.jetbrains.kotlin.idea.refactoring.pullUp
@@ -33,6 +22,7 @@ import org.jetbrains.kotlin.idea.refactoring.memberInfo.getChildrenToAnalyze
import org.jetbrains.kotlin.idea.refactoring.memberInfo.resolveToDescriptorWrapperAware import org.jetbrains.kotlin.idea.refactoring.memberInfo.resolveToDescriptorWrapperAware
import org.jetbrains.kotlin.idea.references.KtReference import org.jetbrains.kotlin.idea.references.KtReference
import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.references.resolveToDescriptors
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest
import org.jetbrains.kotlin.idea.search.declarationsSearch.searchInheritors import org.jetbrains.kotlin.idea.search.declarationsSearch.searchInheritors
@@ -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. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.idea.refactoring.memberInfo.KtPsiClassWrapper
import org.jetbrains.kotlin.idea.refactoring.pullUp.renderForConflicts import org.jetbrains.kotlin.idea.refactoring.pullUp.renderForConflicts
import org.jetbrains.kotlin.idea.references.KtReference import org.jetbrains.kotlin.idea.references.KtReference
import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.references.resolveToDescriptors
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-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. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@@ -13,9 +13,11 @@ import com.intellij.psi.search.SearchScope
import com.intellij.refactoring.rename.RenameJavaMethodProcessor import com.intellij.refactoring.rename.RenameJavaMethodProcessor
import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.idea.references.SyntheticPropertyAccessorReference import org.jetbrains.kotlin.idea.references.SyntheticPropertyAccessorReference
import org.jetbrains.kotlin.idea.references.SyntheticPropertyAccessorReferenceDescriptorImpl
import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
import org.jetbrains.kotlin.utils.addToStdlib.filterIsInstanceWithChecker
import org.jetbrains.kotlin.utils.ifEmpty import org.jetbrains.kotlin.utils.ifEmpty
class KotlinAwareJavaGetterRenameProcessor : RenameJavaMethodProcessor() { class KotlinAwareJavaGetterRenameProcessor : RenameJavaMethodProcessor() {
@@ -38,12 +40,12 @@ class KotlinAwareJavaGetterRenameProcessor : RenameJavaMethodProcessor() {
.filter { it.parameters.size == 1 && it.returnType == PsiType.VOID } .filter { it.parameters.size == 1 && it.returnType == PsiType.VOID }
.flatMap { .flatMap {
super.findReferences(it, searchScope, searchInCommentsAndStrings) super.findReferences(it, searchScope, searchInCommentsAndStrings)
.filterIsInstance<SyntheticPropertyAccessorReference.Setter>() .filterIsInstanceWithChecker<SyntheticPropertyAccessorReference> { !it.getter }
} }
.ifEmpty { return getterReferences } .ifEmpty { return getterReferences }
return ArrayList<PsiReference>(getterReferences.size + setterReferences.size).apply { return ArrayList<PsiReference>(getterReferences.size + setterReferences.size).apply {
addAll(getterReferences) addAll(getterReferences)
setterReferences.mapTo(this) { SyntheticPropertyAccessorReference.Getter(it.expression) } setterReferences.mapTo(this) { SyntheticPropertyAccessorReferenceDescriptorImpl(it.expression, getter = true) }
} }
} }
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* 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.search.ideaExtensions package org.jetbrains.kotlin.idea.search.ideaExtensions
@@ -94,7 +83,7 @@ class KotlinOverridingMethodReferenceSearcher : MethodUsagesSearcher() {
return readWriteAccess.isRead != isGetter && readWriteAccess.isWrite == isGetter return readWriteAccess.isRead != isGetter && readWriteAccess.isWrite == isGetter
} }
if (ref is SyntheticPropertyAccessorReference) { if (ref is SyntheticPropertyAccessorReference) {
return (ref is SyntheticPropertyAccessorReference.Getter) != isGetter return ref.getter != isGetter
} }
return false return false
} }
@@ -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. * 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.toArgumentList
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.types.* import org.jetbrains.kotlin.nj2k.types.*
import org.jetbrains.kotlin.resolve.ArrayFqNames
import org.jetbrains.kotlin.resolve.CollectionLiteralResolver
class ArrayInitializerConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) { class ArrayInitializerConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) {
override fun applyToElement(element: JKTreeElement): JKTreeElement { override fun applyToElement(element: JKTreeElement): JKTreeElement {
@@ -23,9 +21,9 @@ class ArrayInitializerConversion(context: NewJ2kConverterContext) : RecursiveApp
val primitiveArrayType = element.type.type as? JKJavaPrimitiveType val primitiveArrayType = element.type.type as? JKJavaPrimitiveType
val arrayConstructorName = val arrayConstructorName =
if (primitiveArrayType != null) 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 else
CollectionLiteralResolver.ARRAY_OF_FUNCTION.asString() ArrayFqNames.ARRAY_OF_FUNCTION.asString()
val typeArguments = val typeArguments =
if (primitiveArrayType == null) JKTypeArgumentList(listOf(element::type.detached())) if (primitiveArrayType == null) JKTypeArgumentList(listOf(element::type.detached()))
else JKTypeArgumentList() else JKTypeArgumentList()
+1
View File
@@ -93,6 +93,7 @@ val projectsToShadow by extra(listOf(
":idea:idea-jvm", ":idea:idea-jvm",
":idea:idea-git", ":idea:idea-git",
":idea:idea-jps-common", ":idea:idea-jps-common",
":idea:idea-frontend-independent",
*if (Ide.IJ()) *if (Ide.IJ())
arrayOf( arrayOf(
":idea:idea-maven", ":idea:idea-maven",
+1
View File
@@ -183,6 +183,7 @@ include ":kotlin-build-common",
":idea:jvm-debugger:jvm-debugger-coroutine", ":idea:jvm-debugger:jvm-debugger-coroutine",
":idea:jvm-debugger:jvm-debugger-test", ":idea:jvm-debugger:jvm-debugger-test",
":idea:scripting-support", ":idea:scripting-support",
":idea:idea-frontend-independent",
":libraries:tools:new-project-wizard", ":libraries:tools:new-project-wizard",
":idea:idea-new-project-wizard", ":idea:idea-new-project-wizard",
":libraries:tools:new-project-wizard:new-project-wizard-cli", ":libraries:tools:new-project-wizard:new-project-wizard-cli",