[Java. Logging] Simple logger generator implementation

IDEA-331693

GitOrigin-RevId: b7d8cfc3499501305dabfa31c6ba2957f55ea679
This commit is contained in:
Georgii Ustinov
2024-01-15 17:01:28 +02:00
committed by intellij-monorepo-bot
parent f6f404db98
commit 3891baf2cf
5 changed files with 98 additions and 33 deletions

View File

@@ -9,10 +9,15 @@ import java.util.List;
public final class JavaLoggingUtils {
public static final String JAVA_LOGGING = "java.util.logging.Logger";
public static final String JAVA_LOGGING_FACTORY = JAVA_LOGGING;
public static final String SLF4J = "org.slf4j.Logger";
public static final String SLF4J_FACTORY = "org.slf4j.LoggerFactory";
public static final String COMMONS_LOGGING = "org.apache.commons.logging.Log";
public static final String COMMONS_LOGGING_FACTORY = "org.apache.commons.logging.LogFactory";
public static final String LOG4J = "org.apache.log4j.Logger";
public static final String LOG4J_FACTORY = LOG4J;
public static final String LOG4J2 = "org.apache.logging.log4j.Logger";
public static final String LOG4J2_FACTORY = "org.apache.logging.log4j.LogManager";
public static final List<String> DEFAULT_LOGGERS = List.of(JAVA_LOGGING, SLF4J, COMMONS_LOGGING, LOG4J, LOG4J2);

View File

@@ -1,26 +0,0 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.generation
import com.intellij.codeInsight.CodeInsightActionHandler
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiFile
import com.intellij.psi.util.PsiTreeUtil
class GenerateLogFieldHandler : CodeInsightActionHandler {
override fun invoke(project: Project, editor: Editor, file: PsiFile) {
val currentElement = file.findElementAt(editor.caretModel.offset)
val nestedClasses = mutableListOf<PsiClass>()
var psiClass = PsiTreeUtil.getParentOfType(currentElement, PsiClass::class.java)
while (psiClass != null) {
nestedClasses.add(psiClass)
psiClass = PsiTreeUtil.getParentOfType(currentElement, PsiClass::class.java)
}
}
}

View File

@@ -0,0 +1,88 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.generation
import com.intellij.codeInsight.CodeInsightActionHandler
import com.intellij.java.library.JavaLibraryUtil
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.module.ModuleUtil
import com.intellij.openapi.project.Project
import com.intellij.psi.*
import com.intellij.psi.codeStyle.JavaCodeStyleManager
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi.util.PsiUtil
import com.siyeh.ig.psiutils.JavaLoggingUtils.*
class GenerateLoggerHandler : CodeInsightActionHandler {
companion object {
private val LOGGERS = listOf(
LogInfo(SLF4J, SLF4J_FACTORY, "getLogger","%s.class"),
LogInfo(COMMONS_LOGGING, COMMONS_LOGGING_FACTORY, "getLog", "%s.class"),
LogInfo(LOG4J, LOG4J_FACTORY, "getLogger", "%s.class"),
LogInfo(LOG4J2, LOG4J2_FACTORY, "getLogger", "%s.class"),
LogInfo(JAVA_LOGGING, JAVA_LOGGING_FACTORY, "getLogger", "%s.class.getName()"),
)
private const val LOGGER_IDENTIFIER = "LOGGER"
private fun isPossibleToPlaceLogger(psiClass: PsiClass) : Boolean {
for (psiField in psiClass.fields) {
if (psiField.name == LOGGER_IDENTIFIER) return false
val typeName = psiField.type.canonicalText
for (logger in LOGGERS) {
if (logger.loggerName == typeName) return false
}
}
return true
}
fun getPossiblePlacesForLogger(element : PsiElement) : List<PsiClass> {
val places = mutableListOf<PsiClass>()
var psiClass : PsiClass? = PsiTreeUtil.getParentOfType(element, PsiClass::class.java) ?: return places
while (psiClass != null) {
if (isPossibleToPlaceLogger(psiClass)) {
places.add(psiClass)
}
psiClass = PsiTreeUtil.getParentOfType(psiClass, PsiClass::class.java)
}
return places
}
}
override fun invoke(project: Project, editor: Editor, file: PsiFile) {
val currentElement = file.findElementAt(editor.caretModel.offset) ?: return
val places = getPossiblePlacesForLogger(currentElement)
val lastClass = places.lastOrNull() ?: return
val className = lastClass.name ?: return
val factory = JavaPsiFacade.getElementFactory(project)
val module = ModuleUtil.findModuleForFile(file)
for (logger in LOGGERS) {
if (JavaLibraryUtil.hasLibraryClass(module, logger.loggerName)) {
val fieldText = logger.createLoggerFieldText(className)
val field = factory.createFieldFromText(fieldText, lastClass)
PsiUtil.setModifierProperty(field, PsiModifier.STATIC, true)
PsiUtil.setModifierProperty(field, PsiModifier.FINAL, true)
PsiUtil.setModifierProperty(field, PsiModifier.PRIVATE, true)
JavaCodeStyleManager.getInstance(project).shortenClassReferences(field)
lastClass.add(field)
break
}
}
}
private class LogInfo(val loggerName : String, val factoryName : String, val methodName: String, val classNamePattern: String) {
fun createLoggerFieldText(className : String) =
"$loggerName $LOGGER_IDENTIFIER = ${factoryName}.$methodName(${String.format(classNamePattern, className)});"
}
}

View File

@@ -1,17 +1,15 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.generation.actions
import com.intellij.codeInsight.generation.GenerateLogFieldHandler
import com.intellij.codeInsight.generation.GenerateLoggerHandler
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiFile
import com.intellij.psi.util.PsiTreeUtil
class GenerateLogFieldAction : BaseGenerateAction(GenerateLogFieldHandler()) {
class GenerateLoggerAction : BaseGenerateAction(GenerateLoggerHandler()) {
override fun isValidForFile(project: Project, editor: Editor, file: PsiFile): Boolean {
val element = file.findElementAt(editor.caretModel.offset)
return PsiTreeUtil.getParentOfType(element, PsiClass::class.java) != null
val element = file.findElementAt(editor.caretModel.offset) ?: return false
return GenerateLoggerHandler.getPossiblePlacesForLogger(element).isNotEmpty()
}
}

View File

@@ -281,7 +281,7 @@
<action id="GenerateTestDataPathFiles" class="com.intellij.testIntegration.GenerateTestDataPathFileAction"/>
<separator/>
<action id="GenerateConstructor" class="com.intellij.codeInsight.generation.actions.GenerateConstructorAction"/>
<action id="GenerateLogField" class="com.intellij.codeInsight.generation.actions.GenerateLogFieldAction"/>
<action id="GenerateLogField" class="com.intellij.codeInsight.generation.actions.GenerateLoggerAction"/>
<action id="GenerateGetter" class="com.intellij.codeInsight.generation.actions.GenerateGetterAction"/>
<action id="GenerateSetter" class="com.intellij.codeInsight.generation.actions.GenerateSetterAction"/>
<action id="GenerateGetterAndSetter" class="com.intellij.codeInsight.generation.actions.GenerateGetterAndSetterAction"/>