From d8a4a32e9f704c7b06599be297a52bb02ae1773c Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Fri, 27 Jan 2017 14:44:43 +0300 Subject: [PATCH] Do not report UNUSED_PARAMETER in function literal for 1.0 compatibility mode #KT-16010 Fixed --- .../cfg/ControlFlowInformationProvider.kt | 20 +++++++++++++------ .../kotlin/resolve/ControlFlowAnalyzer.java | 17 +++++++++++----- .../tests/UnusedParametersVersion10.kt | 3 +++ .../tests/UnusedParametersVersion10.txt | 3 +++ .../checkers/DiagnosticsTestGenerated.java | 6 ++++++ .../idea/project/ResolveElementCache.kt | 4 ++-- 6 files changed, 40 insertions(+), 13 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/UnusedParametersVersion10.kt create mode 100644 compiler/testData/diagnostics/tests/UnusedParametersVersion10.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt index ec0292b905f..bcae261813e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt @@ -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 = diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ControlFlowAnalyzer.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ControlFlowAnalyzer.java index 036e6fdad4b..b551265b261 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ControlFlowAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ControlFlowAnalyzer.java @@ -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; diff --git a/compiler/testData/diagnostics/tests/UnusedParametersVersion10.kt b/compiler/testData/diagnostics/tests/UnusedParametersVersion10.kt new file mode 100644 index 00000000000..b3c56ab9bd4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/UnusedParametersVersion10.kt @@ -0,0 +1,3 @@ +// !LANGUAGE: -SingleUnderscoreForParameterName + +val x = 1.let { arg -> } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/UnusedParametersVersion10.txt b/compiler/testData/diagnostics/tests/UnusedParametersVersion10.txt new file mode 100644 index 00000000000..6ba11bfce59 --- /dev/null +++ b/compiler/testData/diagnostics/tests/UnusedParametersVersion10.txt @@ -0,0 +1,3 @@ +package + +public val x: kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 0b53ea874aa..758411a8041 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -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"); diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt index 8b9bcb4a991..75251d09696 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.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