Commit 480e393b authored by Justin Paupore's avatar Justin Paupore
Browse files

[K2] Port NamingConventionInspections to K2

Port the inspections in NamingConventionInspections to K2. The bulk of
these inspections are PSI-only, but FunctionNameInspection requires
resolve, so it has been split into a base class to handle the PSI-only
portions of the inspection, and two concrete implementations (one each
for K1 and K2), to handle the analysis.

To more cleanly distinguish between ported and unported inspections, add
an inspections-k1 module to accompany inspections-shared and
inspections-k2.

^KTIJ-22913 fixed
parent 964ce61e
Branches unavailable Tags unavailable
No related merge requests found
Showing with 256 additions and 1 deletion
+256 -1
......@@ -1195,6 +1195,8 @@
<module fileurl="file://$PROJECT_DIR$/plugins/kotlin/code-insight/api/kotlin.code-insight.api.iml" filepath="$PROJECT_DIR$/plugins/kotlin/code-insight/api/kotlin.code-insight.api.iml" />
<module fileurl="file://$PROJECT_DIR$/plugins/kotlin/code-insight/descriptions/kotlin.code-insight.descriptions.iml" filepath="$PROJECT_DIR$/plugins/kotlin/code-insight/descriptions/kotlin.code-insight.descriptions.iml" />
<module fileurl="file://$PROJECT_DIR$/plugins/kotlin/code-insight/impl-base/kotlin.code-insight.impl-base.iml" filepath="$PROJECT_DIR$/plugins/kotlin/code-insight/impl-base/kotlin.code-insight.impl-base.iml" />
<module fileurl="file://$PROJECT_DIR$/plugins/kotlin/code-insight/inspections-k1/kotlin.code-insight.inspections-k1.iml" filepath="$PROJECT_DIR$/plugins/kotlin/code-insight/inspections-k1/kotlin.code-insight.inspections-k1.iml" />
<module fileurl="file://$PROJECT_DIR$/plugins/kotlin/code-insight/inspections-k1/tests/kotlin.code-insight.inspections-k1.tests.iml" filepath="$PROJECT_DIR$/plugins/kotlin/code-insight/inspections-k1/tests/kotlin.code-insight.inspections-k1.tests.iml" />
<module fileurl="file://$PROJECT_DIR$/plugins/kotlin/code-insight/inspections-k2/kotlin.code-insight.inspections-k2.iml" filepath="$PROJECT_DIR$/plugins/kotlin/code-insight/inspections-k2/kotlin.code-insight.inspections-k2.iml" />
<module fileurl="file://$PROJECT_DIR$/plugins/kotlin/code-insight/inspections-k2/tests/kotlin.code-insight.inspections-k2.tests.iml" filepath="$PROJECT_DIR$/plugins/kotlin/code-insight/inspections-k2/tests/kotlin.code-insight.inspections-k2.tests.iml" />
<module fileurl="file://$PROJECT_DIR$/plugins/kotlin/code-insight/inspections-shared/kotlin.code-insight.inspections-shared.iml" filepath="$PROJECT_DIR$/plugins/kotlin/code-insight/inspections-shared/kotlin.code-insight.inspections-shared.iml" />
......
......@@ -163,6 +163,7 @@ object KotlinPluginBuilder {
"kotlin.code-insight.descriptions",
"kotlin.code-insight.intentions-k1",
"kotlin.code-insight.intentions-k2",
"kotlin.code-insight.inspections-k1",
"kotlin.code-insight.inspections-k2",
"kotlin.code-insight.k1",
"kotlin.code-insight.k2",
......
......@@ -53,6 +53,7 @@
<orderEntry type="module" module-name="kotlin.util.test-generator-fe10" scope="RUNTIME" />
<orderEntry type="module" module-name="kotlin.code-insight.intentions-shared.tests.k1" scope="RUNTIME" />
<orderEntry type="module" module-name="kotlin.code-insight.inspections-shared.tests.k1" scope="RUNTIME" />
<orderEntry type="module" module-name="kotlin.code-insight.inspections-k1.tests" scope="RUNTIME" />
<orderEntry type="module" module-name="kotlin.code-insight.impl-base" scope="RUNTIME" />
<orderEntry type="module" module-name="kotlin.code-insight.live-templates-k1" scope="RUNTIME" />
<orderEntry type="module" module-name="kotlin.completion.tests-shared" scope="RUNTIME" />
......
......@@ -40,6 +40,7 @@
<orderEntry type="module" module-name="kotlin.formatter" />
<orderEntry type="module" module-name="kotlin.code-insight.api" />
<orderEntry type="module" module-name="kotlin.code-insight.utils" />
<orderEntry type="module" module-name="intellij.platform.core.ui" />
<orderEntry type="module" module-name="intellij.platform.lang.impl" />
<orderEntry type="module" module-name="intellij.platform.editor" />
<orderEntry type="module" module-name="intellij.java.psi" />
......
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.kotlin.idea.quickfix
package org.jetbrains.kotlin.idea.codeinsights.impl.base.quickFix
import com.intellij.codeInsight.FileModificationService
import com.intellij.codeInspection.LocalQuickFix
......
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="kotlinc.kotlin-stdlib" level="project" />
<orderEntry type="module" module-name="kotlin.base.util" />
<orderEntry type="module" module-name="kotlin.base.psi" />
<orderEntry type="module" module-name="kotlin.base.resources" />
<orderEntry type="module" module-name="kotlin.base.code-insight" />
<orderEntry type="module" module-name="kotlin.formatter" />
<orderEntry type="module" module-name="kotlin.code-insight.api" />
<orderEntry type="module" module-name="kotlin.code-insight.utils" />
<orderEntry type="module" module-name="kotlin.base.project-structure" />
<orderEntry type="module" module-name="kotlin.code-insight.impl-base" />
<orderEntry type="module" module-name="intellij.platform.core.impl" />
<orderEntry type="module" module-name="intellij.platform.analysis" />
<orderEntry type="module" module-name="intellij.platform.editor" />
<orderEntry type="module" module-name="intellij.platform.lang" />
<orderEntry type="module" module-name="intellij.java.psi" />
<orderEntry type="module" module-name="intellij.java.analysis.impl" />
<orderEntry type="module" module-name="intellij.platform.lang.impl" />
<orderEntry type="module" module-name="kotlin.code-insight.inspections-shared" />
<orderEntry type="library" name="kotlinc.kotlin-compiler-common" level="project" />
<orderEntry type="library" name="kotlinc.kotlin-compiler-fe10" level="project" />
<orderEntry type="module" module-name="kotlin.base.fe10.analysis" />
<orderEntry type="module" module-name="kotlin.core" />
</component>
</module>
\ No newline at end of file
<idea-plugin package="org.jetbrains.kotlin.idea.k1.codeinsight.inspections">
<dependencies>
<module name="kotlin.code-insight.inspections-shared"/>
</dependencies>
<extensions defaultExtensionNs="com.intellij">
<localInspection implementationClass="org.jetbrains.kotlin.idea.k1.codeinsight.inspections.FunctionNameInspection"
language="kotlin"
groupPath="Kotlin"
groupBundle="messages.KotlinBundle" groupKey="group.names.naming.conventions"
enabledByDefault="true"
level="WEAK WARNING" key="inspection.function.name.display.name" bundle="messages.KotlinBundle"/>
</extensions>
</idea-plugin>
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.k1.codeinsight.inspections
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.codeInsight.inspections.shared.AbstractFunctionNameInspection
import org.jetbrains.kotlin.idea.refactoring.fqName.fqName
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.supertypes
class FunctionNameInspection : AbstractFunctionNameInspection() {
override fun KtNamedFunction.isFactoryFunctionByAnalyze(): Boolean {
val functionName = this.name ?: return false
val returnType = resolveToDescriptorIfAny()?.returnType ?: return false
return returnType.shortName() == functionName || returnType.supertypes().any { it.shortName() == functionName }
}
private fun KotlinType.shortName(): String? = fqName?.takeUnless(FqName::isRoot)?.shortName()?.asString()
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="kotlin.plugin.k1" scope="TEST" />
<orderEntry type="library" scope="TEST" name="kotlinc.kotlin-stdlib" level="project" />
<orderEntry type="library" scope="TEST" name="kotlinc.kotlin-compiler-common" level="project" />
<orderEntry type="library" scope="TEST" name="kotlinc.kotlin-compiler-tests" level="project" />
<orderEntry type="module" module-name="kotlin.base.test" scope="TEST" />
<orderEntry type="module" module-name="kotlin.idea.tests" scope="TEST" />
<orderEntry type="module" module-name="kotlin.tests-common" scope="TEST" />
<orderEntry type="module" module-name="kotlin.code-insight.inspections-k1" scope="TEST" />
</component>
</module>
\ No newline at end of file
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.k1.inspections.tests
import org.jetbrains.kotlin.idea.inspections.AbstractInspectionTest
abstract class AbstractK1InspectionTest : AbstractInspectionTest()
\ No newline at end of file
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.k1.inspections.tests;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.idea.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.idea.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.jetbrains.kotlin.idea.base.test.TestRoot;
import org.junit.runner.RunWith;
/**
* This class is generated by {@link org.jetbrains.kotlin.testGenerator.generator.TestGenerator}.
* DO NOT MODIFY MANUALLY.
*/
@SuppressWarnings("all")
@TestRoot("code-insight/inspections-k1/tests")
@TestDataPath("$CONTENT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("testData/inspections")
public abstract class K1InspectionTestGenerated extends AbstractK1InspectionTest {
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("testData/inspections/functionName")
public abstract static class FunctionName extends AbstractK1InspectionTest {
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("testData/inspections/functionName/inspectionData")
public static class InspectionData extends AbstractK1InspectionTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
@TestMetadata("inspections.test")
public void testInspections_test() throws Exception {
runTest("testData/inspections/functionName/inspectionData/inspections.test");
}
}
}
}
// INSPECTION_CLASS: org.jetbrains.kotlin.idea.k1.codeinsight.inspections.FunctionNameInspection
\ No newline at end of file
......@@ -39,6 +39,7 @@
<orderEntry type="module" module-name="kotlin.code-insight.api" />
<orderEntry type="module" module-name="kotlin.code-insight.utils" />
<orderEntry type="module" module-name="kotlin.code-insight.impl-base" />
<orderEntry type="module" module-name="kotlin.code-insight.inspections-shared" />
<orderEntry type="module" module-name="kotlin.code-insight.descriptions" />
<orderEntry type="module" module-name="intellij.platform.lang.impl" />
<orderEntry type="module" module-name="intellij.platform.editor" />
......
......@@ -254,5 +254,12 @@
suppressId="unused" editorAttributes="NOT_USED_ELEMENT_ATTRIBUTES"
key="inspection.unused.symbol.display.name" bundle="messages.KotlinBundle"/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.k2.codeinsight.inspections.FunctionNameInspection"
language="kotlin"
groupPath="Kotlin"
groupBundle="messages.KotlinBundle" groupKey="group.names.naming.conventions"
enabledByDefault="true"
level="WEAK WARNING" key="inspection.function.name.display.name" bundle="messages.KotlinBundle"/>
</extensions>
</idea-plugin>
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.k2.codeinsight.inspections
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.analyze
import org.jetbrains.kotlin.analysis.api.types.KtType
import org.jetbrains.kotlin.idea.codeInsight.inspections.shared.AbstractFunctionNameInspection
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtNamedFunction
class FunctionNameInspection : AbstractFunctionNameInspection() {
override fun KtNamedFunction.isFactoryFunctionByAnalyze(): Boolean = analyze(this) {
val functionName = name ?: return false
val returnType = getReturnKtType()
return returnType.hasShortName(functionName)
|| returnType.getAllSuperTypes().any { it.hasShortName(functionName) }
}
context(KtAnalysisSession)
private fun KtType.hasShortName(shortName: String): Boolean {
val typeShortName =
expandedClassSymbol
?.classIdIfNonLocal
?.relativeClassName
?.takeUnless(FqName::isRoot)
?.shortName()
?.identifierOrNullIfSpecial
?: return false
return shortName == typeShortName
}
}
\ No newline at end of file
<problems>
<problem>
<file>test.kt</file>
<line>1</line>
<description>Function name &lt;code&gt;Foo&lt;/code&gt; should start with a lowercase letter #loc</description>
</problem>
<problem>
<file>test.kt</file>
<line>3</line>
<description>Function name &lt;code&gt;FOO_BAR&lt;/code&gt; should start with a lowercase letter #loc</description>
</problem>
<problem>
<file>test.kt</file>
<line>7</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Class naming convention</problem_class>
<description>Function name &lt;code&gt;`a b`&lt;/code&gt; may contain only letters and digits #loc</description>
</problem>
<problem>
<file>test.kt</file>
<line>10</line>
<description>Function name &lt;code&gt;a_b&lt;/code&gt; should not contain underscores #loc</description>
</problem>
<problem>
<file>test.kt</file>
<line>17</line>
<module>light_idea_test_case</module>
<package>test</package>
<entry_point TYPE="method" FQNAME="test.TestKt int Vector3d()" />
<problem_class id="FunctionName" severity="WEAK WARNING" attribute_key="INFO_ATTRIBUTES">Function naming convention</problem_class>
<description>Function name &lt;code&gt;Vector3d&lt;/code&gt; should start with a lowercase letter #loc</description>
<highlighted_element>Vector3d</highlighted_element>
<offset>4</offset>
<length>8</length>
</problem>
</problems>
// INSPECTION_CLASS: org.jetbrains.kotlin.idea.k2.codeinsight.inspections.FunctionNameInspection
\ No newline at end of file
fun Foo() {}
fun FOO_BAR() {}
fun xyzzy() {}
fun `a b`() {}
interface I {
fun a_b()
}
class C : I {
override fun a_b() {} // Shouldn't be reported
}
fun Vector3d(): Int = 42
interface D
fun D(): D = object : D {}
interface E
fun E() = object : E {}
typealias F = () -> String
fun F(): F = { "" }
class G
fun G(b: Boolean): G? = if (b) G() else null
class Generic<ID>(val id: ID)
fun Generic(): Generic<Int> = Generic(0)
class Generic2<ID>(val id: ID)
fun Generic2() = Generic2(0)
class Generic3<ID>(val id: ID)
fun Generic3(b: Boolean): Generic3<Int>? = if (b) Generic3(0) else null
interface Baz
class BazImpl : Baz
fun Baz() = BazImpl()
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment