[devkit] NonDefaultConstructorInspection: allow Project-level @Service

GitOrigin-RevId: 08596753330c590d935d2715c27c196b0e0787c7
This commit is contained in:
Yann Cébron
2019-08-13 13:03:27 +03:00
committed by intellij-monorepo-bot
parent ce69dc2057
commit c3ebede877
4 changed files with 34 additions and 5 deletions
@@ -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<ProblemDescriptor>? = 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) {
@@ -0,0 +1,4 @@
@com.intellij.openapi.components.Service
public class ProjectService {
public ProjectService(com.intellij.openapi.project.Project project) {}
}
@@ -0,0 +1,4 @@
@com.intellij.openapi.components.Service
public class ProjectServiceNonAllowedCtorArg {
<error descr="Service should not have constructor with parameters (except Project or Module if requested on corresponding level). To not instantiate services in constructor.">public ProjectServiceNonAllowedCtorArg(com.intellij.openapi.project.Project project, String notAllowed) {}</error>
}
@@ -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")
}
}