Add performance stress tests
This commit is contained in:
+117
-73
@@ -13,22 +13,16 @@ import com.intellij.codeInsight.daemon.impl.IdentifierHighlighterPassFactory
|
|||||||
import com.intellij.codeInsight.lookup.LookupElement
|
import com.intellij.codeInsight.lookup.LookupElement
|
||||||
import com.intellij.ide.startup.impl.StartupManagerImpl
|
import com.intellij.ide.startup.impl.StartupManagerImpl
|
||||||
import com.intellij.openapi.actionSystem.IdeActions
|
import com.intellij.openapi.actionSystem.IdeActions
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
|
||||||
import com.intellij.openapi.application.runWriteAction
|
import com.intellij.openapi.application.runWriteAction
|
||||||
import com.intellij.openapi.editor.EditorFactory
|
import com.intellij.openapi.editor.EditorFactory
|
||||||
import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl
|
|
||||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||||
import com.intellij.openapi.module.ModuleManager
|
|
||||||
import com.intellij.openapi.project.DumbService
|
import com.intellij.openapi.project.DumbService
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.projectRoots.JavaSdk
|
import com.intellij.openapi.projectRoots.JavaSdk
|
||||||
import com.intellij.openapi.projectRoots.Sdk
|
import com.intellij.openapi.projectRoots.Sdk
|
||||||
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl
|
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl
|
||||||
import com.intellij.openapi.startup.StartupManager
|
import com.intellij.openapi.startup.StartupManager
|
||||||
import com.intellij.openapi.vcs.changes.ChangeListManager
|
|
||||||
import com.intellij.openapi.vcs.changes.ChangeListManagerImpl
|
|
||||||
import com.intellij.openapi.vfs.VirtualFileManager
|
|
||||||
import com.intellij.psi.PsiDocumentManager
|
import com.intellij.psi.PsiDocumentManager
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.psi.PsiManager
|
import com.intellij.psi.PsiManager
|
||||||
@@ -40,14 +34,11 @@ import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl
|
|||||||
import com.intellij.util.ArrayUtilRt
|
import com.intellij.util.ArrayUtilRt
|
||||||
import com.intellij.util.ThrowableRunnable
|
import com.intellij.util.ThrowableRunnable
|
||||||
import com.intellij.util.indexing.UnindexedFilesUpdater
|
import com.intellij.util.indexing.UnindexedFilesUpdater
|
||||||
import com.intellij.util.io.exists
|
|
||||||
import com.intellij.util.ui.UIUtil
|
import com.intellij.util.ui.UIUtil
|
||||||
import org.jetbrains.kotlin.idea.configuration.getModulesWithKotlinFiles
|
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager
|
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager
|
||||||
import org.jetbrains.kotlin.idea.framework.KotlinSdkType
|
import org.jetbrains.kotlin.idea.framework.KotlinSdkType
|
||||||
import org.jetbrains.kotlin.idea.perf.Stats.Companion.WARM_UP
|
import org.jetbrains.kotlin.idea.perf.Stats.Companion.WARM_UP
|
||||||
import org.jetbrains.kotlin.idea.perf.Stats.Companion.runAndMeasure
|
import org.jetbrains.kotlin.idea.perf.Stats.Companion.runAndMeasure
|
||||||
import org.jetbrains.kotlin.idea.project.getAndCacheLanguageLevelByDependencies
|
|
||||||
import org.jetbrains.kotlin.idea.test.invalidateLibraryCache
|
import org.jetbrains.kotlin.idea.test.invalidateLibraryCache
|
||||||
import org.jetbrains.kotlin.idea.testFramework.*
|
import org.jetbrains.kotlin.idea.testFramework.*
|
||||||
import org.jetbrains.kotlin.idea.testFramework.Fixture.Companion.cleanupCaches
|
import org.jetbrains.kotlin.idea.testFramework.Fixture.Companion.cleanupCaches
|
||||||
@@ -55,9 +46,9 @@ import org.jetbrains.kotlin.idea.testFramework.Fixture.Companion.close
|
|||||||
import org.jetbrains.kotlin.idea.testFramework.Fixture.Companion.isAKotlinScriptFile
|
import org.jetbrains.kotlin.idea.testFramework.Fixture.Companion.isAKotlinScriptFile
|
||||||
import org.jetbrains.kotlin.idea.testFramework.Fixture.Companion.openFileInEditor
|
import org.jetbrains.kotlin.idea.testFramework.Fixture.Companion.openFileInEditor
|
||||||
import org.jetbrains.kotlin.idea.testFramework.Fixture.Companion.openFixture
|
import org.jetbrains.kotlin.idea.testFramework.Fixture.Companion.openFixture
|
||||||
|
import org.jetbrains.kotlin.idea.testFramework.ProjectOpenAction.SIMPLE_JAVA_MODULE
|
||||||
import org.jetbrains.kotlin.idea.util.getProjectJdkTableSafe
|
import org.jetbrains.kotlin.idea.util.getProjectJdkTableSafe
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.file.Paths
|
|
||||||
|
|
||||||
abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
|
abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
|
||||||
|
|
||||||
@@ -114,12 +105,14 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
|
|||||||
ThrowableRunnable { super.tearDown() },
|
ThrowableRunnable { super.tearDown() },
|
||||||
ThrowableRunnable {
|
ThrowableRunnable {
|
||||||
if (myProject != null) {
|
if (myProject != null) {
|
||||||
|
logMessage { "myProject is about to be closed" }
|
||||||
DaemonCodeAnalyzerSettings.getInstance().isImportHintEnabled = true // return default value to avoid unnecessary save
|
DaemonCodeAnalyzerSettings.getInstance().isImportHintEnabled = true // return default value to avoid unnecessary save
|
||||||
(StartupManager.getInstance(project()) as StartupManagerImpl).checkCleared()
|
(StartupManager.getInstance(project()) as StartupManagerImpl).checkCleared()
|
||||||
(DaemonCodeAnalyzer.getInstance(project()) as DaemonCodeAnalyzerImpl).cleanupAfterTest()
|
(DaemonCodeAnalyzer.getInstance(project()) as DaemonCodeAnalyzerImpl).cleanupAfterTest()
|
||||||
closeProject(project())
|
closeProject(project())
|
||||||
myApplication.setDataProvider(null)
|
myApplication.setDataProvider(null)
|
||||||
myProject = null
|
myProject = null
|
||||||
|
logMessage { "myProject is closed" }
|
||||||
}
|
}
|
||||||
}).run()
|
}).run()
|
||||||
}
|
}
|
||||||
@@ -129,6 +122,15 @@ 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 perfOpenHelloWorld(stats: Stats, note: String = ""): Project =
|
||||||
|
perfOpenProject(
|
||||||
|
name = "helloKotlin",
|
||||||
|
stats = stats,
|
||||||
|
note = note,
|
||||||
|
path = "idea/testData/perfTest/helloKotlin",
|
||||||
|
openAction = SIMPLE_JAVA_MODULE
|
||||||
|
)
|
||||||
|
|
||||||
protected fun perfOpenProject(
|
protected fun perfOpenProject(
|
||||||
name: String,
|
name: String,
|
||||||
stats: Stats,
|
stats: Stats,
|
||||||
@@ -147,64 +149,35 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
|
|||||||
var lastProject: Project? = null
|
var lastProject: Project? = null
|
||||||
var counter = 0
|
var counter = 0
|
||||||
|
|
||||||
|
val openProject = OpenProject(
|
||||||
|
projectPath = path,
|
||||||
|
projectName = name,
|
||||||
|
jdk = jdk18,
|
||||||
|
projectOpenAction = openAction
|
||||||
|
)
|
||||||
|
|
||||||
performanceTest<Unit, Project> {
|
performanceTest<Unit, Project> {
|
||||||
name("open project${if (note.isNotEmpty()) " $note" else ""}")
|
name("open project $name${if (note.isNotEmpty()) " $note" else ""}")
|
||||||
stats(stats)
|
stats(stats)
|
||||||
warmUpIterations(warmUpIterations)
|
warmUpIterations(warmUpIterations)
|
||||||
iterations(iterations)
|
iterations(iterations)
|
||||||
checkStability(!fast)
|
checkStability(!fast)
|
||||||
test {
|
test {
|
||||||
val project = openAction.openProject(
|
it.value = ProjectOpenAction.openProject(openProject)
|
||||||
projectPath = path,
|
|
||||||
projectName = name,
|
|
||||||
jdk = jdk18
|
|
||||||
)
|
|
||||||
|
|
||||||
dispatchAllInvocationEvents()
|
|
||||||
|
|
||||||
runStartupActivities(project)
|
|
||||||
|
|
||||||
logMessage { "project $name is ${if (project.isInitialized) "initialized" else "not initialized"}" }
|
|
||||||
|
|
||||||
with(ChangeListManager.getInstance(project) as ChangeListManagerImpl) {
|
|
||||||
waitUntilRefreshed()
|
|
||||||
}
|
|
||||||
|
|
||||||
it.value = project
|
|
||||||
}
|
}
|
||||||
tearDown {
|
tearDown {
|
||||||
it.value?.let { project ->
|
it.value?.let { project ->
|
||||||
|
|
||||||
runAndMeasure("refresh gradle project $name") {
|
|
||||||
refreshGradleProjectIfNeeded(projectPath, project)
|
|
||||||
}
|
|
||||||
|
|
||||||
ApplicationManager.getApplication().executeOnPooledThread {
|
|
||||||
DumbService.getInstance(project).waitForSmartMode()
|
|
||||||
|
|
||||||
for (module in getModulesWithKotlinFiles(project)) {
|
|
||||||
module.getAndCacheLanguageLevelByDependencies()
|
|
||||||
}
|
|
||||||
}.get()
|
|
||||||
|
|
||||||
val modules = ModuleManager.getInstance(project).modules
|
|
||||||
assertTrue("project $name has to have at least one module", modules.isNotEmpty())
|
|
||||||
|
|
||||||
logMessage { "modules of $name: ${modules.map { m -> m.name }}" }
|
|
||||||
|
|
||||||
lastProject = project
|
lastProject = project
|
||||||
VirtualFileManager.getInstance().syncRefresh()
|
openAction.postOpenProject(openProject = openProject, project = project)
|
||||||
|
|
||||||
runWriteAction {
|
|
||||||
project.save()
|
|
||||||
}
|
|
||||||
|
|
||||||
logMessage { "project '$name' successfully opened" }
|
logMessage { "project '$name' successfully opened" }
|
||||||
|
|
||||||
// close all project but last - we're going to return and use it further
|
// close all project but last - we're going to return and use it further
|
||||||
if (counter < warmUpIterations + iterations - 1) {
|
if (counter < warmUpIterations + iterations - 1) {
|
||||||
myApplication.setDataProvider(null)
|
myApplication.setDataProvider(null)
|
||||||
|
logMessage { "project '$name' is about to be closed" }
|
||||||
closeProject(project)
|
closeProject(project)
|
||||||
|
logMessage { "project '$name' successfully closed" }
|
||||||
}
|
}
|
||||||
counter++
|
counter++
|
||||||
}
|
}
|
||||||
@@ -235,22 +208,6 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
|
|||||||
return lastProject ?: error("unable to open project $name at $path")
|
return lastProject ?: error("unable to open project $name at $path")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshGradleProjectIfNeeded(projectPath: String, project: Project) {
|
|
||||||
if (listOf("build.gradle.kts", "build.gradle").map { name -> Paths.get(projectPath, name).exists() }.find { e -> e } != true) return
|
|
||||||
|
|
||||||
ExternalProjectsManagerImpl.getInstance(project).setStoreExternally(true)
|
|
||||||
|
|
||||||
refreshGradleProject(projectPath, project)
|
|
||||||
|
|
||||||
dispatchAllInvocationEvents()
|
|
||||||
|
|
||||||
// WARNING: [VD] DO NOT SAVE PROJECT AS IT COULD PERSIST WRONG MODULES INFO
|
|
||||||
|
|
||||||
// runInEdtAndWait {
|
|
||||||
// PlatformTestUtil.saveProject(project)
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun perfTypeAndAutocomplete(
|
fun perfTypeAndAutocomplete(
|
||||||
stats: Stats,
|
stats: Stats,
|
||||||
fileName: String,
|
fileName: String,
|
||||||
@@ -294,7 +251,7 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
|
|||||||
testBlock = { fixture: Fixture ->
|
testBlock = { fixture: Fixture ->
|
||||||
fixture.complete()
|
fixture.complete()
|
||||||
},
|
},
|
||||||
tearDownCheck = { _, value: Array<LookupElement>? ->
|
tearDownCheck = { fixture, value: Array<LookupElement>? ->
|
||||||
val items = value?.map { e -> e.lookupString }?.toList() ?: emptyList()
|
val items = value?.map { e -> e.lookupString }?.toList() ?: emptyList()
|
||||||
for (lookupElement in lookupElements) {
|
for (lookupElement in lookupElements) {
|
||||||
assertTrue("'$lookupElement' has to be present in items $items", items.contains(lookupElement))
|
assertTrue("'$lookupElement' has to be present in items $items", items.contains(lookupElement))
|
||||||
@@ -369,12 +326,12 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
|
|||||||
iterations(15)
|
iterations(15)
|
||||||
profileEnabled(true)
|
profileEnabled(true)
|
||||||
setUp {
|
setUp {
|
||||||
val tasksIdx = editor.document.text.indexOf(marker)
|
val markerOffset = editor.document.text.indexOf(marker)
|
||||||
assertTrue("marker '$marker' not found in $fileName", tasksIdx > 0)
|
assertTrue("marker '$marker' not found in $fileName", markerOffset > 0)
|
||||||
if (typeAfterMarker) {
|
if (typeAfterMarker) {
|
||||||
editor.caretModel.moveToOffset(tasksIdx + marker.length + 1)
|
editor.caretModel.moveToOffset(markerOffset + marker.length + 1)
|
||||||
} else {
|
} else {
|
||||||
editor.caretModel.moveToOffset(tasksIdx - 1)
|
editor.caretModel.moveToOffset(markerOffset - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (surroundItem in surroundItems) {
|
for (surroundItem in surroundItems) {
|
||||||
@@ -420,7 +377,8 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
|
|||||||
) = perfTypeAndHighlight(
|
) = perfTypeAndHighlight(
|
||||||
project(), stats, fileName, marker, insertString, surroundItems,
|
project(), stats, fileName, marker, insertString, surroundItems,
|
||||||
typeAfterMarker = typeAfterMarker,
|
typeAfterMarker = typeAfterMarker,
|
||||||
revertChangesAtTheEnd = revertChangesAtTheEnd, note = note
|
revertChangesAtTheEnd = revertChangesAtTheEnd,
|
||||||
|
note = note
|
||||||
)
|
)
|
||||||
|
|
||||||
fun perfTypeAndHighlight(
|
fun perfTypeAndHighlight(
|
||||||
@@ -488,6 +446,92 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun perfType(
|
||||||
|
stats: Stats,
|
||||||
|
fileName: String,
|
||||||
|
marker: String,
|
||||||
|
insertString: String,
|
||||||
|
surroundItems: String = "\n",
|
||||||
|
typeAfterMarker: Boolean = true,
|
||||||
|
revertChangesAtTheEnd: Boolean = true,
|
||||||
|
note: String = "",
|
||||||
|
delay: Long? = null
|
||||||
|
) = perfType(
|
||||||
|
project(), stats, fileName, marker, insertString, surroundItems,
|
||||||
|
typeAfterMarker = typeAfterMarker,
|
||||||
|
revertChangesAtTheEnd = revertChangesAtTheEnd,
|
||||||
|
note = note,
|
||||||
|
delay = delay
|
||||||
|
)
|
||||||
|
|
||||||
|
fun perfType(
|
||||||
|
project: Project,
|
||||||
|
stats: Stats,
|
||||||
|
fileName: String,
|
||||||
|
marker: String,
|
||||||
|
insertString: String,
|
||||||
|
surroundItems: String = "\n",
|
||||||
|
typeAfterMarker: Boolean = true,
|
||||||
|
revertChangesAtTheEnd: Boolean = true,
|
||||||
|
note: String = "",
|
||||||
|
delay: Long? = null
|
||||||
|
) {
|
||||||
|
performanceTest<Pair<String, Fixture>, List<HighlightInfo>> {
|
||||||
|
name("type ${notePrefix(note)}$fileName")
|
||||||
|
stats(stats)
|
||||||
|
warmUpIterations(8)
|
||||||
|
iterations(15)
|
||||||
|
setUp {
|
||||||
|
val fixture = openFixture(project, fileName)
|
||||||
|
val editor = fixture.editor
|
||||||
|
|
||||||
|
val initialText = editor.document.text
|
||||||
|
updateScriptDependenciesIfNeeded(fileName, fixture, project)
|
||||||
|
|
||||||
|
val tasksIdx = editor.document.text.indexOf(marker)
|
||||||
|
assertTrue("marker '$marker' not found in $fileName", tasksIdx > 0)
|
||||||
|
if (typeAfterMarker) {
|
||||||
|
editor.caretModel.moveToOffset(tasksIdx + marker.length + 1)
|
||||||
|
} else {
|
||||||
|
editor.caretModel.moveToOffset(tasksIdx - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (surroundItem in surroundItems) {
|
||||||
|
EditorTestUtil.performTypingAction(editor, surroundItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.caretModel.moveToOffset(editor.caretModel.offset - if (typeAfterMarker) 1 else 2)
|
||||||
|
|
||||||
|
if (!typeAfterMarker) {
|
||||||
|
for (surroundItem in surroundItems) {
|
||||||
|
EditorTestUtil.performTypingAction(editor, surroundItem)
|
||||||
|
}
|
||||||
|
editor.caretModel.moveToOffset(editor.caretModel.offset - 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
it.setUpValue = Pair(initialText, fixture)
|
||||||
|
}
|
||||||
|
test {
|
||||||
|
val fixture = it.setUpValue!!.second
|
||||||
|
for (i in insertString.indices) {
|
||||||
|
fixture.type(insertString[i])
|
||||||
|
delay?.let { d -> Thread.sleep(d) }
|
||||||
|
}
|
||||||
|
it.value = fixture.doHighlighting()
|
||||||
|
}
|
||||||
|
tearDown {
|
||||||
|
it.value?.let { list ->
|
||||||
|
assertNotEmpty(list)
|
||||||
|
}
|
||||||
|
it.setUpValue?.let { pair ->
|
||||||
|
pair.second.revertChanges(revertChangesAtTheEnd, pair.first)
|
||||||
|
}
|
||||||
|
commitAllDocuments()
|
||||||
|
}
|
||||||
|
profileEnabled(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun perfCopyAndPaste(
|
fun perfCopyAndPaste(
|
||||||
stats: Stats,
|
stats: Stats,
|
||||||
sourceFileName: String,
|
sourceFileName: String,
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* 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.perf
|
||||||
|
|
||||||
|
import java.nio.file.*
|
||||||
|
|
||||||
|
fun Path.copyRecursively(targetDirectory: Path) {
|
||||||
|
val src = this
|
||||||
|
Files.walk(src)
|
||||||
|
.forEach { source -> Files.copy(source, targetDirectory.resolve(src.relativize(source)), StandardCopyOption.REPLACE_EXISTING) }
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@ class PerfTestBuilder<SV, TV> {
|
|||||||
private var profileEnabled: Boolean = false
|
private var profileEnabled: Boolean = false
|
||||||
private var checkStability: Boolean = true
|
private var checkStability: Boolean = true
|
||||||
|
|
||||||
fun run() {
|
internal fun run() {
|
||||||
stats.perfTest(
|
stats.perfTest(
|
||||||
testName = name,
|
testName = name,
|
||||||
warmUpIterations = warmUpIterations,
|
warmUpIterations = warmUpIterations,
|
||||||
|
|||||||
+2
-12
@@ -20,8 +20,7 @@ import org.jetbrains.kotlin.idea.perf.Stats.Companion.tcSuite
|
|||||||
import org.jetbrains.kotlin.idea.testFramework.Fixture
|
import org.jetbrains.kotlin.idea.testFramework.Fixture
|
||||||
import org.jetbrains.kotlin.idea.testFramework.Fixture.Companion.cleanupCaches
|
import org.jetbrains.kotlin.idea.testFramework.Fixture.Companion.cleanupCaches
|
||||||
import org.jetbrains.kotlin.idea.testFramework.Fixture.Companion.isAKotlinScriptFile
|
import org.jetbrains.kotlin.idea.testFramework.Fixture.Companion.isAKotlinScriptFile
|
||||||
import org.jetbrains.kotlin.idea.testFramework.ProjectOpenAction.EXISTING_IDEA_PROJECT
|
import org.jetbrains.kotlin.idea.testFramework.ProjectOpenAction.GRADLE_PROJECT
|
||||||
import org.jetbrains.kotlin.idea.testFramework.ProjectOpenAction.SIMPLE_JAVA_MODULE
|
|
||||||
import java.util.concurrent.atomic.AtomicLong
|
import java.util.concurrent.atomic.AtomicLong
|
||||||
import kotlin.test.assertNotEquals
|
import kotlin.test.assertNotEquals
|
||||||
|
|
||||||
@@ -217,20 +216,11 @@ class PerformanceProjectsTest : AbstractPerformanceProjectsTest() {
|
|||||||
stats = stats,
|
stats = stats,
|
||||||
note = "",
|
note = "",
|
||||||
path = "../perfTestProject",
|
path = "../perfTestProject",
|
||||||
openAction = EXISTING_IDEA_PROJECT,
|
openAction = GRADLE_PROJECT,
|
||||||
fast = fast
|
fast = fast
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun perfOpenHelloWorld(stats: Stats, note: String = ""): Project =
|
|
||||||
perfOpenProject(
|
|
||||||
name = "helloKotlin",
|
|
||||||
stats = stats,
|
|
||||||
note = note,
|
|
||||||
path = "idea/testData/perfTest/helloKotlin",
|
|
||||||
openAction = SIMPLE_JAVA_MODULE
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun perfScriptDependenciesBuildGradleKts(it: Stats) {
|
private fun perfScriptDependenciesBuildGradleKts(it: Stats) {
|
||||||
perfScriptDependencies("build.gradle.kts", stats = it)
|
perfScriptDependencies("build.gradle.kts", stats = it)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* 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.perf
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.idea.perf.Stats.Companion.tcSuite
|
||||||
|
|
||||||
|
class PerformanceStressTest : AbstractPerformanceProjectsTest() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
var warmedUp: Boolean = false
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
val hwStats: Stats = Stats("helloWorld project")
|
||||||
|
|
||||||
|
init {
|
||||||
|
// there is no @AfterClass for junit3.8
|
||||||
|
Runtime.getRuntime().addShutdownHook(Thread { hwStats.close() })
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setUp() {
|
||||||
|
super.setUp()
|
||||||
|
// warm up: open simple small project
|
||||||
|
if (!warmedUp) {
|
||||||
|
warmUpProject(hwStats, "src/HelloMain.kt") {
|
||||||
|
openProject {
|
||||||
|
name("helloWorld")
|
||||||
|
|
||||||
|
kotlinFile("HelloMain") {
|
||||||
|
topFunction("main") {
|
||||||
|
param("args", "Array<String>")
|
||||||
|
body("""println("Hello World!")""")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
warmedUp = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testLotsOfOverloadedMethods() {
|
||||||
|
// KT-35135
|
||||||
|
val generatedTypes = mutableListOf(listOf<String>())
|
||||||
|
generateTypes(arrayOf("Int", "String", "Long", "List<Int>", "Array<Int>"), generatedTypes)
|
||||||
|
|
||||||
|
tcSuite("Lots of overloaded method project") {
|
||||||
|
myProject = openProject {
|
||||||
|
name("kt-35135")
|
||||||
|
buildGradle("idea/testData/perfTest/simpleTemplate/")
|
||||||
|
|
||||||
|
kotlinFile("OverloadX") {
|
||||||
|
pkg("pkg")
|
||||||
|
|
||||||
|
topClass("OverloadX") {
|
||||||
|
openClass()
|
||||||
|
|
||||||
|
for (types in generatedTypes) {
|
||||||
|
function("foo") {
|
||||||
|
openFunction()
|
||||||
|
returnType("String")
|
||||||
|
for ((index, type) in types.withIndex()) {
|
||||||
|
param("arg$index", type)
|
||||||
|
}
|
||||||
|
body("TODO()")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlinFile("SomeClass") {
|
||||||
|
pkg("pkg")
|
||||||
|
|
||||||
|
topClass("SomeClass") {
|
||||||
|
superClass("OverloadX")
|
||||||
|
|
||||||
|
body("ov")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val stats = Stats("kt-35135 project")
|
||||||
|
stats.use { stats ->
|
||||||
|
perfType(
|
||||||
|
stats,
|
||||||
|
"src/main/java/pkg/SomeClass.kt",
|
||||||
|
"ov",
|
||||||
|
"override fun foo(): String = TODO()",
|
||||||
|
note = "override fun foo()",
|
||||||
|
delay = 50
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private tailrec fun generateTypes(types: Array<String>, results: MutableList<List<String>>, index: Int = 0, maxCount: Int = 3000) {
|
||||||
|
val newResults = mutableListOf<List<String>>()
|
||||||
|
for (list in results) {
|
||||||
|
if (list.size < index) continue
|
||||||
|
for (t in types) {
|
||||||
|
val newList = mutableListOf<String>()
|
||||||
|
newList.addAll(list)
|
||||||
|
newList.add(t)
|
||||||
|
newResults.add(newList.toList())
|
||||||
|
if (results.size + newResults.size >= maxCount) {
|
||||||
|
results.addAll(newResults)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
results.addAll(newResults)
|
||||||
|
generateTypes(types, results, index + 1, maxCount)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,227 @@
|
|||||||
|
/*
|
||||||
|
* 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.perf
|
||||||
|
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.projectRoots.JavaSdk
|
||||||
|
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl
|
||||||
|
import com.intellij.util.io.*
|
||||||
|
import org.jetbrains.kotlin.idea.testFramework.OpenProject
|
||||||
|
import org.jetbrains.kotlin.idea.testFramework.ProjectOpenAction
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Paths
|
||||||
|
|
||||||
|
abstract class AbstractSource {
|
||||||
|
protected val body = StringBuilder()
|
||||||
|
|
||||||
|
protected open fun newLineAfterCodeBlock(): Boolean = true
|
||||||
|
|
||||||
|
protected open fun intendLevel(): Int = 0
|
||||||
|
|
||||||
|
private fun intendPrefix() = " ".repeat(2 * intendLevel())
|
||||||
|
|
||||||
|
fun body(code: Any) {
|
||||||
|
this.body.append(code.toString().prependIndent(intendPrefix()))
|
||||||
|
if (newLineAfterCodeBlock()) this.body.append('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = body.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class AbstractClassSource(val name: String) : AbstractSource() {
|
||||||
|
override fun intendLevel(): Int = 1
|
||||||
|
|
||||||
|
fun function(name: String, funSource: FunSource.() -> Unit) {
|
||||||
|
val funSource = FunSource(name).apply(funSource)
|
||||||
|
super.body(funSource)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CompanionObjectSource : AbstractClassSource("") {
|
||||||
|
override fun toString(): String = "companion object {\n$body}"
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClassSource(name: String, private val topLevel: Boolean = true) : AbstractClassSource(name) {
|
||||||
|
|
||||||
|
private var openClass: Boolean = false
|
||||||
|
|
||||||
|
private var superClass: String? = null
|
||||||
|
private val interfaces = mutableListOf<String>()
|
||||||
|
|
||||||
|
fun superClass(superClass: String) {
|
||||||
|
check(this.superClass == null) { "super class is already specified for $name: ${this.superClass}" }
|
||||||
|
this.superClass = superClass
|
||||||
|
}
|
||||||
|
|
||||||
|
fun interfaces(iface: String) {
|
||||||
|
interfaces.add(iface)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun openClass() {
|
||||||
|
openClass(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun openClass(openClass: Boolean) {
|
||||||
|
this.openClass = openClass
|
||||||
|
}
|
||||||
|
|
||||||
|
fun companionObject(companionObjectSource: CompanionObjectSource.() -> Unit) {
|
||||||
|
check(topLevel) { "companion object is allowed only in top-level classes, wrong class: $name" }
|
||||||
|
val source = CompanionObjectSource().apply(companionObjectSource)
|
||||||
|
super.body(source)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun openPrefix(): String = if (!openClass) "" else "open "
|
||||||
|
|
||||||
|
private fun superAndInterfaces(): String {
|
||||||
|
val superStr = if (superClass != null) {
|
||||||
|
": $superClass()"
|
||||||
|
} else ""
|
||||||
|
|
||||||
|
return if (interfaces.isEmpty()) superStr
|
||||||
|
else {
|
||||||
|
val interfacesStr = interfaces.joinToString()
|
||||||
|
if (superStr.isEmpty()) ": $interfacesStr" else "$superStr, $interfacesStr"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = "${openPrefix()}class $name ${superAndInterfaces()} {\n$body}"
|
||||||
|
}
|
||||||
|
|
||||||
|
class FunSource(val name: String) : AbstractSource() {
|
||||||
|
private val params = mutableMapOf<String, String>()
|
||||||
|
private var openFunction: Boolean = false
|
||||||
|
private var returnType: String? = null
|
||||||
|
|
||||||
|
override fun intendLevel(): Int = 1
|
||||||
|
|
||||||
|
fun openFunction() {
|
||||||
|
this.openFunction = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun param(name: String, type: String) {
|
||||||
|
this.params[name] = type
|
||||||
|
}
|
||||||
|
|
||||||
|
fun returnType(returnType: String) {
|
||||||
|
this.returnType = returnType
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun modifiers(): String {
|
||||||
|
val s = if (openFunction) "open" else ""
|
||||||
|
return if (s.isEmpty()) s else "$s "
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun retType(): String {
|
||||||
|
returnType ?: return ""
|
||||||
|
return ": $returnType "
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String =
|
||||||
|
"${modifiers()}fun $name(${params.map { it.key + ": " + it.value }.joinToString()}) ${retType()}{\n$body}"
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinFileSource : AbstractSource() {
|
||||||
|
|
||||||
|
internal var pkg: String? = null
|
||||||
|
|
||||||
|
fun pkg(pkg: String) {
|
||||||
|
check(this.pkg == null) { "package directive is already specified: ${this.pkg}" }
|
||||||
|
this.pkg = pkg
|
||||||
|
super.body("package $pkg\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun topClass(name: String, clsSource: ClassSource.() -> Unit) {
|
||||||
|
val classSource = ClassSource(name).apply(clsSource)
|
||||||
|
super.body(classSource)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun topFunction(name: String, funSource: FunSource.() -> Unit) {
|
||||||
|
val funSource = FunSource(name).apply(funSource)
|
||||||
|
super.body(funSource)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProjectBuilder {
|
||||||
|
internal var buildGradle: String? = null
|
||||||
|
internal lateinit var name: String
|
||||||
|
private val kotlinFiles = mutableListOf<Pair<String, KotlinFileSource>>()
|
||||||
|
|
||||||
|
fun buildGradle(buildGradle: String) {
|
||||||
|
this.buildGradle = buildGradle
|
||||||
|
}
|
||||||
|
|
||||||
|
fun name(name: String) {
|
||||||
|
this.name = name
|
||||||
|
}
|
||||||
|
|
||||||
|
fun kotlinFile(name: String, kotlinFileSource: KotlinFileSource.() -> Unit) {
|
||||||
|
val source = KotlinFileSource().apply(kotlinFileSource)
|
||||||
|
kotlinFiles.add(Pair(name, source))
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun generateFiles(): String {
|
||||||
|
val targetDirectory = Files.createTempDirectory(name)
|
||||||
|
Runtime.getRuntime().addShutdownHook(Thread {
|
||||||
|
targetDirectory.delete(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
val javaMainSrcDir = if (buildGradle != null) {
|
||||||
|
val buildGradlePath = Paths.get(buildGradle)
|
||||||
|
when {
|
||||||
|
buildGradlePath.isFile() -> {
|
||||||
|
buildGradlePath.copy(targetDirectory)
|
||||||
|
}
|
||||||
|
buildGradlePath.isDirectory() -> {
|
||||||
|
val buildGradleFile =
|
||||||
|
listOf("build.gradle.kts", "build.gradle").map { buildGradlePath.resolve(it) }.firstOrNull { it.exists() }
|
||||||
|
?: error("neither build.gradle.kts nor build.gradle found at $buildGradlePath")
|
||||||
|
buildGradleFile.copy(targetDirectory.resolve(buildGradleFile.fileName))
|
||||||
|
}
|
||||||
|
else -> error("illegal type of build gradle path: $buildGradlePath")
|
||||||
|
}
|
||||||
|
|
||||||
|
targetDirectory.resolve("src/main/java")
|
||||||
|
} else {
|
||||||
|
targetDirectory.resolve("src")
|
||||||
|
}
|
||||||
|
javaMainSrcDir.createDirectories()
|
||||||
|
kotlinFiles.forEach { (name, source) ->
|
||||||
|
val srcDir = source.pkg?.let { pkg ->
|
||||||
|
val path = javaMainSrcDir.resolve(pkg.replace('.', '/'))
|
||||||
|
path.createDirectories()
|
||||||
|
path
|
||||||
|
} ?: javaMainSrcDir
|
||||||
|
srcDir.resolve("$name.kt").toFile().writeText(source.toString())
|
||||||
|
}
|
||||||
|
//
|
||||||
|
return targetDirectory.toAbsolutePath().toFile().absolutePath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun openProject(initializer: ProjectBuilder.() -> Unit): Project {
|
||||||
|
val projectBuilder = ProjectBuilder().apply(initializer)
|
||||||
|
val projectPath = projectBuilder.generateFiles()
|
||||||
|
|
||||||
|
val jdkTableImpl = JavaAwareProjectJdkTableImpl.getInstanceEx()
|
||||||
|
val homePath = if (jdkTableImpl.internalJdk.homeDirectory!!.name == "jre") {
|
||||||
|
jdkTableImpl.internalJdk.homeDirectory!!.parent.path
|
||||||
|
} else {
|
||||||
|
jdkTableImpl.internalJdk.homePath!!
|
||||||
|
}
|
||||||
|
val javaSdk = JavaSdk.getInstance()
|
||||||
|
val jdk18 = javaSdk.createJdk("1.8", homePath)
|
||||||
|
val openAction = if (projectBuilder.buildGradle != null) ProjectOpenAction.GRADLE_PROJECT else ProjectOpenAction.SIMPLE_JAVA_MODULE
|
||||||
|
val openProject = OpenProject(
|
||||||
|
projectPath = projectPath,
|
||||||
|
projectName = projectBuilder.name,
|
||||||
|
jdk = jdk18,
|
||||||
|
projectOpenAction = openAction
|
||||||
|
)
|
||||||
|
val project = ProjectOpenAction.openProject(openProject)
|
||||||
|
openAction.postOpenProject(project = project, openProject = openProject)
|
||||||
|
return project
|
||||||
|
}
|
||||||
@@ -61,6 +61,10 @@ class Fixture(val project: Project, val editor: Editor, val psiFile: PsiFile, va
|
|||||||
delegate.type(s)
|
delegate.type(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun type(c: Char) {
|
||||||
|
delegate.type(c)
|
||||||
|
}
|
||||||
|
|
||||||
fun performEditorAction(actionId: String): Boolean {
|
fun performEditorAction(actionId: String): Boolean {
|
||||||
selectEditor()
|
selectEditor()
|
||||||
return delegate.performEditorAction(actionId)
|
return delegate.performEditorAction(actionId)
|
||||||
|
|||||||
+80
@@ -6,20 +6,34 @@
|
|||||||
package org.jetbrains.kotlin.idea.testFramework
|
package org.jetbrains.kotlin.idea.testFramework
|
||||||
|
|
||||||
import com.intellij.ide.highlighter.ModuleFileType
|
import com.intellij.ide.highlighter.ModuleFileType
|
||||||
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
import com.intellij.openapi.application.runWriteAction
|
import com.intellij.openapi.application.runWriteAction
|
||||||
|
import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl
|
||||||
import com.intellij.openapi.module.ModuleManager
|
import com.intellij.openapi.module.ModuleManager
|
||||||
import com.intellij.openapi.module.ModuleTypeId
|
import com.intellij.openapi.module.ModuleTypeId
|
||||||
|
import com.intellij.openapi.project.DumbService
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.project.ex.ProjectManagerEx
|
import com.intellij.openapi.project.ex.ProjectManagerEx
|
||||||
import com.intellij.openapi.projectRoots.Sdk
|
import com.intellij.openapi.projectRoots.Sdk
|
||||||
import com.intellij.openapi.roots.ProjectRootManager
|
import com.intellij.openapi.roots.ProjectRootManager
|
||||||
|
import com.intellij.openapi.vcs.changes.ChangeListManager
|
||||||
|
import com.intellij.openapi.vcs.changes.ChangeListManagerImpl
|
||||||
import com.intellij.openapi.vfs.LocalFileSystem
|
import com.intellij.openapi.vfs.LocalFileSystem
|
||||||
|
import com.intellij.openapi.vfs.VirtualFileManager
|
||||||
import com.intellij.testFramework.PsiTestUtil
|
import com.intellij.testFramework.PsiTestUtil
|
||||||
|
import com.intellij.testFramework.UsefulTestCase
|
||||||
|
import com.intellij.util.io.exists
|
||||||
|
import org.jetbrains.kotlin.idea.configuration.getModulesWithKotlinFiles
|
||||||
|
import org.jetbrains.kotlin.idea.perf.Stats.Companion.runAndMeasure
|
||||||
|
import org.jetbrains.kotlin.idea.project.getAndCacheLanguageLevelByDependencies
|
||||||
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
|
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.nio.file.Paths
|
||||||
import kotlin.test.assertNotNull
|
import kotlin.test.assertNotNull
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
data class OpenProject(val projectPath: String, val projectName: String, val jdk: Sdk, val projectOpenAction: ProjectOpenAction)
|
||||||
|
|
||||||
enum class ProjectOpenAction {
|
enum class ProjectOpenAction {
|
||||||
SIMPLE_JAVA_MODULE {
|
SIMPLE_JAVA_MODULE {
|
||||||
override fun openProject(projectPath: String, projectName: String, jdk: Sdk): Project {
|
override fun openProject(projectPath: String, projectName: String, jdk: Sdk): Project {
|
||||||
@@ -73,7 +87,73 @@ enum class ProjectOpenAction {
|
|||||||
|
|
||||||
return project
|
return project
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun refreshGradleProjectIfNeeded(projectPath: String, project: Project) {
|
||||||
|
if (listOf("build.gradle.kts", "build.gradle").map { name -> Paths.get(projectPath, name).exists() }
|
||||||
|
.find { e -> e } != true) return
|
||||||
|
|
||||||
|
ExternalProjectsManagerImpl.getInstance(project).setStoreExternally(true)
|
||||||
|
|
||||||
|
refreshGradleProject(projectPath, project)
|
||||||
|
|
||||||
|
dispatchAllInvocationEvents()
|
||||||
|
|
||||||
|
// WARNING: [VD] DO NOT SAVE PROJECT AS IT COULD PERSIST WRONG MODULES INFO
|
||||||
|
|
||||||
|
// runInEdtAndWait {
|
||||||
|
// PlatformTestUtil.saveProject(project)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun postOpenProject(project: Project, openProject: OpenProject) {
|
||||||
|
runAndMeasure("refresh gradle project ${openProject.projectName}") {
|
||||||
|
refreshGradleProjectIfNeeded(openProject.projectPath, project)
|
||||||
|
}
|
||||||
|
|
||||||
|
super.postOpenProject(project, openProject)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
abstract fun openProject(projectPath: String, projectName: String, jdk: Sdk): Project
|
abstract fun openProject(projectPath: String, projectName: String, jdk: Sdk): Project
|
||||||
|
|
||||||
|
open fun postOpenProject(project: Project, openProject: OpenProject) {
|
||||||
|
ApplicationManager.getApplication().executeOnPooledThread {
|
||||||
|
DumbService.getInstance(project).waitForSmartMode()
|
||||||
|
|
||||||
|
for (module in getModulesWithKotlinFiles(project)) {
|
||||||
|
module.getAndCacheLanguageLevelByDependencies()
|
||||||
|
}
|
||||||
|
}.get()
|
||||||
|
|
||||||
|
val modules = ModuleManager.getInstance(project).modules
|
||||||
|
UsefulTestCase.assertTrue("project ${openProject.projectName} has to have at least one module", modules.isNotEmpty())
|
||||||
|
|
||||||
|
logMessage { "modules of ${openProject.projectName}: ${modules.map { m -> m.name }}" }
|
||||||
|
|
||||||
|
VirtualFileManager.getInstance().syncRefresh()
|
||||||
|
|
||||||
|
//runWriteAction { project.save() }
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun openProject(openProject: OpenProject): Project {
|
||||||
|
val project = openProject.projectOpenAction.openProject(
|
||||||
|
projectPath = openProject.projectPath,
|
||||||
|
projectName = openProject.projectName,
|
||||||
|
jdk = openProject.jdk
|
||||||
|
)
|
||||||
|
|
||||||
|
dispatchAllInvocationEvents()
|
||||||
|
|
||||||
|
runStartupActivities(project)
|
||||||
|
|
||||||
|
logMessage { "project ${openProject.projectName} is ${if (project.isInitialized) "initialized" else "not initialized"}" }
|
||||||
|
|
||||||
|
with(ChangeListManager.getInstance(project) as ChangeListManagerImpl) {
|
||||||
|
waitUntilRefreshed()
|
||||||
|
}
|
||||||
|
return project
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+38
-3
@@ -5,7 +5,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.testFramework
|
package org.jetbrains.kotlin.idea.testFramework
|
||||||
|
|
||||||
|
import com.intellij.openapi.components.ServiceManager
|
||||||
|
import com.intellij.openapi.externalSystem.model.DataNode
|
||||||
|
import com.intellij.openapi.externalSystem.model.project.ProjectData
|
||||||
|
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId
|
||||||
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode
|
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode
|
||||||
|
import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback
|
||||||
|
import com.intellij.openapi.externalSystem.service.project.ProjectDataManager
|
||||||
import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl
|
import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl
|
||||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
||||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil
|
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil
|
||||||
@@ -16,10 +22,11 @@ import org.jetbrains.plugins.gradle.service.project.open.setupGradleSettings
|
|||||||
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings
|
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings
|
||||||
import org.jetbrains.plugins.gradle.util.GradleConstants
|
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||||
import org.jetbrains.plugins.gradle.util.GradleLog
|
import org.jetbrains.plugins.gradle.util.GradleLog
|
||||||
|
import java.io.File
|
||||||
import kotlin.test.assertNotNull
|
import kotlin.test.assertNotNull
|
||||||
|
|
||||||
fun refreshGradleProject(projectPath: String, project: Project) {
|
fun refreshGradleProject(projectPath: String, project: Project) {
|
||||||
_importProject(projectPath, project)
|
_importProject(File(projectPath).absolutePath, project)
|
||||||
|
|
||||||
dispatchAllInvocationEvents()
|
dispatchAllInvocationEvents()
|
||||||
}
|
}
|
||||||
@@ -58,6 +65,34 @@ private fun _attachGradleProjectAndRefresh(
|
|||||||
if (settings.getLinkedProjectSettings(externalProjectPath) == null) {
|
if (settings.getLinkedProjectSettings(externalProjectPath) == null) {
|
||||||
settings.linkProject(gradleProjectSettings)
|
settings.linkProject(gradleProjectSettings)
|
||||||
}
|
}
|
||||||
//ExternalSystemUtil.refreshProject(project, GradleConstants.SYSTEM_ID, externalProjectPath, true, ProgressExecutionMode.MODAL_SYNC)
|
//ExternalSystemUtil.refreshProject(project, GradleConstants.SYSTEM_ID, externalProjectPath, false, ProgressExecutionMode.MODAL_SYNC)
|
||||||
ExternalSystemUtil.refreshProject(project, GradleConstants.SYSTEM_ID, externalProjectPath, false, ProgressExecutionMode.MODAL_SYNC)
|
|
||||||
|
val progressExecutionMode = ProgressExecutionMode.MODAL_SYNC
|
||||||
|
val externalSystemId = GradleConstants.SYSTEM_ID
|
||||||
|
val callback = object : ExternalProjectRefreshCallback {
|
||||||
|
override fun onFailure(errorMessage: String, errorDetails: String?) {
|
||||||
|
super.onFailure(errorMessage, errorDetails)
|
||||||
|
throw RuntimeException(errorMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(
|
||||||
|
externalTaskId: ExternalSystemTaskId,
|
||||||
|
errorMessage: String,
|
||||||
|
errorDetails: String?
|
||||||
|
) {
|
||||||
|
super.onFailure(externalTaskId, errorMessage, errorDetails)
|
||||||
|
throw RuntimeException(errorMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSuccess(externalProject: DataNode<ProjectData>?) {
|
||||||
|
if (externalProject == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val synchronous = progressExecutionMode == ProgressExecutionMode.MODAL_SYNC
|
||||||
|
ServiceManager.getService(
|
||||||
|
ProjectDataManager::class.java
|
||||||
|
).importData(externalProject, project, synchronous)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ExternalSystemUtil.refreshProject(project, externalSystemId, externalProjectPath, callback, false, progressExecutionMode, true)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
kotlin("jvm") version "1.3.61"
|
||||||
|
}
|
||||||
|
|
||||||
|
version = "1.0.0-SNAPSHOT"
|
||||||
|
|
||||||
|
tasks.withType<KotlinCompile> {
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
freeCompilerArgs = listOf("-Xjsr305=strict")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
||||||
|
compile("org.jetbrains.kotlin:kotlin-reflect")
|
||||||
|
compile("org.jetbrains:annotations:16.0.1")
|
||||||
|
}
|
||||||
|
|
||||||
|
val compileKotlin: KotlinCompile by tasks
|
||||||
|
compileKotlin.kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
}
|
||||||
|
val compileTestKotlin: KotlinCompile by tasks
|
||||||
|
compileTestKotlin.kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user