[Java. Logging] Add support to prioritize loggers by their frequency of completion

IDEA-345098

GitOrigin-RevId: 0332c3732b42542d26e34da07bbe66f08c781fe9
This commit is contained in:
Georgii Ustinov
2024-02-15 17:18:38 +00:00
committed by intellij-monorepo-bot
parent 7ab815c8ac
commit 1ba530f276
3 changed files with 44 additions and 41 deletions
@@ -11,7 +11,7 @@ import com.intellij.util.Consumer
class ExcludeLoggerFromCompletionLookupActionProvider : LookupActionProvider {
override fun fillActions(lookupElement: LookupElement, lookup: Lookup, consumer: Consumer<in LookupElementAction>) {
if (lookupElement is LoggerLookupElement) {
for (s in AddImportAction.getAllExcludableStrings(lookupElement.loggerTypeName)) {
for (s in AddImportAction.getAllExcludableStrings(lookupElement.typeName)) {
consumer.consume(ExcludeFromCompletionAction(lookup.project, s))
}
}
@@ -2,16 +2,12 @@
package com.intellij.codeInsight.completion
import com.intellij.codeInsight.generation.GenerateLoggerUtil
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.lang.logging.JvmLogger
import com.intellij.lang.logging.JvmLoggerFieldDelegate
import com.intellij.openapi.module.ModuleUtil
import com.intellij.openapi.project.Project
import com.intellij.patterns.PlatformPatterns.psiElement
import com.intellij.patterns.StandardPatterns
import com.intellij.psi.*
import com.intellij.psi.util.parentOfType
import com.intellij.psi.JavaTokenType
import com.intellij.psi.PsiExpressionStatement
import com.intellij.psi.PsiJavaToken
import com.intellij.util.ProcessingContext
class JavaLoggerCompletionContributor : CompletionContributor() {
@@ -29,7 +25,6 @@ class JavaLoggerCompletionContributor : CompletionContributor() {
override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet) {
val javaResultWithSorting = JavaCompletionSorting.addJavaSorting(parameters, result)
val module = ModuleUtil.findModuleForFile(parameters.originalFile) ?: return
val project = module.project
val availableLoggers = GenerateLoggerUtil.findSuitableLoggers(module, true)
val element = parameters.originalPosition ?: return
@@ -40,39 +35,10 @@ class JavaLoggerCompletionContributor : CompletionContributor() {
val place = possiblePlaces.firstOrNull() ?: return
for (logger in availableLoggers) {
val lookupElement = buildLoggerElement(project, place, logger)
val lookupElement = LoggerLookupElement(logger, place)
javaResultWithSorting.addElement(lookupElement)
}
}
})
}
private fun buildLoggerElement(project: Project, place: PsiClass, logger: JvmLogger): LookupElement =
LoggerLookupElement(
LookupElementBuilder
.create(logger.loggerTypeName, JvmLoggerFieldDelegate.LOGGER_IDENTIFIER)
.withTailText(" ${logger.loggerTypeName}")
.withTypeText(logger.toString())
.withInsertHandler { insertionContext, _ ->
val loggerText = logger.createLogger(project, place) ?: return@withInsertHandler
logger.insertLoggerAtClass(insertionContext.project, place, loggerText)
replaceWithStaticReferenceIfCollisions(project, insertionContext, place)
},
logger.loggerTypeName
)
private fun replaceWithStaticReferenceIfCollisions(project: Project,
insertionContext: InsertionContext,
place: PsiClass) {
val file = insertionContext.file
val element = file.findElementAt(insertionContext.startOffset)?.parentOfType<PsiReferenceExpression>(false) ?: return
val resolved = element.resolve() as? PsiField
val containingClass = resolved?.containingClass
if (resolved == null || !PsiManager.getInstance(project).areElementsEquivalent(place, containingClass)) {
val factory = JavaPsiFacade.getElementFactory(project)
val className = place.qualifiedName ?: return
val staticRefExpression = factory.createExpressionFromText("$className.${JvmLoggerFieldDelegate.LOGGER_IDENTIFIER}", place)
element.replace(staticRefExpression)
}
}
}
@@ -2,6 +2,43 @@
package com.intellij.codeInsight.completion
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.codeInsight.lookup.LookupElementDecorator
import com.intellij.codeInsight.lookup.LookupElementPresentation
import com.intellij.lang.logging.JvmLogger
import com.intellij.lang.logging.JvmLoggerFieldDelegate
import com.intellij.psi.*
import com.intellij.psi.statistics.StatisticsInfo
import com.intellij.psi.util.parentOfType
class LoggerLookupElement(element: LookupElement, val loggerTypeName : String) : LookupElementDecorator<LookupElement>(element)
class LoggerLookupElement(private val logger: JvmLogger, private val place: PsiClass) : LookupElement(), JavaCompletionStatistician.CustomStatisticsInfoProvider {
val typeName: String = logger.loggerTypeName
override fun getLookupString(): String = JvmLoggerFieldDelegate.LOGGER_IDENTIFIER
override fun handleInsert(context: InsertionContext) {
val loggerText = logger.createLogger(context.project, place) ?: return
logger.insertLoggerAtClass(context.project, place, loggerText)
replaceWithStaticReferenceIfCollisions(context, place)
}
override fun renderElement(presentation: LookupElementPresentation) {
super.renderElement(presentation)
presentation.tailText = " ${logger.loggerTypeName}"
presentation.typeText = "$logger"
}
private fun replaceWithStaticReferenceIfCollisions(context: InsertionContext,
place: PsiClass) {
val file = context.file
val element = file.findElementAt(context.startOffset)?.parentOfType<PsiReferenceExpression>(false) ?: return
val resolved = element.resolve() as? PsiField
val containingClass = resolved?.containingClass
if (resolved == null || !PsiManager.getInstance(context.project).areElementsEquivalent(place, containingClass)) {
val factory = JavaPsiFacade.getElementFactory(context.project)
val className = place.qualifiedName ?: return
val staticRefExpression = factory.createExpressionFromText("$className.${JvmLoggerFieldDelegate.LOGGER_IDENTIFIER}", place)
element.replace(staticRefExpression)
}
}
override fun getStatisticsInfo(): StatisticsInfo = StatisticsInfo("Jvm logger", logger.loggerTypeName)
}