[java-inspections] IDEA-337706 Support conversion System.out to log calls

- support custom names for Lombok
- loggerTypeName now always returns full qualified class of logger
- `com.intellij.lang.logging.JvmLogger.Companion.getAllNamedContainingClasses` return List for compatibility with Java

GitOrigin-RevId: c07ed5bdb2f684fdc7be864d8cd7192d3ea0245c
This commit is contained in:
Mikhail Pyltsin
2024-04-02 17:57:35 +02:00
committed by intellij-monorepo-bot
parent e84bc31482
commit 206d995dcd
6 changed files with 29 additions and 16 deletions

View File

@@ -28,7 +28,7 @@ class JvmLoggerCompletionContributor : CompletionContributor() {
val availableLoggers = JvmLogger.findSuitableLoggers(module, true)
val element = parameters.originalPosition ?: return
val allPlaces = JvmLogger.getAllNamedContainingClasses(element).toList()
val allPlaces = JvmLogger.getAllNamedContainingClasses(element)
val possiblePlaces = JvmLogger.getPossiblePlacesForLogger(element, availableLoggers)
if (allPlaces.size != possiblePlaces.size) return

View File

@@ -5,19 +5,15 @@ import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.codeInsight.lookup.LookupElementPresentation
import com.intellij.lang.logging.JvmLogger
import com.intellij.lang.logging.JvmLoggerFieldDelegate
import com.intellij.openapi.components.service
import com.intellij.psi.*
import com.intellij.psi.statistics.StatisticsInfo
import com.intellij.psi.util.parentOfType
import com.intellij.ui.logging.JvmLoggingSettingsStorage
class JvmLoggerLookupElement(private val logger: JvmLogger, private val place: PsiClass) : LookupElement(), JavaCompletionStatistician.CustomStatisticsInfoProvider {
val typeName: String = logger.loggerTypeName
override fun getLookupString(): String {
val project = place.project
val settings = project.service<JvmLoggingSettingsStorage>().state
return settings.loggerName ?: JvmLoggerFieldDelegate.LOGGER_IDENTIFIER
return logger.getLogFieldName(place) ?: JvmLoggerFieldDelegate.LOGGER_IDENTIFIER
}
override fun handleInsert(context: InsertionContext) {

View File

@@ -81,6 +81,11 @@ interface JvmLogger {
*/
fun createLogger(project: Project, clazz: PsiClass): PsiElement?
/**
* @return the name of the log field for the class, or null if it is impossible to define
*/
fun getLogFieldName(clazz: PsiClass): String?
companion object {
private val EP_NAME = ExtensionPointName<JvmLogger>("com.intellij.jvm.logging")
@@ -130,8 +135,9 @@ interface JvmLogger {
* @param element the [PsiElement] from which to retrieve the nested classes
* @return [Sequence] of [PsiClass] representing the nested classes
*/
fun getAllNamedContainingClasses(element: PsiElement): Sequence<PsiClass> = element.parentsOfType(PsiClass::class.java, true)
fun getAllNamedContainingClasses(element: PsiElement): List<PsiClass> = element.parentsOfType(PsiClass::class.java, true)
.filter { clazz -> clazz !is PsiAnonymousClass && clazz !is PsiImplicitClass }
.toList()
/**
* Retrieves the possible places for inserting a logger element based on the given [element] and [loggerList].
@@ -143,7 +149,6 @@ interface JvmLogger {
*/
fun getPossiblePlacesForLogger(element: PsiElement, loggerList: List<JvmLogger>): List<PsiClass> = getAllNamedContainingClasses(element)
.filter { clazz -> isPossibleToPlaceLogger(clazz, loggerList) }
.toList()
.reversed()
private fun isPossibleToPlaceLogger(psiClass: PsiClass, loggerList: List<JvmLogger>): Boolean = loggerList.all {

View File

@@ -62,6 +62,11 @@ class JvmLoggerFieldDelegate(
}
}
override fun getLogFieldName(clazz: PsiClass): String? {
val settings = clazz.project.service<JvmLoggingSettingsStorage>().state
return settings.loggerName
}
companion object {
const val LOGGER_IDENTIFIER = "log"
}

View File

@@ -29,6 +29,8 @@ class UnspecifiedLogger : JvmLogger {
override fun createLogger(project: Project, clazz: PsiClass): PsiElement = throw UnsupportedOperationException()
override fun getLogFieldName(clazz: PsiClass): String? = null
override fun toString(): String = JavaBundle.message("java.configurable.logger.unspecified")
companion object {

View File

@@ -10,19 +10,20 @@ import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.psi.codeStyle.JavaCodeStyleManager
import de.plushnikov.intellij.plugin.processor.clazz.log.AbstractLogProcessor
import de.plushnikov.intellij.plugin.util.LombokLibraryUtil
/**
* Represents a delegate implementation of the JvmLogger interface that is used to insert loggers which are [PsiAnnotation].
* Use it to handle with Lombok loggers
* @param fieldLoggerName the fully qualified name of the logger's type.
* @param loggerTypeName the fully qualified name of annotation used to generate logger
* @param loggerTypeName the fully qualified name of the logger's type.
* @param annotationTypeName the fully qualified name of annotation used to generate logger
* @param priority the priority of the logger.
*/
class JvmLoggerAnnotationDelegate(
private val fieldLoggerName: String,
override val id: String,
override val loggerTypeName: String,
override val id: String,
private val annotationTypeName: String,
override val priority: Int
) : JvmLogger {
override fun insertLoggerAtClass(project: Project, clazz: PsiClass, logger: PsiElement): PsiElement? {
@@ -33,18 +34,22 @@ class JvmLoggerAnnotationDelegate(
override fun isAvailable(project: Project?): Boolean {
return project != null &&
JavaPsiFacade.getInstance(project).findClass(fieldLoggerName, ProjectContainingLibrariesScope.getScope(project)) != null
JavaPsiFacade.getInstance(project).findClass(loggerTypeName, ProjectContainingLibrariesScope.getScope(project)) != null
&& LombokLibraryUtil.hasLombokLibrary(project)
}
override fun isAvailable(module: Module?): Boolean {
return module != null && JavaLibraryUtil.hasLibraryClass(module, fieldLoggerName) && LombokLibraryUtil.hasLombokClasses(module)
return module != null && JavaLibraryUtil.hasLibraryClass(module, loggerTypeName) && LombokLibraryUtil.hasLombokClasses(module)
}
override fun isPossibleToPlaceLoggerAtClass(clazz: PsiClass): Boolean = clazz.hasAnnotation(loggerTypeName).not()
override fun isPossibleToPlaceLoggerAtClass(clazz: PsiClass): Boolean = clazz.hasAnnotation(annotationTypeName).not()
override fun createLogger(project: Project, clazz: PsiClass): PsiAnnotation {
val factory = JavaPsiFacade.getElementFactory(project)
return factory.createAnnotationFromText("@$loggerTypeName", clazz)
return factory.createAnnotationFromText("@$annotationTypeName", clazz)
}
override fun getLogFieldName(clazz: PsiClass): String {
return AbstractLogProcessor.getLoggerName(clazz)
}
}