Added AllowNullableArrayArgsInMain (1.4+) language setting
This commit is contained in:
@@ -125,7 +125,9 @@ class MainFunctionDetector {
|
||||
if (typeArguments.size != 1) return false
|
||||
|
||||
val typeArgument = typeArguments[0].type
|
||||
if (!KotlinBuiltIns.isStringOrNullableString(typeArgument)) {
|
||||
if (!(languageVersionSettings.supportsFeature(LanguageFeature.AllowNullableArrayArgsInMain) &&
|
||||
KotlinBuiltIns.isStringOrNullableString(typeArgument) || KotlinBuiltIns.isString(typeArgument))
|
||||
) {
|
||||
return false
|
||||
}
|
||||
if (typeArguments[0].projectionKind === Variance.IN_VARIANCE) {
|
||||
|
||||
+8
-4
@@ -92,12 +92,16 @@ fun parseLanguageVersionSettings(directives: Map<String, String>): CompilerTestL
|
||||
fun defaultLanguageVersionSettings(): CompilerTestLanguageVersionSettings =
|
||||
CompilerTestLanguageVersionSettings(emptyMap(), ApiVersion.LATEST_STABLE, LanguageVersion.LATEST_STABLE)
|
||||
|
||||
fun setupLanguageVersionSettingsForMultifileCompilerTests(files: List<File>, environment: KotlinCoreEnvironment) {
|
||||
fun languageVersionSettingsFromText(fileTexts: List<String>): LanguageVersionSettings {
|
||||
val allDirectives = HashMap<String, String>()
|
||||
for (file in files) {
|
||||
allDirectives.putAll(KotlinTestUtils.parseDirectives(file.readText()))
|
||||
for (fileText in fileTexts) {
|
||||
allDirectives.putAll(KotlinTestUtils.parseDirectives(fileText))
|
||||
}
|
||||
environment.configuration.languageVersionSettings = parseLanguageVersionSettingsOrDefault(allDirectives)
|
||||
return parseLanguageVersionSettingsOrDefault(allDirectives)
|
||||
}
|
||||
|
||||
fun setupLanguageVersionSettingsForMultifileCompilerTests(files: List<File>, environment: KotlinCoreEnvironment) {
|
||||
environment.configuration.languageVersionSettings = languageVersionSettingsFromText(files.map { it.readText() })
|
||||
}
|
||||
|
||||
fun setupLanguageVersionSettingsForCompilerTests(originalFileText: String, environment: KotlinCoreEnvironment) {
|
||||
|
||||
@@ -110,6 +110,7 @@ enum class LanguageFeature(
|
||||
MixedNamedArgumentsInTheirOwnPosition(KOTLIN_1_4),
|
||||
ProhibitTailrecOnVirtualMember(KOTLIN_1_4, kind = BUG_FIX),
|
||||
ProperComputationOrderOfTailrecDefaultParameters(KOTLIN_1_4),
|
||||
AllowNullableArrayArgsInMain(KOTLIN_1_4),
|
||||
|
||||
ProperVisibilityForCompanionObjectInstanceField(sinceVersion = null, kind = BUG_FIX),
|
||||
// Temporarily disabled, see KT-27084/KT-22379
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.CachedValue
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.cli.common.arguments.*
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
@@ -168,6 +169,17 @@ val Module.languageVersionSettings: LanguageVersionSettings
|
||||
return cachedValue.value
|
||||
}
|
||||
|
||||
@TestOnly // public for tests
|
||||
fun Module.setLanguageVersionSettings(value: LanguageVersionSettings) =
|
||||
putUserData(
|
||||
LANGUAGE_VERSION_SETTINGS,
|
||||
CachedValuesManager.getManager(project).createCachedValue({
|
||||
CachedValueProvider.Result(
|
||||
value, ProjectRootModificationTracker.getInstance(project)
|
||||
)
|
||||
}, false)
|
||||
)
|
||||
|
||||
private fun Module.createCachedValueForLanguageVersionSettings(): CachedValue<LanguageVersionSettings> {
|
||||
return CachedValuesManager.getManager(project).createCachedValue({
|
||||
CachedValueProvider.Result(
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
fun main(args: Array<String?>) { // yes
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// !LANGUAGE: +AllowNullableArrayArgsInMain
|
||||
|
||||
fun main(args: Array<String?>) { // yes
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fun main(args: Array<String?>) { // no
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fun main(args: Array<String?>?) { // yes
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// !LANGUAGE: +AllowNullableArrayArgsInMain
|
||||
|
||||
fun main(args: Array<String?>?) { // yes
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
fun main(args: Array<String?>?) { // no
|
||||
}
|
||||
@@ -19,9 +19,11 @@ import com.intellij.psi.PsiManager
|
||||
import com.intellij.refactoring.RefactoringFactory
|
||||
import com.intellij.testFramework.MapDataContext
|
||||
import com.intellij.testFramework.PsiTestUtil
|
||||
import org.jetbrains.kotlin.checkers.languageVersionSettingsFromText
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||
import org.jetbrains.kotlin.idea.MainFunctionDetector
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.project.setLanguageVersionSettings
|
||||
import org.jetbrains.kotlin.idea.search.allScope
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinFullClassNameIndex
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelFunctionFqnNameIndex
|
||||
@@ -34,12 +36,11 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.allChildren
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner
|
||||
import org.junit.Assert
|
||||
import org.junit.runner.RunWith
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
private val RUN_PREFIX = "// RUN:"
|
||||
private const val RUN_PREFIX = "// RUN:"
|
||||
|
||||
@RunWith(JUnit3WithIdeaConfigurationRunner::class)
|
||||
class RunConfigurationTest: KotlinCodeInsightTestCase() {
|
||||
@@ -56,44 +57,49 @@ class RunConfigurationTest: KotlinCodeInsightTestCase() {
|
||||
val runConfiguration = createConfigurationFromMain("some.main")
|
||||
val javaParameters = getJavaRunParameters(runConfiguration)
|
||||
|
||||
Assert.assertTrue(javaParameters.classPath.rootDirs.contains(createResult.srcOutputDir))
|
||||
Assert.assertTrue(javaParameters.classPath.rootDirs.contains(createResult.testOutputDir))
|
||||
assertTrue(javaParameters.classPath.rootDirs.contains(createResult.srcOutputDir))
|
||||
assertTrue(javaParameters.classPath.rootDirs.contains(createResult.testOutputDir))
|
||||
|
||||
fun functionVisitor(function: KtNamedFunction) {
|
||||
val file = function.containingKtFile
|
||||
val options = function.bodyExpression?.allChildren?.filterIsInstance<PsiComment>()?.map { it.text.trim().replace("//", "").trim() }?.filter { it.isNotBlank() }?.toList() ?: emptyList()
|
||||
if (options.isNotEmpty()) {
|
||||
val assertIsMain = "yes" in options
|
||||
val assertIsNotMain = "no" in options
|
||||
|
||||
val languageVersionSettings = languageVersionSettingsFromText(listOf(file.text))
|
||||
createResult.module.setLanguageVersionSettings(languageVersionSettings)
|
||||
val isMainFunction =
|
||||
MainFunctionDetector(LanguageVersionSettingsImpl.DEFAULT) { it.resolveToDescriptorIfAny() }.isMain(function)
|
||||
MainFunctionDetector(languageVersionSettings) { it.resolveToDescriptorIfAny() }.isMain(function)
|
||||
|
||||
if (assertIsMain) {
|
||||
Assert.assertTrue("The function ${function.fqName?.asString()} should be main", isMainFunction)
|
||||
assertTrue("$file: The function ${function.fqName?.asString()} should be main", isMainFunction)
|
||||
}
|
||||
if (assertIsNotMain) {
|
||||
Assert.assertFalse("The function ${function.fqName?.asString()} should NOT be main", isMainFunction)
|
||||
assertFalse("$file: The function ${function.fqName?.asString()} should NOT be main", isMainFunction)
|
||||
}
|
||||
|
||||
if (isMainFunction) {
|
||||
createConfigurationFromMain(function.fqName?.asString()!!).checkConfiguration()
|
||||
|
||||
Assert.assertNotNull("Kotlin configuration producer should produce configuration for ${function.fqName?.asString()}",
|
||||
KotlinRunConfigurationProducer.getEntryPointContainer(function))
|
||||
assertNotNull(
|
||||
"$file: Kotlin configuration producer should produce configuration for ${function.fqName?.asString()}",
|
||||
KotlinRunConfigurationProducer.getEntryPointContainer(function)
|
||||
)
|
||||
} else {
|
||||
try {
|
||||
createConfigurationFromMain(function.fqName?.asString()!!).checkConfiguration()
|
||||
Assert.fail("configuration for function ${function.fqName?.asString()} at least shouldn't pass checkConfiguration()")
|
||||
fail("$file: configuration for function ${function.fqName?.asString()} at least shouldn't pass checkConfiguration()")
|
||||
} catch (expected: Throwable) {
|
||||
}
|
||||
|
||||
if (function.containingFile.text.startsWith("// entryPointExists")) {
|
||||
Assert.assertNotNull(
|
||||
"Kotlin configuration producer should produce configuration for ${function.fqName?.asString()}",
|
||||
assertNotNull(
|
||||
"$file: Kotlin configuration producer should produce configuration for ${function.fqName?.asString()}",
|
||||
KotlinRunConfigurationProducer.getEntryPointContainer(function)
|
||||
)
|
||||
} else {
|
||||
Assert.assertNull(
|
||||
assertNull(
|
||||
"Kotlin configuration producer shouldn't produce configuration for ${function.fqName?.asString()}",
|
||||
KotlinRunConfigurationProducer.getEntryPointContainer(function)
|
||||
)
|
||||
@@ -132,8 +138,8 @@ class RunConfigurationTest: KotlinCodeInsightTestCase() {
|
||||
|
||||
val javaParameters = getJavaRunParameters(kotlinRunConfiguration)
|
||||
|
||||
Assert.assertTrue(javaParameters.classPath.rootDirs.contains(dependencyModuleSrcDir))
|
||||
Assert.assertTrue(javaParameters.classPath.rootDirs.contains(moduleWithDependencySrcDir))
|
||||
assertTrue(javaParameters.classPath.rootDirs.contains(dependencyModuleSrcDir))
|
||||
assertTrue(javaParameters.classPath.rootDirs.contains(moduleWithDependencySrcDir))
|
||||
}
|
||||
|
||||
fun testLongCommandLine() {
|
||||
@@ -170,7 +176,7 @@ class RunConfigurationTest: KotlinCodeInsightTestCase() {
|
||||
val rename = RefactoringFactory.getInstance(getTestProject()).createRename(obj, "Bar")
|
||||
rename.run()
|
||||
|
||||
Assert.assertEquals("renameTest.Bar", runConfiguration.MAIN_CLASS_NAME)
|
||||
assertEquals("renameTest.Bar", runConfiguration.MAIN_CLASS_NAME)
|
||||
}
|
||||
|
||||
fun testUpdateOnPackageRename() {
|
||||
@@ -183,7 +189,7 @@ class RunConfigurationTest: KotlinCodeInsightTestCase() {
|
||||
val rename = RefactoringFactory.getInstance(getTestProject()).createRename(pkg, "afterRenameTest")
|
||||
rename.run()
|
||||
|
||||
Assert.assertEquals("afterRenameTest.Foo", runConfiguration.MAIN_CLASS_NAME)
|
||||
assertEquals("afterRenameTest.Foo", runConfiguration.MAIN_CLASS_NAME)
|
||||
}
|
||||
|
||||
fun testWithModuleForJdk6() {
|
||||
@@ -204,7 +210,7 @@ class RunConfigurationTest: KotlinCodeInsightTestCase() {
|
||||
|
||||
val javaParameters = getJavaRunParameters(createConfigurationFromMain("some.main"))
|
||||
|
||||
Assert.assertEquals(moduleName, javaParameters.moduleName)
|
||||
assertEquals(moduleName, javaParameters.moduleName)
|
||||
}
|
||||
|
||||
private fun doTest(configureRuntime: (Module, Sdk) -> Unit) {
|
||||
@@ -239,7 +245,7 @@ class RunConfigurationTest: KotlinCodeInsightTestCase() {
|
||||
}
|
||||
}
|
||||
)
|
||||
Assert.assertEquals(expectedClasses, actualClasses)
|
||||
assertEquals(expectedClasses, actualClasses)
|
||||
}
|
||||
finally {
|
||||
ConfigLibraryUtil.unConfigureKotlinRuntimeAndSdk(createModuleResult.module, mockJdk())
|
||||
|
||||
Reference in New Issue
Block a user