Introduce inspection for unused main parameter #KT-26999 Fixed

This commit is contained in:
Mikhail Glukhikh
2018-10-30 18:39:20 +03:00
parent ad44118605
commit 318d6e7111
11 changed files with 113 additions and 2 deletions
@@ -671,8 +671,18 @@ class ControlFlowInformationProvider private constructor(
val mainFunctionDetector = MainFunctionDetector(trace.bindingContext, languageVersionSettings)
val isMain = owner is KtNamedFunction && mainFunctionDetector.isMain(owner)
val functionName = functionDescriptor.name
if (isMain && !languageVersionSettings.supportsFeature(LanguageFeature.WarningOnMainUnusedParameter)
|| functionDescriptor.isOverridableOrOverrides
if (isMain) {
when {
!languageVersionSettings.supportsFeature(LanguageFeature.ExtendedMainConvention) -> {
return
}
!languageVersionSettings.supportsFeature(LanguageFeature.WarningOnMainUnusedParameter) -> {
trace.record(UNUSED_MAIN_PARAMETER, element)
return
}
}
}
if (functionDescriptor.isOverridableOrOverrides
|| owner.hasModifier(KtTokens.OVERRIDE_KEYWORD)
|| OperatorNameConventions.GET_VALUE == functionName
|| OperatorNameConventions.SET_VALUE == functionName
@@ -103,6 +103,7 @@ public interface BindingContext {
WritableSlice<KtExpression, DataFlowInfo> DATAFLOW_INFO_AFTER_CONDITION = Slices.createSimpleSlice();
WritableSlice<VariableDescriptor, DataFlowValue> BOUND_INITIALIZER_VALUE = Slices.createSimpleSlice();
WritableSlice<KtExpression, LeakingThisDescriptor> LEAKING_THIS = Slices.createSimpleSlice();
WritableSlice<KtParameter, Boolean> UNUSED_MAIN_PARAMETER = Slices.createSimpleSlice();
/**
* A qualifier corresponds to a receiver expression (if any). For 'A.B' qualifier is recorded for 'A'.
@@ -0,0 +1,5 @@
<html>
<body>
This inspection reports an unused main function parameter which is not necessary since Kotlin 1.3.
</body>
</html>
+9
View File
@@ -3075,6 +3075,15 @@
language="kotlin"
/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.UnusedMainParameterInspection"
displayName="Main parameter is not necessary"
groupPath="Kotlin"
groupName="Style issues"
enabledByDefault="true"
level="WEAK WARNING"
language="kotlin"
/>
<referenceImporter implementation="org.jetbrains.kotlin.idea.quickfix.KotlinReferenceImporter"/>
<fileType.fileViewProviderFactory filetype="KJSM" implementationClass="com.intellij.psi.ClassFileViewProviderFactory"/>
@@ -0,0 +1,35 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. 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.inspections
import com.intellij.codeInspection.IntentionWrapper
import com.intellij.codeInspection.LocalInspectionToolSession
import com.intellij.codeInspection.ProblemHighlightType
import com.intellij.codeInspection.ProblemsHolder
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithContent
import org.jetbrains.kotlin.idea.quickfix.RemoveUnusedFunctionParameterFix
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.parameterVisitor
import org.jetbrains.kotlin.resolve.BindingContext.UNUSED_MAIN_PARAMETER
class UnusedMainParameterInspection : AbstractKotlinInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession) =
parameterVisitor(fun(parameter: KtParameter) {
val function = parameter.ownerFunction as? KtNamedFunction ?: return
if (function.name != "main") return
val context = function.analyzeWithContent()
if (context[UNUSED_MAIN_PARAMETER, parameter] == true) {
holder.registerProblem(
parameter,
"Since Kotlin 1.3 main parameter is not necessary",
ProblemHighlightType.LIKE_UNUSED_SYMBOL,
IntentionWrapper(RemoveUnusedFunctionParameterFix(parameter), parameter.containingFile)
)
}
})
}
@@ -0,0 +1 @@
org.jetbrains.kotlin.idea.inspections.UnusedMainParameterInspection
@@ -0,0 +1,6 @@
// PROBLEM: none
// LANGUAGE_VERSION: 1.4
fun main(<caret>args: Array<String>) {
}
@@ -0,0 +1,6 @@
// PROBLEM: none
// LANGUAGE_VERSION: 1.2
fun main(<caret>args: Array<String>) {
}
@@ -0,0 +1,5 @@
// LANGUAGE_VERSION: 1.3
fun main(<caret>args: Array<String>) {
}
@@ -0,0 +1,5 @@
// LANGUAGE_VERSION: 1.3
fun main() {
}
@@ -6468,6 +6468,34 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
}
}
@TestMetadata("idea/testData/inspectionsLocal/unusedMainParameter")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class UnusedMainParameter extends AbstractLocalInspectionTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInUnusedMainParameter() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/unusedMainParameter"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
}
@TestMetadata("future.kt")
public void testFuture() throws Exception {
runTest("idea/testData/inspectionsLocal/unusedMainParameter/future.kt");
}
@TestMetadata("legacy.kt")
public void testLegacy() throws Exception {
runTest("idea/testData/inspectionsLocal/unusedMainParameter/legacy.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("idea/testData/inspectionsLocal/unusedMainParameter/simple.kt");
}
}
@TestMetadata("idea/testData/inspectionsLocal/unusedReceiverParameter")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)