-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
FIR IDE: introduce out of block modification tracker tests
- Loading branch information
1 parent
da7b12f
commit 911662b
Showing
6 changed files
with
207 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
...l-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructureUtil.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* | ||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. | ||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. | ||
*/ | ||
|
||
package org.jetbrains.kotlin.idea.fir.low.level.api.file.structure | ||
|
||
import org.jetbrains.kotlin.psi.* | ||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject | ||
|
||
internal object FileStructureUtil { | ||
fun isStructureElementContainer(ktDeclaration: KtDeclaration): Boolean = when { | ||
ktDeclaration !is KtClassOrObject && ktDeclaration !is KtDeclarationWithBody && ktDeclaration !is KtProperty && ktDeclaration !is KtTypeAlias -> false | ||
ktDeclaration is KtEnumEntry -> false | ||
ktDeclaration.containingClassOrObject is KtEnumEntry -> false | ||
else -> !KtPsiUtil.isLocal(ktDeclaration) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
131 changes: 131 additions & 0 deletions
131
...org/jetbrains/kotlin/idea/fir/low/level/api/trackers/KotlinModuleOutOfBlockTrackerTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
/* | ||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. | ||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. | ||
*/ | ||
|
||
package org.jetbrains.kotlin.idea.fir.low.level.api.trackers | ||
|
||
import com.intellij.openapi.command.WriteCommandAction | ||
import com.intellij.openapi.module.Module | ||
import com.intellij.openapi.vfs.LocalFileSystem | ||
import com.intellij.openapi.vfs.VirtualFileManager | ||
import com.intellij.psi.PsiDocumentManager | ||
import com.intellij.psi.PsiManager | ||
import com.intellij.testFramework.PsiTestUtil | ||
import junit.framework.Assert | ||
import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest | ||
import org.jetbrains.kotlin.idea.util.application.runWriteAction | ||
import org.jetbrains.kotlin.idea.util.rootManager | ||
import org.jetbrains.kotlin.idea.util.sourceRoots | ||
import org.jetbrains.kotlin.psi.KtFile | ||
import org.jetbrains.kotlin.psi.KtNamedFunction | ||
import java.nio.file.Files | ||
import kotlin.io.path.ExperimentalPathApi | ||
import kotlin.io.path.writeText | ||
|
||
class KotlinModuleOutOfBlockTrackerTest : AbstractMultiModuleTest() { | ||
override fun getTestDataPath(): String = error("Should not be called") | ||
|
||
fun testThatModuleOutOfBlockChangeInfluenceOnlySingleModule() { | ||
val moduleA = createModuleWithModificationTracker("a") { | ||
listOf( | ||
FileWithText("main.kt", "fun main() = 10") | ||
) | ||
} | ||
val moduleB = createModuleWithModificationTracker("b") | ||
val moduleC = createModuleWithModificationTracker("c") | ||
|
||
|
||
val moduleAWithTracker = ModuleWithModificationTracker(moduleA) | ||
val moduleBWithTracker = ModuleWithModificationTracker(moduleB) | ||
val moduleCWithTracker = ModuleWithModificationTracker(moduleC) | ||
|
||
moduleA.typeInFunctionBody("main.kt", textAfterTyping = "fun main() = hello10") | ||
|
||
Assert.assertTrue( | ||
"Out of block modification count for module A with out of block should change after typing, modification count is ${moduleAWithTracker.modificationCount}", | ||
moduleAWithTracker.changed() | ||
) | ||
Assert.assertFalse( | ||
"Out of block modification count for module B without out of block should not change after typing, modification count is ${moduleBWithTracker.modificationCount}", | ||
moduleBWithTracker.changed() | ||
) | ||
Assert.assertFalse( | ||
"Out of block modification count for module C without out of block should not change after typing, modification count is ${moduleCWithTracker.modificationCount}", | ||
moduleCWithTracker.changed() | ||
) | ||
} | ||
|
||
fun testThatInEveryModuleOutOfBlockWillHappenAfterContentRootChange() { | ||
val moduleA = createModuleWithModificationTracker("a") | ||
val moduleB = createModuleWithModificationTracker("b") | ||
val moduleC = createModuleWithModificationTracker("c") | ||
|
||
val moduleAWithTracker = ModuleWithModificationTracker(moduleA) | ||
val moduleBWithTracker = ModuleWithModificationTracker(moduleB) | ||
val moduleCWithTracker = ModuleWithModificationTracker(moduleC) | ||
|
||
runWriteAction { | ||
moduleA.sourceRoots.first().createChildData(/* requestor = */ null, "file.kt") | ||
} | ||
|
||
Assert.assertTrue( | ||
"Out of block modification count for module A should change after content root change, modification count is ${moduleAWithTracker.modificationCount}", | ||
moduleAWithTracker.changed() | ||
) | ||
Assert.assertTrue( | ||
"Out of block modification count for module B should change after content root change, modification count is ${moduleBWithTracker.modificationCount}", | ||
moduleBWithTracker.changed() | ||
) | ||
Assert.assertTrue( | ||
"Out of block modification count for module C should change after content root change modification count is ${moduleCWithTracker.modificationCount}", | ||
moduleCWithTracker.changed() | ||
) | ||
} | ||
|
||
private fun Module.typeInFunctionBody(fileName: String, textAfterTyping: String) { | ||
val file = "${sourceRoots.first().url}/$fileName" | ||
val virtualFile = VirtualFileManager.getInstance().findFileByUrl(file)!! | ||
val ktFile = PsiManager.getInstance(project).findFile(virtualFile) as KtFile | ||
configureByExistingFile(virtualFile) | ||
|
||
val singleFunction = ktFile.declarations.single() as KtNamedFunction | ||
|
||
editor.caretModel.moveToOffset(singleFunction.bodyExpression!!.textOffset) | ||
type("hello") | ||
PsiDocumentManager.getInstance(project).commitAllDocuments() | ||
Assert.assertEquals(textAfterTyping, ktFile.text) | ||
} | ||
|
||
@OptIn(ExperimentalPathApi::class) | ||
private fun createModuleWithModificationTracker( | ||
name: String, | ||
createFiles: () -> List<FileWithText> = { emptyList() }, | ||
): Module { | ||
val tmpDir = createTempDirectory().toPath() | ||
createFiles().forEach { file -> | ||
Files.createFile(tmpDir.resolve(file.name)).writeText(file.text) | ||
} | ||
val module: Module = createModule("$tmpDir/$name", moduleType) | ||
val root = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(tmpDir.toFile())!! | ||
WriteCommandAction.writeCommandAction(module.project).run<RuntimeException> { | ||
root.refresh(false, true) | ||
} | ||
|
||
PsiTestUtil.addSourceContentToRoots(module, root) | ||
return module | ||
} | ||
|
||
private data class FileWithText(val name: String, val text: String) | ||
|
||
private class ModuleWithModificationTracker(module: Module) { | ||
private val modificationTracker = module.createModuleWithoutDependenciesOutOfBlockModificationTracker() | ||
private val initialModificationCount = modificationTracker.modificationCount | ||
|
||
val modificationCount: Long | ||
get() = modificationTracker.modificationCount | ||
|
||
fun changed(): Boolean = | ||
modificationTracker.modificationCount != initialModificationCount | ||
} | ||
} |