Drop UNREACHABLE_CODE eager text range calculation

#KT-35242 Fixed
This commit is contained in:
Vladimir Dolzhenko
2019-12-04 17:47:21 +01:00
parent 9e4d7df86e
commit 272ca002d7
19 changed files with 321 additions and 126 deletions
@@ -281,7 +281,7 @@ class ControlFlowInformationProvider private constructor(
private fun reportUnreachableCode(unreachableCode: UnreachableCode) {
for (element in unreachableCode.elements) {
trace.report(Errors.UNREACHABLE_CODE.on(element, unreachableCode.getUnreachableTextRanges(element)))
trace.report(Errors.UNREACHABLE_CODE.on(element, unreachableCode.reachableElements, unreachableCode.unreachableElements))
}
}
@@ -29,97 +29,112 @@ import java.util.*
interface UnreachableCode {
val elements: Set<KtElement>
fun getUnreachableTextRanges(element: KtElement): List<TextRange>
val reachableElements: Set<KtElement>
val unreachableElements: Set<KtElement>
companion object {
fun getUnreachableTextRanges(
element: KtElement,
reachableElements: Set<KtElement>,
unreachableElements: Set<KtElement>
): List<TextRange> {
return if (element.hasChildrenInSet(reachableElements)) {
with(
element.getLeavesOrReachableChildren(reachableElements, unreachableElements)
.removeReachableElementsWithMeaninglessSiblings(reachableElements).mergeAdjacentTextRanges()
) {
if (isNotEmpty()) this
// Specific case like condition in when:
// element is dead but its only child is alive and has the same text range
else listOf(element.textRange.endOffset.let { TextRange(it, it) })
}
} else {
listOf(element.textRange!!)
}
}
private fun KtElement.hasChildrenInSet(set: Set<KtElement>): Boolean =
PsiTreeUtil.collectElements(this) { it != this }.any { it in set }
private fun KtElement.getLeavesOrReachableChildren(
reachableElements: Set<KtElement>,
unreachableElements: Set<KtElement>
): List<PsiElement> {
val children = ArrayList<PsiElement>()
acceptChildren(object : PsiElementVisitor() {
override fun visitElement(element: PsiElement) {
val isReachable =
element is KtElement && reachableElements.contains(element) && !element.hasChildrenInSet(unreachableElements)
if (isReachable || element.children.isEmpty()) {
children.add(element)
} else {
element.acceptChildren(this)
}
}
})
return children
}
private fun List<PsiElement>.removeReachableElementsWithMeaninglessSiblings(reachableElements: Set<KtElement>): List<PsiElement> {
fun PsiElement.isMeaningless() = this is PsiWhiteSpace
|| this.node?.elementType == KtTokens.COMMA
|| this is PsiComment
val childrenToRemove = HashSet<PsiElement>()
fun collectSiblingsIfMeaningless(elementIndex: Int, direction: Int) {
val index = elementIndex + direction
if (index !in 0 until size) return
val element = this[index]
if (element.isMeaningless()) {
childrenToRemove.add(element)
collectSiblingsIfMeaningless(index, direction)
}
}
for ((index, element) in this.withIndex()) {
if (reachableElements.contains(element)) {
childrenToRemove.add(element)
collectSiblingsIfMeaningless(index, -1)
collectSiblingsIfMeaningless(index, 1)
}
}
return this.filter { it !in childrenToRemove }
}
private fun List<PsiElement>.mergeAdjacentTextRanges(): List<TextRange> {
val result = ArrayList<TextRange>()
val lastRange = fold(null as TextRange?) { currentTextRange, element ->
val elementRange = element.textRange!!
when {
currentTextRange == null -> {
elementRange
}
currentTextRange.endOffset == elementRange.startOffset -> {
currentTextRange.union(elementRange)
}
else -> {
result.add(currentTextRange)
elementRange
}
}
}
if (lastRange != null) {
result.add(lastRange)
}
return result
}
}
}
class UnreachableCodeImpl(
private val reachableElements: Set<KtElement>,
private val unreachableElements: Set<KtElement>
override val reachableElements: Set<KtElement>,
override val unreachableElements: Set<KtElement>
) : UnreachableCode {
// This is needed in order to highlight only '1 < 2' and not '1', '<' and '2' as well
override val elements: Set<KtElement> = KtPsiUtil.findRootExpressions(unreachableElements)
override fun getUnreachableTextRanges(element: KtElement): List<TextRange> {
return if (element.hasChildrenInSet(reachableElements)) {
with(element.getLeavesOrReachableChildren().removeReachableElementsWithMeaninglessSiblings().mergeAdjacentTextRanges()) {
if (isNotEmpty()) this
// Specific case like condition in when:
// element is dead but its only child is alive and has the same text range
else listOf(element.textRange.endOffset.let { TextRange(it, it) })
}
} else {
listOf(element.textRange!!)
}
}
private fun KtElement.hasChildrenInSet(set: Set<KtElement>): Boolean =
PsiTreeUtil.collectElements(this) { it != this }.any { it in set }
private fun KtElement.getLeavesOrReachableChildren(): List<PsiElement> {
val children = ArrayList<PsiElement>()
acceptChildren(object : PsiElementVisitor() {
override fun visitElement(element: PsiElement) {
val isReachable =
element is KtElement && reachableElements.contains(element) && !element.hasChildrenInSet(unreachableElements)
if (isReachable || element.children.isEmpty()) {
children.add(element)
} else {
element.acceptChildren(this)
}
}
})
return children
}
private fun List<PsiElement>.removeReachableElementsWithMeaninglessSiblings(): List<PsiElement> {
fun PsiElement.isMeaningless() = this is PsiWhiteSpace
|| this.node?.elementType == KtTokens.COMMA
|| this is PsiComment
val childrenToRemove = HashSet<PsiElement>()
fun collectSiblingsIfMeaningless(elementIndex: Int, direction: Int) {
val index = elementIndex + direction
if (index !in 0..(size - 1)) return
val element = this[index]
if (element.isMeaningless()) {
childrenToRemove.add(element)
collectSiblingsIfMeaningless(index, direction)
}
}
for ((index, element) in this.withIndex()) {
if (reachableElements.contains(element)) {
childrenToRemove.add(element)
collectSiblingsIfMeaningless(index, -1)
collectSiblingsIfMeaningless(index, 1)
}
}
return this.filter { it !in childrenToRemove }
}
private fun List<PsiElement>.mergeAdjacentTextRanges(): List<TextRange> {
val result = ArrayList<TextRange>()
val lastRange = fold(null as TextRange?) { currentTextRange, element ->
val elementRange = element.textRange!!
when {
currentTextRange == null -> {
elementRange
}
currentTextRange.endOffset == elementRange.startOffset -> {
currentTextRange.union(elementRange)
}
else -> {
result.add(currentTextRange)
elementRange
}
}
}
if (lastRange != null) {
result.add(lastRange)
}
return result
}
}
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.diagnostics;
import com.google.common.collect.ImmutableSet;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import kotlin.Pair;
@@ -37,6 +36,7 @@ import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.jetbrains.kotlin.diagnostics.PositioningStrategies.*;
import static org.jetbrains.kotlin.diagnostics.Severity.*;
@@ -886,7 +886,7 @@ public interface Errors {
// Control flow / Data flow
DiagnosticFactory1<KtElement, List<TextRange>> UNREACHABLE_CODE = DiagnosticFactory1.create(
DiagnosticFactory2<KtElement, Set<KtElement>, Set<KtElement>> UNREACHABLE_CODE = DiagnosticFactory2.create(
WARNING, PositioningStrategies.UNREACHABLE_CODE);
DiagnosticFactory0<KtVariableDeclaration> VARIABLE_WITH_NO_TYPE_NO_INITIALIZER = DiagnosticFactory0.create(ERROR, DECLARATION_NAME);
@@ -21,6 +21,7 @@ import com.intellij.psi.PsiElement
import com.intellij.psi.PsiNameIdentifierOwner
import com.intellij.psi.tree.TokenSet
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.cfg.UnreachableCode
import org.jetbrains.kotlin.diagnostics.Errors.ACTUAL_WITHOUT_EXPECT
import org.jetbrains.kotlin.diagnostics.Errors.NO_ACTUAL_FOR_EXPECT
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
@@ -579,7 +580,8 @@ object PositioningStrategies {
@JvmField
val UNREACHABLE_CODE: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
override fun markDiagnostic(diagnostic: ParametrizedDiagnostic<out PsiElement>): List<TextRange> {
return Errors.UNREACHABLE_CODE.cast(diagnostic).a
val unreachableCode = Errors.UNREACHABLE_CODE.cast(diagnostic)
return UnreachableCode.getUnreachableTextRanges(unreachableCode.psiElement, unreachableCode.a, unreachableCode.b)
}
}
@@ -351,7 +351,7 @@ public class DefaultErrorMessages {
MAP.put(VAL_OR_VAR_ON_CATCH_PARAMETER, "''{0}'' on catch parameter is not allowed", TO_STRING);
MAP.put(VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER, "''{0}'' on secondary constructor parameter is not allowed", TO_STRING);
MAP.put(UNREACHABLE_CODE, "Unreachable code", TO_STRING);
MAP.put(UNREACHABLE_CODE, "Unreachable code", EMPTY, EMPTY);
MAP.put(MANY_COMPANION_OBJECTS, "Only one companion object is allowed per class");
@@ -67,6 +67,9 @@ object Renderers {
element.toString()
}
@JvmField
val EMPTY = Renderer<Any> { "" }
@JvmField
val STRING = Renderer<String> { it }
@@ -620,6 +620,10 @@ fun main(args: Array<String>) {
model("codeInsight/outOfBlock", pattern = KT_OR_KTS)
}
testClass<AbstractChangeLocalityDetectorTest> {
model("codeInsight/changeLocality", pattern = KT_OR_KTS)
}
testClass<AbstractDataFlowValueRenderingTest> {
model("dataFlowValueRendering")
}
@@ -93,8 +93,9 @@ class KotlinCodeBlockModificationListener(
// skip change if it contains only virtual/fake change
if (changedElements.isNotEmpty() &&
// ignore formatting (whitespaces etc)
// ignore formatting (whitespaces etc) change
(isFormattingChange(changeSet) ||
// ignore comment change
isCommentChange(changeSet) ||
changedElements.all { !it.psi.isPhysical })
) return
@@ -215,6 +216,20 @@ class KotlinCodeBlockModificationListener(
changeSet.getChangesByElement(it).affectedChildren.all { c -> c is PsiWhiteSpace }
}
/**
* Has to be aligned with [getInsideCodeBlockModificationScope] :
*
* result of analysis has to be reflected in dirty scope,
* the only difference is whitespaces and comments
*/
fun getInsideCodeBlockModificationDirtyScope(element: PsiElement): PsiElement? {
if (!element.isPhysical) return null
// dirty scope for whitespaces and comments is the element itself
if (element is PsiWhiteSpace || element is PsiComment || element is KDoc) return element
return getInsideCodeBlockModificationScope(element)?.blockDeclaration ?: null
}
fun getInsideCodeBlockModificationScope(element: PsiElement): BlockModificationScopeElement? {
val lambda = element.getTopmostParentOfType<KtLambdaExpression>()
if (lambda is KtLambdaExpression) {
@@ -259,13 +274,10 @@ class KotlinCodeBlockModificationListener(
val declaration = if (blockDeclaration.initializer != null)
blockDeclaration
else
KtPsiUtil.getTopmostParentOfTypes(
blockDeclaration,
// property could be initialized on a class level
KtClass::class.java,
// ktFile to check top level property declarations
KtFile::class.java
) as KtElement
// property could be initialized on a class level
KtPsiUtil.getTopmostParentOfTypes(blockDeclaration, KtClass::class.java) as? KtElement ?:
// ktFile to check top level property declarations
return null
return BlockModificationScopeElement(declaration, expression)
}
}
@@ -18,13 +18,12 @@ package org.jetbrains.kotlin.idea.highlighter
import com.intellij.codeInsight.daemon.ChangeLocalityDetector
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.caches.trackers.KotlinCodeBlockModificationListener.Companion.getInsideCodeBlockModificationScope
import org.jetbrains.kotlin.idea.caches.trackers.KotlinCodeBlockModificationListener.Companion.getInsideCodeBlockModificationDirtyScope
class KotlinChangeLocalityDetector : ChangeLocalityDetector {
override fun getChangeHighlightingDirtyScopeFor(element: PsiElement): PsiElement? {
val modificationScope =
getInsideCodeBlockModificationScope(element) ?: return null
return modificationScope.blockDeclaration
// in some cases it returns a bit wider scope for the element as it is not possible to track changes here
// e.g.: delete a space in expression `foo( )` results to entire expression `foo()`
return getInsideCodeBlockModificationDirtyScope(element)
}
}
@@ -21,18 +21,36 @@ object DirectiveBasedActionUtils {
return
}
val expectedErrors = InTextDirectivesUtils.findLinesWithPrefixesRemoved(file.text, "// ERROR:").sorted()
checkForUnexpected(file, diagnosticsProvider, "// ERROR:", "errors", Severity.ERROR)
}
fun checkForUnexpectedWarnings(file: KtFile, diagnosticsProvider: (KtFile) -> Diagnostics = { it.analyzeWithContent().diagnostics }) {
if (InTextDirectivesUtils.findLinesWithPrefixesRemoved(file.text, "// ENABLE-WARNINGS").isEmpty()) {
return
}
checkForUnexpected(file, diagnosticsProvider, "// WARNING:", "warnings", Severity.WARNING)
}
private fun checkForUnexpected(
file: KtFile,
diagnosticsProvider: (KtFile) -> Diagnostics,
directive: String,
name: String,
severity: Severity
) {
val expected = InTextDirectivesUtils.findLinesWithPrefixesRemoved(file.text, directive).sorted()
val diagnostics = diagnosticsProvider(file)
val actualErrors = diagnostics
.filter { it.severity == Severity.ERROR }
val actual = diagnostics
.filter { it.severity == severity }
.map { DefaultErrorMessages.render(it).replace("\n", "<br>") }
.sorted()
UsefulTestCase.assertOrderedEquals(
"All actual errors should be mentioned in test data with // ERROR: directive. But no unnecessary errors should be me mentioned",
actualErrors,
expectedErrors
"All actual $name should be mentioned in test data with '$directive' directive. But no unnecessary $name should be me mentioned",
actual,
expected
)
}
+17
View File
@@ -0,0 +1,17 @@
// SCOPE: '// some change'
class Comment {
fun q() {
}
val someValue: String
get() {
return "X"
}
fun baa() {
<selection>// some change</selection>
val list = listOf<String>(TODO(""))
}
}
+18
View File
@@ -0,0 +1,18 @@
// SCOPE: 'fun baa() {'
// SCOPE: ' val list = listOf<String>("Z")'
// SCOPE: ' }'
class Comment {
fun q() {
}
val someValue: String
get() {
return "X"
}
fun baa() {
val list = listOf<String>(<selection>"Z"</selection>)
}
}
@@ -1,5 +1,7 @@
// OUT_OF_CODE_BLOCK: FALSE
// ERROR: Unresolved reference: awhen
// OUT_OF_CODE_BLOCK: TRUE
// TYPE: 'z'
// ERROR: Unresolved reference: zwhen
enum class A {
e1, e2, e3
}
@@ -12,4 +14,7 @@ val B.foo: Int
A.e1 -> 1
A.e2 -> 4
}
}
}
// TODO: Investigate
// SKIP_ANALYZE_CHECK
@@ -0,0 +1,11 @@
// OUT_OF_CODE_BLOCK: FALSE
// TYPE: '1'
// ENABLE-WARNINGS
// WARNING: Unreachable code
fun test() {
return
val a = <caret>
}
@@ -1,4 +1,4 @@
// OUT_OF_CODE_BLOCK: FALSE
// OUT_OF_CODE_BLOCK: TRUE
// TYPE: '//'
// ERROR: Property must be initialized
@@ -6,4 +6,7 @@ var prop1: Int
set(value) {
<caret> println("prop.setter")
field = value
}
}
// TODO: Investigate
// SKIP_ANALYZE_CHECK
@@ -0,0 +1,41 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.codeInsight
import com.intellij.psi.PsiElement
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.idea.highlighter.KotlinChangeLocalityDetector
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.InTextDirectivesUtils
private const val SCOPE_DIRECTIVE = "// SCOPE:"
abstract class AbstractChangeLocalityDetectorTest : KotlinLightCodeInsightFixtureTestCase() {
protected fun doTest(unused: String?) {
val ktFile = myFixture.configureByFile(fileName()) as KtFile
val expectedScopeLines = InTextDirectivesUtils.findListWithPrefixes(ktFile.text, SCOPE_DIRECTIVE)
assertTrue("scope has to be specified with $SCOPE_DIRECTIVE", expectedScopeLines.isNotEmpty())
val selectionModel = editor.selectionModel
assertTrue("changed item has to be specified in <selection></selection", selectionModel.hasSelection())
val element = PsiTreeUtil.findElementOfClassAtRange(
ktFile,
selectionModel.selectionStart,
selectionModel.selectionEnd,
PsiElement::class.java
)
?: error("No PsiElement at selection range")
val changeLocalityDetector = KotlinChangeLocalityDetector()
val dirtyScope = changeLocalityDetector.getChangeHighlightingDirtyScopeFor(element)
?: error("scope has to be calculated")
println("dirtyScopeFor ${element.text} is ${dirtyScope?.text}")
assertEquals(expectedScopeLines.joinToString("\n"), dirtyScope.text)
}
}
@@ -13,7 +13,6 @@ import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiManager
import com.intellij.psi.impl.PsiModificationTrackerImpl
import com.intellij.psi.util.PsiTreeUtil
import junit.framework.TestCase
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithAllCompilerChecks
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.caches.trackers.outOfBlockModificationCount
@@ -22,6 +21,7 @@ import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.kdoc.psi.api.KDoc
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.test.InTextDirectivesUtils
@@ -33,14 +33,14 @@ abstract class AbstractOutOfBlockModificationTest : KotlinLightCodeInsightFixtur
ktFile.text,
SKIP_ANALYZE_CHECK_DIRECTIVE
)
TestCase.assertTrue(
assertTrue(
"It's allowed to skip check with analyze only for tests where out-of-block is expected",
!isSkipCheckDefined || expectedOutOfBlock
)
val tracker =
PsiManager.getInstance(myFixture.project).modificationTracker as PsiModificationTrackerImpl
val element = ktFile.findElementAt(myFixture.caretOffset)
TestCase.assertNotNull("Should be valid element", element)
assertNotNull("Should be valid element", element)
val oobBeforeType = ktFile.outOfBlockModificationCount
val modificationCountBeforeType = tracker.modificationCount
@@ -51,11 +51,11 @@ abstract class AbstractOutOfBlockModificationTest : KotlinLightCodeInsightFixtur
PsiDocumentManager.getInstance(myFixture.project).commitDocument(myFixture.getDocument(myFixture.file))
val oobAfterCount = ktFile.outOfBlockModificationCount
val modificationCountAfterType = tracker.modificationCount
TestCase.assertTrue(
assertTrue(
"Modification tracker should always be changed after type",
modificationCountBeforeType != modificationCountAfterType
)
TestCase.assertEquals(
assertEquals(
"Result for out of block test is differs from expected on element in file:\n"
+ FileUtil.loadFile(testDataFile()),
expectedOutOfBlock, oobBeforeType != oobAfterCount
@@ -68,7 +68,9 @@ abstract class AbstractOutOfBlockModificationTest : KotlinLightCodeInsightFixtur
}
private fun checkForUnexpectedErrors(ktFile: KtFile) {
DirectiveBasedActionUtils.checkForUnexpectedErrors(ktFile) { it.analyzeWithAllCompilerChecks().bindingContext.diagnostics }
val diagnosticsProvider: (KtFile) -> Diagnostics = { it.analyzeWithAllCompilerChecks().bindingContext.diagnostics }
DirectiveBasedActionUtils.checkForUnexpectedWarnings(ktFile, diagnosticsProvider)
DirectiveBasedActionUtils.checkForUnexpectedErrors(ktFile, diagnosticsProvider)
}
private fun checkOOBWithDescriptorsResolve(expectedOutOfBlock: Boolean) {
@@ -83,14 +85,14 @@ abstract class AbstractOutOfBlockModificationTest : KotlinLightCodeInsightFixtur
val ktElement = ktExpression ?: ktDeclaration ?: return
val facade = ktElement.containingKtFile.getResolutionFacade()
val session = facade.getFrontendService(ResolveSession::class.java)
session.forceResolveAll()
val context = session.bindingContext
if (ktExpression != null && ktExpression !== ktDeclaration) {
val expressionProcessed = context.get(
BindingContext.PROCESSED,
if (ktExpression is KtFunctionLiteral) ktExpression.getParent() as KtLambdaExpression else ktExpression
) === java.lang.Boolean.TRUE
TestCase.assertEquals(
val expression = if (ktExpression is KtFunctionLiteral) ktExpression.getParent() as KtLambdaExpression else ktExpression
val processed = context.get(BindingContext.PROCESSED, expression)
val expressionProcessed = processed === java.lang.Boolean.TRUE
assertEquals(
"Expected out-of-block should result expression analyzed and vise versa", expectedOutOfBlock,
expressionProcessed
)
@@ -100,7 +102,7 @@ abstract class AbstractOutOfBlockModificationTest : KotlinLightCodeInsightFixtur
BindingContext.DECLARATION_TO_DESCRIPTOR,
ktDeclaration
) != null
TestCase.assertEquals(
assertEquals(
"Expected out-of-block should result declaration analyzed and vise versa", expectedOutOfBlock,
declarationProcessed
)
@@ -0,0 +1,40 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.codeInsight;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("idea/testData/codeInsight/changeLocality")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class ChangeLocalityDetectorTestGenerated extends AbstractChangeLocalityDetectorTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInChangeLocality() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/codeInsight/changeLocality"), Pattern.compile("^(.+)\\.(kt|kts)$"), true);
}
@TestMetadata("Comment.kt")
public void testComment() throws Exception {
runTest("idea/testData/codeInsight/changeLocality/Comment.kt");
}
@TestMetadata("InMethod.kt")
public void testInMethod() throws Exception {
runTest("idea/testData/codeInsight/changeLocality/InMethod.kt");
}
}
@@ -178,6 +178,11 @@ public class OutOfBlockModificationTestGenerated extends AbstractOutOfBlockModif
runTest("idea/testData/codeInsight/outOfBlock/InMethod.kt");
}
@TestMetadata("InMethodUnreacableCode.kt")
public void testInMethodUnreacableCode() throws Exception {
runTest("idea/testData/codeInsight/outOfBlock/InMethodUnreacableCode.kt");
}
@TestMetadata("InNestedClass.kt")
public void testInNestedClass() throws Exception {
runTest("idea/testData/codeInsight/outOfBlock/InNestedClass.kt");