Do not report UNUSED_PARAMETER in function literal for 1.0 compatibility mode #KT-16010 Fixed

This commit is contained in:
Mikhail Glukhikh
2017-01-27 14:44:43 +03:00
committed by mglukhikh
parent 9fdf16e5d7
commit d8a4a32e9f
6 changed files with 40 additions and 13 deletions
@@ -31,6 +31,8 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.MarkInstruction
import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.VariableDeclarationInstruction
import org.jetbrains.kotlin.cfg.pseudocode.sideEffectFree
import org.jetbrains.kotlin.cfg.pseudocodeTraverser.*
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.referencedProperty
import org.jetbrains.kotlin.diagnostics.Diagnostic
@@ -61,15 +63,16 @@ import java.util.*
class ControlFlowInformationProvider private constructor(
private val subroutine: KtElement,
private val trace: BindingTrace,
private val pseudocode: Pseudocode
private val pseudocode: Pseudocode,
private val languageVersionSettings: LanguageVersionSettings
) {
private val pseudocodeVariablesData by lazy {
PseudocodeVariablesData(pseudocode, trace.bindingContext)
}
constructor(declaration: KtElement, trace: BindingTrace)
: this(declaration, trace, ControlFlowProcessor(trace).generatePseudocode(declaration))
constructor(declaration: KtElement, trace: BindingTrace, languageVersionSettings: LanguageVersionSettings)
: this(declaration, trace, ControlFlowProcessor(trace).generatePseudocode(declaration), languageVersionSettings)
fun checkForLocalClassOrObjectMode() {
// Local classes and objects are analyzed twice: when TopDownAnalyzer processes it and as a part of its container.
@@ -174,7 +177,8 @@ class ControlFlowInformationProvider private constructor(
val functionDescriptor = trace.bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element) as? CallableDescriptor
val expectedType = functionDescriptor?.returnType
val providerForLocalDeclaration = ControlFlowInformationProvider(element, trace, localDeclarationInstruction.body)
val providerForLocalDeclaration = ControlFlowInformationProvider(
element, trace, localDeclarationInstruction.body, languageVersionSettings)
providerForLocalDeclaration.checkFunction(expectedType)
}
@@ -604,7 +608,7 @@ class ControlFlowInformationProvider private constructor(
if (element.isSingleUnderscore) return
when {
// KtDestructuringDeclarationEntry -> KtDestructuringDeclaration -> KtParameter -> KtParameterList
element is KtDestructuringDeclarationEntry && element.parent?.parent?.parent is KtParameterList ->
element is KtDestructuringDeclarationEntry && element.parent.parent?.parent is KtParameterList ->
report(Errors.UNUSED_DESTRUCTURED_PARAMETER_ENTRY.on(element, variableDescriptor), ctxt)
KtPsiUtil.isRemovableVariableDeclaration(element) ->
@@ -630,7 +634,7 @@ class ControlFlowInformationProvider private constructor(
}
private fun processUnusedParameter(ctxt: VariableUseContext, element: KtParameter, variableDescriptor: VariableDescriptor) {
val owner = element.parent?.parent
val owner = element.parent.parent
when (owner) {
is KtPrimaryConstructor -> if (!element.hasValOrVar()) {
val containingClass = owner.getContainingClassOrObject()
@@ -642,6 +646,10 @@ class ControlFlowInformationProvider private constructor(
}
}
is KtFunction -> {
if (owner is KtFunctionLiteral &&
!languageVersionSettings.supportsFeature(LanguageFeature.SingleUnderscoreForParameterName)) {
return
}
val mainFunctionDetector = MainFunctionDetector(trace.bindingContext)
val isMain = owner is KtNamedFunction && mainFunctionDetector.isMain(owner)
val functionDescriptor =
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.cfg.ControlFlowInformationProvider;
import org.jetbrains.kotlin.config.LanguageVersionSettings;
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor;
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor;
@@ -33,10 +34,14 @@ import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
public class ControlFlowAnalyzer {
@NotNull private final BindingTrace trace;
@NotNull private final KotlinBuiltIns builtIns;
@NotNull private final LanguageVersionSettings languageVersionSettings;
public ControlFlowAnalyzer(@NotNull BindingTrace trace, @NotNull KotlinBuiltIns builtIns) {
public ControlFlowAnalyzer(
@NotNull BindingTrace trace, @NotNull KotlinBuiltIns builtIns, @NotNull LanguageVersionSettings languageVersionSettings
) {
this.trace = trace;
this.builtIns = builtIns;
this.languageVersionSettings = languageVersionSettings;
}
public void process(@NotNull BodiesResolveContext c) {
@@ -68,7 +73,8 @@ public class ControlFlowAnalyzer {
}
private void checkSecondaryConstructor(@NotNull KtSecondaryConstructor constructor) {
ControlFlowInformationProvider controlFlowInformationProvider = new ControlFlowInformationProvider(constructor, trace);
ControlFlowInformationProvider controlFlowInformationProvider =
new ControlFlowInformationProvider(constructor, trace, languageVersionSettings);
controlFlowInformationProvider.checkDeclaration();
controlFlowInformationProvider.checkFunction(builtIns.getUnitType());
}
@@ -76,8 +82,8 @@ public class ControlFlowAnalyzer {
private void checkDeclarationContainer(@NotNull BodiesResolveContext c, KtDeclarationContainer declarationContainer) {
// A pseudocode of class/object initialization corresponds to a class/object
// or initialization of properties corresponds to a package declared in a file
ControlFlowInformationProvider
controlFlowInformationProvider = new ControlFlowInformationProvider((KtElement) declarationContainer, trace);
ControlFlowInformationProvider controlFlowInformationProvider =
new ControlFlowInformationProvider((KtElement) declarationContainer, trace, languageVersionSettings);
if (c.getTopDownAnalysisMode().isLocalDeclarations()) {
controlFlowInformationProvider.checkForLocalClassOrObjectMode();
return;
@@ -98,7 +104,8 @@ public class ControlFlowAnalyzer {
private void checkFunction(@NotNull BodiesResolveContext c, @NotNull KtDeclarationWithBody function, @Nullable KotlinType expectedReturnType) {
if (!function.hasBody()) return;
ControlFlowInformationProvider controlFlowInformationProvider = new ControlFlowInformationProvider(function, trace);
ControlFlowInformationProvider controlFlowInformationProvider =
new ControlFlowInformationProvider(function, trace, languageVersionSettings);
if (c.getTopDownAnalysisMode().isLocalDeclarations()) {
controlFlowInformationProvider.checkForLocalClassOrObjectMode();
return;
@@ -0,0 +1,3 @@
// !LANGUAGE: -SingleUnderscoreForParameterName
val x = 1.let { arg -> }
@@ -0,0 +1,3 @@
package
public val x: kotlin.Unit
@@ -782,6 +782,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("UnusedParametersVersion10.kt")
public void testUnusedParametersVersion10() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/UnusedParametersVersion10.kt");
doTest(fileName);
}
@TestMetadata("UnusedVariables.kt")
public void testUnusedVariables() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/UnusedVariables.kt");
@@ -346,7 +346,7 @@ class ResolveElementCache(
}
val controlFlowTrace = DelegatingBindingTrace(trace.bindingContext, "Element control flow resolve", resolveElement)
ControlFlowInformationProvider(resolveElement, controlFlowTrace).checkDeclaration()
ControlFlowInformationProvider(resolveElement, controlFlowTrace, resolveElement.languageVersionSettings).checkDeclaration()
controlFlowTrace.addOwnDataTo(trace, null, false)
return Pair(trace.bindingContext, statementFilterUsed)
@@ -482,7 +482,7 @@ class ResolveElementCache(
forceResolveAnnotationsInside(property)
for (accessor in property.accessors) {
ControlFlowInformationProvider(accessor, trace).checkDeclaration()
ControlFlowInformationProvider(accessor, trace, accessor.languageVersionSettings).checkDeclaration()
}
return trace