diff --git a/idea/idea-test-framework/test/org/jetbrains/kotlin/idea/test/KotlinLightCodeInsightFixtureTestCase.kt.181 b/idea/idea-test-framework/test/org/jetbrains/kotlin/idea/test/KotlinLightCodeInsightFixtureTestCase.kt.181 new file mode 100644 index 00000000000..94e97f66be8 --- /dev/null +++ b/idea/idea-test-framework/test/org/jetbrains/kotlin/idea/test/KotlinLightCodeInsightFixtureTestCase.kt.181 @@ -0,0 +1,223 @@ +/* + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.test + +import com.intellij.codeInsight.CodeInsightTestCase +import com.intellij.codeInsight.daemon.impl.EditorTracker +import com.intellij.ide.startup.impl.StartupManagerImpl +import com.intellij.openapi.actionSystem.ActionPlaces +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.actionSystem.Presentation +import com.intellij.openapi.actionSystem.ex.ActionManagerEx +import com.intellij.openapi.application.WriteAction +import com.intellij.openapi.editor.ex.EditorEx +import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProviderImpl +import com.intellij.openapi.module.Module +import com.intellij.openapi.project.Project +import com.intellij.openapi.startup.StartupManager +import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.util.text.StringUtil +import com.intellij.openapi.vfs.VfsUtilCore +import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess +import com.intellij.psi.PsiManager +import com.intellij.psi.search.FileTypeIndex +import com.intellij.psi.search.ProjectScope +import com.intellij.testFramework.LightProjectDescriptor +import com.intellij.testFramework.LoggedErrorProcessor +import org.apache.log4j.Logger +import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments +import org.jetbrains.kotlin.cli.common.arguments.parseCommandLineArguments +import org.jetbrains.kotlin.config.* +import org.jetbrains.kotlin.idea.KotlinFileType +import org.jetbrains.kotlin.idea.actions.internal.KotlinInternalMode +import org.jetbrains.kotlin.idea.facet.configureFacet +import org.jetbrains.kotlin.idea.facet.getOrCreateFacet +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.test.InTextDirectivesUtils +import org.jetbrains.kotlin.test.KotlinTestUtils +import org.jetbrains.kotlin.test.TestMetadata +import org.jetbrains.kotlin.utils.addIfNotNull +import org.jetbrains.kotlin.utils.rethrow +import java.io.File +import java.io.IOException +import java.util.* +import kotlin.reflect.full.findAnnotation + +abstract class KotlinLightCodeInsightFixtureTestCase : KotlinLightCodeInsightFixtureTestCaseBase() { + private var kotlinInternalModeOriginalValue = false + + private val exceptions = ArrayList() + + protected val module: Module get() = myFixture.module + + protected open val captureExceptions = true + + override fun setUp() { + super.setUp() + (StartupManager.getInstance(project) as StartupManagerImpl).runPostStartupActivities() + VfsRootAccess.allowRootAccess(KotlinTestUtils.getHomeDirectory()) + + kotlinInternalModeOriginalValue = KotlinInternalMode.enabled + KotlinInternalMode.enabled = true + + project.getComponent(EditorTracker::class.java)?.projectOpened() + + invalidateLibraryCache(project) + + if (captureExceptions) { + LoggedErrorProcessor.setNewInstance(object : LoggedErrorProcessor() { + override fun processError(message: String?, t: Throwable?, details: Array?, logger: Logger) { + exceptions.addIfNotNull(t) + super.processError(message, t, details, logger) + } + }) + } + } + + override fun tearDown() { + LoggedErrorProcessor.restoreDefaultProcessor() + + KotlinInternalMode.enabled = kotlinInternalModeOriginalValue + VfsRootAccess.disallowRootAccess(KotlinTestUtils.getHomeDirectory()) + + doKotlinTearDown(project) { + super.tearDown() + } + + if (exceptions.isNotEmpty()) { + exceptions.forEach { it.printStackTrace() } + throw AssertionError("Exceptions in other threads happened") + } + } + + override fun getProjectDescriptor(): LightProjectDescriptor + = getProjectDescriptorFromFileDirective() + + protected fun getProjectDescriptorFromTestName(): LightProjectDescriptor { + val testName = StringUtil.toLowerCase(getTestName(false)) + + if (testName.endsWith("runtime")) { + return KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE + } + else if (testName.endsWith("stdlib")) { + return ProjectDescriptorWithStdlibSources.INSTANCE + } + + return KotlinLightProjectDescriptor.INSTANCE + } + + protected fun getProjectDescriptorFromFileDirective(): LightProjectDescriptor { + if (!isAllFilesPresentInTest()) { + try { + val fileText = FileUtil.loadFile(File(testDataPath, fileName()), true) + + val withLibraryDirective = InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileText, "WITH_LIBRARY:") + if (!withLibraryDirective.isEmpty()) { + return SdkAndMockLibraryProjectDescriptor( + PluginTestCaseBase.getTestDataPathBase() + "/" + withLibraryDirective.get( + 0 + ), true + ) + } + else if (InTextDirectivesUtils.isDirectiveDefined(fileText, "RUNTIME_WITH_SOURCES")) { + return ProjectDescriptorWithStdlibSources.INSTANCE + } + else if (InTextDirectivesUtils.isDirectiveDefined(fileText, "RUNTIME_WITH_KOTLIN_TEST")) { + return KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE_WITH_KOTLIN_TEST + } + else if (InTextDirectivesUtils.isDirectiveDefined(fileText, "RUNTIME_WITH_FULL_JDK")) { + return KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE_FULL_JDK + } + else if (InTextDirectivesUtils.isDirectiveDefined(fileText, "RUNTIME_WITH_REFLECT")) { + return KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE_WITH_REFLECT + } + else if (InTextDirectivesUtils.isDirectiveDefined(fileText, "RUNTIME") || + InTextDirectivesUtils.isDirectiveDefined(fileText, "WITH_RUNTIME")) { + return KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE + } + else if (InTextDirectivesUtils.isDirectiveDefined(fileText, "JS")) { + return KotlinStdJSProjectDescriptor + } + else if (InTextDirectivesUtils.isDirectiveDefined(fileText, "ENABLE_MULTIPLATFORM")) { + return KotlinProjectDescriptorWithFacet.KOTLIN_STABLE_WITH_MULTIPLATFORM + } + } + catch (e: IOException) { + throw rethrow(e) + } + } + return KotlinLightProjectDescriptor.INSTANCE + } + + protected fun isAllFilesPresentInTest(): Boolean = KotlinTestUtils.isAllFilesPresentTest(getTestName(false)) + + protected open fun fileName(): String + = KotlinTestUtils.getTestDataFileName(this::class.java, this.name) ?: (getTestName(false) + ".kt") + + protected fun performNotWriteEditorAction(actionId: String): Boolean { + val dataContext = (myFixture.editor as EditorEx).dataContext + + val managerEx = ActionManagerEx.getInstanceEx() + val action = managerEx.getAction(actionId) + val event = AnActionEvent(null, dataContext, ActionPlaces.UNKNOWN, Presentation(), managerEx, 0) + + action.update(event) + if (!event.presentation.isEnabled) { + return false + } + + managerEx.fireBeforeActionPerformed(action, dataContext, event) + action.actionPerformed(event) + + managerEx.fireAfterActionPerformed(action, dataContext, event) + return true + } + + override fun getTestDataPath(): String { + return this::class.findAnnotation()?.value ?: super.getTestDataPath() + } +} + +fun configureCompilerOptions(fileText: String, project: Project, module: Module) { + val version = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// LANGUAGE_VERSION: ") + val jvmTarget = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// JVM_TARGET: ") + val options = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// COMPILER_ARGUMENTS: ") + if (version != null || jvmTarget != null || options != null) { + val accessToken = WriteAction.start() + try { + val modelsProvider = IdeModifiableModelsProviderImpl(project) + val facet = module.getOrCreateFacet(modelsProvider, useProjectSettings = false) + + facet.configureFacet( + version ?: LanguageVersion.LATEST_STABLE.versionString, + LanguageFeature.State.DISABLED, + if (jvmTarget != null) TargetPlatformKind.Jvm(JvmTarget.fromString(jvmTarget)!!) else null, + modelsProvider + ) + if (options != null) { + val compilerSettings = facet.configuration.settings.compilerSettings ?: CompilerSettings().also { + facet.configuration.settings.compilerSettings = it + } + compilerSettings.additionalArguments = options + facet.configuration.settings.updateMergedArguments() + } + modelsProvider.commit() + } + finally { + accessToken.finish() + } + } +} + +fun Project.allKotlinFiles(): List { + val virtualFiles = FileTypeIndex.getFiles(KotlinFileType.INSTANCE, ProjectScope.getProjectScope(this)) + return virtualFiles + .map { PsiManager.getInstance(this).findFile(it) } + .filterIsInstance() +} + +fun Project.findFileWithCaret() = + allKotlinFiles().single { "" in VfsUtilCore.loadText(it.virtualFile) } diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/crossLanguage/KotlinElementActionsFactory.kt.181 b/idea/src/org/jetbrains/kotlin/idea/quickfix/crossLanguage/KotlinElementActionsFactory.kt.181 index 1b22241b547..c46e15500c4 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/crossLanguage/KotlinElementActionsFactory.kt.181 +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/crossLanguage/KotlinElementActionsFactory.kt.181 @@ -25,6 +25,7 @@ import com.intellij.lang.jvm.JvmModifiersOwner import com.intellij.lang.jvm.actions.* import com.intellij.openapi.project.Project import com.intellij.psi.* +import com.intellij.psi.codeStyle.SuggestedNameInfo import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration @@ -163,7 +164,7 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() { private inline fun JvmElement.toKtElement() = sourceElement?.unwrapped as? T - private fun fakeParametersExpressions(parameters: ExpectedParameters, project: Project): Array? = + private fun fakeParametersExpressions(parameters: List>>, project: Project): Array? = when { parameters.isEmpty() -> emptyArray() else -> JavaPsiFacade @@ -271,7 +272,8 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() { val resolutionFacade = targetKtClass.getResolutionFacade() val nullableAnyType = resolutionFacade.moduleDescriptor.builtIns.nullableAnyType val helper = JvmPsiConversionHelper.getInstance(targetKtClass.project) - val parameterInfos = request.parameters.mapIndexed { index, param -> + val parameters = request.parameters as List>> + val parameterInfos = parameters.mapIndexed { index, param: Pair> -> val ktType = helper.asPsiType(param)?.resolveToKotlinType(resolutionFacade) ?: nullableAnyType val name = param.first.names.firstOrNull() ?: "arg${index + 1}" ParameterInfo(TypeInfo(ktType, Variance.IN_VARIANCE), listOf(name)) @@ -293,7 +295,7 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() { val primaryConstructor = targetKtClass.primaryConstructor ?: return@run null val lightMethod = primaryConstructor.toLightMethods().firstOrNull() ?: return@run null val project = targetKtClass.project - val fakeParametersExpressions = fakeParametersExpressions(request.parameters, project) ?: return@run null + val fakeParametersExpressions = fakeParametersExpressions(parameters, project) ?: return@run null QuickFixFactory.getInstance() .createChangeMethodSignatureFromUsageFix( lightMethod, @@ -374,7 +376,8 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() { val resolutionFacade = targetContainer.getResolutionFacade() val returnTypeInfo = request.returnType.toKotlinTypeInfo(resolutionFacade) - val parameterInfos = request.parameters.map { (suggestedNames, expectedTypes) -> + val parameters = request.parameters as List>> + val parameterInfos = parameters.map { (suggestedNames, expectedTypes) -> ParameterInfo(expectedTypes.toKotlinTypeInfo(resolutionFacade), suggestedNames.names.toList()) } val functionInfo = FunctionInfo( @@ -395,5 +398,5 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() { } } -private fun JvmPsiConversionHelper.asPsiType(param: ExpectedParameter): PsiType? = +private fun JvmPsiConversionHelper.asPsiType(param: Pair>): PsiType? = param.second.firstOrNull()?.theType?.let { convertType(it) } diff --git a/idea/tests/org/jetbrains/kotlin/idea/configuration/ConfigureKotlinInTempDirTest.kt.181 b/idea/tests/org/jetbrains/kotlin/idea/configuration/ConfigureKotlinInTempDirTest.kt.181 index e222350bebd..28768a2e1c1 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/configuration/ConfigureKotlinInTempDirTest.kt.181 +++ b/idea/tests/org/jetbrains/kotlin/idea/configuration/ConfigureKotlinInTempDirTest.kt.181 @@ -53,7 +53,7 @@ open class ConfigureKotlinInTempDirTest : AbstractConfigureKotlinTest() { @Throws(IOException::class) fun testNoKotlincExistsNoSettingsRuntime10() { val application = ApplicationManager.getApplication() as ApplicationImpl - application.doNotSave(false) + application.isSaveAllowed = false Assert.assertEquals(LanguageVersion.KOTLIN_1_0, module.languageVersionSettings.languageVersion) Assert.assertEquals(LanguageVersion.KOTLIN_1_0, myProject.getLanguageVersionSettings(null).languageVersion) application.saveAll() @@ -62,7 +62,7 @@ open class ConfigureKotlinInTempDirTest : AbstractConfigureKotlinTest() { fun testNoKotlincExistsNoSettingsLatestRuntime() { val application = ApplicationManager.getApplication() as ApplicationImpl - application.doNotSave(false) + application.isSaveAllowed = false Assert.assertEquals(LanguageVersion.LATEST_STABLE, module.languageVersionSettings.languageVersion) Assert.assertEquals(LanguageVersion.LATEST_STABLE, myProject.getLanguageVersionSettings(null).languageVersion) application.saveAll() @@ -71,7 +71,7 @@ open class ConfigureKotlinInTempDirTest : AbstractConfigureKotlinTest() { fun testKotlincExistsNoSettingsLatestRuntimeNoVersionAutoAdvance() { val application = ApplicationManager.getApplication() as ApplicationImpl - application.doNotSave(false) + application.isSaveAllowed = false Assert.assertEquals(LanguageVersion.LATEST_STABLE, module.languageVersionSettings.languageVersion) Assert.assertEquals(LanguageVersion.LATEST_STABLE, myProject.getLanguageVersionSettings(null).languageVersion) KotlinCommonCompilerArgumentsHolder.getInstance(project).update { @@ -84,7 +84,7 @@ open class ConfigureKotlinInTempDirTest : AbstractConfigureKotlinTest() { fun testDropKotlincOnVersionAutoAdvance() { val application = ApplicationManager.getApplication() as ApplicationImpl - application.doNotSave(false) + application.isSaveAllowed = false Assert.assertEquals(LanguageVersion.LATEST_STABLE, module.languageVersionSettings.languageVersion) KotlinCommonCompilerArgumentsHolder.getInstance(project).update { autoAdvanceLanguageVersion = true @@ -119,7 +119,7 @@ open class ConfigureKotlinInTempDirTest : AbstractConfigureKotlinTest() { fun testLoadAndSaveProjectWithV2FacetConfig() { val moduleFileContentBefore = String(module.moduleFile!!.contentsToByteArray()) val application = ApplicationManager.getApplication() as ApplicationImpl - application.doNotSave(false) + application.isSaveAllowed = false application.saveAll() val moduleFileContentAfter = String(module.moduleFile!!.contentsToByteArray()) Assert.assertEquals(moduleFileContentBefore, moduleFileContentAfter) diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/CommonIntentionActionsTest.kt.181 b/idea/tests/org/jetbrains/kotlin/idea/quickfix/CommonIntentionActionsTest.kt.181 index 3ed1638d936..570c765b8ae 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/CommonIntentionActionsTest.kt.181 +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/CommonIntentionActionsTest.kt.181 @@ -39,15 +39,28 @@ import org.junit.Assert class CommonIntentionActionsTest : LightPlatformCodeInsightFixtureTestCase() { private class SimpleMethodRequest( - project: Project, - override val methodName: String, - override val modifiers: Collection = emptyList(), - override val returnType: ExpectedTypes = emptyList(), - override val annotations: Collection = emptyList(), - override val parameters: List = emptyList(), - override val targetSubstitutor: JvmSubstitutor = PsiJvmSubstitutor(project, PsiSubstitutor.EMPTY) + project: Project, + private val methodName: String, + private val modifiers: Collection = emptyList(), + private val returnType: ExpectedTypes = emptyList(), + private val annotations: Collection = emptyList(), + private val parameters: List>> = emptyList(), + private val targetSubstitutor: JvmSubstitutor = PsiJvmSubstitutor(project, PsiSubstitutor.EMPTY) ) : CreateMethodRequest { - override val isValid: Boolean = true + override fun getTargetSubstitutor(): JvmSubstitutor = targetSubstitutor + + override fun getModifiers() = modifiers + + override fun getMethodName() = methodName + + override fun getAnnotations() = annotations + + override fun getParameters() = parameters + + override fun getReturnType() = returnType + + override fun isValid(): Boolean = true + } private class NameInfo(vararg names: String) : SuggestedNameInfo(names) diff --git a/versions.gradle.kts.181 b/versions.gradle.kts.181 index 3ec53af4179..929a49bc3f1 100644 --- a/versions.gradle.kts.181 +++ b/versions.gradle.kts.181 @@ -1,5 +1,5 @@ -extra["versions.intellijSdk"] = "181.3494.3" +extra["versions.intellijSdk"] = "181.3870.7" extra["versions.androidBuildTools"] = "r23.0.1" extra["versions.idea.NodeJS"] = "181.3494.12" //extra["versions.androidStudioRelease"] = "3.1.0.5"