From 1ba530f276b841b68c28577396eda7b4a8caa20f Mon Sep 17 00:00:00 2001 From: Georgii Ustinov Date: Thu, 15 Feb 2024 15:54:19 +0200 Subject: [PATCH] [Java. Logging] Add support to prioritize loggers by their frequency of completion IDEA-345098 GitOrigin-RevId: 0332c3732b42542d26e34da07bbe66f08c781fe9 --- ...oggerFromCompletionLookupActionProvider.kt | 2 +- .../JavaLoggerCompletionContributor.kt | 42 ++----------------- .../completion/LoggerLookupElement.kt | 41 +++++++++++++++++- 3 files changed, 44 insertions(+), 41 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ExcludeLoggerFromCompletionLookupActionProvider.kt b/java/java-impl/src/com/intellij/codeInsight/completion/ExcludeLoggerFromCompletionLookupActionProvider.kt index 86b035b5d238..49ed93d4d2d3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ExcludeLoggerFromCompletionLookupActionProvider.kt +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ExcludeLoggerFromCompletionLookupActionProvider.kt @@ -11,7 +11,7 @@ import com.intellij.util.Consumer class ExcludeLoggerFromCompletionLookupActionProvider : LookupActionProvider { override fun fillActions(lookupElement: LookupElement, lookup: Lookup, consumer: Consumer) { if (lookupElement is LoggerLookupElement) { - for (s in AddImportAction.getAllExcludableStrings(lookupElement.loggerTypeName)) { + for (s in AddImportAction.getAllExcludableStrings(lookupElement.typeName)) { consumer.consume(ExcludeFromCompletionAction(lookup.project, s)) } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaLoggerCompletionContributor.kt b/java/java-impl/src/com/intellij/codeInsight/completion/JavaLoggerCompletionContributor.kt index effab93a8365..86421aa3e5f2 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaLoggerCompletionContributor.kt +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaLoggerCompletionContributor.kt @@ -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(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) - } - } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/LoggerLookupElement.kt b/java/java-impl/src/com/intellij/codeInsight/completion/LoggerLookupElement.kt index f29bd206ed15..0f2040825858 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/LoggerLookupElement.kt +++ b/java/java-impl/src/com/intellij/codeInsight/completion/LoggerLookupElement.kt @@ -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(element) \ No newline at end of file +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(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) +} \ No newline at end of file