mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[kotlin] KTIJ-37212 make ReplaceManualRangeWithIndicesCallsInspection support getCall array access.
GitOrigin-RevId: ca0f39f29e3fc4f6aea82a611cede284e4c93cd9
This commit is contained in:
committed by
intellij-monorepo-bot
parent
c8b48a46eb
commit
cad4e7a412
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||
import org.jetbrains.kotlin.psi.KtCallElement
|
||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||
@@ -430,3 +431,11 @@ fun KtSimpleNameExpression.canBeUsedInImport(): Boolean {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this element is on the left-hand side of an assignment expression.
|
||||
* Traverses parent hierarchy to handle cases like `(arr[i]) = value`.
|
||||
*/
|
||||
fun PsiElement.isAssignmentLHS(): Boolean = parents(withSelf = false).any {
|
||||
KtPsiUtil.isAssignment(it) && (it as KtBinaryExpression).left == this
|
||||
}
|
||||
|
||||
+10
@@ -9727,6 +9727,16 @@ public abstract class K2LocalInspectionTestGenerated extends AbstractK2LocalInsp
|
||||
runTest("../../../idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/forNotTarget.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("getMethod.kt")
|
||||
public void testGetMethod() throws Exception {
|
||||
runTest("../../../idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/getMethod.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("getMethodDifferentArray.kt")
|
||||
public void testGetMethodDifferentArray() throws Exception {
|
||||
runTest("../../../idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/getMethodDifferentArray.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("implicitReceiver.kt")
|
||||
public void testImplicitReceiver() throws Exception {
|
||||
runTest("../../../idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/implicitReceiver.kt");
|
||||
|
||||
+51
-42
@@ -20,6 +20,8 @@ import org.jetbrains.kotlin.analysis.api.types.KaType
|
||||
import org.jetbrains.kotlin.idea.base.codeInsight.KotlinDeclarationNameValidator
|
||||
import org.jetbrains.kotlin.idea.base.codeInsight.KotlinNameSuggester
|
||||
import org.jetbrains.kotlin.idea.base.codeInsight.KotlinNameSuggestionProvider
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.base.psi.isAssignmentLHS
|
||||
import org.jetbrains.kotlin.idea.base.psi.replaced
|
||||
import org.jetbrains.kotlin.idea.base.psi.safeDeparenthesize
|
||||
import org.jetbrains.kotlin.idea.base.resources.KotlinBundle
|
||||
@@ -28,13 +30,15 @@ import org.jetbrains.kotlin.idea.codeInsight.inspections.shared.AbstractRangeIns
|
||||
import org.jetbrains.kotlin.idea.codeinsight.api.applicable.inspections.KotlinApplicableInspectionBase
|
||||
import org.jetbrains.kotlin.idea.codeinsight.api.applicable.inspections.KotlinModCommandQuickFix
|
||||
import org.jetbrains.kotlin.idea.codeinsight.utils.ImplicitReceiverInfo
|
||||
import org.jetbrains.kotlin.idea.codeinsight.utils.LoopToCollectionTransformUtils
|
||||
import org.jetbrains.kotlin.idea.codeinsight.utils.LoopToCollectionTransformUtils.findGetCallAccess
|
||||
import org.jetbrains.kotlin.idea.codeinsight.utils.getImplicitReceiverInfo
|
||||
import org.jetbrains.kotlin.idea.codeinsight.utils.LoopToCollectionTransformUtils.transformLoop
|
||||
import org.jetbrains.kotlin.idea.codeinsight.utils.LoopToCollectionTransformUtils.transformLoopWithIndex
|
||||
import org.jetbrains.kotlin.idea.codeinsight.utils.RangeKtExpressionType
|
||||
import org.jetbrains.kotlin.idea.codeinsight.utils.RangeKtExpressionType.DOWN_TO
|
||||
import org.jetbrains.kotlin.idea.codeinsight.utils.RangeKtExpressionType.RANGE_TO
|
||||
import org.jetbrains.kotlin.idea.codeinsight.utils.RangeKtExpressionType.RANGE_UNTIL
|
||||
import org.jetbrains.kotlin.idea.codeinsight.utils.RangeKtExpressionType.UNTIL
|
||||
import org.jetbrains.kotlin.idea.codeinsight.utils.getImplicitReceiverInfo
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
@@ -45,11 +49,11 @@ import org.jetbrains.kotlin.psi.KtContainerNode
|
||||
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtForExpression
|
||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.KtParenthesizedExpression
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||
import org.jetbrains.kotlin.psi.KtQualifiedExpression
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.psi.KtThisExpression
|
||||
import org.jetbrains.kotlin.psi.KtVisitor
|
||||
import org.jetbrains.kotlin.psi.KtVisitorVoid
|
||||
@@ -94,7 +98,7 @@ class ReplaceManualRangeWithIndicesCallsInspection : KotlinApplicableInspectionB
|
||||
val indexUsagePattern: IndexUsagePattern,
|
||||
val implicitReceiverInfo: ImplicitReceiverInfo?,
|
||||
val suggestedElementName: String?,
|
||||
val arrayAccessUsages: List<SmartPsiElementPointer<KtArrayAccessExpression>>,
|
||||
val indexedAccessUsages: List<SmartPsiElementPointer<KtExpression>>, // Either KtArrayAccessExpression or KtDotQualifiedExpression
|
||||
)
|
||||
|
||||
private fun getProblemDescription(context: Context): @InspectionMessage String {
|
||||
@@ -164,15 +168,15 @@ class ReplaceManualRangeWithIndicesCallsInspection : KotlinApplicableInspectionB
|
||||
}
|
||||
} else null
|
||||
|
||||
// Store array access usages as smart pointers for use in quick fixes
|
||||
val arrayAccessPointers = indexUsageAnalysis.arrayAccessUsages.map { it.createSmartPointer() }
|
||||
// Store indexed access usages as smart pointers for use in quick fixes
|
||||
val indexedAccessPointers = indexUsageAnalysis.indexedAccessUsages.map { it.createSmartPointer() }
|
||||
|
||||
return Context(
|
||||
explicitReceiver,
|
||||
indexUsageAnalysis.pattern,
|
||||
implicitReceiverInfo,
|
||||
suggestedElementName,
|
||||
arrayAccessPointers
|
||||
indexedAccessPointers
|
||||
)
|
||||
}
|
||||
|
||||
@@ -231,18 +235,19 @@ class ReplaceManualRangeWithIndicesCallsInspection : KotlinApplicableInspectionB
|
||||
|
||||
/**
|
||||
* Result of analyzing how the loop index variable is used in the loop body.
|
||||
* Supports both bracket notation (`arr[i]`) and `.get()` method calls (`arr.get(i)`).
|
||||
*/
|
||||
private data class IndexUsageAnalysis(
|
||||
val pattern: IndexUsagePattern,
|
||||
val arrayAccessUsages: List<KtArrayAccessExpression>,
|
||||
val indexedAccessUsages: List<KtExpression>, // Either KtArrayAccessExpression or KtDotQualifiedExpression
|
||||
)
|
||||
|
||||
/**
|
||||
* Analyzes how the loop index variable is used in the loop body.
|
||||
*
|
||||
* @return IndexUsageAnalysis containing:
|
||||
* - pattern: ELEMENT_LOOP (all array accesses), WITH_INDEX (mixed), or INDICES_ONLY (no array accesses)
|
||||
* - arrayAccessUsages: list of valid array access expressions for transformation
|
||||
* - pattern: ELEMENT_LOOP (all indexed accesses), WITH_INDEX (mixed), or INDICES_ONLY (no indexed accesses)
|
||||
* - indexedAccessUsages: list of valid indexed access expressions for transformation
|
||||
*/
|
||||
private fun analyzeIndexUsagePattern(range: RangeExpression, explicitReceiver: KtExpression?): IndexUsageAnalysis {
|
||||
val forExpression = findContainingForLoop(range)
|
||||
@@ -253,51 +258,55 @@ class ReplaceManualRangeWithIndicesCallsInspection : KotlinApplicableInspectionB
|
||||
val usages = ReferencesSearch.search(loopParam).findAll()
|
||||
if (usages.isEmpty()) return IndexUsageAnalysis(IndexUsagePattern.INDICES_ONLY, emptyList())
|
||||
|
||||
val validArrayAccesses = mutableListOf<KtArrayAccessExpression>()
|
||||
val validIndexedAccesses = mutableListOf<KtExpression>()
|
||||
var otherUsageCount = 0
|
||||
|
||||
for (reference in usages) {
|
||||
val usage = reference.element
|
||||
val arrayAccess = usage.parents.match(KtContainerNode::class, last = KtArrayAccessExpression::class)
|
||||
|
||||
// Check for bracket notation: arr[i]
|
||||
val arrayAccess = usage.parents.match(KtContainerNode::class, last = KtArrayAccessExpression::class)
|
||||
if (arrayAccess != null && isValidElementLoopCandidate(arrayAccess, explicitReceiver)) {
|
||||
validArrayAccesses.add(arrayAccess)
|
||||
} else {
|
||||
otherUsageCount++
|
||||
validIndexedAccesses.add(arrayAccess)
|
||||
continue
|
||||
}
|
||||
|
||||
// Check for .get() method call: arr.get(i)
|
||||
val getCall = findGetCallAccess(usage)
|
||||
if (getCall != null && isValidGetCallCandidate(getCall, explicitReceiver)) {
|
||||
validIndexedAccesses.add(getCall)
|
||||
continue
|
||||
}
|
||||
|
||||
otherUsageCount++
|
||||
}
|
||||
|
||||
val pattern = when {
|
||||
validArrayAccesses.isNotEmpty() && otherUsageCount == 0 -> IndexUsagePattern.ELEMENT_LOOP
|
||||
validArrayAccesses.isNotEmpty() && otherUsageCount > 0 -> IndexUsagePattern.WITH_INDEX
|
||||
validIndexedAccesses.isNotEmpty() && otherUsageCount == 0 -> IndexUsagePattern.ELEMENT_LOOP
|
||||
validIndexedAccesses.isNotEmpty() && otherUsageCount > 0 -> IndexUsagePattern.WITH_INDEX
|
||||
else -> IndexUsagePattern.INDICES_ONLY
|
||||
}
|
||||
|
||||
return IndexUsageAnalysis(pattern, validArrayAccesses)
|
||||
return IndexUsageAnalysis(pattern, validIndexedAccesses)
|
||||
}
|
||||
|
||||
private fun findContainingForLoop(range: RangeExpression): KtForExpression? =
|
||||
range.expression.parents.match(KtContainerNode::class, last = KtForExpression::class)
|
||||
|
||||
private fun isValidElementLoopCandidate(arrayAccess: KtArrayAccessExpression, explicitReceiver: KtExpression?): Boolean {
|
||||
// Must use the loop parameter as the only index
|
||||
if (arrayAccess.indexExpressions.size != 1) return false
|
||||
return receiversMatch(arrayAccess.arrayExpression, explicitReceiver) && !arrayAccess.isAssignmentLHS()
|
||||
}
|
||||
|
||||
// Check if the array receiver matches the size call receiver
|
||||
val receiversMatch = if (explicitReceiver != null) {
|
||||
// Explicit receiver case: arr.size -> arr[i]
|
||||
(arrayAccess.arrayExpression as? KtSimpleNameExpression)?.getReferencedName() ==
|
||||
(explicitReceiver as? KtSimpleNameExpression)?.getReferencedName()
|
||||
} else {
|
||||
// Implicit receiver case: size -> this[i]
|
||||
arrayAccess.arrayExpression is KtThisExpression
|
||||
}
|
||||
private fun isValidGetCallCandidate(getCall: KtDotQualifiedExpression, explicitReceiver: KtExpression?): Boolean {
|
||||
return receiversMatch(getCall.receiverExpression, explicitReceiver) && !getCall.isAssignmentLHS()
|
||||
}
|
||||
|
||||
if (!receiversMatch) return false
|
||||
|
||||
// Don't suggest if array access is being assigned to (it's being modified)
|
||||
val parent = arrayAccess.parent
|
||||
return parent !is KtBinaryExpression || parent.left != arrayAccess || parent.operationToken !in KtTokens.ALL_ASSIGNMENTS
|
||||
private fun receiversMatch(accessReceiver: KtExpression?, explicitReceiver: KtExpression?): Boolean {
|
||||
if (explicitReceiver == null) return accessReceiver?.safeDeparenthesize() is KtThisExpression
|
||||
if (accessReceiver == null) return false
|
||||
return (accessReceiver as? KtNameReferenceExpression)?.mainReference?.resolve() ==
|
||||
(explicitReceiver as? KtNameReferenceExpression)?.mainReference?.resolve()
|
||||
}
|
||||
|
||||
private fun createQuickFixes(context: Context): List<KotlinModCommandQuickFix<KtExpression>> {
|
||||
@@ -390,14 +399,14 @@ class ReplaceManualRangeWithIndicesCallsInspection : KotlinApplicableInspectionB
|
||||
val loopRange = forExpression.loopRange ?: return
|
||||
val elementName = context.suggestedElementName ?: return
|
||||
|
||||
// Get writable array accesses from smart pointers
|
||||
val arrayAccesses = context.arrayAccessUsages.mapNotNull { pointer ->
|
||||
// Get writable indexed accesses from smart pointers
|
||||
val indexedAccesses = context.indexedAccessUsages.mapNotNull { pointer ->
|
||||
pointer.element?.let { updater.getWritable(it) }
|
||||
}
|
||||
if (arrayAccesses.isEmpty()) return
|
||||
if (indexedAccesses.isEmpty()) return
|
||||
|
||||
val collection = resolveCollectionExpression(project)
|
||||
LoopToCollectionTransformUtils.transformLoop(project, arrayAccesses, loopParameter, loopRange, collection, elementName)
|
||||
transformLoop(project, indexedAccesses, loopParameter, loopRange, collection, elementName)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -431,15 +440,15 @@ class ReplaceManualRangeWithIndicesCallsInspection : KotlinApplicableInspectionB
|
||||
val loopRange = forExpression.loopRange ?: return
|
||||
val elementName = context.suggestedElementName ?: return
|
||||
|
||||
// Get writable array accesses from smart pointers
|
||||
val arrayAccesses = context.arrayAccessUsages.mapNotNull { pointer ->
|
||||
// Get writable indexed accesses from smart pointers
|
||||
val indexedAccesses = context.indexedAccessUsages.mapNotNull { pointer ->
|
||||
pointer.element?.let { updater.getWritable(it) }
|
||||
}
|
||||
if (arrayAccesses.isEmpty()) return
|
||||
if (indexedAccesses.isEmpty()) return
|
||||
|
||||
val collection = resolveCollectionExpression(project)
|
||||
LoopToCollectionTransformUtils.transformLoopWithIndex(
|
||||
project, arrayAccesses, loopParameter, loopRange, collection, elementName
|
||||
transformLoopWithIndex(
|
||||
project, indexedAccesses, loopParameter, loopRange, collection, elementName
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+38
-18
@@ -2,14 +2,20 @@
|
||||
package org.jetbrains.kotlin.idea.codeinsight.utils
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
||||
import org.jetbrains.kotlin.psi.KtBlockStringTemplateEntry
|
||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
import org.jetbrains.kotlin.psi.KtValueArgument
|
||||
import org.jetbrains.kotlin.psi.KtValueArgumentList
|
||||
import org.jetbrains.kotlin.psi.createExpressionByPattern
|
||||
import org.jetbrains.kotlin.psi.psiUtil.canPlaceAfterSimpleNameEntry
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
import org.jetbrains.kotlin.util.match
|
||||
|
||||
/**
|
||||
* Utility functions for transforming index-based loops to collection loops.
|
||||
@@ -17,14 +23,27 @@ import org.jetbrains.kotlin.psi.psiUtil.canPlaceAfterSimpleNameEntry
|
||||
@ApiStatus.Internal
|
||||
object LoopToCollectionTransformUtils {
|
||||
|
||||
/**
|
||||
* Finds a `.get()` method call that contains the given usage element as its argument.
|
||||
*
|
||||
* @param usage the usage element (typically a reference to the loop parameter)
|
||||
* @return the [KtDotQualifiedExpression] representing the `.get()` call, or null if not found
|
||||
*/
|
||||
fun findGetCallAccess(usage: PsiElement): KtDotQualifiedExpression? {
|
||||
val callExpr = usage.parents.match(KtValueArgument::class, KtValueArgumentList::class, last = KtCallExpression::class)
|
||||
?: return null
|
||||
val isGetCall = callExpr.calleeExpression?.text == "get" && callExpr.valueArguments.size == 1
|
||||
return (callExpr.parent as? KtDotQualifiedExpression).takeIf { isGetCall }
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms an index-based loop to a collection-based loop by:
|
||||
* 1. Replacing the loop parameter with the provided element name
|
||||
* 2. Replacing all array access expressions with direct element references
|
||||
* 1. Replacing the loop parameter with the specified element name
|
||||
* 2. Replacing all indexed access expressions (both arr[i] and arr.get(i)) with direct element references
|
||||
* 3. Replacing the loop range with the collection expression
|
||||
*
|
||||
* @param project the current project
|
||||
* @param arrayAccesses array access expressions to replace with element references
|
||||
* @param indexedAccesses indexed access expressions to replace with element references (KtArrayAccessExpression or KtDotQualifiedExpression for .get())
|
||||
* @param loopParameter the original loop parameter
|
||||
* @param loopRange the original loop range
|
||||
* @param newLoopRange the new collection expression to iterate over
|
||||
@@ -32,7 +51,7 @@ object LoopToCollectionTransformUtils {
|
||||
*/
|
||||
fun transformLoop(
|
||||
project: Project,
|
||||
arrayAccesses: List<KtArrayAccessExpression>,
|
||||
indexedAccesses: List<KtExpression>,
|
||||
loopParameter: KtParameter,
|
||||
loopRange: KtExpression,
|
||||
newLoopRange: KtExpression,
|
||||
@@ -42,9 +61,9 @@ object LoopToCollectionTransformUtils {
|
||||
|
||||
val newParameter = factory.createLoopParameter(elementName)
|
||||
|
||||
// Replace all array access expressions with direct element references
|
||||
arrayAccesses.forEach { arrayAccess ->
|
||||
replaceArrayAccessWithElement(factory, arrayAccess, elementName)
|
||||
// Replace all indexed access expressions with direct element references
|
||||
indexedAccesses.forEach { accessExpr ->
|
||||
replaceIndexedAccessWithElement(factory, accessExpr, elementName)
|
||||
}
|
||||
|
||||
loopParameter.replace(newParameter)
|
||||
@@ -52,25 +71,26 @@ object LoopToCollectionTransformUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces an array access expression with a simple element reference.
|
||||
* Replaces an indexed access expression with a simple element reference.
|
||||
* Handles both bracket notation (arr[i]) and .get() method calls (arr.get(i)).
|
||||
* When inside a string template ${...}, creates the simplified $name form directly if possible.
|
||||
*/
|
||||
private fun replaceArrayAccessWithElement(factory: KtPsiFactory, arrayAccess: KtArrayAccessExpression, elementName: String) {
|
||||
val blockEntry = arrayAccess.parent as? KtBlockStringTemplateEntry
|
||||
private fun replaceIndexedAccessWithElement(factory: KtPsiFactory, accessExpr: KtExpression, elementName: String) {
|
||||
val blockEntry = accessExpr.parent as? KtBlockStringTemplateEntry
|
||||
if (blockEntry != null && canPlaceAfterSimpleNameEntry(blockEntry.nextSibling)) {
|
||||
blockEntry.replace(factory.createSimpleNameStringTemplateEntry(elementName))
|
||||
} else {
|
||||
arrayAccess.replace(factory.createExpression(elementName))
|
||||
accessExpr.replace(factory.createExpression(elementName))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms an index-based loop to a withIndex() loop by:
|
||||
* 1. Replacing the loop parameter with a destructuring declaration (indexName, elementName)
|
||||
* 2. Replacing array access expressions with direct element references
|
||||
* 2. Replacing indexed access expressions with direct element references
|
||||
* 3. Replacing the loop range with collection.withIndex()
|
||||
* @param project the current project
|
||||
* @param arrayAccesses array access expressions to replace with element references
|
||||
* @param indexedAccesses indexed access expressions to replace with element references (KtArrayAccessExpression or KtDotQualifiedExpression for .get())
|
||||
* @param loopParameter the original loop parameter (the index variable)
|
||||
* @param loopRange the original loop range
|
||||
* @param collectionExpression the collection to iterate with withIndex()
|
||||
@@ -78,7 +98,7 @@ object LoopToCollectionTransformUtils {
|
||||
*/
|
||||
fun transformLoopWithIndex(
|
||||
project: Project,
|
||||
arrayAccesses: List<KtArrayAccessExpression>,
|
||||
indexedAccesses: List<KtExpression>,
|
||||
loopParameter: KtParameter,
|
||||
loopRange: KtExpression,
|
||||
collectionExpression: KtExpression,
|
||||
@@ -90,9 +110,9 @@ object LoopToCollectionTransformUtils {
|
||||
val newParameter = factory.createDestructuringParameter("($indexName, $elementName)")
|
||||
val newLoopRange = factory.createExpressionByPattern("$0.withIndex()", collectionExpression)
|
||||
|
||||
// Replace all array access expressions with direct element references
|
||||
arrayAccesses.forEach { arrayAccess ->
|
||||
replaceArrayAccessWithElement(factory, arrayAccess, elementName)
|
||||
// Replace all indexed access expressions with direct element references
|
||||
indexedAccesses.forEach { accessExpr ->
|
||||
replaceIndexedAccessWithElement(factory, accessExpr, elementName)
|
||||
}
|
||||
|
||||
loopParameter.replace(newParameter)
|
||||
|
||||
+1
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.idea.base.codeInsight.KotlinNameSuggestionProvider
|
||||
import org.jetbrains.kotlin.idea.base.fe10.codeInsight.newDeclaration.Fe10KotlinNameSuggester
|
||||
import org.jetbrains.kotlin.idea.base.fe10.codeInsight.newDeclaration.Fe10KotlinNewDeclarationNameValidator
|
||||
import org.jetbrains.kotlin.idea.base.psi.isAssignmentLHS
|
||||
import org.jetbrains.kotlin.idea.base.psi.unifier.toRange
|
||||
import org.jetbrains.kotlin.idea.base.resources.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeInContext
|
||||
|
||||
+10
@@ -14411,6 +14411,16 @@ public abstract class LocalInspectionTestGenerated extends AbstractK1LocalInspec
|
||||
runTest("testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/forNotTarget.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("getMethod.kt")
|
||||
public void testGetMethod() throws Exception {
|
||||
runTest("testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/getMethod.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("getMethodDifferentArray.kt")
|
||||
public void testGetMethodDifferentArray() throws Exception {
|
||||
runTest("testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/getMethodDifferentArray.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("implicitReceiver.kt")
|
||||
public void testImplicitReceiver() throws Exception {
|
||||
runTest("testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/implicitReceiver.kt");
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// WITH_STDLIB
|
||||
// FIX: Replace with loop over elements
|
||||
fun test(args: Array<String>) {
|
||||
for (index in 0..ar<caret>gs.size - 1) {
|
||||
val out = args.get(index)
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// WITH_STDLIB
|
||||
// FIX: Replace with loop over elements
|
||||
fun test(args: Array<String>) {
|
||||
for (element in args) {
|
||||
val out = element
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// WITH_STDLIB
|
||||
// FIX: Replace with indices
|
||||
fun test(args: Array<String>, other: Array<String>) {
|
||||
for (index in 0..<caret>args.size - 1) {
|
||||
val a = args.get(index)
|
||||
val b = other.get(index)
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// WITH_STDLIB
|
||||
// FIX: Replace with indices
|
||||
fun test(args: Array<String>, other: Array<String>) {
|
||||
for (index in args.indices) {
|
||||
val a = args.get(index)
|
||||
val b = other.get(index)
|
||||
}
|
||||
}
|
||||
+1
-5
@@ -24,9 +24,9 @@ import org.jetbrains.kotlin.idea.refactoring.introduce.KotlinIntroduceVariableHe
|
||||
import org.jetbrains.kotlin.idea.refactoring.selectElement
|
||||
import org.jetbrains.kotlin.idea.util.ElementKind
|
||||
import org.jetbrains.kotlin.idea.util.application.isUnitTestMode
|
||||
import org.jetbrains.kotlin.idea.base.psi.isAssignmentLHS
|
||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||
import org.jetbrains.kotlin.psi.KtClassBody
|
||||
import org.jetbrains.kotlin.psi.KtConstructorCalleeExpression
|
||||
@@ -242,10 +242,6 @@ abstract class KotlinIntroduceVariableHandler : RefactoringActionHandler {
|
||||
protected companion object {
|
||||
val INTRODUCE_VARIABLE: String get() = KotlinBundle.message("introduce.variable")
|
||||
|
||||
fun PsiElement.isAssignmentLHS(): Boolean = parents.any {
|
||||
KtPsiUtil.isAssignment(it) && (it as KtBinaryExpression).left == this
|
||||
}
|
||||
|
||||
fun showErrorHint(project: Project, editor: Editor?, @NlsContexts.DialogMessage message: String) {
|
||||
CommonRefactoringUtil.showErrorHint(project, editor, message, INTRODUCE_VARIABLE, HelpID.INTRODUCE_VARIABLE)
|
||||
}
|
||||
|
||||
+1
@@ -51,6 +51,7 @@ import org.jetbrains.kotlin.idea.base.analysis.api.utils.getImplicitReceivers
|
||||
import org.jetbrains.kotlin.idea.base.analysis.api.utils.shortenReferences
|
||||
import org.jetbrains.kotlin.idea.base.codeInsight.KotlinDeclarationNameValidator
|
||||
import org.jetbrains.kotlin.idea.base.codeInsight.KotlinNameSuggestionProvider
|
||||
import org.jetbrains.kotlin.idea.base.psi.isAssignmentLHS
|
||||
import org.jetbrains.kotlin.idea.base.resources.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.codeinsight.utils.ConvertToBlockBodyUtils
|
||||
import org.jetbrains.kotlin.idea.codeinsight.utils.NamedArgumentUtils
|
||||
|
||||
Reference in New Issue
Block a user