diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt
index 37b3cbab23f..99207c3d726 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt
@@ -1,17 +1,6 @@
/*
- * Copyright 2010-2017 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Copyright 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.
*/
package org.jetbrains.kotlin.psi
@@ -85,6 +74,9 @@ class KtPsiFactory @JvmOverloads constructor(private val project: Project, val m
fun createThisExpression() =
(createExpression("this.x") as KtQualifiedExpression).receiverExpression as KtThisExpression
+ fun createThisExpression(qualifier: String) =
+ (createExpression("this@$qualifier.x") as KtQualifiedExpression).receiverExpression as KtThisExpression
+
fun createCallArguments(text: String): KtValueArgumentList {
val property = createProperty("val x = foo $text")
return (property.initializer as KtCallExpression).valueArgumentList!!
diff --git a/idea/resources/inspectionDescriptions/ScopeFunctionConversion.html b/idea/resources/inspectionDescriptions/ScopeFunctionConversion.html
new file mode 100644
index 00000000000..b4bbf752b87
--- /dev/null
+++ b/idea/resources/inspectionDescriptions/ScopeFunctionConversion.html
@@ -0,0 +1,5 @@
+
+
+Provides actions for converting scope functions ('let', 'run', 'apply', 'also') between each other.
+
+
\ No newline at end of file
diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 39429f72f16..77da28a49f4 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -2644,6 +2644,15 @@
language="kotlin"
/>
+
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/ScopeFunctionConversionInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/ScopeFunctionConversionInspection.kt
new file mode 100644
index 00000000000..4d5cae50a85
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/inspections/ScopeFunctionConversionInspection.kt
@@ -0,0 +1,364 @@
+/*
+ * 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.
+ */
+
+package org.jetbrains.kotlin.idea.inspections
+
+import com.intellij.codeInspection.*
+import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.fileEditor.FileEditorManager
+import com.intellij.openapi.project.Project
+import com.intellij.psi.PsiDocumentManager
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiElementVisitor
+import com.intellij.psi.SmartPsiElementPointer
+import com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler
+import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
+import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
+import org.jetbrains.kotlin.idea.caches.resolve.analyze
+import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
+import org.jetbrains.kotlin.idea.core.ShortenReferences
+import org.jetbrains.kotlin.idea.refactoring.getThisLabelName
+import org.jetbrains.kotlin.idea.references.resolveMainReferenceToDescriptors
+import org.jetbrains.kotlin.idea.util.getReceiverTargetDescriptor
+import org.jetbrains.kotlin.idea.util.getResolutionScope
+import org.jetbrains.kotlin.incremental.components.NoLookupLocation
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
+import org.jetbrains.kotlin.psi.psiUtil.endOffset
+import org.jetbrains.kotlin.psi.psiUtil.getOrCreateParameterList
+import org.jetbrains.kotlin.psi.psiUtil.startOffset
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.resolve.BindingContext.FUNCTION
+import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
+import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
+import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
+import org.jetbrains.kotlin.resolve.scopes.LexicalScope
+import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
+import org.jetbrains.kotlin.resolve.scopes.utils.collectDescriptorsFiltered
+import org.jetbrains.kotlin.resolve.scopes.utils.findVariable
+import org.jetbrains.kotlin.types.KotlinType
+
+private val counterpartNames = mapOf(
+ "apply" to "also",
+ "run" to "let",
+ "also" to "apply",
+ "let" to "run"
+)
+
+class ScopeFunctionConversionInspection : AbstractKotlinInspection() {
+ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor {
+ return callExpressionVisitor { expression ->
+ val counterpartName = getCounterpart(expression)
+ if (counterpartName != null) {
+ holder.registerProblem(
+ expression.calleeExpression!!,
+ "Call can be replaced with another scope function",
+ ProblemHighlightType.INFORMATION,
+ if (counterpartName == "also" || counterpartName == "let")
+ ConvertScopeFunctionToParameter(counterpartName)
+ else
+ ConvertScopeFunctionToReceiver(counterpartName)
+ )
+ }
+
+ }
+ }
+}
+
+private fun getCounterpart(expression: KtCallExpression): String? {
+ val callee = expression.calleeExpression as? KtNameReferenceExpression ?: return null
+ val calleeName = callee.getReferencedName()
+ val counterpartName = counterpartNames[calleeName]
+ val lambdaArgument = expression.lambdaArguments.singleOrNull()
+ if (counterpartName != null && lambdaArgument != null) {
+ if (lambdaArgument.getLambdaExpression().valueParameters.isNotEmpty()) {
+ return null
+ }
+ val bindingContext = callee.analyze(BodyResolveMode.PARTIAL)
+ val resolvedCall = callee.getResolvedCall(bindingContext) ?: return null
+ if (resolvedCall.resultingDescriptor.fqNameSafe.asString() == "kotlin.$calleeName" &&
+ nameResolvesToStdlib(expression, bindingContext, counterpartName)
+ ) {
+ return counterpartName
+ }
+ }
+ return null
+}
+
+private fun nameResolvesToStdlib(expression: KtCallExpression, bindingContext: BindingContext, name: String): Boolean {
+ val scope = expression.getResolutionScope(bindingContext) ?: return true
+ val descriptors = scope.collectDescriptorsFiltered(nameFilter = { it.asString() == name })
+ return descriptors.isNotEmpty() && descriptors.all { it.fqNameSafe.asString() == "kotlin.$name" }
+}
+
+class Replacement private constructor(
+ private val elementPointer: SmartPsiElementPointer,
+ private val replacementFactory: KtPsiFactory.(T) -> PsiElement
+) {
+ companion object {
+ fun create(element: T, replacementFactory: KtPsiFactory.(T) -> PsiElement): Replacement {
+ return Replacement(element.createSmartPointer(), replacementFactory)
+ }
+ }
+
+ fun apply(factory: KtPsiFactory) {
+ elementPointer.element?.let {
+ it.replace(factory.replacementFactory(it))
+ }
+ }
+
+ val endOffset
+ get() = elementPointer.element!!.endOffset
+}
+
+class ReplacementCollection {
+ private lateinit var project: Project
+ private val replacements = mutableListOf>()
+ var createParameter: KtPsiFactory.() -> PsiElement? = { null }
+ var elementToRename: PsiElement? = null
+
+ fun add(element: T, replacementFactory: KtPsiFactory.(T) -> PsiElement) {
+ project = element.project
+ replacements.add(Replacement.create(element, replacementFactory))
+ }
+
+ fun apply() {
+ if (replacements.isNotEmpty()) {
+ val factory = KtPsiFactory(project)
+ elementToRename = factory.createParameter()
+
+ // Calls need to be processed in outside-in order
+ replacements.sortBy { it.endOffset }
+
+ for (replacement in replacements) {
+ replacement.apply(factory)
+ }
+ }
+ }
+
+ fun isNotEmpty() = replacements.isNotEmpty()
+}
+
+abstract class ConvertScopeFunctionFix(private val counterpartName: String) : LocalQuickFix {
+ override fun getFamilyName() = "Convert to '$counterpartName'"
+
+ override fun applyFix(project: Project, problemDescriptor: ProblemDescriptor) {
+ val callee = problemDescriptor.psiElement as KtNameReferenceExpression
+ val callExpression = callee.parent as? KtCallExpression ?: return
+ val bindingContext = callExpression.analyze()
+
+ val lambda = callExpression.lambdaArguments.firstOrNull() ?: return
+ val functionLiteral = lambda.getLambdaExpression().functionLiteral
+ val lambdaDescriptor = bindingContext[FUNCTION, functionLiteral] ?: return
+
+ val replacements = ReplacementCollection()
+ analyzeLambda(bindingContext, lambda, lambdaDescriptor, replacements)
+ callee.replace(KtPsiFactory(project).createExpression(counterpartName) as KtNameReferenceExpression)
+ if (replacements.isNotEmpty()) {
+ replacements.apply()
+ }
+ postprocessLambda(lambda)
+
+ if (replacements.isNotEmpty() && replacements.elementToRename != null && !ApplicationManager.getApplication().isUnitTestMode) {
+ replacements.elementToRename!!.startInPlaceRename()
+ }
+ }
+
+ protected abstract fun postprocessLambda(lambda: KtLambdaArgument)
+
+ protected abstract fun analyzeLambda(
+ bindingContext: BindingContext,
+ lambda: KtLambdaArgument,
+ lambdaDescriptor: SimpleFunctionDescriptor,
+ replacements: ReplacementCollection
+ )
+}
+
+class ConvertScopeFunctionToParameter(counterpartName: String) : ConvertScopeFunctionFix(counterpartName) {
+ override fun analyzeLambda(
+ bindingContext: BindingContext,
+ lambda: KtLambdaArgument,
+ lambdaDescriptor: SimpleFunctionDescriptor,
+ replacements: ReplacementCollection
+ ) {
+ val project = lambda.project
+ val factory = KtPsiFactory(project)
+ val functionLiteral = lambda.getLambdaExpression().functionLiteral
+ val lambdaExtensionReceiver = lambdaDescriptor.extensionReceiverParameter
+ val lambdaDispatchReceiver = lambdaDescriptor.dispatchReceiverParameter
+
+ var parameterName = "it"
+ val scopes = mutableSetOf()
+ if (needUniqueNameForParameter(lambda, scopes)) {
+ val parameterType = lambdaExtensionReceiver?.type ?: lambdaDispatchReceiver?.type
+ parameterName = findUniqueParameterName(parameterType, scopes)
+ replacements.createParameter = {
+ val lambdaParameterList = functionLiteral.getOrCreateParameterList()
+ val parameterToAdd = createLambdaParameterList(parameterName).parameters.first()
+ lambdaParameterList.addParameterBefore(parameterToAdd, lambdaParameterList.parameters.firstOrNull())
+ }
+ }
+
+ lambda.accept(object : KtTreeVisitorVoid() {
+ override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) {
+ super.visitSimpleNameExpression(expression)
+ val resolvedCall = expression.getResolvedCall(bindingContext) ?: return
+ val dispatchReceiverTarget = resolvedCall.dispatchReceiver?.getReceiverTargetDescriptor(bindingContext)
+ val extensionReceiverTarget = resolvedCall.extensionReceiver?.getReceiverTargetDescriptor(bindingContext)
+ if (dispatchReceiverTarget == lambdaDescriptor || extensionReceiverTarget == lambdaDescriptor) {
+ val parent = expression.parent
+ if (parent is KtCallExpression && expression == parent.calleeExpression) {
+ replacements.add(parent) { element ->
+ factory.createExpressionByPattern("$0.$1", parameterName, element)
+ }
+ } else if (parent is KtQualifiedExpression && parent.receiverExpression is KtThisExpression) {
+ // do nothing
+ } else {
+ val referencedName = expression.getReferencedName()
+ replacements.add(expression) {
+ createExpression("$parameterName.$referencedName")
+ }
+ }
+ }
+ }
+
+ override fun visitThisExpression(expression: KtThisExpression) {
+ val resolvedCall = expression.getResolvedCall(bindingContext) ?: return
+ if (resolvedCall.resultingDescriptor == lambdaDispatchReceiver ||
+ resolvedCall.resultingDescriptor == lambdaExtensionReceiver) {
+ replacements.add(expression) { createExpression(parameterName) }
+ }
+ }
+ })
+ }
+
+ override fun postprocessLambda(lambda: KtLambdaArgument) {
+ ShortenReferences { ShortenReferences.Options(removeThisLabels = true) }.process(lambda) { element ->
+ if (element is KtThisExpression && element.getLabelName() != null)
+ ShortenReferences.FilterResult.PROCESS
+ else
+ ShortenReferences.FilterResult.GO_INSIDE
+ }
+ }
+
+ private fun needUniqueNameForParameter(
+ lambdaArgument: KtLambdaArgument,
+ scopes: MutableSet
+ ): Boolean {
+ val resolutionScope = lambdaArgument.getResolutionScope()
+ scopes.add(resolutionScope)
+ var needUniqueName = false
+ if (resolutionScope.findVariable(Name.identifier("it"), NoLookupLocation.FROM_IDE) != null) {
+ needUniqueName = true
+ // Don't return here - we still need to gather the list of nested scopes
+ }
+
+ lambdaArgument.accept(object : KtTreeVisitorVoid() {
+ override fun visitDeclaration(dcl: KtDeclaration) {
+ super.visitDeclaration(dcl)
+ checkNeedUniqueName(dcl)
+ }
+
+ override fun visitLambdaExpression(lambdaExpression: KtLambdaExpression) {
+ super.visitLambdaExpression(lambdaExpression)
+ lambdaExpression.bodyExpression?.statements?.firstOrNull()?.let { checkNeedUniqueName(it) }
+ }
+
+ private fun checkNeedUniqueName(dcl: KtElement) {
+ val nestedResolutionScope = dcl.getResolutionScope()
+ scopes.add(nestedResolutionScope)
+ if (nestedResolutionScope.findVariable(Name.identifier("it"), NoLookupLocation.FROM_IDE) != null) {
+ needUniqueName = true
+ }
+ }
+ })
+
+ return needUniqueName
+ }
+
+
+ private fun findUniqueParameterName(
+ parameterType: KotlinType?,
+ resolutionScopes: Collection
+ ): String {
+ fun isNameUnique(parameterName: String): Boolean {
+ return resolutionScopes.none { it.findVariable(Name.identifier(parameterName), NoLookupLocation.FROM_IDE) != null }
+ }
+
+ return if (parameterType != null)
+ KotlinNameSuggester.suggestNamesByType(parameterType, ::isNameUnique).first()
+ else {
+ KotlinNameSuggester.suggestNameByName("p", ::isNameUnique)
+ }
+ }
+}
+
+class ConvertScopeFunctionToReceiver(counterpartName: String) : ConvertScopeFunctionFix(counterpartName) {
+ override fun analyzeLambda(
+ bindingContext: BindingContext,
+ lambda: KtLambdaArgument,
+ lambdaDescriptor: SimpleFunctionDescriptor,
+ replacements: ReplacementCollection
+ ) {
+ lambda.accept(object : KtTreeVisitorVoid() {
+ override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) {
+ super.visitSimpleNameExpression(expression)
+ if (expression.getReferencedName() == "it") {
+ val result = expression.resolveMainReferenceToDescriptors().singleOrNull()
+ if (result is ValueParameterDescriptor && result.containingDeclaration == lambdaDescriptor) {
+ replacements.add(expression) { createThisExpression() }
+ }
+ } else {
+ val resolvedCall = expression.getResolvedCall(bindingContext) ?: return
+ val dispatchReceiver = resolvedCall.dispatchReceiver
+ if (dispatchReceiver is ImplicitReceiver) {
+ val parent = expression.parent
+ val thisLabelName = dispatchReceiver.declarationDescriptor.getThisLabelName()
+ if (parent is KtCallExpression && expression == parent.calleeExpression) {
+ replacements.add(parent) { element ->
+ createExpressionByPattern("this@$0.$1", thisLabelName, element)
+ }
+ } else {
+ val referencedName = expression.getReferencedName()
+ replacements.add(expression) {
+ createExpression("this@$thisLabelName.$referencedName")
+ }
+ }
+ }
+ }
+ }
+
+ override fun visitThisExpression(expression: KtThisExpression) {
+ val resolvedCall = expression.getResolvedCall(bindingContext) ?: return
+ val qualifierName = resolvedCall.resultingDescriptor.containingDeclaration.name
+ replacements.add(expression) { createThisExpression(qualifierName.asString()) }
+ }
+ })
+ }
+
+ override fun postprocessLambda(lambda: KtLambdaArgument) {
+ ShortenReferences { ShortenReferences.Options(removeThis = true, removeThisLabels = true) }.process(lambda) { element ->
+ if (element is KtThisExpression && element.getLabelName() != null)
+ ShortenReferences.FilterResult.PROCESS
+ else if (element is KtQualifiedExpression && element.receiverExpression is KtThisExpression)
+ ShortenReferences.FilterResult.PROCESS
+ else
+ ShortenReferences.FilterResult.GO_INSIDE
+ }
+ }
+}
+
+private fun PsiElement.startInPlaceRename() {
+ val project = project
+ val document = containingFile.viewProvider.document ?: return
+ val editor = FileEditorManager.getInstance(project).selectedTextEditor ?: return
+ if (editor.document == document) {
+ PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.document)
+
+ editor.caretModel.moveToOffset(startOffset)
+ VariableInplaceRenameHandler().doRename(this, editor, null)
+ }
+}
diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/kotlinRefactoringUtil.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/kotlinRefactoringUtil.kt
index 88978d1b09c..b2343e05ed1 100644
--- a/idea/src/org/jetbrains/kotlin/idea/refactoring/kotlinRefactoringUtil.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/kotlinRefactoringUtil.kt
@@ -1,17 +1,6 @@
/*
- * Copyright 2010-2016 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Copyright 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.
*/
package org.jetbrains.kotlin.idea.refactoring
@@ -835,6 +824,7 @@ internal fun DeclarationDescriptor.getThisLabelName(): String {
if (this is AnonymousFunctionDescriptor) {
val function = source.getPsi() as? KtFunction
val argument = function?.parent as? KtValueArgument
+ ?: (function?.parent as? KtLambdaExpression)?.parent as? KtValueArgument
val callElement = argument?.getStrictParentOfType()
val callee = callElement?.calleeExpression as? KtSimpleNameExpression
if (callee != null) return callee.text
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/.inspection b/idea/testData/inspectionsLocal/scopeFunctions/.inspection
new file mode 100644
index 00000000000..175389c51cb
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/.inspection
@@ -0,0 +1 @@
+org.jetbrains.kotlin.idea.inspections.ScopeFunctionConversionInspection
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/alsoToApply/simple.kt b/idea/testData/inspectionsLocal/scopeFunctions/alsoToApply/simple.kt
new file mode 100644
index 00000000000..5762ea6a087
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/alsoToApply/simple.kt
@@ -0,0 +1,5 @@
+// WITH_RUNTIME
+
+val x = "".also {
+ it.length
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/alsoToApply/simple.kt.after b/idea/testData/inspectionsLocal/scopeFunctions/alsoToApply/simple.kt.after
new file mode 100644
index 00000000000..c08ae9b07e2
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/alsoToApply/simple.kt.after
@@ -0,0 +1,5 @@
+// WITH_RUNTIME
+
+val x = "".apply {
+ length
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/doubleNestedLambdas.kt b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/doubleNestedLambdas.kt
new file mode 100644
index 00000000000..853d70940fe
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/doubleNestedLambdas.kt
@@ -0,0 +1,9 @@
+// WITH_RUNTIME
+
+val x = hashSetOf("abc").apply {
+ forEach {
+ forEach {
+ println(this)
+ }
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/doubleNestedLambdas.kt.after b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/doubleNestedLambdas.kt.after
new file mode 100644
index 00000000000..02d8751511d
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/doubleNestedLambdas.kt.after
@@ -0,0 +1,9 @@
+// WITH_RUNTIME
+
+val x = hashSetOf("abc").also { hashSet ->
+ hashSet.forEach {
+ hashSet.forEach {
+ println(hashSet)
+ }
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/innerLambda.kt b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/innerLambda.kt
new file mode 100644
index 00000000000..90ffcdbe1b6
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/innerLambda.kt
@@ -0,0 +1,8 @@
+// WITH_RUNTIME
+// FIX: Convert to 'also'
+
+val x = "".also {
+ "".apply {
+ this.length + it.length
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/innerLambda.kt.after b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/innerLambda.kt.after
new file mode 100644
index 00000000000..917230b66fd
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/innerLambda.kt.after
@@ -0,0 +1,8 @@
+// WITH_RUNTIME
+// FIX: Convert to 'also'
+
+val x = "".also {
+ "".also { s ->
+ s.length + it.length
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/itInNestedLambda.kt b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/itInNestedLambda.kt
new file mode 100644
index 00000000000..ae1a5a60f99
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/itInNestedLambda.kt
@@ -0,0 +1,7 @@
+// WITH_RUNTIME
+
+val x = hashSetOf("abc").apply {
+ forEach {
+ println(this)
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/itInNestedLambda.kt.after b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/itInNestedLambda.kt.after
new file mode 100644
index 00000000000..04107772bc1
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/itInNestedLambda.kt.after
@@ -0,0 +1,7 @@
+// WITH_RUNTIME
+
+val x = hashSetOf("abc").also { hashSet ->
+ hashSet.forEach {
+ println(hashSet)
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/method.kt b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/method.kt
new file mode 100644
index 00000000000..6da2ead8f37
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/method.kt
@@ -0,0 +1,6 @@
+// WITH_RUNTIME
+// FIX: Convert to 'also'
+
+val x = hashSetOf().apply {
+ add("x")
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/method.kt.after b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/method.kt.after
new file mode 100644
index 00000000000..15b6c3979bd
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/method.kt.after
@@ -0,0 +1,6 @@
+// WITH_RUNTIME
+// FIX: Convert to 'also'
+
+val x = hashSetOf().also {
+ it.add("x")
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/outerLambda.kt b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/outerLambda.kt
new file mode 100644
index 00000000000..5a32a53dd5d
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/outerLambda.kt
@@ -0,0 +1,9 @@
+// WITH_RUNTIME
+// FIX: Convert to 'also'
+
+val x = "".apply {
+ "".apply {
+ this.length
+ length
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/outerLambda.kt.after b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/outerLambda.kt.after
new file mode 100644
index 00000000000..ab8897ddb34
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/outerLambda.kt.after
@@ -0,0 +1,9 @@
+// WITH_RUNTIME
+// FIX: Convert to 'also'
+
+val x = "".also {
+ "".apply {
+ this.length
+ length
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/simple.kt b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/simple.kt
new file mode 100644
index 00000000000..205ca70898a
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/simple.kt
@@ -0,0 +1,7 @@
+// WITH_RUNTIME
+// FIX: Convert to 'also'
+
+val x = "".apply {
+ this.length
+ length
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/simple.kt.after b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/simple.kt.after
new file mode 100644
index 00000000000..3deac90bcba
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/simple.kt.after
@@ -0,0 +1,7 @@
+// WITH_RUNTIME
+// FIX: Convert to 'also'
+
+val x = "".also {
+ it.length
+ it.length
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/thisQualifier.kt b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/thisQualifier.kt
new file mode 100644
index 00000000000..1db942152cf
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/thisQualifier.kt
@@ -0,0 +1,8 @@
+// WITH_RUNTIME
+// FIX: Convert to 'also'
+
+class C {
+ val x = hashSetOf().apply {
+ add(this@C)
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/thisQualifier.kt.after b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/thisQualifier.kt.after
new file mode 100644
index 00000000000..b408322298c
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/thisQualifier.kt.after
@@ -0,0 +1,8 @@
+// WITH_RUNTIME
+// FIX: Convert to 'also'
+
+class C {
+ val x = hashSetOf().also {
+ it.add(this)
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/letToRun/nestedLambda.kt b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/nestedLambda.kt
new file mode 100644
index 00000000000..f3d4fdc62ba
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/nestedLambda.kt
@@ -0,0 +1,7 @@
+// WITH_RUNTIME
+
+val x = hashSetOf("abc").let {
+ it.forEach {
+ println(it)
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/letToRun/nestedLambda.kt.after b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/nestedLambda.kt.after
new file mode 100644
index 00000000000..083955a0f1c
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/nestedLambda.kt.after
@@ -0,0 +1,7 @@
+// WITH_RUNTIME
+
+val x = hashSetOf("abc").run {
+ forEach {
+ println(it)
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/letToRun/outerThis.kt b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/outerThis.kt
new file mode 100644
index 00000000000..b69435a15de
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/outerThis.kt
@@ -0,0 +1,7 @@
+// WITH_RUNTIME
+
+class C {
+ val c = "abc".let {
+ println(it + this)
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/letToRun/outerThis.kt.after b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/outerThis.kt.after
new file mode 100644
index 00000000000..4d7d9bd6bc0
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/outerThis.kt.after
@@ -0,0 +1,7 @@
+// WITH_RUNTIME
+
+class C {
+ val c = "abc".run {
+ println(this + this@C)
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThis.kt b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThis.kt
new file mode 100644
index 00000000000..83b34362741
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThis.kt
@@ -0,0 +1,15 @@
+// WITH_RUNTIME
+
+class C {
+ fun foo() = "c"
+ val bar = "C"
+}
+
+class D {
+ fun foo() = "d"
+ val bar = "D"
+
+ val x = C().let {
+ foo() + it.foo() + bar + it.bar
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThis.kt.after b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThis.kt.after
new file mode 100644
index 00000000000..ffc5d92e899
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThis.kt.after
@@ -0,0 +1,15 @@
+// WITH_RUNTIME
+
+class C {
+ fun foo() = "c"
+ val bar = "C"
+}
+
+class D {
+ fun foo() = "d"
+ val bar = "D"
+
+ val x = C().run {
+ this@D.foo() + foo() + this@D.bar + bar
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThisNoConflict.kt b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThisNoConflict.kt
new file mode 100644
index 00000000000..3d7dfaf3d41
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThisNoConflict.kt
@@ -0,0 +1,15 @@
+// WITH_RUNTIME
+
+class C {
+ fun foo(s: String, s2: String = ""): String = "c"
+ val bar = "C"
+}
+
+class D {
+ fun baz(s: String): String = "d"
+ val quux = "D"
+
+ val x = C().let {
+ it.foo(baz(it.foo(quux + it.bar)), baz(it.bar))
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThisNoConflict.kt.after b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThisNoConflict.kt.after
new file mode 100644
index 00000000000..987f6d03453
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThisNoConflict.kt.after
@@ -0,0 +1,15 @@
+// WITH_RUNTIME
+
+class C {
+ fun foo(s: String, s2: String = ""): String = "c"
+ val bar = "C"
+}
+
+class D {
+ fun baz(s: String): String = "d"
+ val quux = "D"
+
+ val x = C().run {
+ foo(baz(foo(quux + bar)), baz(bar))
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThisWithLambda.kt b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThisWithLambda.kt
new file mode 100644
index 00000000000..3bfe7c7a13c
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThisWithLambda.kt
@@ -0,0 +1,19 @@
+// WITH_RUNTIME
+
+class C {
+ fun foo() = "c"
+ val bar = "C"
+}
+
+class D {
+ fun foo() = "d"
+ val bar = "D"
+
+}
+
+val d = D()
+val x = d.apply {
+ C().let {
+ foo() + it.foo() + bar + it.bar
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThisWithLambda.kt.after b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThisWithLambda.kt.after
new file mode 100644
index 00000000000..0779c05d46b
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThisWithLambda.kt.after
@@ -0,0 +1,19 @@
+// WITH_RUNTIME
+
+class C {
+ fun foo() = "c"
+ val bar = "C"
+}
+
+class D {
+ fun foo() = "d"
+ val bar = "D"
+
+}
+
+val d = D()
+val x = d.apply {
+ C().run {
+ this@apply.foo() + foo() + this@apply.bar + bar
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThisWithLambdaNoConflict.kt b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThisWithLambdaNoConflict.kt
new file mode 100644
index 00000000000..6f3f9b27918
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThisWithLambdaNoConflict.kt
@@ -0,0 +1,19 @@
+// WITH_RUNTIME
+
+class C {
+ fun foo() = "c"
+ val bar = "C"
+}
+
+class D {
+ fun baz() = "d"
+ val quux = "D"
+
+}
+
+val d = D()
+val x = d.apply {
+ C().let {
+ baz() + it.foo() + quux + it.bar
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThisWithLambdaNoConflict.kt.after b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThisWithLambdaNoConflict.kt.after
new file mode 100644
index 00000000000..ca16a32433e
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThisWithLambdaNoConflict.kt.after
@@ -0,0 +1,19 @@
+// WITH_RUNTIME
+
+class C {
+ fun foo() = "c"
+ val bar = "C"
+}
+
+class D {
+ fun baz() = "d"
+ val quux = "D"
+
+}
+
+val d = D()
+val x = d.apply {
+ C().run {
+ baz() + foo() + quux + bar
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/letToRun/simple.kt b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/simple.kt
new file mode 100644
index 00000000000..18dc9809f0b
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/simple.kt
@@ -0,0 +1,6 @@
+// WITH_RUNTIME
+// FIX: Convert to 'run'
+
+val x = "".let {
+ it.length
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/letToRun/simple.kt.after b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/simple.kt.after
new file mode 100644
index 00000000000..8f58bd93179
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/simple.kt.after
@@ -0,0 +1,6 @@
+// WITH_RUNTIME
+// FIX: Convert to 'run'
+
+val x = "".run {
+ length
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/letToRun/thisInStringTemplate.kt b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/thisInStringTemplate.kt
new file mode 100644
index 00000000000..527e0236938
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/thisInStringTemplate.kt
@@ -0,0 +1,7 @@
+// WITH_RUNTIME
+
+class C {
+ val c = "abc".let {
+ println("$it")
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/letToRun/thisInStringTemplate.kt.after b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/thisInStringTemplate.kt.after
new file mode 100644
index 00000000000..6d65e9d527b
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/letToRun/thisInStringTemplate.kt.after
@@ -0,0 +1,7 @@
+// WITH_RUNTIME
+
+class C {
+ val c = "abc".run {
+ println("$this")
+ }
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/runToLet/simple.kt b/idea/testData/inspectionsLocal/scopeFunctions/runToLet/simple.kt
new file mode 100644
index 00000000000..94784debe15
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/runToLet/simple.kt
@@ -0,0 +1,7 @@
+// WITH_RUNTIME
+// FIX: Convert to 'let'
+
+val x = "".run {
+ this.length
+ length
+}
diff --git a/idea/testData/inspectionsLocal/scopeFunctions/runToLet/simple.kt.after b/idea/testData/inspectionsLocal/scopeFunctions/runToLet/simple.kt.after
new file mode 100644
index 00000000000..74db8594d4c
--- /dev/null
+++ b/idea/testData/inspectionsLocal/scopeFunctions/runToLet/simple.kt.after
@@ -0,0 +1,7 @@
+// WITH_RUNTIME
+// FIX: Convert to 'let'
+
+val x = "".let {
+ it.length
+ it.length
+}
diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
index 580287ddf09..5931a92d115 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
@@ -3421,6 +3421,153 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
}
}
+ @TestMetadata("idea/testData/inspectionsLocal/scopeFunctions")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class ScopeFunctions extends AbstractLocalInspectionTest {
+ public void testAllFilesPresentInScopeFunctions() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/scopeFunctions"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
+ }
+
+ @TestMetadata("idea/testData/inspectionsLocal/scopeFunctions/alsoToApply")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class AlsoToApply extends AbstractLocalInspectionTest {
+ public void testAllFilesPresentInAlsoToApply() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/scopeFunctions/alsoToApply"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
+ }
+
+ @TestMetadata("simple.kt")
+ public void testSimple() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/scopeFunctions/alsoToApply/simple.kt");
+ doTest(fileName);
+ }
+ }
+
+ @TestMetadata("idea/testData/inspectionsLocal/scopeFunctions/applyToAlso")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class ApplyToAlso extends AbstractLocalInspectionTest {
+ public void testAllFilesPresentInApplyToAlso() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/scopeFunctions/applyToAlso"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
+ }
+
+ @TestMetadata("doubleNestedLambdas.kt")
+ public void testDoubleNestedLambdas() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/doubleNestedLambdas.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("innerLambda.kt")
+ public void testInnerLambda() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/innerLambda.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("itInNestedLambda.kt")
+ public void testItInNestedLambda() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/itInNestedLambda.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("method.kt")
+ public void testMethod() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/method.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("outerLambda.kt")
+ public void testOuterLambda() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/outerLambda.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("simple.kt")
+ public void testSimple() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/simple.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("thisQualifier.kt")
+ public void testThisQualifier() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/scopeFunctions/applyToAlso/thisQualifier.kt");
+ doTest(fileName);
+ }
+ }
+
+ @TestMetadata("idea/testData/inspectionsLocal/scopeFunctions/letToRun")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class LetToRun extends AbstractLocalInspectionTest {
+ public void testAllFilesPresentInLetToRun() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/scopeFunctions/letToRun"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
+ }
+
+ @TestMetadata("nestedLambda.kt")
+ public void testNestedLambda() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/scopeFunctions/letToRun/nestedLambda.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("outerThis.kt")
+ public void testOuterThis() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/scopeFunctions/letToRun/outerThis.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("qualifyThis.kt")
+ public void testQualifyThis() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThis.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("qualifyThisNoConflict.kt")
+ public void testQualifyThisNoConflict() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThisNoConflict.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("qualifyThisWithLambda.kt")
+ public void testQualifyThisWithLambda() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThisWithLambda.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("qualifyThisWithLambdaNoConflict.kt")
+ public void testQualifyThisWithLambdaNoConflict() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/scopeFunctions/letToRun/qualifyThisWithLambdaNoConflict.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("simple.kt")
+ public void testSimple() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/scopeFunctions/letToRun/simple.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("thisInStringTemplate.kt")
+ public void testThisInStringTemplate() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/scopeFunctions/letToRun/thisInStringTemplate.kt");
+ doTest(fileName);
+ }
+ }
+
+ @TestMetadata("idea/testData/inspectionsLocal/scopeFunctions/runToLet")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class RunToLet extends AbstractLocalInspectionTest {
+ public void testAllFilesPresentInRunToLet() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/scopeFunctions/runToLet"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
+ }
+
+ @TestMetadata("simple.kt")
+ public void testSimple() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/scopeFunctions/runToLet/simple.kt");
+ doTest(fileName);
+ }
+ }
+ }
+
@TestMetadata("idea/testData/inspectionsLocal/selfAssignment")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)