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