diff --git a/plugins/devkit/devkit-core/src/inspections/NonDefaultConstructorInspection.kt b/plugins/devkit/devkit-core/src/inspections/NonDefaultConstructorInspection.kt index ee349eafad2e..43b9aa1c0305 100644 --- a/plugins/devkit/devkit-core/src/inspections/NonDefaultConstructorInspection.kt +++ b/plugins/devkit/devkit-core/src/inspections/NonDefaultConstructorInspection.kt @@ -44,10 +44,12 @@ class NonDefaultConstructorInspection : DevKitUastInspectionBase() { val area: Area? val isService: Boolean + var isServiceAnnotation = false // hack, allow Project-level @Service var extensionPoint: ExtensionPoint? = null if (javaPsi.hasAnnotation("com.intellij.openapi.components.Service")) { area = null isService = true + isServiceAnnotation = true } else { // fast path - check by qualified name @@ -69,7 +71,7 @@ class NonDefaultConstructorInspection : DevKitUastInspectionBase() { var errors: MutableList? = null loop@ for (method in constructors) { val parameters = method.parameterList - if (isAllowedParameters(parameters, extensionPoint, isAppLevelExtensionPoint)) { + if (isAllowedParameters(parameters, extensionPoint, isAppLevelExtensionPoint, isServiceAnnotation)) { // allow to have empty constructor and extra (e.g. DartQuickAssistIntention) return null } @@ -178,15 +180,20 @@ private fun checkAttributes(tag: XmlTag, qualifiedName: String): Boolean { } } -private fun isAllowedParameters(list: PsiParameterList, extensionPoint: ExtensionPoint?, isAppLevelExtensionPoint: Boolean): Boolean { +private fun isAllowedParameters(list: PsiParameterList, + extensionPoint: ExtensionPoint?, + isAppLevelExtensionPoint: Boolean, + isServiceAnnotation: Boolean): Boolean { if (list.isEmpty) { return true } // hardcoded for now, later will be generalized - if (isAppLevelExtensionPoint || extensionPoint?.effectiveQualifiedName == "com.intellij.semContributor") { - // disallow any parameters - return false + if (!isServiceAnnotation) { + if (isAppLevelExtensionPoint || extensionPoint?.effectiveQualifiedName == "com.intellij.semContributor") { + // disallow any parameters + return false + } } if (list.parametersCount != 1) { diff --git a/plugins/devkit/devkit-java-tests/testData/inspections/nonDefaultConstructor/ProjectService.java b/plugins/devkit/devkit-java-tests/testData/inspections/nonDefaultConstructor/ProjectService.java new file mode 100644 index 000000000000..c7acf13192a5 --- /dev/null +++ b/plugins/devkit/devkit-java-tests/testData/inspections/nonDefaultConstructor/ProjectService.java @@ -0,0 +1,4 @@ +@com.intellij.openapi.components.Service +public class ProjectService { + public ProjectService(com.intellij.openapi.project.Project project) {} +} diff --git a/plugins/devkit/devkit-java-tests/testData/inspections/nonDefaultConstructor/ProjectServiceNonAllowedCtorArg.java b/plugins/devkit/devkit-java-tests/testData/inspections/nonDefaultConstructor/ProjectServiceNonAllowedCtorArg.java new file mode 100644 index 000000000000..2a3ee15fc999 --- /dev/null +++ b/plugins/devkit/devkit-java-tests/testData/inspections/nonDefaultConstructor/ProjectServiceNonAllowedCtorArg.java @@ -0,0 +1,4 @@ +@com.intellij.openapi.components.Service +public class ProjectServiceNonAllowedCtorArg { + public ProjectServiceNonAllowedCtorArg(com.intellij.openapi.project.Project project, String notAllowed) {} +} diff --git a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/NonDefaultConstructorInspectionTest.kt b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/NonDefaultConstructorInspectionTest.kt index e793bc19d964..ecbc7210e0c0 100644 --- a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/NonDefaultConstructorInspectionTest.kt +++ b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/NonDefaultConstructorInspectionTest.kt @@ -1,9 +1,11 @@ // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.idea.devkit.inspections +import com.intellij.testFramework.TestDataPath import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase import org.jetbrains.idea.devkit.DevkitJavaTestsUtil +@TestDataPath("\$CONTENT_ROOT/testData/inspections/nonDefaultConstructor") class NonDefaultConstructorInspectionTest : LightJavaCodeInsightFixtureTestCase() { override fun getBasePath() = "${DevkitJavaTestsUtil.TESTDATA_PATH}inspections/nonDefaultConstructor" @@ -21,4 +23,16 @@ class NonDefaultConstructorInspectionTest : LightJavaCodeInsightFixtureTestCase( myFixture.addClass("package com.intellij.codeInsight.completion; public class CompletionContributor {}") myFixture.testHighlighting("CustomConstructor.java") } + + fun `test Project @Service`() { + myFixture.addClass("package com.intellij.openapi.project; public class Project {}") + myFixture.addClass("package com.intellij.openapi.components; public @interface Service {}") + myFixture.testHighlighting("ProjectService.java") + } + + fun `test Project @Service with non allowed CTOR arg`() { + myFixture.addClass("package com.intellij.openapi.project; public class Project {}") + myFixture.addClass("package com.intellij.openapi.components; public @interface Service {}") + myFixture.testHighlighting("ProjectServiceNonAllowedCtorArg.java") + } } \ No newline at end of file