Do not invalidate package caches on generic events, KT-25264

This commit is contained in:
Vladimir Dolzhenko
2019-07-17 17:18:10 +02:00
parent 3e9765f5bb
commit 022275b781
15 changed files with 145 additions and 62 deletions
@@ -924,7 +924,7 @@ fun main(args: Array<String>) {
} }
testClass<AbstractCompletionCharFilterTest> { testClass<AbstractCompletionCharFilterTest> {
model("handlers/charFilter") model("handlers/charFilter", pattern = KT_WITHOUT_DOTS_IN_NAME)
} }
testClass<AbstractMultiFileJvmBasicCompletionTest> { testClass<AbstractMultiFileJvmBasicCompletionTest> {
@@ -1219,7 +1219,7 @@ fun main(args: Array<String>) {
} }
testClass<AbstractPerformanceCompletionCharFilterTest> { testClass<AbstractPerformanceCompletionCharFilterTest> {
model("handlers/charFilter", testMethod = "doPerfTest") model("handlers/charFilter", testMethod = "doPerfTest", pattern = KT_WITHOUT_DOTS_IN_NAME)
} }
} }
/* /*
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.idea.caches package org.jetbrains.kotlin.idea.caches
import com.intellij.ProjectTopics import com.intellij.ProjectTopics
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.diagnostic.Logger
@@ -87,7 +86,7 @@ class KotlinPackageContentModificationListener(private val project: Project) {
class KotlinPackageStatementPsiTreeChangePreprocessor(private val project: Project) : PsiTreeChangePreprocessor { class KotlinPackageStatementPsiTreeChangePreprocessor(private val project: Project) : PsiTreeChangePreprocessor {
override fun treeChanged(event: PsiTreeChangeEventImpl) { override fun treeChanged(event: PsiTreeChangeEventImpl) {
val eFile = event.file ?: event.child as? PsiFile val eFile = event.file ?: event.child as? PsiFile
if (eFile == null) LOG.debugIfEnabled(project, "Got PsiEvent: $event without file", true) if (eFile == null) LOG.debugIfEnabled(project, true) { "Got PsiEvent: $event without file" }
val file = eFile as? KtFile ?: return val file = eFile as? KtFile ?: return
when (event.code) { when (event.code) {
@@ -96,7 +95,7 @@ class KotlinPackageStatementPsiTreeChangePreprocessor(private val project: Proje
PsiTreeChangeEventImpl.PsiEventType.CHILD_REPLACED, PsiTreeChangeEventImpl.PsiEventType.CHILD_REPLACED,
PsiTreeChangeEventImpl.PsiEventType.CHILD_REMOVED -> { PsiTreeChangeEventImpl.PsiEventType.CHILD_REMOVED -> {
val child = event.child ?: run { val child = event.child ?: run {
LOG.debugIfEnabled(project, "Got PsiEvent: $event without child", true) LOG.debugIfEnabled(project, true) { "Got PsiEvent: $event without child" }
return return
} }
if (child.getParentOfType<KtPackageDirective>(false) != null) if (child.getParentOfType<KtPackageDirective>(false) != null)
@@ -104,10 +103,10 @@ class KotlinPackageStatementPsiTreeChangePreprocessor(private val project: Proje
} }
PsiTreeChangeEventImpl.PsiEventType.CHILDREN_CHANGED -> { PsiTreeChangeEventImpl.PsiEventType.CHILDREN_CHANGED -> {
val parent = event.parent ?: run { val parent = event.parent ?: run {
LOG.debugIfEnabled(project, "Got PsiEvent: $event without parent", true) LOG.debugIfEnabled(project, true) { "Got PsiEvent: $event without parent" }
return return
} }
if (parent.getChildrenOfType<KtPackageDirective>().any()) if (!event.isGenericChange && (parent.getChildrenOfType<KtPackageDirective>().any() || parent is KtPackageDirective))
ServiceManager.getService(project, PerModulePackageCacheService::class.java).notifyPackageChange(file) ServiceManager.getService(project, PerModulePackageCacheService::class.java).notifyPackageChange(file)
} }
else -> { else -> {
@@ -244,7 +243,7 @@ class PerModulePackageCacheService(private val project: Project) {
} }
private fun invalidateCacheForModuleSourceInfo(moduleSourceInfo: ModuleSourceInfo) { private fun invalidateCacheForModuleSourceInfo(moduleSourceInfo: ModuleSourceInfo) {
LOG.debugIfEnabled(project, "Invalidated cache for $moduleSourceInfo", false) LOG.debugIfEnabled(project) { "Invalidated cache for $moduleSourceInfo" }
val perSourceInfoData = cache[moduleSourceInfo.module] ?: return val perSourceInfoData = cache[moduleSourceInfo.module] ?: return
val dataForSourceInfo = perSourceInfoData[moduleSourceInfo] ?: return val dataForSourceInfo = perSourceInfoData[moduleSourceInfo] ?: return
dataForSourceInfo.clear() dataForSourceInfo.clear()
@@ -264,14 +263,14 @@ class PerModulePackageCacheService(private val project: Project) {
if (sourceRootUrls.any { url -> if (sourceRootUrls.any { url ->
vfile.containedInOrContains(url) vfile.containedInOrContains(url)
}) { }) {
LOG.debugIfEnabled(project, "Invalidated cache for $module") LOG.debugIfEnabled(project) { "Invalidated cache for $module" }
data.clear() data.clear()
} }
} }
} else { } else {
val infoByVirtualFile = getModuleInfoByVirtualFile(project, vfile) val infoByVirtualFile = getModuleInfoByVirtualFile(project, vfile)
if (infoByVirtualFile == null || infoByVirtualFile !is ModuleSourceInfo) { if (infoByVirtualFile == null || infoByVirtualFile !is ModuleSourceInfo) {
LOG.debugIfEnabled(project, "Skip $vfile as it has mismatched ModuleInfo=$infoByVirtualFile") LOG.debugIfEnabled(project) { "Skip $vfile as it has mismatched ModuleInfo=$infoByVirtualFile" }
} }
(infoByVirtualFile as? ModuleSourceInfo)?.let { (infoByVirtualFile as? ModuleSourceInfo)?.let {
invalidateCacheForModuleSourceInfo(it) invalidateCacheForModuleSourceInfo(it)
@@ -283,13 +282,13 @@ class PerModulePackageCacheService(private val project: Project) {
pendingKtFileChanges.processPending { file -> pendingKtFileChanges.processPending { file ->
if (file.virtualFile != null && file.virtualFile !in projectScope) { if (file.virtualFile != null && file.virtualFile !in projectScope) {
LOG.debugIfEnabled(project, "Skip $file without vFile, or not in scope: ${file.virtualFile?.let { it !in projectScope }}") LOG.debugIfEnabled(project) { "Skip $file without vFile, or not in scope: ${file.virtualFile?.let { it !in projectScope }}" }
return@processPending return@processPending
} }
val nullableModuleInfo = file.getNullableModuleInfo() val nullableModuleInfo = file.getNullableModuleInfo()
(nullableModuleInfo as? ModuleSourceInfo)?.let { invalidateCacheForModuleSourceInfo(it) } (nullableModuleInfo as? ModuleSourceInfo)?.let { invalidateCacheForModuleSourceInfo(it) }
if (nullableModuleInfo == null || nullableModuleInfo !is ModuleSourceInfo) { if (nullableModuleInfo == null || nullableModuleInfo !is ModuleSourceInfo) {
LOG.debugIfEnabled(project, "Skip $file as it has mismatched ModuleInfo=$nullableModuleInfo") LOG.debugIfEnabled(project) { "Skip $file as it has mismatched ModuleInfo=$nullableModuleInfo" }
} }
implicitPackagePrefixCache.update(file) implicitPackagePrefixCache.update(file)
} }
@@ -329,7 +328,7 @@ class PerModulePackageCacheService(private val project: Project) {
return cacheForCurrentModuleInfo.getOrPut(packageFqName) { return cacheForCurrentModuleInfo.getOrPut(packageFqName) {
val packageExists = PackageIndexUtil.packageExists(packageFqName, moduleInfo.contentScope(), project) val packageExists = PackageIndexUtil.packageExists(packageFqName, moduleInfo.contentScope(), project)
LOG.debugIfEnabled(project, "Computed cache value for $packageFqName in $moduleInfo is $packageExists") LOG.debugIfEnabled(project) { "Computed cache value for $packageFqName in $moduleInfo is $packageExists" }
packageExists packageExists
} }
} }
@@ -351,16 +350,14 @@ class PerModulePackageCacheService(private val project: Project) {
} }
} }
private fun Logger.debugIfEnabled(project: Project, withCurrentTrace: Boolean = false, message: () -> String) {
private fun Logger.debugIfEnabled(project: Project, message: String, withCurrentTrace: Boolean = false) {
if (ApplicationManager.getApplication().isUnitTestMode && project.DEBUG_LOG_ENABLE_PerModulePackageCache) { if (ApplicationManager.getApplication().isUnitTestMode && project.DEBUG_LOG_ENABLE_PerModulePackageCache) {
val msg = message()
if (withCurrentTrace) { if (withCurrentTrace) {
val e = Exception().apply { fillInStackTrace() } val e = Exception().apply { fillInStackTrace() }
this.debug(message, e) this.debug(msg, e)
} else { } else {
this.debug(message) this.debug(msg)
} }
} }
} }
@@ -0,0 +1,5 @@
package org.jetbrains.annotations
@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.LOCAL_VARIABLE, AnnotationTarget.FIELD)
public annotation class PropertyKey(public val resourceBundle: String)
@@ -0,0 +1,3 @@
foobar = 0
foo.bar = 1
bar.baz = 2
@@ -0,0 +1,10 @@
import org.jetbrains.annotations.PropertyKey
fun message(@PropertyKey(resourceBundle = "MessageBundle1.dependency") key: String) = key
fun test() {
message("<caret>")
}
// ELEMENT: foo.bar
// CHARS: 'foo\n'
@@ -0,0 +1,10 @@
import org.jetbrains.annotations.PropertyKey
fun message(@PropertyKey(resourceBundle = "MessageBundle1.dependency") key: String) = key
fun test() {
message("foo.bar")
}
// ELEMENT: foo.bar
// CHARS: 'foo\n'
@@ -24,6 +24,7 @@ abstract class AbstractCompletionHandlerTest(private val defaultCompletionType:
private val ELEMENT_TEXT_PREFIX = "ELEMENT_TEXT:" private val ELEMENT_TEXT_PREFIX = "ELEMENT_TEXT:"
private val TAIL_TEXT_PREFIX = "TAIL_TEXT:" private val TAIL_TEXT_PREFIX = "TAIL_TEXT:"
private val COMPLETION_CHAR_PREFIX = "CHAR:" private val COMPLETION_CHAR_PREFIX = "CHAR:"
private val COMPLETION_CHARS_PREFIX = "CHARS:"
private val CODE_STYLE_SETTING_PREFIX = "CODE_STYLE_SETTING:" private val CODE_STYLE_SETTING_PREFIX = "CODE_STYLE_SETTING:"
protected open fun doTest(testPath: String) { protected open fun doTest(testPath: String) {
@@ -42,12 +43,10 @@ abstract class AbstractCompletionHandlerTest(private val defaultCompletionType:
val itemText = InTextDirectivesUtils.findStringWithPrefixes(fileText, ELEMENT_TEXT_PREFIX) val itemText = InTextDirectivesUtils.findStringWithPrefixes(fileText, ELEMENT_TEXT_PREFIX)
val tailText = InTextDirectivesUtils.findStringWithPrefixes(fileText, TAIL_TEXT_PREFIX) val tailText = InTextDirectivesUtils.findStringWithPrefixes(fileText, TAIL_TEXT_PREFIX)
val completionCharString = InTextDirectivesUtils.findStringWithPrefixes(fileText, COMPLETION_CHAR_PREFIX) val completionChars = completionChars(
val completionChar = when(completionCharString) { char = InTextDirectivesUtils.findStringWithPrefixes(fileText, COMPLETION_CHAR_PREFIX),
"\\n", null -> '\n' chars = InTextDirectivesUtils.findStringWithPrefixes(fileText, COMPLETION_CHARS_PREFIX)
"\\t" -> '\t' )
else -> completionCharString.singleOrNull() ?: error("Incorrect completion char: \"$completionCharString\"")
}
val completionType = ExpectedCompletionUtils.getCompletionType(fileText) ?: defaultCompletionType val completionType = ExpectedCompletionUtils.getCompletionType(fileText) ?: defaultCompletionType
@@ -70,7 +69,15 @@ abstract class AbstractCompletionHandlerTest(private val defaultCompletionType:
} }
} }
doTestWithTextLoaded(completionType, invocationCount, lookupString, itemText, tailText, completionChar, File(testPath).name + ".after") doTestWithTextLoaded(
completionType,
invocationCount,
lookupString,
itemText,
tailText,
completionChars,
File(testPath).name + ".after"
)
} finally { } finally {
if (configured) { if (configured) {
rollbackCompilerOptions(project, module) rollbackCompilerOptions(project, module)
@@ -31,7 +31,7 @@ class BasicCompletionHandlerTest : CompletionHandlerTestBase(){
private fun doTest(time: Int, lookupString: String?, itemText: String?, tailText: String?, completionChar: Char) { private fun doTest(time: Int, lookupString: String?, itemText: String?, tailText: String?, completionChar: Char) {
fixture.configureByFile(fileName()) fixture.configureByFile(fileName())
doTestWithTextLoaded(CompletionType.BASIC, time, lookupString, itemText, tailText, completionChar, fileName() + ".after") doTestWithTextLoaded(CompletionType.BASIC, time, lookupString, itemText, tailText, completionChar.toString(), fileName() + ".after")
} }
fun testClassCompletionImport() = doTest(2, "SortedSet", null, '\n') fun testClassCompletionImport() = doTest(2, "SortedSet", null, '\n')
@@ -26,7 +26,7 @@ public class CompletionCharFilterTestGenerated extends AbstractCompletionCharFil
} }
public void testAllFilesPresentInCharFilter() throws Exception { public void testAllFilesPresentInCharFilter() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/handlers/charFilter"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/handlers/charFilter"), Pattern.compile("^([^.]+)\\.kt$"), TargetBackend.ANY, true);
} }
@TestMetadata("Colon.kt") @TestMetadata("Colon.kt")
@@ -144,6 +144,11 @@ public class CompletionCharFilterTestGenerated extends AbstractCompletionCharFil
runTest("idea/idea-completion/testData/handlers/charFilter/LParenth.kt"); runTest("idea/idea-completion/testData/handlers/charFilter/LParenth.kt");
} }
@TestMetadata("MessageBundle1.kt")
public void testMessageBundle1() throws Exception {
runTest("idea/idea-completion/testData/handlers/charFilter/MessageBundle1.kt");
}
@TestMetadata("NamedParameter1.kt") @TestMetadata("NamedParameter1.kt")
public void testNamedParameter1() throws Exception { public void testNamedParameter1() throws Exception {
runTest("idea/idea-completion/testData/handlers/charFilter/NamedParameter1.kt"); runTest("idea/idea-completion/testData/handlers/charFilter/NamedParameter1.kt");
@@ -20,26 +20,40 @@ abstract class CompletionHandlerTestBase() : KotlinLightCodeInsightFixtureTestCa
get() = myFixture get() = myFixture
protected fun doTestWithTextLoaded( protected fun doTestWithTextLoaded(
completionType: CompletionType, completionType: CompletionType,
time: Int, time: Int,
lookupString: String?, lookupString: String?,
itemText: String?, itemText: String?,
tailText: String?, tailText: String?,
completionChar: Char, completionChars: String,
afterFilePath: String afterFilePath: String
) { ) {
for (idx in 0 until completionChars.length - 1) {
fixture.type(completionChars[idx])
}
fixture.complete(completionType, time) fixture.complete(completionType, time)
if (lookupString != null || itemText != null || tailText != null) { if (lookupString != null || itemText != null || tailText != null) {
val item = getExistentLookupElement(lookupString, itemText, tailText) val item = getExistentLookupElement(lookupString, itemText, tailText)
if (item != null) { if (item != null) {
selectItem(item, completionChar) selectItem(item, completionChars.last())
} }
} }
fixture.checkResultByFile(afterFilePath) fixture.checkResultByFile(afterFilePath)
} }
protected fun completionChars(char: String?, chars: String?): String =
when (char) {
null -> when (chars) {
null -> "\n"
else -> chars.replace("\\n", "\n").replace("\\t", "\t")
}
"\\n" -> "\n"
"\\t" -> "\t"
else -> char.single().toString() ?: error("Incorrect completion char: \"$char\"")
}
protected fun getExistentLookupElement(lookupString: String?, itemText: String?, tailText: String?): LookupElement? { protected fun getExistentLookupElement(lookupString: String?, itemText: String?, tailText: String?): LookupElement? {
val lookup = LookupManager.getInstance(project)?.activeLookup as LookupImpl? ?: return null val lookup = LookupManager.getInstance(project)?.activeLookup as LookupImpl? ?: return null
val items = lookup.items val items = lookup.items
@@ -14,7 +14,7 @@ fun CodeInsightTestFixture.configureWithExtraFile(path: String, vararg extraName
val fileName = File(path).name val fileName = File(path).name
val noExtensionPath = FileUtil.getNameWithoutExtension(fileName) val noExtensionPath = FileUtil.getNameWithoutExtension(fileName)
val extensions = arrayOf("kt", "java") val extensions = arrayOf("kt", "java", "properties")
val extraPaths: List<String> = extraNameParts val extraPaths: List<String> = extraNameParts
.flatMap { extensions.map { ext -> "$noExtensionPath$it.$ext" } } .flatMap { extensions.map { ext -> "$noExtensionPath$it.$ext" } }
.mapNotNull { File(testDataPath, it).takeIf { it.exists() }?.name } .mapNotNull { File(testDataPath, it).takeIf { it.exists() }?.name }
@@ -22,7 +22,7 @@ import org.junit.AfterClass
import java.io.File import java.io.File
/** /**
* inspired by @see AbstractCompletionHandlerTest * inspired by @see AbstractCompletionHandlerTests
*/ */
abstract class AbstractPerformanceCompletionHandlerTests( abstract class AbstractPerformanceCompletionHandlerTests(
private val defaultCompletionType: CompletionType, private val defaultCompletionType: CompletionType,
@@ -34,6 +34,7 @@ abstract class AbstractPerformanceCompletionHandlerTests(
private val ELEMENT_TEXT_PREFIX = "ELEMENT_TEXT:" private val ELEMENT_TEXT_PREFIX = "ELEMENT_TEXT:"
private val TAIL_TEXT_PREFIX = "TAIL_TEXT:" private val TAIL_TEXT_PREFIX = "TAIL_TEXT:"
private val COMPLETION_CHAR_PREFIX = "CHAR:" private val COMPLETION_CHAR_PREFIX = "CHAR:"
private val COMPLETION_CHARS_PREFIX = "CHARS:"
private val CODE_STYLE_SETTING_PREFIX = "CODE_STYLE_SETTING:" private val CODE_STYLE_SETTING_PREFIX = "CODE_STYLE_SETTING:"
companion object { companion object {
@@ -74,12 +75,10 @@ abstract class AbstractPerformanceCompletionHandlerTests(
val itemText = InTextDirectivesUtils.findStringWithPrefixes(fileText, ELEMENT_TEXT_PREFIX) val itemText = InTextDirectivesUtils.findStringWithPrefixes(fileText, ELEMENT_TEXT_PREFIX)
val tailText = InTextDirectivesUtils.findStringWithPrefixes(fileText, TAIL_TEXT_PREFIX) val tailText = InTextDirectivesUtils.findStringWithPrefixes(fileText, TAIL_TEXT_PREFIX)
val completionCharString = InTextDirectivesUtils.findStringWithPrefixes(fileText, COMPLETION_CHAR_PREFIX) val completionChars = completionChars(
val completionChar = when(completionCharString) { char = InTextDirectivesUtils.findStringWithPrefixes(fileText, COMPLETION_CHAR_PREFIX),
"\\n", null -> '\n' chars = InTextDirectivesUtils.findStringWithPrefixes(fileText, COMPLETION_CHARS_PREFIX)
"\\t" -> '\t' )
else -> completionCharString.singleOrNull() ?: error("Incorrect completion char: \"$completionCharString\"")
}
val completionType = ExpectedCompletionUtils.getCompletionType(fileText) ?: defaultCompletionType val completionType = ExpectedCompletionUtils.getCompletionType(fileText) ?: defaultCompletionType
@@ -102,7 +101,7 @@ abstract class AbstractPerformanceCompletionHandlerTests(
} }
doPerfTestWithTextLoaded( doPerfTestWithTextLoaded(
testPath, completionType, invocationCount, lookupString, itemText, tailText, completionChar testPath, completionType, invocationCount, lookupString, itemText, tailText, completionChars
) )
} finally { } finally {
if (configured) { if (configured) {
@@ -120,7 +119,7 @@ abstract class AbstractPerformanceCompletionHandlerTests(
lookupString: String?, lookupString: String?,
itemText: String?, itemText: String?,
tailText: String?, tailText: String?,
completionChar: Char completionChars: String
) { ) {
val testName = getTestName(false) val testName = getTestName(false)
@@ -132,7 +131,7 @@ abstract class AbstractPerformanceCompletionHandlerTests(
setUpFixture(testPath) setUpFixture(testPath)
}, },
test = { test = {
perfTestCore(completionType, time, lookupString, itemText, tailText, completionChar) perfTestCore(completionType, time, lookupString, itemText, tailText, completionChars)
}, },
tearDown = { tearDown = {
runWriteAction { runWriteAction {
@@ -147,14 +146,20 @@ abstract class AbstractPerformanceCompletionHandlerTests(
lookupString: String?, lookupString: String?,
itemText: String?, itemText: String?,
tailText: String?, tailText: String?,
completionChar: Char completionChars: String
) { ) {
completionChars?.let {
for (idx in 0 until it.length - 1) {
fixture.type(it[idx])
}
}
fixture.complete(completionType, time) fixture.complete(completionType, time)
if (lookupString != null || itemText != null || tailText != null) { if (lookupString != null || itemText != null || tailText != null) {
val item = getExistentLookupElement(lookupString, itemText, tailText) val item = getExistentLookupElement(lookupString, itemText, tailText)
if (item != null) { if (item != null) {
selectItem(item, completionChar) selectItem(item, completionChars.last())
} }
} }
} }
@@ -103,6 +103,16 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
} }
} }
protected fun warmUpProject(stats: Stats) {
val project = innerPerfOpenProject("helloKotlin", stats, "warm-up")
try {
val perfHighlightFile = perfHighlightFile(project, "src/HelloMain.kt", stats, "warm-up")
assertTrue("kotlin project has been not imported properly", perfHighlightFile.isNotEmpty())
} finally {
closeProject(project)
}
}
override fun tearDown() { override fun tearDown() {
RunAll( RunAll(
ThrowableRunnable { super.tearDown() }, ThrowableRunnable { super.tearDown() },
@@ -122,6 +132,9 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
return if (lastIndexOf >= 0) fileName.substring(lastIndexOf + 1) else fileName return if (lastIndexOf >= 0) fileName.substring(lastIndexOf + 1) else fileName
} }
protected fun perfOpenKotlinProject(stats: Stats) =
perfOpenProject("perfTestProject", stats = stats, path = "..")
protected fun perfOpenProject(name: String, stats: Stats, path: String = "idea/testData/perfTest") { protected fun perfOpenProject(name: String, stats: Stats, path: String = "idea/testData/perfTest") {
myProject = innerPerfOpenProject(name, stats, path = path, note = "") myProject = innerPerfOpenProject(name, stats, path = path, note = "")
} }
@@ -291,8 +304,8 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
stats: Stats, stats: Stats,
note: String = "" note: String = ""
): List<HighlightInfo> { ): List<HighlightInfo> {
var highlightInfos: List<HighlightInfo> = emptyList() return highlightFile {
IdentifierHighlighterPassFactory.doWithHighlightingEnabled { var highlightInfos: List<HighlightInfo> = emptyList()
stats.perfTest<EditorFile, List<HighlightInfo>>( stats.perfTest<EditorFile, List<HighlightInfo>>(
testName = "highlighting ${if (note.isNotEmpty()) "$note " else ""}${simpleFilename(fileName)}", testName = "highlighting ${if (note.isNotEmpty()) "$note " else ""}${simpleFilename(fileName)}",
setUp = { setUp = {
@@ -309,9 +322,21 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
PsiManager.getInstance(project).dropPsiCaches() PsiManager.getInstance(project).dropPsiCaches()
} }
) )
highlightInfos
} }
//println("${"-".repeat(40)}\n$fileName ->\n${highlightInfos.joinToString("\n")}\n") }
fun highlightFile(psiFile: PsiFile): List<HighlightInfo> {
return highlightFile {
highlightFile(myProject!!, psiFile)
}
}
private fun highlightFile(block: () -> List<HighlightInfo>): List<HighlightInfo> {
var highlightInfos: List<HighlightInfo> = emptyList()
IdentifierHighlighterPassFactory.doWithHighlightingEnabled {
highlightInfos = block()
}
return highlightInfos return highlightInfos
} }
@@ -392,7 +417,7 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
} }
} }
private fun openFileInEditor(project: Project, name: String): EditorFile { fun openFileInEditor(project: Project, name: String): EditorFile {
val fileDocumentManager = FileDocumentManager.getInstance() val fileDocumentManager = FileDocumentManager.getInstance()
val fileEditorManager = FileEditorManager.getInstance(project) val fileEditorManager = FileEditorManager.getInstance(project)
@@ -421,6 +446,6 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
return virtualFile!!.toPsiFile(project)!! return virtualFile!!.toPsiFile(project)!!
} }
private data class EditorFile(val psiFile: PsiFile, val document: Document) data class EditorFile(val psiFile: PsiFile, val document: Document)
} }
@@ -26,7 +26,7 @@ public class PerformanceCompletionCharFilterTestGenerated extends AbstractPerfor
} }
public void testAllFilesPresentInCharFilter() throws Exception { public void testAllFilesPresentInCharFilter() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/handlers/charFilter"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/handlers/charFilter"), Pattern.compile("^([^.]+)\\.kt$"), TargetBackend.ANY, true);
} }
@TestMetadata("Colon.kt") @TestMetadata("Colon.kt")
@@ -144,6 +144,11 @@ public class PerformanceCompletionCharFilterTestGenerated extends AbstractPerfor
runTest("idea/idea-completion/testData/handlers/charFilter/LParenth.kt"); runTest("idea/idea-completion/testData/handlers/charFilter/LParenth.kt");
} }
@TestMetadata("MessageBundle1.kt")
public void testMessageBundle1() throws Exception {
runTest("idea/idea-completion/testData/handlers/charFilter/MessageBundle1.kt");
}
@TestMetadata("NamedParameter1.kt") @TestMetadata("NamedParameter1.kt")
public void testNamedParameter1() throws Exception { public void testNamedParameter1() throws Exception {
runTest("idea/idea-completion/testData/handlers/charFilter/NamedParameter1.kt"); runTest("idea/idea-completion/testData/handlers/charFilter/NamedParameter1.kt");
@@ -35,10 +35,7 @@ class PerformanceProjectsTest : AbstractPerformanceProjectsTest() {
super.setUp() super.setUp()
// warm up: open simple small project // warm up: open simple small project
if (!warmedUp) { if (!warmedUp) {
val project = innerPerfOpenProject("helloKotlin", hwStats, "warm-up") warmUpProject(hwStats)
val perfHighlightFile = perfHighlightFile(project, "src/HelloMain.kt", hwStats, "warm-up")
assertTrue("kotlin project has been not imported properly", perfHighlightFile.isNotEmpty())
closeProject(project)
warmedUp = true warmedUp = true
} }
@@ -58,7 +55,7 @@ class PerformanceProjectsTest : AbstractPerformanceProjectsTest() {
tcSuite("Kotlin project") { tcSuite("Kotlin project") {
val stats = Stats("kotlin project") val stats = Stats("kotlin project")
stats.use { stats.use {
perfOpenProject("perfTestProject", stats = it, path = "..") perfOpenKotlinProject(it)
perfHighlightFile("compiler/psi/src/org/jetbrains/kotlin/psi/KtFile.kt", stats = it) perfHighlightFile("compiler/psi/src/org/jetbrains/kotlin/psi/KtFile.kt", stats = it)
@@ -71,7 +68,7 @@ class PerformanceProjectsTest : AbstractPerformanceProjectsTest() {
tcSuite("Kotlin project highlight build gradle") { tcSuite("Kotlin project highlight build gradle") {
val stats = Stats("kotlin project highlight build gradle") val stats = Stats("kotlin project highlight build gradle")
stats.use { stats.use {
perfOpenProject("perfTestProject", stats = it, path = "..") perfOpenKotlinProject(it)
enableAnnotatorsAndLoadDefinitions() enableAnnotatorsAndLoadDefinitions()