diff --git a/jvm/jvm-analysis-impl/src/com/intellij/analysis/customization/console/ClassFinderFilter.kt b/jvm/jvm-analysis-impl/src/com/intellij/analysis/customization/console/ClassFinderFilter.kt index bfe60f950abe..8fd0ba0f7c87 100644 --- a/jvm/jvm-analysis-impl/src/com/intellij/analysis/customization/console/ClassFinderFilter.kt +++ b/jvm/jvm-analysis-impl/src/com/intellij/analysis/customization/console/ClassFinderFilter.kt @@ -103,13 +103,18 @@ internal class ClassFinderFilter(private val myProject: Project, myScope: Global endExclusive: Int, cache: ClassInfoCache, result: MutableList) { - 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 diff --git a/jvm/jvm-analysis-impl/src/com/intellij/analysis/customization/console/ClassInfoCache.kt b/jvm/jvm-analysis-impl/src/com/intellij/analysis/customization/console/ClassInfoCache.kt index c42c1256fc34..f5f4b3af9d75 100644 --- a/jvm/jvm-analysis-impl/src/com/intellij/analysis/customization/console/ClassInfoCache.kt +++ b/jvm/jvm-analysis-impl/src/com/intellij/analysis/customization/console/ClassInfoCache.kt @@ -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) diff --git a/jvm/jvm-analysis-impl/src/com/intellij/analysis/customization/console/LogFinderHyperlinkHandler.kt b/jvm/jvm-analysis-impl/src/com/intellij/analysis/customization/console/LogFinderHyperlinkHandler.kt index 982e3c3e3601..c96da319b550 100644 --- a/jvm/jvm-analysis-impl/src/com/intellij/analysis/customization/console/LogFinderHyperlinkHandler.kt +++ b/jvm/jvm-analysis-impl/src/com/intellij/analysis/customization/console/LogFinderHyperlinkHandler.kt @@ -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 diff --git a/jvm/jvm-analysis-impl/src/com/intellij/codeInspection/logging/LoggingPlaceholderUtil.kt b/jvm/jvm-analysis-impl/src/com/intellij/codeInspection/logging/LoggingPlaceholderUtil.kt index bc87ba83d0ff..dbf47beb03fe 100644 --- a/jvm/jvm-analysis-impl/src/com/intellij/codeInspection/logging/LoggingPlaceholderUtil.kt +++ b/jvm/jvm-analysis-impl/src/com/intellij/codeInspection/logging/LoggingPlaceholderUtil.kt @@ -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) {