NI: Allow to resolve to functions with SAM conversion and passing array without spread as vararg (with warning)
^KT-35224 Fixed
This commit is contained in:
Generated
+15
@@ -18603,6 +18603,21 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/samConversions"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("arrayAsVarargAfterSamArgument.kt")
|
||||
public void testArrayAsVarargAfterSamArgument() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/samConversions/arrayAsVarargAfterSamArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("arrayAsVarargAfterSamArgumentProhibited.kt")
|
||||
public void testArrayAsVarargAfterSamArgumentProhibited() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/samConversions/arrayAsVarargAfterSamArgumentProhibited.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt")
|
||||
public void testArrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/samConversions/arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("checkSamConversionsAreDisabledByDefault.kt")
|
||||
public void testCheckSamConversionsAreDisabledByDefault() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/samConversions/checkSamConversionsAreDisabledByDefault.kt");
|
||||
|
||||
@@ -46,7 +46,8 @@ class JavaSyntheticScopes(
|
||||
|
||||
init {
|
||||
val samConversionPerArgumentIsEnabled =
|
||||
languageVersionSettings.supportsFeature(LanguageFeature.SamConversionPerArgument)
|
||||
languageVersionSettings.supportsFeature(LanguageFeature.SamConversionPerArgument) &&
|
||||
languageVersionSettings.supportsFeature(LanguageFeature.ProhibitVarargAsArrayAfterSamArgument)
|
||||
|
||||
val javaSyntheticPropertiesScope = JavaSyntheticPropertiesScope(storageManager, lookupTracker)
|
||||
val scopesFromExtensions = SyntheticScopeProviderExtension
|
||||
@@ -59,7 +60,10 @@ class JavaSyntheticScopes(
|
||||
samConventionResolver,
|
||||
deprecationResolver,
|
||||
lookupTracker,
|
||||
samViaSyntheticScopeDisabled = samConversionPerArgumentIsEnabled
|
||||
samViaSyntheticScopeDisabled = samConversionPerArgumentIsEnabled,
|
||||
shouldGenerateCandidateForVarargAfterSam = !languageVersionSettings.supportsFeature(
|
||||
LanguageFeature.ProhibitVarargAsArrayAfterSamArgument
|
||||
)
|
||||
)
|
||||
|
||||
scopes = listOf(javaSyntheticPropertiesScope, samAdapterFunctionsScope) + scopesFromExtensions
|
||||
@@ -70,7 +74,8 @@ class JavaSyntheticScopes(
|
||||
samConventionResolver,
|
||||
deprecationResolver,
|
||||
lookupTracker,
|
||||
samViaSyntheticScopeDisabled = false
|
||||
samViaSyntheticScopeDisabled = false,
|
||||
shouldGenerateCandidateForVarargAfterSam = false
|
||||
)
|
||||
|
||||
scopesWithForceEnabledSamAdapters =
|
||||
|
||||
+33
-16
@@ -17,8 +17,6 @@
|
||||
package org.jetbrains.kotlin.synthetic
|
||||
|
||||
import com.intellij.util.SmartList
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
@@ -37,6 +35,7 @@ import org.jetbrains.kotlin.load.java.sam.SamAdapterDescriptor
|
||||
import org.jetbrains.kotlin.load.java.sam.SamConstructorDescriptor
|
||||
import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.calls.components.isVararg
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.wrapWithCapturingSubstitution
|
||||
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
@@ -58,8 +57,10 @@ class SamAdapterFunctionsScope(
|
||||
private val samResolver: SamConversionResolver,
|
||||
private val deprecationResolver: DeprecationResolver,
|
||||
private val lookupTracker: LookupTracker,
|
||||
private val samViaSyntheticScopeDisabled: Boolean
|
||||
private val samViaSyntheticScopeDisabled: Boolean,
|
||||
private val shouldGenerateCandidateForVarargAfterSam: Boolean
|
||||
) : SyntheticScope.Default() {
|
||||
private val shouldGenerateAdditionalSamCandidate = !samViaSyntheticScopeDisabled || shouldGenerateCandidateForVarargAfterSam
|
||||
|
||||
private val extensionForFunction =
|
||||
storageManager.createMemoizedFunctionWithNullableValues<FunctionDescriptor, FunctionDescriptor> { function ->
|
||||
@@ -96,12 +97,18 @@ class SamAdapterFunctionsScope(
|
||||
return SamAdapterExtensionFunctionDescriptorImpl.create(function, samResolver)
|
||||
}
|
||||
|
||||
override fun getSyntheticMemberFunctions(receiverTypes: Collection<KotlinType>, name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
|
||||
if (samViaSyntheticScopeDisabled) return emptyList()
|
||||
override fun getSyntheticMemberFunctions(
|
||||
receiverTypes: Collection<KotlinType>,
|
||||
name: Name,
|
||||
location: LookupLocation
|
||||
): Collection<FunctionDescriptor> {
|
||||
if (!shouldGenerateAdditionalSamCandidate) return emptyList()
|
||||
|
||||
var result: SmartList<FunctionDescriptor>? = null
|
||||
for (type in receiverTypes) {
|
||||
for (function in type.memberScope.getContributedFunctions(name, location)) {
|
||||
if (samViaSyntheticScopeDisabled && !function.shouldGenerateCandidateForVarargAfterSamAndHasVararg) continue
|
||||
|
||||
val extension = extensionForFunction(function.original)?.substituteForReceiverType(type)
|
||||
if (extension != null) {
|
||||
recordSamLookupsForParameters(function, location)
|
||||
@@ -125,6 +132,9 @@ class SamAdapterFunctionsScope(
|
||||
}
|
||||
}
|
||||
|
||||
private val FunctionDescriptor.shouldGenerateCandidateForVarargAfterSamAndHasVararg
|
||||
get() = shouldGenerateCandidateForVarargAfterSam && valueParameters.lastOrNull()?.isVararg == true
|
||||
|
||||
private fun FunctionDescriptor.substituteForReceiverType(receiverType: KotlinType): FunctionDescriptor? {
|
||||
val containingClass = containingDeclaration as? ClassDescriptor ?: return null
|
||||
val correspondingSupertype = findCorrespondingSupertype(receiverType, containingClass.defaultType) ?: return null
|
||||
@@ -138,19 +148,22 @@ class SamAdapterFunctionsScope(
|
||||
}
|
||||
|
||||
override fun getSyntheticMemberFunctions(receiverTypes: Collection<KotlinType>): Collection<FunctionDescriptor> {
|
||||
if (samViaSyntheticScopeDisabled) return emptyList()
|
||||
if (!shouldGenerateAdditionalSamCandidate) return emptyList()
|
||||
|
||||
return receiverTypes.flatMapTo(LinkedHashSet<FunctionDescriptor>()) { type ->
|
||||
type.memberScope.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS)
|
||||
.filterIsInstance<FunctionDescriptor>()
|
||||
.mapNotNull {
|
||||
extensionForFunction(it.original)?.substituteForReceiverType(type)
|
||||
}
|
||||
.filterIsInstance<FunctionDescriptor>()
|
||||
.run {
|
||||
if (samViaSyntheticScopeDisabled) filter { it.shouldGenerateCandidateForVarargAfterSamAndHasVararg } else this
|
||||
}
|
||||
.mapNotNull {
|
||||
extensionForFunction(it.original)?.substituteForReceiverType(type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSyntheticStaticFunctions(scope: ResolutionScope, name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
|
||||
if (samViaSyntheticScopeDisabled) return emptyList()
|
||||
if (!shouldGenerateAdditionalSamCandidate) return emptyList()
|
||||
|
||||
return getSamFunctions(scope.getContributedFunctions(name, location), location)
|
||||
}
|
||||
@@ -159,7 +172,7 @@ class SamAdapterFunctionsScope(
|
||||
val classifier = scope.getContributedClassifier(name, location) ?: return emptyList()
|
||||
recordSamLookupsToClassifier(classifier, location)
|
||||
|
||||
if (samViaSyntheticScopeDisabled) return listOfNotNull(getSamConstructor(classifier))
|
||||
if (!shouldGenerateAdditionalSamCandidate) return listOfNotNull(getSamConstructor(classifier))
|
||||
|
||||
return getAllSamConstructors(classifier)
|
||||
}
|
||||
@@ -173,7 +186,7 @@ class SamAdapterFunctionsScope(
|
||||
}
|
||||
|
||||
override fun getSyntheticStaticFunctions(scope: ResolutionScope): Collection<FunctionDescriptor> {
|
||||
if (samViaSyntheticScopeDisabled) return emptyList()
|
||||
if (!shouldGenerateAdditionalSamCandidate) return emptyList()
|
||||
|
||||
return getSamFunctions(scope.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS), location = null)
|
||||
}
|
||||
@@ -181,13 +194,13 @@ class SamAdapterFunctionsScope(
|
||||
override fun getSyntheticConstructors(scope: ResolutionScope): Collection<FunctionDescriptor> {
|
||||
val classifiers = scope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS).filterIsInstance<ClassifierDescriptor>()
|
||||
|
||||
if (samViaSyntheticScopeDisabled) return classifiers.mapNotNull { getSamConstructor(it) }
|
||||
if (!shouldGenerateAdditionalSamCandidate) return classifiers.mapNotNull { getSamConstructor(it) }
|
||||
|
||||
return classifiers.flatMap { getAllSamConstructors(it) }
|
||||
}
|
||||
|
||||
override fun getSyntheticConstructor(constructor: ConstructorDescriptor): ConstructorDescriptor? {
|
||||
if (samViaSyntheticScopeDisabled) return null
|
||||
if (samViaSyntheticScopeDisabled && !constructor.shouldGenerateCandidateForVarargAfterSamAndHasVararg) return null
|
||||
|
||||
return when (constructor) {
|
||||
is JavaClassConstructorDescriptor -> createJavaSamAdapterConstructor(constructor)
|
||||
@@ -211,10 +224,14 @@ class SamAdapterFunctionsScope(
|
||||
functions: Collection<DeclarationDescriptor>,
|
||||
location: LookupLocation?
|
||||
): List<SamAdapterDescriptor<JavaMethodDescriptor>> {
|
||||
if (!shouldGenerateAdditionalSamCandidate) return emptyList()
|
||||
|
||||
return functions.mapNotNull { function ->
|
||||
if (function !is JavaMethodDescriptor) return@mapNotNull null
|
||||
if (function.dispatchReceiverParameter != null) return@mapNotNull null // consider only statics
|
||||
if (!SingleAbstractMethodUtils.isSamAdapterNecessary(function)) return@mapNotNull null
|
||||
if (samViaSyntheticScopeDisabled && !function.shouldGenerateCandidateForVarargAfterSamAndHasVararg)
|
||||
return@mapNotNull null
|
||||
|
||||
location?.let { recordSamLookupsForParameters(function, it) }
|
||||
|
||||
@@ -227,7 +244,7 @@ class SamAdapterFunctionsScope(
|
||||
}
|
||||
|
||||
private fun getSamAdaptersFromConstructors(classifier: ClassifierDescriptor): List<FunctionDescriptor> {
|
||||
if (classifier !is JavaClassDescriptor) return emptyList()
|
||||
if (!shouldGenerateAdditionalSamCandidate || classifier !is JavaClassDescriptor) return emptyList()
|
||||
|
||||
return arrayListOf<FunctionDescriptor>().apply {
|
||||
for (constructor in classifier.constructors) {
|
||||
|
||||
@@ -765,6 +765,7 @@ public interface Errors {
|
||||
DiagnosticFactory1<PsiElement, TypeParameterDescriptor> TYPE_INFERENCE_ONLY_INPUT_TYPES = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, InferenceErrorData> TYPE_INFERENCE_UPPER_BOUND_VIOLATED = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory2<KtElement, KotlinType, KotlinType> TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
DiagnosticFactory0<KtExpression> TYPE_INFERENCE_FAILED_ON_SPECIAL_CONSTRUCT = DiagnosticFactory0.create(ERROR, SPECIAL_CONSTRUCT_TOKEN);
|
||||
|
||||
|
||||
+1
@@ -859,6 +859,7 @@ public class DefaultErrorMessages {
|
||||
"(argument types, receiver type or expected type). Try to specify it explicitly.", NAME);
|
||||
MAP.put(TYPE_INFERENCE_UPPER_BOUND_VIOLATED, "{0}", TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER);
|
||||
MAP.put(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH, "Type inference failed. Expected type mismatch: inferred type is {1} but {0} was expected", RENDER_TYPE, RENDER_TYPE);
|
||||
MAP.put(TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG, "Please use spread operator to pass an array as vararg. It will be an error in 1.5.");
|
||||
|
||||
MAP.put(TYPE_INFERENCE_FAILED_ON_SPECIAL_CONSTRUCT, "Type inference for control flow expression failed. Please specify its type explicitly.");
|
||||
|
||||
|
||||
+4
@@ -175,6 +175,10 @@ class DiagnosticReporterByTrackingStrategy(
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ResolvedToSamWithVarargDiagnostic::class.java -> {
|
||||
trace.report(TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG.on(callArgument.psiCallArgument.valueArgument.asElement()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
@@ -6,6 +6,8 @@
|
||||
package org.jetbrains.kotlin.resolve.calls.components
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
|
||||
@@ -45,6 +47,7 @@ class KotlinCallCompleter(
|
||||
|
||||
candidate.addExpectedTypeConstraint(returnType, expectedType)
|
||||
candidate.addExpectedTypeFromCastConstraint(returnType, resolutionCallbacks)
|
||||
candidate.checkSamWithVararg(diagnosticHolder)
|
||||
|
||||
return if (resolutionCallbacks.inferenceSession.shouldRunCompletion(candidate))
|
||||
candidate.runCompletion(
|
||||
@@ -56,6 +59,22 @@ class KotlinCallCompleter(
|
||||
candidate.asCallResolutionResult(ConstraintSystemCompletionMode.PARTIAL, diagnosticHolder)
|
||||
}
|
||||
|
||||
private fun KotlinResolutionCandidate.checkSamWithVararg(diagnosticHolder: KotlinDiagnosticsHolder.SimpleHolder) {
|
||||
val samConversionPerArgumentWithWarningsForVarargAfterSam =
|
||||
callComponents.languageVersionSettings.supportsFeature(LanguageFeature.SamConversionPerArgument) &&
|
||||
!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitVarargAsArrayAfterSamArgument)
|
||||
|
||||
if (samConversionPerArgumentWithWarningsForVarargAfterSam && resolvedCall.candidateDescriptor is SyntheticMemberDescriptor<*>) {
|
||||
val declarationDescriptor = resolvedCall.candidateDescriptor.baseDescriptorForSynthetic as? FunctionDescriptor ?: return
|
||||
|
||||
if (declarationDescriptor.valueParameters.lastOrNull()?.isVararg == true) {
|
||||
diagnosticHolder.addDiagnostic(
|
||||
ResolvedToSamWithVarargDiagnostic(resolvedCall.atom.argumentsInParenthesis.lastOrNull() ?: return)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createAllCandidatesResult(
|
||||
candidates: Collection<KotlinResolutionCandidate>,
|
||||
expectedType: UnwrappedType?,
|
||||
|
||||
+5
-1
@@ -294,7 +294,11 @@ private fun KotlinResolutionCandidate.getExpectedTypeWithSAMConversion(
|
||||
argument: KotlinCallArgument,
|
||||
candidateParameter: ParameterDescriptor
|
||||
): UnwrappedType? {
|
||||
if (!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.SamConversionPerArgument)) return null
|
||||
val generatingAdditionalSamCandidateIsEnabled =
|
||||
!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.SamConversionPerArgument) &&
|
||||
!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitVarargAsArrayAfterSamArgument)
|
||||
|
||||
if (generatingAdditionalSamCandidateIsEnabled) return null
|
||||
if (!callComponents.samConversionTransformer.shouldRunSamConversionForFunction(resolvedCall.candidateDescriptor)) return null
|
||||
|
||||
val argumentIsFunctional = when (argument) {
|
||||
|
||||
+7
-1
@@ -202,4 +202,10 @@ class OnlyInputTypesDiagnostic(val typeVariable: NewTypeVariable) : KotlinCallDi
|
||||
override fun report(reporter: DiagnosticReporter) {
|
||||
reporter.onCall(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ResolvedToSamWithVarargDiagnostic(val argument: KotlinCallArgument) : KotlinCallDiagnostic(RESOLVED_TO_SAM_WITH_VARARG) {
|
||||
override fun report(reporter: DiagnosticReporter) {
|
||||
reporter.onCallArgument(argument, this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,6 +83,7 @@ enum class ResolutionCandidateApplicability {
|
||||
INAPPLICABLE_ARGUMENTS_MAPPING_ERROR, // arguments not mapped to parameters (i.e. different size of arguments and parameters)
|
||||
INAPPLICABLE_WRONG_RECEIVER, // receiver not matched
|
||||
HIDDEN, // removed from resolve
|
||||
RESOLVED_TO_SAM_WITH_VARARG, // migration warning up to 1.5 (when resolve to function with SAM conversion and array without spread as vararg)
|
||||
}
|
||||
|
||||
abstract class ResolutionDiagnostic(candidateApplicability: ResolutionCandidateApplicability) :
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
// !LANGUAGE: +NewInference +SamConversionForKotlinFunctions +SamConversionPerArgument
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// FILE: Test.java
|
||||
public class Test {
|
||||
public static String foo1(Runnable r, String... strs) {
|
||||
return null;
|
||||
}
|
||||
public String foo2(Runnable r1, Runnable r2, String... strs) {
|
||||
return null;
|
||||
}
|
||||
public Test(Runnable r, String... strs) {}
|
||||
public Test(Runnable r1, Runnable r2, String... strs) {}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun box(): String {
|
||||
val x1 = {}
|
||||
val x2: Runnable = Runnable { }
|
||||
val x3 = arrayOf<String>()
|
||||
|
||||
Test.foo1({}, arrayOf())
|
||||
Test.foo1({}, *arrayOf())
|
||||
Test.foo1({}, x3)
|
||||
Test.foo1({}, *arrayOf(""))
|
||||
|
||||
Test.foo1(x1, arrayOf())
|
||||
Test.foo1(x1, *arrayOf())
|
||||
Test.foo1(x2, *arrayOf())
|
||||
|
||||
Test.foo1(x1, x3)
|
||||
Test.foo1(x1, *x3)
|
||||
Test.foo1(x2, *arrayOf(""))
|
||||
|
||||
val i1 = Test({}, arrayOf())
|
||||
val i2 = Test({}, *arrayOf())
|
||||
val i3 = Test({}, x3)
|
||||
val i4 = Test({}, arrayOf(""))
|
||||
val i5 = Test({}, {}, *arrayOf(""))
|
||||
val i6 = Test({}, {}, arrayOf())
|
||||
|
||||
i1.foo2({}, {}, arrayOf())
|
||||
i2.foo2({}, {}, *arrayOf())
|
||||
i3.foo2(x2, {}, *arrayOf())
|
||||
|
||||
i4.foo2({}, {}, arrayOf(""))
|
||||
i5.foo2({}, {}, *x3)
|
||||
i6.foo2(x2, {}, *arrayOf(""))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Vendored
+41
@@ -0,0 +1,41 @@
|
||||
// !LANGUAGE: +NewInference +SamConversionForKotlinFunctions
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// FILE: Test.java
|
||||
public class Test {
|
||||
public static String foo1(Runnable r, String... strs) {
|
||||
return null;
|
||||
}
|
||||
public String foo2(Runnable r1, Runnable r2, String... strs) {
|
||||
return null;
|
||||
}
|
||||
public Test(Runnable r, String... strs) {}
|
||||
public Test(Runnable r1, Runnable r2, String... strs) {}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun box(): String {
|
||||
val x1 = {}
|
||||
val x2: Runnable = Runnable { }
|
||||
val x3 = arrayOf<String>()
|
||||
|
||||
Test.foo1({}, arrayOf())
|
||||
Test.foo1({}, arrayOf(""))
|
||||
|
||||
Test.foo1(x1, arrayOf())
|
||||
Test.foo1(x2, *arrayOf())
|
||||
|
||||
Test.foo1(x1, x3)
|
||||
Test.foo1(x2, *arrayOf(""))
|
||||
|
||||
val i1 = Test({}, arrayOf())
|
||||
val i3 = Test({}, x3)
|
||||
val i4 = Test({}, arrayOf(""))
|
||||
val i6 = Test({}, {}, arrayOf())
|
||||
|
||||
i1.foo2({}, {}, arrayOf())
|
||||
i1.foo2({}, {}, arrayOf(""))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// !LANGUAGE: +SamConversionPerArgument +NewInference
|
||||
// !LANGUAGE: +SamConversionPerArgument +NewInference +ProhibitVarargAsArrayAfterSamArgument
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
// FILE: A.java
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
// !LANGUAGE: +NewInference +SamConversionForKotlinFunctions +SamConversionPerArgument
|
||||
// IGNORE_BACKEND: JS
|
||||
// SKIP_TXT
|
||||
|
||||
// FILE: Test.java
|
||||
public class Test {
|
||||
public static String foo1(Runnable r, String... strs) {
|
||||
return null;
|
||||
}
|
||||
public String foo2(Runnable r1, Runnable r2, String... strs) {
|
||||
return null;
|
||||
}
|
||||
public Test(Runnable r, String... strs) {}
|
||||
public Test(Runnable r, Runnable r, String... strs) {}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun main(x2: Runnable) {
|
||||
val x1 = {}
|
||||
val x3 = arrayOf<String>()
|
||||
|
||||
Test.foo1({}, <!TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG!>arrayOf()<!>)
|
||||
Test.foo1({}, *arrayOf())
|
||||
Test.foo1({}, <!TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG!>x3<!>)
|
||||
Test.foo1({}, *arrayOf(""))
|
||||
|
||||
Test.foo1(x1, <!TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG!>arrayOf()<!>)
|
||||
Test.foo1(x1, *arrayOf())
|
||||
Test.foo1(x2, <!TYPE_MISMATCH!>arrayOf()<!>)
|
||||
Test.foo1(x2, *arrayOf())
|
||||
|
||||
Test.foo1(x1, <!TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG!>x3<!>)
|
||||
Test.foo1(x1, *x3)
|
||||
Test.foo1(x2, <!TYPE_MISMATCH!>arrayOf("")<!>)
|
||||
Test.foo1(x2, *arrayOf(""))
|
||||
|
||||
val i1 = Test({}, <!TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG!>arrayOf()<!>)
|
||||
val i2 = Test({}, *arrayOf())
|
||||
val i3 = Test({}, <!TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG!>x3<!>)
|
||||
val i4 = Test({}, <!TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG!>arrayOf("")<!>)
|
||||
val i5 = Test({}, {}, *arrayOf(""))
|
||||
val i6 = Test({}, {}, <!TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG!>arrayOf()<!>)
|
||||
|
||||
i1.foo2({}, {}, <!TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG!>arrayOf()<!>)
|
||||
i1.foo2({}, {}, *arrayOf())
|
||||
i1.foo2({}, <!TYPE_MISMATCH!>x2<!>, <!TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG!>arrayOf()<!>)
|
||||
i1.foo2(x2, {}, *arrayOf())
|
||||
|
||||
i1.foo2({}, {}, <!TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG!>arrayOf("")<!>)
|
||||
i1.foo2({}, {}, *x3)
|
||||
i1.foo2({}, <!TYPE_MISMATCH!>x2<!>, <!TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG!>x3<!>)
|
||||
i1.foo2(x2, {}, *arrayOf(""))
|
||||
}
|
||||
Vendored
+54
@@ -0,0 +1,54 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
// !LANGUAGE: +NewInference +SamConversionForKotlinFunctions +SamConversionPerArgument +ProhibitVarargAsArrayAfterSamArgument
|
||||
// IGNORE_BACKEND: JS
|
||||
// SKIP_TXT
|
||||
|
||||
// FILE: Test.java
|
||||
public class Test {
|
||||
public static String foo1(Runnable r, String... strs) {
|
||||
return null;
|
||||
}
|
||||
public String foo2(Runnable r, Runnable r, String... strs) {
|
||||
return null;
|
||||
}
|
||||
public Test(Runnable r, String... strs) {}
|
||||
public Test(Runnable r, Runnable r, String... strs) {}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun main(x2: Runnable) {
|
||||
val x1 = {}
|
||||
val x3 = arrayOf<String>()
|
||||
|
||||
Test.foo1({}, <!TYPE_MISMATCH!>arrayOf()<!>)
|
||||
Test.foo1({}, *arrayOf())
|
||||
Test.foo1({}, *x3)
|
||||
Test.foo1({}, <!TYPE_MISMATCH!>arrayOf("")<!>)
|
||||
|
||||
Test.foo1(x1, <!TYPE_MISMATCH!>arrayOf()<!>)
|
||||
Test.foo1(x1, *arrayOf())
|
||||
Test.foo1(x2, <!TYPE_MISMATCH!>arrayOf()<!>)
|
||||
Test.foo1(x2, *arrayOf())
|
||||
|
||||
Test.foo1(x1, <!TYPE_MISMATCH!>x3<!>)
|
||||
Test.foo1(x1, *x3)
|
||||
Test.foo1(x2, <!TYPE_MISMATCH!>arrayOf("")<!>)
|
||||
Test.foo1(x2, *arrayOf(""))
|
||||
|
||||
val i1 = <!NONE_APPLICABLE!>Test<!>({}, arrayOf())
|
||||
val i2 = Test({}, *arrayOf())
|
||||
val i3 = <!NONE_APPLICABLE!>Test<!>({}, x3)
|
||||
val i4 = <!NONE_APPLICABLE!>Test<!>({}, arrayOf(""))
|
||||
val i5 = Test({}, {}, *arrayOf(""))
|
||||
val i6 = <!NONE_APPLICABLE!>Test<!>({}, {}, arrayOf())
|
||||
|
||||
i2.foo2({}, {}, <!TYPE_MISMATCH!>arrayOf()<!>)
|
||||
i2.foo2({}, {}, *arrayOf())
|
||||
i2.foo2({}, x2, <!TYPE_MISMATCH!>arrayOf()<!>)
|
||||
i2.foo2(x2, {}, *arrayOf())
|
||||
|
||||
i2.foo2({}, {}, <!TYPE_MISMATCH!>arrayOf("")<!>)
|
||||
i2.foo2({}, {}, *x3)
|
||||
i2.foo2({}, x2, <!TYPE_MISMATCH!>x3<!>)
|
||||
i2.foo2(x2, {}, *arrayOf(""))
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
// !LANGUAGE: +NewInference +SamConversionForKotlinFunctions
|
||||
// IGNORE_BACKEND: JS, JS_IR
|
||||
// SKIP_TXT
|
||||
|
||||
// FILE: Test.java
|
||||
public class Test {
|
||||
public static String foo1(Runnable r, String... strs) {
|
||||
return null;
|
||||
}
|
||||
public String foo2(Runnable r, Runnable r, String... strs) {
|
||||
return null;
|
||||
}
|
||||
public Test(Runnable r, String... strs) {}
|
||||
public Test(Runnable r, Runnable r, String... strs) {}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun main(x2: Runnable) {
|
||||
val x1 = {}
|
||||
val x3 = arrayOf<String>()
|
||||
|
||||
Test.foo1({}, arrayOf())
|
||||
Test.foo1(<!TYPE_MISMATCH!>{}<!>, *arrayOf())
|
||||
Test.foo1(<!TYPE_MISMATCH!>{}<!>, *x3)
|
||||
Test.foo1({}, arrayOf(""))
|
||||
|
||||
Test.foo1(x1, arrayOf())
|
||||
Test.foo1(<!TYPE_MISMATCH!>x1<!>, *arrayOf())
|
||||
Test.foo1(x2, <!TYPE_MISMATCH!>arrayOf()<!>)
|
||||
Test.foo1(x2, *arrayOf())
|
||||
|
||||
Test.foo1(x1, x3)
|
||||
Test.foo1(<!TYPE_MISMATCH!>x1<!>, *x3)
|
||||
Test.foo1(x2, <!TYPE_MISMATCH!>arrayOf("")<!>)
|
||||
Test.foo1(x2, *arrayOf(""))
|
||||
|
||||
val i1 = Test({}, arrayOf())
|
||||
val i2 = <!NONE_APPLICABLE!>Test<!>({}, *arrayOf())
|
||||
val i3 = Test({}, x3)
|
||||
val i4 = Test({}, arrayOf(""))
|
||||
val i5 = <!NONE_APPLICABLE!>Test<!>({}, {}, *arrayOf(""))
|
||||
val i6 = Test({}, {}, arrayOf())
|
||||
|
||||
i1.foo2({}, {}, arrayOf())
|
||||
i1.foo2(<!TYPE_MISMATCH!>{}<!>, <!TYPE_MISMATCH!>{}<!>, *arrayOf())
|
||||
i1.foo2(<!TYPE_MISMATCH!>{}<!>, x2, <!TYPE_MISMATCH!>arrayOf()<!>)
|
||||
i1.foo2(x2, <!TYPE_MISMATCH!>{}<!>, *arrayOf())
|
||||
|
||||
i1.foo2({}, {}, arrayOf(""))
|
||||
i1.foo2(<!TYPE_MISMATCH!>{}<!>, <!TYPE_MISMATCH!>{}<!>, *x3)
|
||||
i1.foo2(<!TYPE_MISMATCH!>{}<!>, x2, <!TYPE_MISMATCH!>x3<!>)
|
||||
i1.foo2(x2, <!TYPE_MISMATCH!>{}<!>, *arrayOf(""))
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// !LANGUAGE: +NewInference +SamConversionPerArgument
|
||||
// !LANGUAGE: +NewInference +SamConversionPerArgument +ProhibitVarargAsArrayAfterSamArgument
|
||||
// FILE: samConversionInGenericConstructorCall.kt
|
||||
fun test1(f: (String) -> String) = C(f)
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// !LANGUAGE: +NewInference +SamConversionPerArgument +SamConversionForKotlinFunctions
|
||||
// !LANGUAGE: +NewInference +SamConversionPerArgument +SamConversionForKotlinFunctions +ProhibitVarargAsArrayAfterSamArgument
|
||||
// FILE: samConversionInGenericConstructorCall_NI.kt
|
||||
fun test3(
|
||||
f1: (String) -> String,
|
||||
|
||||
@@ -18615,6 +18615,21 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/samConversions"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("arrayAsVarargAfterSamArgument.kt")
|
||||
public void testArrayAsVarargAfterSamArgument() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/samConversions/arrayAsVarargAfterSamArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("arrayAsVarargAfterSamArgumentProhibited.kt")
|
||||
public void testArrayAsVarargAfterSamArgumentProhibited() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/samConversions/arrayAsVarargAfterSamArgumentProhibited.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt")
|
||||
public void testArrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/samConversions/arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("checkSamConversionsAreDisabledByDefault.kt")
|
||||
public void testCheckSamConversionsAreDisabledByDefault() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/samConversions/checkSamConversionsAreDisabledByDefault.kt");
|
||||
|
||||
Generated
+15
@@ -18605,6 +18605,21 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/samConversions"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("arrayAsVarargAfterSamArgument.kt")
|
||||
public void testArrayAsVarargAfterSamArgument() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/samConversions/arrayAsVarargAfterSamArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("arrayAsVarargAfterSamArgumentProhibited.kt")
|
||||
public void testArrayAsVarargAfterSamArgumentProhibited() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/samConversions/arrayAsVarargAfterSamArgumentProhibited.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt")
|
||||
public void testArrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/samConversions/arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("checkSamConversionsAreDisabledByDefault.kt")
|
||||
public void testCheckSamConversionsAreDisabledByDefault() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/samConversions/checkSamConversionsAreDisabledByDefault.kt");
|
||||
|
||||
+10
@@ -25784,6 +25784,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("arrayAsVarargAfterSamArgument.kt")
|
||||
public void testArrayAsVarargAfterSamArgument() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sam/arrayAsVarargAfterSamArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt")
|
||||
public void testArrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sam/arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("castFromAny.kt")
|
||||
public void testCastFromAny() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sam/castFromAny.kt");
|
||||
|
||||
+10
@@ -24601,6 +24601,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("arrayAsVarargAfterSamArgument.kt")
|
||||
public void testArrayAsVarargAfterSamArgument() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sam/arrayAsVarargAfterSamArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt")
|
||||
public void testArrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sam/arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("castFromAny.kt")
|
||||
public void testCastFromAny() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sam/castFromAny.kt");
|
||||
|
||||
+10
@@ -24283,6 +24283,16 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("arrayAsVarargAfterSamArgument.kt")
|
||||
public void testArrayAsVarargAfterSamArgument() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sam/arrayAsVarargAfterSamArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt")
|
||||
public void testArrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sam/arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("castFromAny.kt")
|
||||
public void testCastFromAny() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sam/castFromAny.kt");
|
||||
|
||||
+10
@@ -24283,6 +24283,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("arrayAsVarargAfterSamArgument.kt")
|
||||
public void testArrayAsVarargAfterSamArgument() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sam/arrayAsVarargAfterSamArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt")
|
||||
public void testArrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sam/arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("castFromAny.kt")
|
||||
public void testCastFromAny() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sam/castFromAny.kt");
|
||||
|
||||
@@ -116,6 +116,7 @@ enum class LanguageFeature(
|
||||
ProhibitNonReifiedArraysAsReifiedTypeArguments(KOTLIN_1_4, kind = BUG_FIX),
|
||||
ProhibitProtectedCallFromInline(KOTLIN_1_4, kind = BUG_FIX),
|
||||
ProperFinally(KOTLIN_1_4, kind = BUG_FIX),
|
||||
ProhibitVarargAsArrayAfterSamArgument(KOTLIN_1_4, kind = BUG_FIX),
|
||||
|
||||
ProperVisibilityForCompanionObjectInstanceField(sinceVersion = null, kind = BUG_FIX),
|
||||
// Temporarily disabled, see KT-27084/KT-22379
|
||||
|
||||
@@ -132,10 +132,12 @@ class RedundantSamConstructorInspection : AbstractKotlinInspection() {
|
||||
|
||||
if (!resolutionResults.isSuccess) return false
|
||||
|
||||
val generatingAdditionalSamCandidateIsDisabled =
|
||||
parentCall.languageVersionSettings.supportsFeature(LanguageFeature.SamConversionPerArgument) ||
|
||||
parentCall.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitVarargAsArrayAfterSamArgument)
|
||||
|
||||
val samAdapterOriginalDescriptor =
|
||||
if (parentCall.languageVersionSettings.supportsFeature(LanguageFeature.SamConversionPerArgument) &&
|
||||
resolutionResults.resultingCall is NewResolvedCallImpl<*>
|
||||
) {
|
||||
if (generatingAdditionalSamCandidateIsDisabled && resolutionResults.resultingCall is NewResolvedCallImpl<*>) {
|
||||
resolutionResults.resultingDescriptor
|
||||
} else {
|
||||
SamCodegenUtil.getOriginalIfSamAdapter(resolutionResults.resultingDescriptor) ?: return false
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.quickfix
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
|
||||
object AddSpreadOperatorForArrayAsVarargAfterSamFixFactory : KotlinSingleIntentionActionFactory() {
|
||||
public override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||
val diagnosticWithParameters = Errors.TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG.cast(diagnostic)
|
||||
val argument = diagnosticWithParameters.psiElement
|
||||
|
||||
return AddSpreadOperatorForArrayAsVarargAfterSamFix(argument)
|
||||
}
|
||||
}
|
||||
|
||||
class AddSpreadOperatorForArrayAsVarargAfterSamFix(element: PsiElement) : KotlinQuickFixAction<PsiElement>(element) {
|
||||
override fun getFamilyName() = "Add a spread operator before an array passing as vararg"
|
||||
|
||||
override fun getText() = familyName
|
||||
|
||||
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
|
||||
val element = element ?: return
|
||||
|
||||
element.addBefore(KtPsiFactory(file).createStar(), element.firstChild)
|
||||
}
|
||||
}
|
||||
@@ -160,6 +160,7 @@ class QuickFixRegistrar : QuickFixContributor {
|
||||
UNRESOLVED_REFERENCE.registerFactory(ImportFix)
|
||||
UNRESOLVED_REFERENCE.registerFactory(ImportConstructorReferenceFix)
|
||||
DEPRECATED_ACCESS_BY_SHORT_NAME.registerFactory(AddExplicitImportForDeprecatedVisibilityFix.Factory)
|
||||
TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG.registerFactory(AddSpreadOperatorForArrayAsVarargAfterSamFixFactory)
|
||||
|
||||
TOO_MANY_ARGUMENTS.registerFactory(ImportForMismatchingArgumentsFix)
|
||||
NO_VALUE_FOR_PARAMETER.registerFactory(ImportForMismatchingArgumentsFix)
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// FILE: test.before.kt
|
||||
// "Add a spread operator before an array passing as vararg" "false"
|
||||
// ACTION: Add 'toString()' call
|
||||
// ACTION: Create member function 'Test.foo'
|
||||
// ACTION: Introduce import alias
|
||||
// ACTION: Introduce local variable
|
||||
// ACTION: Put arguments on separate lines
|
||||
// ERROR: Type mismatch: inferred type is Array<???> but String! was expected
|
||||
// COMPILER_ARGUMENTS: -XXLanguage:+NewInference -XXLanguage:+SamConversionForKotlinFunctions -XXLanguage:+SamConversionPerArgument -XXLanguage:+ProhibitVarargAsArrayAfterSamArgument
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun main() {
|
||||
Test.foo({}, <caret>arrayOf())
|
||||
}
|
||||
|
||||
// FILE: Test.java
|
||||
public class Test {
|
||||
public static String foo(Runnable r, String... strs) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// FILE: test.before.kt
|
||||
// "Add a spread operator before an array passing as vararg" "true"
|
||||
// WARNING: Please use spread operator to pass an array as vararg. It will be an error in 1.5.
|
||||
// COMPILER_ARGUMENTS: -XXLanguage:+NewInference -XXLanguage:+SamConversionForKotlinFunctions -XXLanguage:+SamConversionPerArgument
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun main() {
|
||||
Test.foo({}, <caret>arrayOf())
|
||||
}
|
||||
|
||||
// FILE: Test.java
|
||||
public class Test {
|
||||
public static String foo(Runnable r, String... strs) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Add a spread operator before an array passing as vararg" "true"
|
||||
// WARNING: Please use spread operator to pass an array as vararg. It will be an error in 1.5.
|
||||
// COMPILER_ARGUMENTS: -XXLanguage:+NewInference -XXLanguage:+SamConversionForKotlinFunctions -XXLanguage:+SamConversionPerArgument
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun main() {
|
||||
Test.foo({}, <caret>*arrayOf())
|
||||
}
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// FILE: test.before.kt
|
||||
// "Add a spread operator before an array passing as vararg" "false"
|
||||
// ACTION: Add explicit type arguments
|
||||
// ACTION: Introduce import alias
|
||||
// ACTION: Introduce local variable
|
||||
// ACTION: Put arguments on separate lines
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun main() {
|
||||
Test.foo({}, <caret>arrayOf())
|
||||
}
|
||||
|
||||
// FILE: Test.java
|
||||
public class Test {
|
||||
public static String foo(Runnable r, String... strs) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+28
@@ -324,6 +324,34 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/addSpreadOperatorForArrayAsVarargAfterSam")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class AddSpreadOperatorForArrayAsVarargAfterSam extends AbstractQuickFixMultiFileTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTestWithExtraFile, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInAddSpreadOperatorForArrayAsVarargAfterSam() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/addSpreadOperatorForArrayAsVarargAfterSam"), Pattern.compile("^(\\w+)\\.((before\\.Main\\.\\w+)|(test))$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("withError.test")
|
||||
public void testWithError() throws Exception {
|
||||
runTest("idea/testData/quickfix/addSpreadOperatorForArrayAsVarargAfterSam/withError.test");
|
||||
}
|
||||
|
||||
@TestMetadata("withWarning.test")
|
||||
public void testWithWarning() throws Exception {
|
||||
runTest("idea/testData/quickfix/addSpreadOperatorForArrayAsVarargAfterSam/withWarning.test");
|
||||
}
|
||||
|
||||
@TestMetadata("withoutWarning.test")
|
||||
public void testWithoutWarning() throws Exception {
|
||||
runTest("idea/testData/quickfix/addSpreadOperatorForArrayAsVarargAfterSam/withoutWarning.test");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/addStarProjections")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
@@ -1174,6 +1174,19 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/addSpreadOperatorForArrayAsVarargAfterSam")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class AddSpreadOperatorForArrayAsVarargAfterSam extends AbstractQuickFixTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInAddSpreadOperatorForArrayAsVarargAfterSam() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/addSpreadOperatorForArrayAsVarargAfterSam"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/addStarProjections")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user