Reformat and cleanup
This commit is contained in:
@@ -1,17 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2016 JetBrains s.r.o.
|
* Copyright 2000-2018 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.
|
||||||
* 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.core
|
package org.jetbrains.kotlin.idea.core
|
||||||
@@ -25,7 +14,6 @@ import com.intellij.psi.util.PsiTreeUtil
|
|||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.idea.analysis.analyzeAsReplacement
|
import org.jetbrains.kotlin.idea.analysis.analyzeAsReplacement
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.core.ShortenReferences.Options
|
|
||||||
import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport
|
import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport
|
||||||
import org.jetbrains.kotlin.idea.imports.getImportableTargets
|
import org.jetbrains.kotlin.idea.imports.getImportableTargets
|
||||||
import org.jetbrains.kotlin.idea.util.ImportDescriptorResult
|
import org.jetbrains.kotlin.idea.util.ImportDescriptorResult
|
||||||
@@ -56,10 +44,10 @@ import java.util.*
|
|||||||
|
|
||||||
class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT }) {
|
class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT }) {
|
||||||
data class Options(
|
data class Options(
|
||||||
val removeThisLabels: Boolean = false,
|
val removeThisLabels: Boolean = false,
|
||||||
val removeThis: Boolean = false,
|
val removeThis: Boolean = false,
|
||||||
// TODO: remove this option and all related stuff (RETAIN_COMPANION etc.) after KT-13934 fixed
|
// TODO: remove this option and all related stuff (RETAIN_COMPANION etc.) after KT-13934 fixed
|
||||||
val removeExplicitCompanion: Boolean = true
|
val removeExplicitCompanion: Boolean = true
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
val DEFAULT = Options()
|
val DEFAULT = Options()
|
||||||
@@ -73,18 +61,18 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
|
|
||||||
val RETAIN_COMPANION = ShortenReferences { Options(removeExplicitCompanion = false) }
|
val RETAIN_COMPANION = ShortenReferences { Options(removeExplicitCompanion = false) }
|
||||||
|
|
||||||
private fun DeclarationDescriptor.asString()
|
private fun DeclarationDescriptor.asString() = DescriptorRenderer.FQ_NAMES_IN_TYPES.render(this)
|
||||||
= DescriptorRenderer.FQ_NAMES_IN_TYPES.render(this)
|
|
||||||
|
|
||||||
private fun KtReferenceExpression.targets(context: BindingContext) = getImportableTargets(context)
|
private fun KtReferenceExpression.targets(context: BindingContext) = getImportableTargets(context)
|
||||||
|
|
||||||
private fun mayImport(descriptor: DeclarationDescriptor, file: KtFile): Boolean {
|
private fun mayImport(descriptor: DeclarationDescriptor, file: KtFile): Boolean {
|
||||||
return descriptor.canBeReferencedViaImport()
|
return descriptor.canBeReferencedViaImport()
|
||||||
&& ImportInsertHelper.getInstance(file.project).mayImportOnShortenReferences(descriptor)
|
&& ImportInsertHelper.getInstance(file.project).mayImportOnShortenReferences(descriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmOverloads fun process(element: KtElement, elementFilter: (PsiElement) -> FilterResult = { FilterResult.PROCESS }): KtElement {
|
@JvmOverloads
|
||||||
|
fun process(element: KtElement, elementFilter: (PsiElement) -> FilterResult = { FilterResult.PROCESS }): KtElement {
|
||||||
return process(listOf(element), elementFilter).single()
|
return process(listOf(element), elementFilter).single()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,26 +98,23 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
range.intersects(elementRange) -> {
|
range.intersects(elementRange) -> {
|
||||||
// for qualified call expression allow to shorten only the part without parenthesis
|
// for qualified call expression allow to shorten only the part without parenthesis
|
||||||
val calleeExpression = ((element as? KtDotQualifiedExpression)
|
val calleeExpression = ((element as? KtDotQualifiedExpression)
|
||||||
?.selectorExpression as? KtCallExpression)
|
?.selectorExpression as? KtCallExpression)
|
||||||
?.calleeExpression
|
?.calleeExpression
|
||||||
if (calleeExpression != null) {
|
if (calleeExpression != null) {
|
||||||
val rangeWithoutParenthesis = TextRange(elementRange.startOffset, calleeExpression.textRange!!.endOffset)
|
val rangeWithoutParenthesis = TextRange(elementRange.startOffset, calleeExpression.textRange!!.endOffset)
|
||||||
if (range.contains(rangeWithoutParenthesis)) FilterResult.PROCESS else FilterResult.GO_INSIDE
|
if (range.contains(rangeWithoutParenthesis)) FilterResult.PROCESS else FilterResult.GO_INSIDE
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
FilterResult.GO_INSIDE
|
FilterResult.GO_INSIDE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> FilterResult.SKIP
|
else -> FilterResult.SKIP
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
FilterResult.SKIP
|
FilterResult.SKIP
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
rangeMarker.dispose()
|
rangeMarker.dispose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,15 +125,19 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
PROCESS
|
PROCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmOverloads fun process(elements: Iterable<KtElement>, elementFilter: (PsiElement) -> FilterResult = { FilterResult.PROCESS }): Collection<KtElement> {
|
@JvmOverloads
|
||||||
|
fun process(
|
||||||
|
elements: Iterable<KtElement>,
|
||||||
|
elementFilter: (PsiElement) -> FilterResult = { FilterResult.PROCESS }
|
||||||
|
): Collection<KtElement> {
|
||||||
return elements.groupBy(KtElement::getContainingKtFile)
|
return elements.groupBy(KtElement::getContainingKtFile)
|
||||||
.flatMap { shortenReferencesInFile(it.key, it.value, elementFilter) }
|
.flatMap { shortenReferencesInFile(it.key, it.value, elementFilter) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun shortenReferencesInFile(
|
private fun shortenReferencesInFile(
|
||||||
file: KtFile,
|
file: KtFile,
|
||||||
elements: List<KtElement>,
|
elements: List<KtElement>,
|
||||||
elementFilter: (PsiElement) -> FilterResult
|
elementFilter: (PsiElement) -> FilterResult
|
||||||
): Collection<KtElement> {
|
): Collection<KtElement> {
|
||||||
//TODO: that's not correct since we have options!
|
//TODO: that's not correct since we have options!
|
||||||
val elementsToUse = dropNestedElements(elements)
|
val elementsToUse = dropNestedElements(elements)
|
||||||
@@ -160,8 +149,7 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
val companionElementFilter = { element: PsiElement ->
|
val companionElementFilter = { element: PsiElement ->
|
||||||
if (element is KtElement && !options(element).removeExplicitCompanion) {
|
if (element is KtElement && !options(element).removeExplicitCompanion) {
|
||||||
FilterResult.SKIP
|
FilterResult.SKIP
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
elementFilter(element)
|
elementFilter(element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,10 +158,10 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
// Processors order is important here so that enclosing elements are not shortened before their children are, e.g.
|
// Processors order is important here so that enclosing elements are not shortened before their children are, e.g.
|
||||||
// test.foo(this@A) -> foo(this)
|
// test.foo(this@A) -> foo(this)
|
||||||
val processors: List<ShorteningProcessor<*>> = listOf(
|
val processors: List<ShorteningProcessor<*>> = listOf(
|
||||||
ShortenTypesProcessor(file, elementFilter, failedToImportDescriptors),
|
ShortenTypesProcessor(file, elementFilter, failedToImportDescriptors),
|
||||||
ShortenThisExpressionsProcessor(file, elementFilter, failedToImportDescriptors),
|
ShortenThisExpressionsProcessor(file, elementFilter, failedToImportDescriptors),
|
||||||
ShortenQualifiedExpressionsProcessor(file, elementFilter, failedToImportDescriptors),
|
ShortenQualifiedExpressionsProcessor(file, elementFilter, failedToImportDescriptors),
|
||||||
RemoveExplicitCompanionObjectReferenceProcessor(file, companionElementFilter, failedToImportDescriptors)
|
RemoveExplicitCompanionObjectReferenceProcessor(file, companionElementFilter, failedToImportDescriptors)
|
||||||
)
|
)
|
||||||
|
|
||||||
// step 1: collect qualified elements to analyze (no resolve at this step)
|
// step 1: collect qualified elements to analyze (no resolve at this step)
|
||||||
@@ -215,7 +203,7 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
|
|
||||||
private fun dropNestedElements(elements: List<KtElement>): LinkedHashSet<KtElement> {
|
private fun dropNestedElements(elements: List<KtElement>): LinkedHashSet<KtElement> {
|
||||||
val elementSet = elements.toSet()
|
val elementSet = elements.toSet()
|
||||||
return elementSet.filterTo(LinkedHashSet<KtElement>(elementSet.size)) { element ->
|
return elementSet.filterTo(LinkedHashSet(elementSet.size)) { element ->
|
||||||
element.parents.none { it in elementSet }
|
element.parents.none { it in elementSet }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -223,7 +211,7 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
private data class ElementToAnalyze<TElement>(val element: TElement, val level: Int)
|
private data class ElementToAnalyze<TElement>(val element: TElement, val level: Int)
|
||||||
|
|
||||||
private abstract class CollectElementsVisitor<TElement : KtElement>(
|
private abstract class CollectElementsVisitor<TElement : KtElement>(
|
||||||
protected val elementFilter: (PsiElement) -> FilterResult
|
protected val elementFilter: (PsiElement) -> FilterResult
|
||||||
) : KtVisitorVoid() {
|
) : KtVisitorVoid() {
|
||||||
|
|
||||||
var options: Options = Options.DEFAULT
|
var options: Options = Options.DEFAULT
|
||||||
@@ -258,8 +246,8 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
}
|
}
|
||||||
|
|
||||||
private abstract class ShorteningProcessor<TElement : KtElement>(
|
private abstract class ShorteningProcessor<TElement : KtElement>(
|
||||||
protected val file: KtFile,
|
protected val file: KtFile,
|
||||||
protected val failedToImportDescriptors: Set<DeclarationDescriptor>
|
protected val failedToImportDescriptors: Set<DeclarationDescriptor>
|
||||||
) {
|
) {
|
||||||
protected val resolutionFacade = file.getResolutionFacade()
|
protected val resolutionFacade = file.getResolutionFacade()
|
||||||
private val elementsToShorten = ArrayList<SmartPsiElementPointer<TElement>>()
|
private val elementsToShorten = ArrayList<SmartPsiElementPointer<TElement>>()
|
||||||
@@ -278,25 +266,24 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
|
|
||||||
val toBeShortened: Boolean
|
val toBeShortened: Boolean
|
||||||
when (result) {
|
when (result) {
|
||||||
is AnalyzeQualifiedElementResult.ShortenNow -> {
|
AnalyzeQualifiedElementResult.ShortenNow -> {
|
||||||
elementsToShorten.add(element.createSmartPointer())
|
elementsToShorten.add(element.createSmartPointer())
|
||||||
toBeShortened = true
|
toBeShortened = true
|
||||||
}
|
}
|
||||||
|
|
||||||
is AnalyzeQualifiedElementResult.ImportDescriptors -> {
|
is AnalyzeQualifiedElementResult.ImportDescriptors -> {
|
||||||
val tryImport = result.descriptors.isNotEmpty()
|
val tryImport = result.descriptors.isNotEmpty()
|
||||||
&& result.descriptors.none { it in failedToImportDescriptors }
|
&& result.descriptors.none { it in failedToImportDescriptors }
|
||||||
&& result.descriptors.all { mayImport(it, file) }
|
&& result.descriptors.all { mayImport(it, file) }
|
||||||
toBeShortened = if (tryImport) {
|
toBeShortened = if (tryImport) {
|
||||||
descriptorsToImport.addAll(result.descriptors)
|
descriptorsToImport.addAll(result.descriptors)
|
||||||
true
|
true
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is AnalyzeQualifiedElementResult.Skip -> {
|
AnalyzeQualifiedElementResult.Skip -> {
|
||||||
toBeShortened = false
|
toBeShortened = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -347,36 +334,36 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class ShortenTypesProcessor(
|
private class ShortenTypesProcessor(
|
||||||
file: KtFile,
|
file: KtFile,
|
||||||
elementFilter: (PsiElement) -> FilterResult,
|
elementFilter: (PsiElement) -> FilterResult,
|
||||||
failedToImportDescriptors: Set<DeclarationDescriptor>
|
failedToImportDescriptors: Set<DeclarationDescriptor>
|
||||||
) : ShorteningProcessor<KtUserType>(file, failedToImportDescriptors) {
|
) : ShorteningProcessor<KtUserType>(file, failedToImportDescriptors) {
|
||||||
|
|
||||||
override val collectElementsVisitor: CollectElementsVisitor<KtUserType> =
|
override val collectElementsVisitor: CollectElementsVisitor<KtUserType> =
|
||||||
object : CollectElementsVisitor<KtUserType>(elementFilter) {
|
object : CollectElementsVisitor<KtUserType>(elementFilter) {
|
||||||
override fun visitUserType(userType: KtUserType) {
|
override fun visitUserType(userType: KtUserType) {
|
||||||
val filterResult = elementFilter(userType)
|
val filterResult = elementFilter(userType)
|
||||||
if (filterResult == FilterResult.SKIP) return
|
if (filterResult == FilterResult.SKIP) return
|
||||||
|
|
||||||
userType.typeArgumentList?.accept(this)
|
userType.typeArgumentList?.accept(this)
|
||||||
|
|
||||||
if (filterResult == FilterResult.PROCESS) {
|
if (filterResult == FilterResult.PROCESS) {
|
||||||
addQualifiedElementToAnalyze(userType)
|
addQualifiedElementToAnalyze(userType)
|
||||||
}
|
|
||||||
|
|
||||||
// elements in qualifier must be under
|
|
||||||
nextLevel()
|
|
||||||
userType.qualifier?.accept(this)
|
|
||||||
prevLevel()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// elements in qualifier must be under
|
||||||
|
nextLevel()
|
||||||
|
userType.qualifier?.accept(this)
|
||||||
|
prevLevel()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun analyzeQualifiedElement(element: KtUserType, bindingContext: BindingContext): AnalyzeQualifiedElementResult {
|
override fun analyzeQualifiedElement(element: KtUserType, bindingContext: BindingContext): AnalyzeQualifiedElementResult {
|
||||||
if (element.qualifier == null) return AnalyzeQualifiedElementResult.Skip
|
if (element.qualifier == null) return AnalyzeQualifiedElementResult.Skip
|
||||||
val referenceExpression = element.referenceExpression ?: return AnalyzeQualifiedElementResult.Skip
|
val referenceExpression = element.referenceExpression ?: return AnalyzeQualifiedElementResult.Skip
|
||||||
|
|
||||||
val target = referenceExpression.targets(bindingContext).singleOrNull()
|
val target = referenceExpression.targets(bindingContext).singleOrNull()
|
||||||
?: return AnalyzeQualifiedElementResult.Skip
|
?: return AnalyzeQualifiedElementResult.Skip
|
||||||
|
|
||||||
val scope = element.getResolutionScope(bindingContext, resolutionFacade)
|
val scope = element.getResolutionScope(bindingContext, resolutionFacade)
|
||||||
val name = target.name
|
val name = target.name
|
||||||
@@ -386,7 +373,9 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
scope.findPackage(name)
|
scope.findPackage(name)
|
||||||
|
|
||||||
val canShortenNow = targetByName?.asString() == target.asString()
|
val canShortenNow = targetByName?.asString() == target.asString()
|
||||||
return if (canShortenNow) AnalyzeQualifiedElementResult.ShortenNow else AnalyzeQualifiedElementResult.ImportDescriptors(listOfNotNull(target))
|
return if (canShortenNow) AnalyzeQualifiedElementResult.ShortenNow else AnalyzeQualifiedElementResult.ImportDescriptors(
|
||||||
|
listOfNotNull(target)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shortenElement(element: KtUserType): KtElement {
|
override fun shortenElement(element: KtUserType): KtElement {
|
||||||
@@ -396,12 +385,13 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
}
|
}
|
||||||
|
|
||||||
private abstract class QualifiedExpressionShorteningProcessor(
|
private abstract class QualifiedExpressionShorteningProcessor(
|
||||||
file: KtFile,
|
file: KtFile,
|
||||||
elementFilter: (PsiElement) -> FilterResult,
|
elementFilter: (PsiElement) -> FilterResult,
|
||||||
failedToImportDescriptors: Set<DeclarationDescriptor>
|
failedToImportDescriptors: Set<DeclarationDescriptor>
|
||||||
) : ShorteningProcessor<KtDotQualifiedExpression>(file, failedToImportDescriptors) {
|
) : ShorteningProcessor<KtDotQualifiedExpression>(file, failedToImportDescriptors) {
|
||||||
|
|
||||||
protected open class MyVisitor(elementFilter: (PsiElement) -> FilterResult) : CollectElementsVisitor<KtDotQualifiedExpression>(elementFilter) {
|
protected open class MyVisitor(elementFilter: (PsiElement) -> FilterResult) :
|
||||||
|
CollectElementsVisitor<KtDotQualifiedExpression>(elementFilter) {
|
||||||
override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression) {
|
override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression) {
|
||||||
val filterResult = elementFilter(expression)
|
val filterResult = elementFilter(expression)
|
||||||
if (filterResult == FilterResult.SKIP) return
|
if (filterResult == FilterResult.SKIP) return
|
||||||
@@ -423,9 +413,9 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class ShortenQualifiedExpressionsProcessor(
|
private class ShortenQualifiedExpressionsProcessor(
|
||||||
file: KtFile,
|
file: KtFile,
|
||||||
elementFilter: (PsiElement) -> FilterResult,
|
elementFilter: (PsiElement) -> FilterResult,
|
||||||
failedToImportDescriptors: Set<DeclarationDescriptor>
|
failedToImportDescriptors: Set<DeclarationDescriptor>
|
||||||
) : QualifiedExpressionShorteningProcessor(file, elementFilter, failedToImportDescriptors) {
|
) : QualifiedExpressionShorteningProcessor(file, elementFilter, failedToImportDescriptors) {
|
||||||
|
|
||||||
override val collectElementsVisitor = object : MyVisitor(elementFilter) {
|
override val collectElementsVisitor = object : MyVisitor(elementFilter) {
|
||||||
@@ -435,13 +425,17 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun analyzeQualifiedElement(element: KtDotQualifiedExpression, bindingContext: BindingContext): AnalyzeQualifiedElementResult {
|
override fun analyzeQualifiedElement(
|
||||||
|
element: KtDotQualifiedExpression,
|
||||||
|
bindingContext: BindingContext
|
||||||
|
): AnalyzeQualifiedElementResult {
|
||||||
val receiver = element.receiverExpression
|
val receiver = element.receiverExpression
|
||||||
if (receiver !is KtThisExpression && bindingContext[BindingContext.QUALIFIER, receiver] == null) return AnalyzeQualifiedElementResult.Skip
|
if (receiver !is KtThisExpression && bindingContext[BindingContext.QUALIFIER, receiver] == null) return AnalyzeQualifiedElementResult.Skip
|
||||||
|
|
||||||
if (PsiTreeUtil.getParentOfType(
|
if (PsiTreeUtil.getParentOfType(
|
||||||
element,
|
element,
|
||||||
KtImportDirective::class.java, KtPackageDirective::class.java) != null) return AnalyzeQualifiedElementResult.Skip
|
KtImportDirective::class.java, KtPackageDirective::class.java
|
||||||
|
) != null) return AnalyzeQualifiedElementResult.Skip
|
||||||
|
|
||||||
val selector = element.selectorExpression ?: return AnalyzeQualifiedElementResult.Skip
|
val selector = element.selectorExpression ?: return AnalyzeQualifiedElementResult.Skip
|
||||||
val callee = selector.getCalleeExpressionIfAny() as? KtReferenceExpression ?: return AnalyzeQualifiedElementResult.Skip
|
val callee = selector.getCalleeExpressionIfAny() as? KtReferenceExpression ?: return AnalyzeQualifiedElementResult.Skip
|
||||||
@@ -459,9 +453,9 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
|
|
||||||
val resolvedCallWhenShort = newCallee.getResolvedCall(newContext)
|
val resolvedCallWhenShort = newCallee.getResolvedCall(newContext)
|
||||||
val targetsMatch = targetsMatch(targets, targetsWhenShort) &&
|
val targetsMatch = targetsMatch(targets, targetsWhenShort) &&
|
||||||
(resolvedCall !is VariableAsFunctionResolvedCall || (
|
(resolvedCall !is VariableAsFunctionResolvedCall || (
|
||||||
resolvedCallWhenShort is VariableAsFunctionResolvedCall? &&
|
resolvedCallWhenShort is VariableAsFunctionResolvedCall? &&
|
||||||
resolvedCallsMatch(resolvedCall, resolvedCallWhenShort)))
|
resolvedCallsMatch(resolvedCall, resolvedCallWhenShort)))
|
||||||
|
|
||||||
|
|
||||||
// If before and after shorten call can be resolved unambiguously, then preform comparing of such calls,
|
// If before and after shorten call can be resolved unambiguously, then preform comparing of such calls,
|
||||||
@@ -474,16 +468,17 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
// TODO: Add possibility to check if descriptor from completion can't be resolved after shorten and not preform shorten than
|
// TODO: Add possibility to check if descriptor from completion can't be resolved after shorten and not preform shorten than
|
||||||
val resolvedCallsMatch = if (resolvedCall != null && resolvedCallWhenShort != null) {
|
val resolvedCallsMatch = if (resolvedCall != null && resolvedCallWhenShort != null) {
|
||||||
resolvedCall.resultingDescriptor.original == resolvedCallWhenShort.resultingDescriptor.original
|
resolvedCall.resultingDescriptor.original == resolvedCallWhenShort.resultingDescriptor.original
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val resolvedCalls = selector.getCall(bindingContext)?.resolveCandidates(bindingContext, resolutionFacade) ?: emptyList()
|
val resolvedCalls = selector.getCall(bindingContext)?.resolveCandidates(bindingContext, resolutionFacade) ?: emptyList()
|
||||||
val callWhenShort = selectorAfterShortening.getCall(newContext)
|
val callWhenShort = selectorAfterShortening.getCall(newContext)
|
||||||
val resolvedCallsWhenShort = selectorAfterShortening.getCall(newContext)?.resolveCandidates(newContext, resolutionFacade) ?: emptyList()
|
val resolvedCallsWhenShort =
|
||||||
|
selectorAfterShortening.getCall(newContext)?.resolveCandidates(newContext, resolutionFacade) ?: emptyList()
|
||||||
|
|
||||||
val descriptorsOfResolvedCallsWhenShort = resolvedCallsWhenShort.map { it.resultingDescriptor.original }
|
val descriptorsOfResolvedCallsWhenShort = resolvedCallsWhenShort.map { it.resultingDescriptor.original }
|
||||||
val descriptorsOfResolvedCalls = resolvedCalls.mapTo(mutableSetOf()) { it.resultingDescriptor.original }
|
val descriptorsOfResolvedCalls = resolvedCalls.mapTo(mutableSetOf()) { it.resultingDescriptor.original }
|
||||||
|
|
||||||
val filter = ShadowedDeclarationsFilter(newContext, resolutionFacade, newCallee, callWhenShort?.explicitReceiver as? ReceiverValue)
|
val filter =
|
||||||
|
ShadowedDeclarationsFilter(newContext, resolutionFacade, newCallee, callWhenShort?.explicitReceiver as? ReceiverValue)
|
||||||
val availableDescriptorsWhenShort = filter.filter(descriptorsOfResolvedCallsWhenShort)
|
val availableDescriptorsWhenShort = filter.filter(descriptorsOfResolvedCallsWhenShort)
|
||||||
|
|
||||||
availableDescriptorsWhenShort.any { it in descriptorsOfResolvedCalls }
|
availableDescriptorsWhenShort.any { it in descriptorsOfResolvedCalls }
|
||||||
@@ -496,10 +491,10 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
val newCall = selectorAfterShortening.getResolvedCall(newContext) ?: return AnalyzeQualifiedElementResult.Skip
|
val newCall = selectorAfterShortening.getResolvedCall(newContext) ?: return AnalyzeQualifiedElementResult.Skip
|
||||||
val receiverKind = originalCall.explicitReceiverKind
|
val receiverKind = originalCall.explicitReceiverKind
|
||||||
val newReceiver = when (receiverKind) {
|
val newReceiver = when (receiverKind) {
|
||||||
ExplicitReceiverKind.BOTH_RECEIVERS, ExplicitReceiverKind.EXTENSION_RECEIVER -> newCall.extensionReceiver
|
ExplicitReceiverKind.BOTH_RECEIVERS, ExplicitReceiverKind.EXTENSION_RECEIVER -> newCall.extensionReceiver
|
||||||
ExplicitReceiverKind.DISPATCH_RECEIVER -> newCall.dispatchReceiver
|
ExplicitReceiverKind.DISPATCH_RECEIVER -> newCall.dispatchReceiver
|
||||||
else -> return AnalyzeQualifiedElementResult.Skip
|
else -> return AnalyzeQualifiedElementResult.Skip
|
||||||
} as? ImplicitReceiver ?: return AnalyzeQualifiedElementResult.Skip
|
} as? ImplicitReceiver ?: return AnalyzeQualifiedElementResult.Skip
|
||||||
|
|
||||||
val thisTarget = receiver.instanceReference.targets(bindingContext).singleOrNull()
|
val thisTarget = receiver.instanceReference.targets(bindingContext).singleOrNull()
|
||||||
if (newReceiver.declarationDescriptor.asString() != thisTarget?.asString()) return AnalyzeQualifiedElementResult.Skip
|
if (newReceiver.declarationDescriptor.asString() != thisTarget?.asString()) return AnalyzeQualifiedElementResult.Skip
|
||||||
@@ -516,7 +511,10 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun copyShortenAndAnalyze(element: KtDotQualifiedExpression, bindingContext: BindingContext): Pair<BindingContext, KtExpression> {
|
private fun copyShortenAndAnalyze(
|
||||||
|
element: KtDotQualifiedExpression,
|
||||||
|
bindingContext: BindingContext
|
||||||
|
): Pair<BindingContext, KtExpression> {
|
||||||
val selector = element.selectorExpression!!
|
val selector = element.selectorExpression!!
|
||||||
|
|
||||||
// selector V V selector V V
|
// selector V V selector V V
|
||||||
@@ -529,7 +527,8 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
if (doubleColonExpression != null && doubleColonExpression.receiverExpression == element) {
|
if (doubleColonExpression != null && doubleColonExpression.receiverExpression == element) {
|
||||||
val doubleColonExpressionCopy = doubleColonExpression.copied()
|
val doubleColonExpressionCopy = doubleColonExpression.copied()
|
||||||
doubleColonExpressionCopy.receiverExpression!!.replace(selector)
|
doubleColonExpressionCopy.receiverExpression!!.replace(selector)
|
||||||
val newBindingContext = doubleColonExpressionCopy.analyzeAsReplacement(doubleColonExpression, bindingContext, resolutionFacade)
|
val newBindingContext =
|
||||||
|
doubleColonExpressionCopy.analyzeAsReplacement(doubleColonExpression, bindingContext, resolutionFacade)
|
||||||
return newBindingContext to doubleColonExpressionCopy.receiverExpression!!
|
return newBindingContext to doubleColonExpressionCopy.receiverExpression!!
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -550,15 +549,14 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
if (targets1.size != targets2.size) return false
|
if (targets1.size != targets2.size) return false
|
||||||
return if (targets1.size == 1) {
|
return if (targets1.size == 1) {
|
||||||
targets1.single().asString() == targets2.single().asString()
|
targets1.single().asString() == targets2.single().asString()
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
targets1.map { it.asString() }.toSet() == targets2.map { it.asString() }.toSet()
|
targets1.map { it.asString() }.toSet() == targets2.map { it.asString() }.toSet()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolvedCallsMatch(rc1: VariableAsFunctionResolvedCall?, rc2: VariableAsFunctionResolvedCall?): Boolean {
|
private fun resolvedCallsMatch(rc1: VariableAsFunctionResolvedCall?, rc2: VariableAsFunctionResolvedCall?): Boolean {
|
||||||
return rc1?.variableCall?.candidateDescriptor?.asString() == rc2?.variableCall?.candidateDescriptor?.asString() &&
|
return rc1?.variableCall?.candidateDescriptor?.asString() == rc2?.variableCall?.candidateDescriptor?.asString() &&
|
||||||
rc1?.functionCall?.candidateDescriptor?.asString() == rc2?.functionCall?.candidateDescriptor?.asString()
|
rc1?.functionCall?.candidateDescriptor?.asString() == rc2?.functionCall?.candidateDescriptor?.asString()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shortenElement(element: KtDotQualifiedExpression): KtElement {
|
override fun shortenElement(element: KtDotQualifiedExpression): KtElement {
|
||||||
@@ -571,21 +569,21 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class ShortenThisExpressionsProcessor(
|
private class ShortenThisExpressionsProcessor(
|
||||||
file: KtFile,
|
file: KtFile,
|
||||||
elementFilter: (PsiElement) -> FilterResult,
|
elementFilter: (PsiElement) -> FilterResult,
|
||||||
failedToImportDescriptors: Set<DeclarationDescriptor>
|
failedToImportDescriptors: Set<DeclarationDescriptor>
|
||||||
) : ShorteningProcessor<KtThisExpression>(file, failedToImportDescriptors) {
|
) : ShorteningProcessor<KtThisExpression>(file, failedToImportDescriptors) {
|
||||||
|
|
||||||
private val simpleThis = KtPsiFactory(file).createExpression("this") as KtThisExpression
|
private val simpleThis = KtPsiFactory(file).createExpression("this") as KtThisExpression
|
||||||
|
|
||||||
override val collectElementsVisitor: CollectElementsVisitor<KtThisExpression> =
|
override val collectElementsVisitor: CollectElementsVisitor<KtThisExpression> =
|
||||||
object : CollectElementsVisitor<KtThisExpression>(elementFilter) {
|
object : CollectElementsVisitor<KtThisExpression>(elementFilter) {
|
||||||
override fun visitThisExpression(expression: KtThisExpression) {
|
override fun visitThisExpression(expression: KtThisExpression) {
|
||||||
if (options.removeThisLabels && elementFilter(expression) == FilterResult.PROCESS && expression.getTargetLabel() != null) {
|
if (options.removeThisLabels && elementFilter(expression) == FilterResult.PROCESS && expression.getTargetLabel() != null) {
|
||||||
addQualifiedElementToAnalyze(expression)
|
addQualifiedElementToAnalyze(expression)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun analyzeQualifiedElement(element: KtThisExpression, bindingContext: BindingContext): AnalyzeQualifiedElementResult {
|
override fun analyzeQualifiedElement(element: KtThisExpression, bindingContext: BindingContext): AnalyzeQualifiedElementResult {
|
||||||
val targetBefore = element.instanceReference.targets(bindingContext).singleOrNull() ?: return AnalyzeQualifiedElementResult.Skip
|
val targetBefore = element.instanceReference.targets(bindingContext).singleOrNull() ?: return AnalyzeQualifiedElementResult.Skip
|
||||||
@@ -600,16 +598,19 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class RemoveExplicitCompanionObjectReferenceProcessor(
|
private class RemoveExplicitCompanionObjectReferenceProcessor(
|
||||||
file: KtFile,
|
file: KtFile,
|
||||||
elementFilter: (PsiElement) -> FilterResult,
|
elementFilter: (PsiElement) -> FilterResult,
|
||||||
failedToImportDescriptors: Set<DeclarationDescriptor>
|
failedToImportDescriptors: Set<DeclarationDescriptor>
|
||||||
) : QualifiedExpressionShorteningProcessor(file, elementFilter, failedToImportDescriptors) {
|
) : QualifiedExpressionShorteningProcessor(file, elementFilter, failedToImportDescriptors) {
|
||||||
|
|
||||||
private fun KtExpression.singleTarget(context: BindingContext): DeclarationDescriptor? {
|
private fun KtExpression.singleTarget(context: BindingContext): DeclarationDescriptor? {
|
||||||
return (getCalleeExpressionIfAny() as? KtReferenceExpression)?.targets(context)?.singleOrNull()
|
return (getCalleeExpressionIfAny() as? KtReferenceExpression)?.targets(context)?.singleOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun analyzeQualifiedElement(element: KtDotQualifiedExpression, bindingContext: BindingContext): AnalyzeQualifiedElementResult {
|
override fun analyzeQualifiedElement(
|
||||||
|
element: KtDotQualifiedExpression,
|
||||||
|
bindingContext: BindingContext
|
||||||
|
): AnalyzeQualifiedElementResult {
|
||||||
val parent = element.parent
|
val parent = element.parent
|
||||||
// TODO: Delete this code when KT-13934 is fixed
|
// TODO: Delete this code when KT-13934 is fixed
|
||||||
if (parent is KtCallableReferenceExpression && parent.receiverExpression == element) return AnalyzeQualifiedElementResult.Skip
|
if (parent is KtCallableReferenceExpression && parent.receiverExpression == element) return AnalyzeQualifiedElementResult.Skip
|
||||||
@@ -618,7 +619,8 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
|
|
||||||
if (PsiTreeUtil.getParentOfType(
|
if (PsiTreeUtil.getParentOfType(
|
||||||
element,
|
element,
|
||||||
KtImportDirective::class.java, KtPackageDirective::class.java) != null) return AnalyzeQualifiedElementResult.Skip
|
KtImportDirective::class.java, KtPackageDirective::class.java
|
||||||
|
) != null) return AnalyzeQualifiedElementResult.Skip
|
||||||
|
|
||||||
val receiverTarget = receiver.singleTarget(bindingContext) as? ClassDescriptor ?: return AnalyzeQualifiedElementResult.Skip
|
val receiverTarget = receiver.singleTarget(bindingContext) as? ClassDescriptor ?: return AnalyzeQualifiedElementResult.Skip
|
||||||
|
|
||||||
@@ -628,14 +630,17 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
|
|||||||
if (receiverTarget.companionObjectDescriptor != selectorTarget) return AnalyzeQualifiedElementResult.Skip
|
if (receiverTarget.companionObjectDescriptor != selectorTarget) return AnalyzeQualifiedElementResult.Skip
|
||||||
|
|
||||||
val selectorsSelector = (parent as? KtDotQualifiedExpression)?.selectorExpression
|
val selectorsSelector = (parent as? KtDotQualifiedExpression)?.selectorExpression
|
||||||
?: return AnalyzeQualifiedElementResult.ShortenNow
|
?: return AnalyzeQualifiedElementResult.ShortenNow
|
||||||
|
|
||||||
val selectorsSelectorTarget = selectorsSelector.singleTarget(bindingContext) ?: return AnalyzeQualifiedElementResult.Skip
|
val selectorsSelectorTarget = selectorsSelector.singleTarget(bindingContext) ?: return AnalyzeQualifiedElementResult.Skip
|
||||||
if (selectorsSelectorTarget is ClassDescriptor) return AnalyzeQualifiedElementResult.Skip
|
if (selectorsSelectorTarget is ClassDescriptor) return AnalyzeQualifiedElementResult.Skip
|
||||||
// TODO: More generic solution may be possible
|
// TODO: More generic solution may be possible
|
||||||
if (selectorsSelectorTarget is PropertyDescriptor) {
|
if (selectorsSelectorTarget is PropertyDescriptor) {
|
||||||
val source = selectorsSelectorTarget.source.getPsi() as? KtProperty
|
val source = selectorsSelectorTarget.source.getPsi() as? KtProperty
|
||||||
if (source != null && isEnumCompanionPropertyWithEntryConflict(source, source.name ?: "")) return AnalyzeQualifiedElementResult.Skip
|
if (source != null && isEnumCompanionPropertyWithEntryConflict(
|
||||||
|
source,
|
||||||
|
source.name ?: ""
|
||||||
|
)) return AnalyzeQualifiedElementResult.Skip
|
||||||
}
|
}
|
||||||
|
|
||||||
return AnalyzeQualifiedElementResult.ShortenNow
|
return AnalyzeQualifiedElementResult.ShortenNow
|
||||||
|
|||||||
Reference in New Issue
Block a user