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.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.resolve
@@ -44,21 +33,6 @@ class CollectionLiteralResolver(
val callResolver: CallResolver,
val languageVersionSettings: LanguageVersionSettings
) {
companion object {
val PRIMITIVE_TYPE_TO_ARRAY: Map<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(
collectionLiteralExpression: KtCollectionLiteralExpression,
context: ExpressionTypingContext
@@ -120,11 +94,11 @@ class CollectionLiteralResolver(
private fun getArrayFunctionCallName(expectedType: KotlinType): Name {
if (NO_EXPECTED_TYPE === expectedType || !KotlinBuiltIns.isPrimitiveArray(expectedType)) {
return ARRAY_OF_FUNCTION
return ArrayFqNames.ARRAY_OF_FUNCTION
}
val descriptor = expectedType.constructor.declarationDescriptor ?: return ARRAY_OF_FUNCTION
val descriptor = expectedType.constructor.declarationDescriptor ?: return ArrayFqNames.ARRAY_OF_FUNCTION
return PRIMITIVE_TYPE_TO_ARRAY[KotlinBuiltIns.getPrimitiveArrayType(descriptor)] ?: ARRAY_OF_FUNCTION
return ArrayFqNames.PRIMITIVE_TYPE_TO_ARRAY[KotlinBuiltIns.getPrimitiveArrayType(descriptor)] ?: ArrayFqNames.ARRAY_OF_FUNCTION
}
}
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.utils.addToStdlib
@@ -50,6 +39,17 @@ inline fun <reified T> Array<*>.firstIsInstance(): T {
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? {
when (this) {
is List<*> -> {
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.kdoc
@@ -20,6 +9,7 @@ import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.references.KtDescriptorsBasedReference
import org.jetbrains.kotlin.idea.references.KtMultiReference
import org.jetbrains.kotlin.kdoc.psi.impl.KDocLink
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName
@@ -28,7 +18,11 @@ import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
class KDocReference(element: KDocName) : KtMultiReference<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> {
val declaration = element.getContainingDoc().getOwner() ?: return arrayListOf()
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.
*/
@@ -66,14 +66,10 @@ class ReferenceImpl(private val argument: KtValueArgument) : PsiReference {
override fun isSoft() = false
}
internal class KotlinDefaultAnnotationMethodImplicitReferenceContributor : KotlinReferenceProviderContributor {
override fun registerReferenceProviders(registrar: KotlinPsiReferenceRegistrar) {
registrar.registerProvider<KtValueArgument> {
if (it.isNamed()) return@registerProvider null
val annotationEntry = it.getParentOfTypeAndBranch<KtAnnotationEntry> { valueArgumentList } ?: return@registerProvider null
if (annotationEntry.valueArguments.size != 1) return@registerProvider null
internal val KotlinDefaultAnnotationMethodImplicitReferenceProvider = provider@{ element: KtValueArgument ->
if (element.isNamed()) return@provider null
val annotationEntry = element.getParentOfTypeAndBranch<KtAnnotationEntry> { valueArgumentList } ?: return@provider null
if (annotationEntry.valueArguments.size != 1) return@provider null
ReferenceImpl(it)
}
}
}
ReferenceImpl(element)
}
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.references
@@ -24,10 +13,10 @@ import org.jetbrains.kotlin.psi.KtPackageDirective
import org.jetbrains.kotlin.psi.KtUserType
import org.jetbrains.kotlin.psi.psiUtil.parents
internal class KotlinReferenceContributor : KotlinReferenceProviderContributor {
class KotlinReferenceContributor : KotlinReferenceProviderContributor {
override fun registerReferenceProviders(registrar: KotlinPsiReferenceRegistrar) {
with(registrar) {
registerProvider(factory = ::KtSimpleNameReference)
registerProvider(factory = ::KtSimpleNameReferenceDescriptorsImpl)
registerMultiProvider<KtNameReferenceExpression> { nameReferenceExpression ->
if (nameReferenceExpression.getReferencedNameElementType() != KtTokens.IDENTIFIER) return@registerMultiProvider emptyArray()
@@ -37,32 +26,34 @@ internal class KotlinReferenceContributor : KotlinReferenceProviderContributor {
when (nameReferenceExpression.readWriteAccess(useResolveForReadWrite = false)) {
ReferenceAccess.READ ->
arrayOf(SyntheticPropertyAccessorReference.Getter(nameReferenceExpression))
arrayOf(SyntheticPropertyAccessorReferenceDescriptorImpl(nameReferenceExpression, getter = true))
ReferenceAccess.WRITE ->
arrayOf(SyntheticPropertyAccessorReference.Setter(nameReferenceExpression))
arrayOf(SyntheticPropertyAccessorReferenceDescriptorImpl(nameReferenceExpression, getter = false))
ReferenceAccess.READ_WRITE ->
arrayOf(
SyntheticPropertyAccessorReference.Getter(nameReferenceExpression),
SyntheticPropertyAccessorReference.Setter(nameReferenceExpression)
SyntheticPropertyAccessorReferenceDescriptorImpl(nameReferenceExpression, getter = true),
SyntheticPropertyAccessorReferenceDescriptorImpl(nameReferenceExpression, getter = false)
)
}
}
registerProvider(factory = ::KtConstructorDelegationReference)
registerProvider(factory = ::KtConstructorDelegationReferenceDescriptorsImpl)
registerProvider(factory = ::KtInvokeFunctionReference)
registerProvider(factory = ::KtInvokeFunctionReferenceDescriptorsImpl)
registerProvider(factory = ::KtArrayAccessReference)
registerProvider(factory = ::KtArrayAccessReferenceDescriptorsImpl)
registerProvider(factory = ::KtCollectionLiteralReference)
registerProvider(factory = ::KtCollectionLiteralReferenceDescriptorsImpl)
registerProvider(factory = ::KtForLoopInReference)
registerProvider(factory = ::KtForLoopInReferenceDescriptorsImpl)
registerProvider(factory = ::KtPropertyDelegationMethodsReference)
registerProvider(factory = ::KtPropertyDelegationMethodsReferenceDescriptorsImpl)
registerProvider(factory = ::KtDestructuringDeclarationReference)
registerProvider(factory = ::KtDestructuringDeclarationReferenceDescriptorsImpl)
registerProvider(factory = ::KDocReference)
registerProvider(KotlinDefaultAnnotationMethodImplicitReferenceProvider)
}
}
}
@@ -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.
*/
@@ -16,8 +16,12 @@ import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry
import org.jetbrains.kotlin.resolve.BindingContext
class KtDestructuringDeclarationReference(element: KtDestructuringDeclarationEntry) :
AbstractKtReference<KtDestructuringDeclarationEntry>(element) {
class KtDestructuringDeclarationReferenceDescriptorsImpl(
element: KtDestructuringDeclarationEntry
) : KtDestructuringDeclarationReference(element), KtDescriptorsBasedReference {
override fun isReferenceTo(element: PsiElement): Boolean =
super<KtDescriptorsBasedReference>.isReferenceTo(element)
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
return listOfNotNull(context[BindingContext.COMPONENT_RESOLVED_CALL, element]?.candidateDescriptor)
}
@@ -30,16 +34,4 @@ class KtDestructuringDeclarationReference(element: KtDestructuringDeclarationEnt
it is CallableMemberDescriptor && it.kind == CallableMemberDescriptor.Kind.SYNTHESIZED
}
}
override fun handleElementRename(newElementName: String): PsiElement? {
if (canRename()) return expression
throw IncorrectOperationException()
}
override val resolvesByNames: Collection<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.
*/
package org.jetbrains.kotlin.idea.references
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.util.OperatorNameConventions
class KtForLoopInReference(element: KtForExpression) : KtMultiReference<KtForExpression>(element) {
override fun getRangeInElement(): TextRange {
val inKeyword = expression.inKeyword ?: return TextRange.EMPTY_RANGE
val offset = inKeyword.startOffsetInParent
return TextRange(offset, offset + inKeyword.textLength)
}
class KtForLoopInReferenceDescriptorsImpl(
element: KtForExpression
) : KtForLoopInReference(element), KtDescriptorsBasedReference {
override fun isReferenceTo(element: PsiElement): Boolean =
super<KtDescriptorsBasedReference>.isReferenceTo(element)
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
val loopRange = expression.loopRange ?: return emptyList()
return LOOP_RANGE_KEYS.mapNotNull { key -> context.get(key, loopRange)?.candidateDescriptor }
}
override val resolvesByNames: Collection<Name>
get() = NAMES
companion object {
private val LOOP_RANGE_KEYS = arrayOf(
BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL,
BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL,
BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL
)
private val NAMES = listOf(
OperatorNameConventions.ITERATOR,
OperatorNameConventions.NEXT,
OperatorNameConventions.HAS_NEXT
)
}
}
@@ -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.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.references
@@ -51,251 +40,83 @@ import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import java.util.*
interface KtReference : PsiPolyVariantReference {
fun resolveToDescriptors(bindingContext: BindingContext): Collection<DeclarationDescriptor>
interface KtDescriptorsBasedReference : KtReference {
override val resolver get() = KotlinDescriptorsBasedReferenceResolver
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> {
@Suppress("UNCHECKED_CAST")
val kotlinResolver = KOTLIN_RESOLVER as ResolveCache.PolyVariantResolver<AbstractKtReference<T>>
return ResolveCache.getInstance(expression.project).resolveWithCaching(this, kotlinResolver, false, incompleteCode)
fun resolveToDescriptors(bindingContext: BindingContext): Collection<DeclarationDescriptor> {
return getTargetDescriptors(bindingContext)
}
fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor>
override fun isReferenceTo(element: PsiElement): Boolean {
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) {
override fun getTargetDescriptors(context: BindingContext) = expression.getReferenceTargets(context)
fun KtReference.resolveToDescriptors(bindingContext: BindingContext): Collection<DeclarationDescriptor> {
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.
*/
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.references
import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiReference
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.util.IncorrectOperationException
import com.intellij.util.SmartList
@@ -33,15 +34,21 @@ import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DataClassDescriptorResolver
import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor
import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets
import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.expressions.OperatorConventions
class KtSimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleReference<KtSimpleNameExpression>(expression) {
class KtSimpleNameReferenceDescriptorsImpl(
expression: KtSimpleNameExpression
) : KtSimpleNameReference(expression), KtDescriptorsBasedReference {
override fun doCanBeReferenceTo(candidateTarget: PsiElement): Boolean =
canBeReferenceTo(candidateTarget)
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
return SmartList<DeclarationDescriptor>().apply {
// Replace Java property with its accessor(s)
for (descriptor in super.getTargetDescriptors(context)) {
for (descriptor in expression.getReferenceTargets(context)) {
val sizeBefore = size
if (descriptor !is JavaPropertyDescriptor) {
@@ -71,7 +78,7 @@ class KtSimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleRefere
if (extension.isReferenceTo(this, element)) return true
}
return super.isReferenceTo(element)
return super<KtDescriptorsBasedReference>.isReferenceTo(element)
}
override fun getRangeInElement(): TextRange {
@@ -141,23 +148,18 @@ class KtSimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleRefere
return expression
}
enum class ShorteningMode {
NO_SHORTENING,
DELAYED_SHORTENING,
FORCED_SHORTENING
}
// By default reference binding is delayed
override fun bindToElement(element: PsiElement): PsiElement =
bindToElement(element, ShorteningMode.DELAYED_SHORTENING)
fun bindToElement(element: PsiElement, shorteningMode: ShorteningMode): PsiElement =
override fun bindToElement(element: PsiElement, shorteningMode: ShorteningMode): PsiElement =
element.getKotlinFqName()?.let { fqName -> bindToFqName(fqName, shorteningMode, element) } ?: expression
fun bindToFqName(
override fun bindToFqName(
fqName: FqName,
shorteningMode: ShorteningMode = ShorteningMode.DELAYED_SHORTENING,
targetElement: PsiElement? = null
shorteningMode: ShorteningMode,
targetElement: PsiElement?
): PsiElement {
val expression = expression
if (fqName.isRoot) return expression
@@ -289,7 +291,7 @@ class KtSimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleRefere
return listOf(element.getReferencedNameAsName())
}
fun getImportAlias(): KtImportAlias? {
override fun getImportAlias(): KtImportAlias? {
fun DeclarationDescriptor.unwrap() = if (this is ImportedFromObjectCallableDescriptor<*>) callableFromObject else this
val element = element
@@ -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.
*/
package org.jetbrains.kotlin.idea.references
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.util.SmartList
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
@@ -22,14 +20,22 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.utils.addIfNotNull
sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpression, private val getter: Boolean) :
KtSimpleReference<KtNameReferenceExpression>(expression) {
class SyntheticPropertyAccessorReferenceDescriptorImpl(
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> {
val descriptors = super.getTargetDescriptors(context)
val descriptors = expression.getReferenceTargets(context)
if (descriptors.none { it is SyntheticJavaPropertyDescriptor }) return emptyList()
val result = SmartList<FunctionDescriptor>()
@@ -45,23 +51,6 @@ sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpre
return result
}
override fun isReferenceTo(element: PsiElement): Boolean {
if (element !is PsiMethod || !isAccessorName(element.name)) return false
if (!getter && expression.readWriteAccess(true) == ReferenceAccess.READ) return false
return super.isReferenceTo(element)
}
private fun isAccessorName(name: String): Boolean {
if (getter) {
return name.startsWith("get") || name.startsWith("is")
}
return name.startsWith("set")
}
override fun getRangeInElement() = TextRange(0, expression.textLength)
override fun canRename() = true
private fun renameByPropertyName(newName: String): PsiElement? {
val nameIdentifier = KtPsiFactory(expression).createNameIdentifier(newName)
expression.getReferencedNameElement().replace(nameIdentifier)
@@ -183,7 +172,4 @@ sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpre
override val resolvesByNames: Collection<Name>
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.
*/
@@ -221,20 +221,20 @@ fun AbstractKtReference<out KtExpression>.renameImplicitConventionalCall(newName
return newExpression
}
val KtSimpleNameExpression.mainReference: KtSimpleNameReference
val KtSimpleNameExpression.mainReference: KtSimpleNameReferenceDescriptorsImpl
get() = references.firstIsInstance()
val KtReferenceExpression.mainReference: KtReference
get() = if (this is KtSimpleNameExpression) mainReference else references.firstIsInstance<KtReference>()
val KtReferenceExpression.mainReference: KtDescriptorsBasedReference
get() = if (this is KtSimpleNameExpression) mainReference else references.firstIsInstance<KtDescriptorsBasedReference>()
val KDocName.mainReference: KDocReference
get() = references.firstIsInstance()
val KtElement.mainReference: KtReference?
val KtElement.mainReference: KtDescriptorsBasedReference?
get() = when (this) {
is KtReferenceExpression -> mainReference
is KDocName -> mainReference
else -> references.firstIsInstanceOrNull<KtReference>()
else -> references.firstIsInstanceOrNull<KtDescriptorsBasedReference>()
}
fun KtElement.resolveMainReferenceToDescriptors(): Collection<DeclarationDescriptor> {
@@ -248,46 +248,6 @@ fun PsiReference.getImportAlias(): KtImportAlias? {
// ----------- Read/write access -----------------------------------------------------------------------------------------------------------------------
enum class ReferenceAccess(val isRead: Boolean, val isWrite: Boolean) {
READ(true, false), WRITE(false, true), READ_WRITE(true, true)
}
fun KtExpression.readWriteAccess(useResolveForReadWrite: Boolean) = readWriteAccessWithFullExpression(useResolveForReadWrite).first
fun KtExpression.readWriteAccessWithFullExpression(useResolveForReadWrite: Boolean): Pair<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 {
if (this is KDocReference) {
val qualifier = element.getQualifier() ?: return true
+1
View File
@@ -16,6 +16,7 @@ dependencies {
compile(project(":compiler:util"))
compile(project(":idea:ide-common"))
compile(project(":idea:idea-jps-common"))
compile(project(":idea:idea-frontend-independent"))
compile(project(":kotlin-util-klib-metadata"))
compile(project(":plugins:android-extensions-compiler"))
compile(project(":kotlin-scripting-compiler-impl"))
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -158,8 +158,6 @@ fun KtCallableDeclaration.canOmitDeclaredType(initializerOrBodyExpression: KtExp
return canChangeTypeToSubtype && expressionType.isSubtypeOf(declaredType)
}
fun String.unquote(): String = KtPsiUtil.unquoteIdentifier(this)
fun FqName.quoteSegmentsIfNeeded(): String {
return pathSegments().joinToString(".") { it.asString().quoteIfNeeded() }
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -45,14 +45,6 @@ import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
import org.jetbrains.kotlin.utils.SmartList
inline fun <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 {
val ktExpression = this.getArgumentExpression()
?: 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.
*/
@@ -8,24 +8,15 @@ package org.jetbrains.kotlin.idea.references
import com.google.common.collect.Lists
import com.intellij.psi.MultiRangeReference
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.core.canMoveLambdaOutsideParentheses
import org.jetbrains.kotlin.idea.core.moveFunctionLiteralOutsideParentheses
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.lexer.KtToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.KtQualifiedExpression
import org.jetbrains.kotlin.psi.buildExpression
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getPossiblyQualifiedCallExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_GET
import org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_SET
import org.jetbrains.kotlin.util.OperatorNameConventions
class KtArrayAccessReference(
abstract class KtArrayAccessReference(
expression: KtArrayAccessExpression
) : KtSimpleReference<KtArrayAccessExpression>(expression), MultiRangeReference {
override val resolvesByNames: Collection<Name>
@@ -33,12 +24,6 @@ class KtArrayAccessReference(
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) =
expression.indicesNode.node.findChildByType(bracketToken)?.textRange?.shiftRight(-expression.textOffset)
@@ -65,15 +50,19 @@ class KtArrayAccessReference(
}
val fullCallExpression = arrayAccessExpression.replaced(replacement)
val callExpression = fullCallExpression.getPossiblyQualifiedCallExpression()
if (callExpression != null && callExpression.canMoveLambdaOutsideParentheses()) {
callExpression.moveFunctionLiteralOutsideParentheses()
if (callExpression != null && canMoveLambdaOutsideParentheses(callExpression)) {
moveFunctionLiteralOutsideParentheses(callExpression)
}
return fullCallExpression
}
return this.renameImplicitConventionalCall(newElementName)
return doRenameImplicitConventionalCall(newElementName)
}
protected abstract fun moveFunctionLiteralOutsideParentheses(callExpression: KtCallExpression)
protected abstract fun canMoveLambdaOutsideParentheses(callExpression: KtCallExpression): Boolean
protected abstract fun doRenameImplicitConventionalCall(newName: String?): KtExpression
companion object {
private val NAMES = Lists.newArrayList(OperatorNameConventions.GET, OperatorNameConventions.SET)
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -8,26 +8,18 @@ package org.jetbrains.kotlin.idea.references
import com.intellij.openapi.util.TextRange
import com.intellij.psi.MultiRangeReference
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtCollectionLiteralExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.CollectionLiteralResolver
import org.jetbrains.kotlin.resolve.ArrayFqNames
class KtCollectionLiteralReference(expression: KtCollectionLiteralExpression) :
abstract class KtCollectionLiteralReference(expression: KtCollectionLiteralExpression) :
KtSimpleReference<KtCollectionLiteralExpression>(expression), MultiRangeReference {
companion object {
private val COLLECTION_LITERAL_CALL_NAMES =
CollectionLiteralResolver.PRIMITIVE_TYPE_TO_ARRAY.values + CollectionLiteralResolver.ARRAY_OF_FUNCTION
private val COLLECTION_LITERAL_CALL_NAMES = ArrayFqNames.PRIMITIVE_TYPE_TO_ARRAY.values + ArrayFqNames.ARRAY_OF_FUNCTION
}
override fun getRangeInElement(): TextRange = element.normalizeRange()
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
val resolvedCall = context[BindingContext.COLLECTION_LITERAL_CALL, element]
return listOfNotNull(resolvedCall?.resultingDescriptor)
}
override fun getRanges(): List<TextRange> {
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
* that can be found in the license/LICENSE.txt file.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.references
import com.intellij.openapi.components.service
import com.intellij.openapi.project.IndexNotReadyException
import com.intellij.psi.ContributedReferenceHost
import com.intellij.psi.PsiElement
@@ -21,15 +22,20 @@ import org.jetbrains.kotlin.psi.KotlinReferenceProvidersService
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.utils.SmartList
internal interface KotlinPsiReferenceProvider {
interface KotlinPsiReferenceProvider {
fun getReferencesByElement(element: PsiElement): Array<PsiReference>
}
internal interface KotlinReferenceProviderContributor {
interface KotlinReferenceProviderContributor {
fun registerReferenceProviders(registrar: KotlinPsiReferenceRegistrar)
companion object {
fun getInstance(): KotlinReferenceProviderContributor = service()
}
}
internal class KotlinPsiReferenceRegistrar {
class KotlinPsiReferenceRegistrar {
val providers: MultiMap<Class<out PsiElement>, KotlinPsiReferenceProvider> = MultiMap.create()
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 {
override fun getReferencesByElement(element: PsiElement): Array<PsiReference> {
@Suppress("UNCHECKED_CAST")
return factory(element as E)
}
}
@@ -58,15 +63,13 @@ class KtIdeReferenceProviderService : KotlinReferenceProvidersService() {
private val originalProvidersBinding: MultiMap<Class<out PsiElement>, KotlinPsiReferenceProvider>
private val providersBindingCache: Map<Class<out PsiElement>, List<KotlinPsiReferenceProvider>>
private val referenceContributors = listOf(KotlinReferenceContributor(), KotlinDefaultAnnotationMethodImplicitReferenceContributor())
init {
val registrar = KotlinPsiReferenceRegistrar()
referenceContributors.forEach { it.registerReferenceProviders(registrar) }
KotlinReferenceProviderContributor.getInstance().registerReferenceProviders(registrar)
originalProvidersBinding = registrar.providers
providersBindingCache = ConcurrentFactoryMap.createMap<Class<out PsiElement>, List<KotlinPsiReferenceProvider>> { klass ->
val result = ContainerUtil.newSmartList<KotlinPsiReferenceProvider>()
val result = SmartList<KotlinPsiReferenceProvider>()
for (bindingClass in originalProvidersBinding.keySet()) {
if (bindingClass.isAssignableFrom(klass)) {
result.addAll(originalProvidersBinding.get(bindingClass))
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.references
@@ -20,40 +9,20 @@ import com.intellij.lang.ASTNode
import com.intellij.openapi.util.TextRange
import com.intellij.psi.MultiRangeReference
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
import org.jetbrains.kotlin.util.OperatorNameConventions
import java.util.*
class KtInvokeFunctionReference(expression: KtCallExpression) : KtSimpleReference<KtCallExpression>(expression), MultiRangeReference {
override val resolvesByNames: Collection<Name>
get() = NAMES
abstract class KtInvokeFunctionReference(expression: KtCallExpression) : KtSimpleReference<KtCallExpression>(expression), MultiRangeReference {
override val resolvesByNames: Collection<Name> get() = NAMES
override fun getRangeInElement(): TextRange {
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> {
val list = ArrayList<TextRange>()
val valueArgumentList = expression.valueArgumentList
@@ -111,11 +80,12 @@ class KtInvokeFunctionReference(expression: KtCallExpression) : KtSimpleReferenc
return fullCallExpression.replace(arrayAccessExpression)
}
return renameImplicitConventionalCall(newElementName)
return doRenameImplicitConventionalCall(newElementName)
}
companion object {
protected abstract fun doRenameImplicitConventionalCall(newName: String?): KtExpression
companion object {
private val NAMES = listOf(OperatorNameConventions.INVOKE)
}
}
@@ -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.
*/
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.idea.core.util.runInReadActionWithWriteActionPriorit
import org.jetbrains.kotlin.idea.patterns.KotlinFunctionPattern
import org.jetbrains.kotlin.idea.references.KtReference
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.references.resolveToDescriptors
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.lexer.KtTokens
@@ -171,6 +171,12 @@
<applicationService serviceInterface="org.jetbrains.kotlin.idea.caches.FileAttributeService"
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 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.
*/
@@ -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.getResolutionFacade
import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings
import org.jetbrains.kotlin.idea.references.KtInvokeFunctionReference
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.references.*
import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.intentions
@@ -35,8 +24,8 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClass
import org.jetbrains.kotlin.psi.psiUtil.getCallNameExpression
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.ArrayFqNames
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.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
@@ -294,8 +283,8 @@ fun KtDotQualifiedExpression.deleteFirstReceiver(): KtExpression {
return this
}
private val ARRAY_OF_METHODS = setOf(CollectionLiteralResolver.ARRAY_OF_FUNCTION) +
CollectionLiteralResolver.PRIMITIVE_TYPE_TO_ARRAY.values.toSet() +
private val ARRAY_OF_METHODS = setOf(ArrayFqNames.ARRAY_OF_FUNCTION) +
ArrayFqNames.PRIMITIVE_TYPE_TO_ARRAY.values.toSet() +
Name.identifier("emptyArray")
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.
*/
@@ -14,8 +14,7 @@ import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.resolve.CollectionLiteralResolver.Companion.ARRAY_OF_FUNCTION
import org.jetbrains.kotlin.resolve.CollectionLiteralResolver.Companion.PRIMITIVE_TYPE_TO_ARRAY
import org.jetbrains.kotlin.resolve.ArrayFqNames
class SurroundWithArrayOfWithSpreadOperatorInFunctionFix(
val wrapper: Name,
@@ -52,7 +51,7 @@ class SurroundWithArrayOfWithSpreadOperatorInFunctionFix(
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)
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.idea.core.setDefaultValue
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.KotlinCallableDefinitionUsage
import org.jetbrains.kotlin.idea.references.KtReference
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.references.resolveToDescriptors
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.addRemoveModifier.setModifierList
import org.jetbrains.kotlin.psi.psiUtil.quoteIfNeeded
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.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.references.KtReference
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.search.declarationsSearch.HierarchySearchRequest
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.
*/
@@ -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.references.KtReference
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.lexer.KtTokens
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.
*/
@@ -13,9 +13,11 @@ import com.intellij.psi.search.SearchScope
import com.intellij.refactoring.rename.RenameJavaMethodProcessor
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
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.name.Name
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
import org.jetbrains.kotlin.utils.addToStdlib.filterIsInstanceWithChecker
import org.jetbrains.kotlin.utils.ifEmpty
class KotlinAwareJavaGetterRenameProcessor : RenameJavaMethodProcessor() {
@@ -38,12 +40,12 @@ class KotlinAwareJavaGetterRenameProcessor : RenameJavaMethodProcessor() {
.filter { it.parameters.size == 1 && it.returnType == PsiType.VOID }
.flatMap {
super.findReferences(it, searchScope, searchInCommentsAndStrings)
.filterIsInstance<SyntheticPropertyAccessorReference.Setter>()
.filterIsInstanceWithChecker<SyntheticPropertyAccessorReference> { !it.getter }
}
.ifEmpty { return getterReferences }
return ArrayList<PsiReference>(getterReferences.size + setterReferences.size).apply {
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.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.search.ideaExtensions
@@ -94,7 +83,7 @@ class KotlinOverridingMethodReferenceSearcher : MethodUsagesSearcher() {
return readWriteAccess.isRead != isGetter && readWriteAccess.isWrite == isGetter
}
if (ref is SyntheticPropertyAccessorReference) {
return (ref is SyntheticPropertyAccessorReference.Getter) != isGetter
return ref.getter != isGetter
}
return false
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -12,9 +12,7 @@ import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.nj2k.toArgumentList
import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.types.*
import org.jetbrains.kotlin.resolve.CollectionLiteralResolver
import org.jetbrains.kotlin.resolve.ArrayFqNames
class ArrayInitializerConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
@@ -23,9 +21,9 @@ class ArrayInitializerConversion(context: NewJ2kConverterContext) : RecursiveApp
val primitiveArrayType = element.type.type as? JKJavaPrimitiveType
val arrayConstructorName =
if (primitiveArrayType != null)
CollectionLiteralResolver.PRIMITIVE_TYPE_TO_ARRAY[PrimitiveType.valueOf(primitiveArrayType.jvmPrimitiveType.name)]!!.asString()
ArrayFqNames.PRIMITIVE_TYPE_TO_ARRAY[PrimitiveType.valueOf(primitiveArrayType.jvmPrimitiveType.name)]!!.asString()
else
CollectionLiteralResolver.ARRAY_OF_FUNCTION.asString()
ArrayFqNames.ARRAY_OF_FUNCTION.asString()
val typeArguments =
if (primitiveArrayType == null) JKTypeArgumentList(listOf(element::type.detached()))
else JKTypeArgumentList()
+1
View File
@@ -93,6 +93,7 @@ val projectsToShadow by extra(listOf(
":idea:idea-jvm",
":idea:idea-git",
":idea:idea-jps-common",
":idea:idea-frontend-independent",
*if (Ide.IJ())
arrayOf(
":idea:idea-maven",
+1
View File
@@ -183,6 +183,7 @@ include ":kotlin-build-common",
":idea:jvm-debugger:jvm-debugger-coroutine",
":idea:jvm-debugger:jvm-debugger-test",
":idea:scripting-support",
":idea:idea-frontend-independent",
":libraries:tools:new-project-wizard",
":idea:idea-new-project-wizard",
":libraries:tools:new-project-wizard:new-project-wizard-cli",