[java-console] IJ-CR-123098 IDEA-331307 Provide navigation for logs for jvm languages

- less allocations
- comments

GitOrigin-RevId: 02fed5473324e7a6414e2ae5a3d34f082ecf10ab
This commit is contained in:
Mikhail Pyltsin
2024-01-19 18:36:01 +01:00
committed by intellij-monorepo-bot
parent 54b20aa15d
commit e50079fc6b
4 changed files with 34 additions and 16 deletions

View File

@@ -103,13 +103,18 @@ internal class ClassFinderFilter(private val myProject: Project, myScope: Global
endExclusive: Int,
cache: ClassInfoCache,
result: MutableList<ProbableClassName>) {
val fullClassName = line.substring(startInclusive, endExclusive).removeSuffix(".")
var actualEndExclusive = endExclusive
if (actualEndExclusive > 0 && line[actualEndExclusive - 1] == '.') {
actualEndExclusive--
}
val fullClassName = line.substring(startInclusive, actualEndExclusive)
if (canBeShortenedFullyQualifiedClassName(fullClassName) && isJavaStyle(fullClassName)) {
val packageName = StringUtil.getPackageName(fullClassName)
val className = fullClassName.substring(packageName.length + 1)
val resolvedClasses = cache.resolveClasses(className, packageName)
if (resolvedClasses.classes.isNotEmpty()) {
val probableClassName = ProbableClassName(startInclusive + fullClassName.lastIndexOf(".") + 1, startInclusive + fullClassName.length,
val probableClassName = ProbableClassName(startInclusive + fullClassName.lastIndexOf(".") + 1,
startInclusive + fullClassName.length,
line, className, packageName, resolvedClasses.classes.values.toList())
result.add(probableClassName)
}
@@ -117,20 +122,25 @@ internal class ClassFinderFilter(private val myProject: Project, myScope: Global
}
private fun isJavaStyle(shortenedClassName: String): Boolean {
val packageName = StringUtil.getPackageName(shortenedClassName)
val className = shortenedClassName.substring(packageName.length + 1)
return !className.contains("_") &&
!packageName.contains("_") &&
className.isNotEmpty() && packageName.isNotEmpty() &&
Character.isUpperCase(className[0]) &&
Character.isLowerCase(packageName[0])
if (shortenedClassName.isEmpty()) return false
val indexOfSeparator = shortenedClassName.lastIndexOf('.')
if (indexOfSeparator <= 0 || indexOfSeparator == shortenedClassName.lastIndex) return false
return !shortenedClassName.contains("_") &&
Character.isUpperCase(shortenedClassName[indexOfSeparator + 1]) &&
Character.isLowerCase(shortenedClassName[0])
}
private fun canBeShortenedFullyQualifiedClassName(fullClassName: String): Boolean {
val parts = fullClassName.split(".")
for (part in parts) {
if (part.isEmpty() || !StringUtil.isJavaIdentifier(part)) {
return false
var length = 0
for (c in fullClassName) {
if (c == '.') {
if (length == 0) {
return false
}
length = 0
}
else {
length++
}
}
return true

View File

@@ -32,6 +32,14 @@ class ClassInfoCache(val project: Project, private val mySearchScope: GlobalSear
return result.toList()
}
/**
* @param clazz The class to check.
* @param targetPackageName The target package name.
* @return True, if clazz package can be shortened to targetPackageName, false otherwise.
* There are two popular ways to shorten:
* 1. Keep only n last characters of the package: aaa.bbb.ccc -> b.ccc
* 2. Keep only the first n characters of each directory: aaa.bbb.ccc -> a.b.cc
*/
private fun canBeShortenedPackages(clazz: PsiClass, targetPackageName: String): Boolean {
val qualifiedName = clazz.qualifiedName ?: return false
val actualPackageName = StringUtil.getPackageName(qualifiedName)

View File

@@ -19,7 +19,6 @@ import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiRecursiveElementVisitor
import org.jetbrains.annotations.Nls
import org.jetbrains.uast.*
internal class LogFinderHyperlinkHandler(private val probableClassName: ProbableClassName) : HyperlinkInfoFactory.HyperlinkHandler {
@@ -91,7 +90,7 @@ internal class LogFinderHyperlinkHandler(private val probableClassName: Probable
return StringUtil.shortenTextWithEllipsis(container, 40, 10)
}
@Nls
@NlsSafe
private fun getText(element: PsiElement): String {
val text = element.text
val document = PsiDocumentManager.getInstance(element.getProject()).getDocument(element.containingFile) ?: return text

View File

@@ -2,6 +2,7 @@
package com.intellij.codeInspection.logging
import com.intellij.psi.PsiVariable
import com.intellij.psi.SyntheticElement
import com.siyeh.ig.callMatcher.CallMapper
import com.siyeh.ig.callMatcher.CallMatcher
import com.siyeh.ig.psiutils.TypeUtils
@@ -80,7 +81,7 @@ private val LOG4J_HOLDER = object : LoggerTypeSearcher {
val target: UVariable = resolvedToUElement as? UVariable ?: return null
val sourcePsi = target.sourcePsi as? PsiVariable
// for lombok or other annotation generators. LOG4J_OLD_STYLE is the most common decision for that
if (sourcePsi != null && !sourcePsi.isPhysical) {
if (sourcePsi is SyntheticElement) {
return PlaceholderLoggerType.LOG4J_OLD_STYLE
}
if (!target.isFinal) {