mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 14:23:28 +07:00
[java-inspections] IDEA-331308 Similar logs inspection
GitOrigin-RevId: 33b43026b651dfee14eaa91e978c0c0c2b793ba2
This commit is contained in:
committed by
intellij-monorepo-bot
parent
da0308f481
commit
8efd59f2ec
@@ -69,6 +69,13 @@
|
||||
key="jvm.inspection.logging.placeholder.count.matches.argument.count.display.name"
|
||||
implementationClass="com.intellij.codeInspection.logging.LoggingPlaceholderCountMatchesArgumentCountInspection"/>
|
||||
<inspectionElementsMerger implementation="com.intellij.codeInspection.logging.LoggingPlaceholderCountMatchesArgumentCountInspectionMerger"/>
|
||||
<localInspection language="UAST" enabledByDefault="true" level="WEAK WARNING" shortName="LoggingSimilarMessage"
|
||||
groupBundle="messages.JvmAnalysisBundle" bundle="messages.JvmAnalysisBundle"
|
||||
groupPathKey="jvm.inspections.group.name" groupKey="jvm.inspections.logging.frameworks.group.name"
|
||||
key="jvm.inspection.logging.similar.message.display.name"
|
||||
implementationClass="com.intellij.codeInspection.logging.LoggingSimilarMessageInspection"
|
||||
runForWholeFile="true"
|
||||
/>
|
||||
|
||||
<!-- Performance -->
|
||||
<localInspection language="UAST" enabledByDefault="true" level="WARNING" shortName="UrlHashCode"
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports SLF4J, Log4j2 logging calls, such as <code>logger.info("message: {}", key)</code> with similar log messages.
|
||||
These calls can be non-distinguishable from each other, and this introduces difficulties to understand where a certain log message is from.
|
||||
<p><b>Example (for Java):</b></p>
|
||||
<pre><code lang="java">
|
||||
private static void request1(String text) {
|
||||
log.info("Message: {}", text); //similar call
|
||||
doSomething1();
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
log.info("Message: {}", i); //similar call
|
||||
doSomething2();
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
|
||||
<!-- tooltip end -->
|
||||
<p><small>New in 2024.1</small></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -173,6 +173,9 @@ jvm.inspection.logging.placeholder.count.matches.argument.count.slf4j.throwable.
|
||||
jvm.inspection.logging.placeholder.count.matches.argument.count.slf4j.throwable.option.yes=Yes
|
||||
jvm.inspection.logging.placeholder.count.matches.argument.count.slf4j.throwable.option.no=No
|
||||
|
||||
jvm.inspection.logging.similar.message.display.name=Non-distinguishable logging calls
|
||||
jvm.inspection.logging.similar.message.problem.descriptor=Similar log messages
|
||||
|
||||
jvm.inspection.logging.condition.disagrees.with.log.statement.display.name=Log condition does not match logging call
|
||||
jvm.inspection.logging.condition.disagrees.with.log.statement.problem.descriptor=Level of condition ''{0}'' does not match level of logging call ''{1}''
|
||||
|
||||
|
||||
@@ -0,0 +1,323 @@
|
||||
// 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.codeInspection.logging
|
||||
|
||||
import com.intellij.analysis.JvmAnalysisBundle
|
||||
import com.intellij.codeInspection.AbstractBaseUastLocalInspectionTool
|
||||
import com.intellij.codeInspection.LocalInspectionToolSession
|
||||
import com.intellij.codeInspection.ProblemDescriptor
|
||||
import com.intellij.codeInspection.ProblemsHolder
|
||||
import com.intellij.java.JavaBundle
|
||||
import com.intellij.java.library.JavaLibraryUtil
|
||||
import com.intellij.modcommand.ModCommand
|
||||
import com.intellij.modcommand.ModCommandQuickFix
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import com.intellij.psi.SmartPointerManager
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.uast.UastHintedVisitorAdapter
|
||||
import org.jetbrains.annotations.Nls
|
||||
import org.jetbrains.uast.*
|
||||
import org.jetbrains.uast.visitor.AbstractUastNonRecursiveVisitor
|
||||
import org.jetbrains.uast.visitor.AbstractUastVisitor
|
||||
|
||||
private const val MIN_TEXT_LENGTH = 3
|
||||
private const val MAX_PART_COUNT = 10
|
||||
|
||||
class LoggingSimilarMessageInspection : AbstractBaseUastLocalInspectionTool() {
|
||||
|
||||
//otherwise results will be inconsistent
|
||||
override fun runForWholeFile(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun buildVisitor(holder: ProblemsHolder,
|
||||
isOnTheFly: Boolean,
|
||||
session: LocalInspectionToolSession): PsiElementVisitor {
|
||||
val project = holder.project
|
||||
if (!(JavaLibraryUtil.hasLibraryClass(project, LoggingUtil.SLF4J_LOGGER) ||
|
||||
JavaLibraryUtil.hasLibraryClass(project, LoggingUtil.LOG4J_LOGGER))) {
|
||||
return PsiElementVisitor.EMPTY_VISITOR
|
||||
}
|
||||
|
||||
return UastHintedVisitorAdapter.create(holder.file.language, PlaceholderCountMatchesArgumentCountVisitor(holder),
|
||||
arrayOf(UFile::class.java), directOnly = true)
|
||||
}
|
||||
|
||||
inner class PlaceholderCountMatchesArgumentCountVisitor(
|
||||
private val holder: ProblemsHolder,
|
||||
) : AbstractUastNonRecursiveVisitor() {
|
||||
|
||||
override fun visitFile(node: UFile): Boolean {
|
||||
val calls = collectCalls(node).toMutableSet()
|
||||
if (calls.isEmpty()) return true
|
||||
val groupedCalls: List<List<UCallExpression>> = calls.groupBy { it.receiver?.tryResolve().toUElementOfType<UVariable>() }
|
||||
.toMutableMap()
|
||||
.values.map { group ->
|
||||
group.groupBy { it.methodName }.values
|
||||
}.flatten()
|
||||
val groups: List<List<MessageLog>> = groupedCalls.map { group ->
|
||||
group.map { MessageLog(it, collectParts(it, LOGGER_TYPE_SEARCHERS.mapFirst(it)).splitWithPlaceholders()) }
|
||||
.filter { log -> log.parts?.any { it.isConstant && it.text != null } ?: false }
|
||||
}
|
||||
for (group in groups) {
|
||||
if (group.size <= 1) continue
|
||||
var currentGroups: Set<List<MessageLog>> = setOf(group)
|
||||
//prefilter
|
||||
if (group.size > 5) {
|
||||
val minLength = group
|
||||
.mapNotNull { it.parts }
|
||||
.filter { it.isNotEmpty() && it[0].isConstant && it[0].text != null && it[0].text?.isNotBlank() == true }
|
||||
.minOfOrNull { it[0].text?.length ?: 0 } ?: return true
|
||||
if (minLength == 0) return true
|
||||
|
||||
currentGroups = group
|
||||
.groupBy {
|
||||
val parts = it.parts ?: return@groupBy ""
|
||||
if (parts.isEmpty()) return@groupBy ""
|
||||
val part0 = parts[0]
|
||||
if (!part0.isConstant || part0.text == null || part0.text.length < minLength) return@groupBy ""
|
||||
part0.text.substring(0, minLength)
|
||||
}
|
||||
.values
|
||||
.toSet()
|
||||
}
|
||||
for (currentGroup in currentGroups) {
|
||||
for (firstIndex in 0..currentGroup.lastIndex) {
|
||||
for (secondIndex in firstIndex + 1..currentGroup.lastIndex) {
|
||||
if (similar(currentGroup[firstIndex].parts, currentGroup[secondIndex].parts)) {
|
||||
registerProblem(holder, currentGroup[firstIndex].call, currentGroup[secondIndex].call)
|
||||
registerProblem(holder, currentGroup[secondIndex].call, currentGroup[firstIndex].call)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.visitFile(node)
|
||||
}
|
||||
|
||||
private fun collectCalls(file: UFile): Set<UCallExpression> {
|
||||
val result = mutableSetOf<UCallExpression>()
|
||||
file.accept(object : AbstractUastVisitor() {
|
||||
override fun visitCallExpression(node: UCallExpression): Boolean {
|
||||
LOGGER_TYPE_SEARCHERS.mapFirst(node) ?: return false
|
||||
result.add(node)
|
||||
return true
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private fun collectParts(node: UCallExpression, searcher: LoggerTypeSearcher?): List<LoggingStringPartEvaluator.PartHolder>? {
|
||||
if (searcher == null) return null
|
||||
val arguments = node.valueArguments
|
||||
val method = node.resolveToUElement() as? UMethod ?: return null
|
||||
val parameters = method.uastParameters
|
||||
val logStringArgument: UExpression?
|
||||
if (parameters.isEmpty() || arguments.isEmpty()) {
|
||||
logStringArgument = findMessageSetterStringArg(node, searcher) ?: return null
|
||||
}
|
||||
else {
|
||||
val index = getLogStringIndex(parameters) ?: return null
|
||||
logStringArgument = arguments[index - 1]
|
||||
}
|
||||
|
||||
return LoggingStringPartEvaluator.calculateValue(logStringArgument)
|
||||
}
|
||||
|
||||
private fun registerProblem(holder: ProblemsHolder, current: UCallExpression, other: UCallExpression) {
|
||||
val anchor = current.sourcePsi ?: return
|
||||
val otherElement = other.sourcePsi ?: return
|
||||
val commonParent = PsiTreeUtil.findCommonParent(anchor, otherElement) ?: return
|
||||
val textRange = anchor.textRange
|
||||
val delta = commonParent.textRange?.startOffset ?: return
|
||||
holder.registerProblem(commonParent, textRange.shiftLeft(delta),
|
||||
JvmAnalysisBundle.message("jvm.inspection.logging.similar.message.problem.descriptor"),
|
||||
NavigateToDuplicateFix(otherElement))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class NavigateToDuplicateFix(call: PsiElement) : ModCommandQuickFix() {
|
||||
private val myPointer = SmartPointerManager.getInstance(call.project).createSmartPsiElementPointer(call)
|
||||
|
||||
override fun getFamilyName(): @Nls String {
|
||||
return JavaBundle.message("navigate.to.duplicate.fix")
|
||||
}
|
||||
|
||||
override fun perform(project: Project, descriptor: ProblemDescriptor): ModCommand {
|
||||
val element = myPointer.element
|
||||
if (element == null) return ModCommand.nop()
|
||||
return ModCommand.select(element)
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<LoggingStringPartEvaluator.PartHolder>?.splitWithPlaceholders(): List<LoggingStringPartEvaluator.PartHolder>? {
|
||||
if (this == null) return null
|
||||
val result = mutableListOf<LoggingStringPartEvaluator.PartHolder>()
|
||||
for (partHolder in this) {
|
||||
if (partHolder.isConstant && partHolder.text != null) {
|
||||
val withoutPlaceholders = partHolder.text.split("{}")
|
||||
for ((index, clearPart) in withoutPlaceholders.withIndex()) {
|
||||
result.add(LoggingStringPartEvaluator.PartHolder(clearPart, true))
|
||||
if (index != withoutPlaceholders.lastIndex) {
|
||||
result.add(LoggingStringPartEvaluator.PartHolder(clearPart, false))
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
result.add(partHolder)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private class PartHolderIterator(private val parts: List<LoggingStringPartEvaluator.PartHolder>) {
|
||||
private var i = 0
|
||||
private var partial: String? = null
|
||||
fun hasNext(): Boolean {
|
||||
return i < parts.size
|
||||
}
|
||||
|
||||
fun isText(): Boolean {
|
||||
val partHolder = parts[i]
|
||||
return partHolder.isConstant && partHolder.text != null
|
||||
}
|
||||
|
||||
fun move() {
|
||||
i++
|
||||
partial = null
|
||||
}
|
||||
|
||||
fun current(): String? {
|
||||
val local = partial
|
||||
if (local != null) {
|
||||
return local
|
||||
}
|
||||
val partHolder = parts[i]
|
||||
return partHolder.text
|
||||
}
|
||||
|
||||
fun isFirst(): Boolean {
|
||||
return i == 0
|
||||
}
|
||||
|
||||
fun move(delta: Int) {
|
||||
partial = current()?.substring(delta)
|
||||
}
|
||||
|
||||
fun isLast(): Boolean {
|
||||
return i == parts.lastIndex
|
||||
}
|
||||
|
||||
fun previousUnknown(): Boolean {
|
||||
return if (i == 0) {
|
||||
false
|
||||
}
|
||||
else {
|
||||
val partHolder = parts[i - 1]
|
||||
!partHolder.isConstant || partHolder.text == null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private data class MessageLog(val call: UCallExpression, val parts: List<LoggingStringPartEvaluator.PartHolder>?)
|
||||
|
||||
private fun similar(first: List<LoggingStringPartEvaluator.PartHolder>?,
|
||||
second: List<LoggingStringPartEvaluator.PartHolder>?): Boolean {
|
||||
if (first == null || second == null) return false
|
||||
if (first.isEmpty() || second.isEmpty()) return false
|
||||
if (first.size >= MAX_PART_COUNT || second.size >= MAX_PART_COUNT) return false
|
||||
val firstIterator = PartHolderIterator(first)
|
||||
val secondIterator = PartHolderIterator(second)
|
||||
var intersection = 0
|
||||
while (firstIterator.hasNext() && secondIterator.hasNext()) {
|
||||
if (!firstIterator.isText()) {
|
||||
firstIterator.move()
|
||||
continue
|
||||
}
|
||||
|
||||
if (!secondIterator.isText()) {
|
||||
secondIterator.move()
|
||||
continue
|
||||
}
|
||||
|
||||
if (firstIterator.current() == secondIterator.current()) {
|
||||
intersection += firstIterator.current()?.length ?: 0
|
||||
firstIterator.move()
|
||||
secondIterator.move()
|
||||
continue
|
||||
}
|
||||
|
||||
if (firstIterator.isFirst() && secondIterator.isFirst()) {
|
||||
if (firstIterator.current()?.startsWith(secondIterator.current() ?: "") == true) {
|
||||
val delta = secondIterator.current()?.length ?: 0
|
||||
intersection += delta
|
||||
secondIterator.move()
|
||||
firstIterator.move(delta)
|
||||
continue
|
||||
}
|
||||
|
||||
if (secondIterator.current()?.startsWith(firstIterator.current() ?: "") == true) {
|
||||
val delta = firstIterator.current()?.length ?: 0
|
||||
intersection += delta
|
||||
firstIterator.move()
|
||||
secondIterator.move(delta)
|
||||
continue
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
if (firstIterator.isLast() && secondIterator.isLast()) {
|
||||
if (firstIterator.current()?.endsWith(secondIterator.current() ?: "") == true) {
|
||||
val delta = secondIterator.current()?.length ?: 0
|
||||
intersection += delta
|
||||
firstIterator.move()
|
||||
secondIterator.move()
|
||||
continue
|
||||
}
|
||||
|
||||
if (secondIterator.current()?.endsWith(firstIterator.current() ?: "") == true) {
|
||||
val delta = firstIterator.current()?.length ?: 0
|
||||
intersection += delta
|
||||
firstIterator.move()
|
||||
secondIterator.move()
|
||||
continue
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
//There can be not only included staff, but intersection.
|
||||
//This intersection is skipped deliberately because it can be used in real logs
|
||||
|
||||
if (secondIterator.previousUnknown()) {
|
||||
var delta = firstIterator.current()?.indexOf(secondIterator.current() ?: "") ?: -1
|
||||
if (delta != -1) {
|
||||
delta += secondIterator.current()?.length ?: 0
|
||||
intersection += delta
|
||||
secondIterator.move()
|
||||
firstIterator.move(delta)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if (firstIterator.previousUnknown()) {
|
||||
var delta = secondIterator.current()?.indexOf(firstIterator.current() ?: "") ?: -1
|
||||
if (delta != -1) {
|
||||
delta += firstIterator.current()?.length ?: 0
|
||||
intersection += delta
|
||||
firstIterator.move()
|
||||
secondIterator.move(delta)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return intersection >= MIN_TEXT_LENGTH
|
||||
}
|
||||
@@ -22,7 +22,13 @@ internal class LoggingStringPartEvaluator {
|
||||
companion object {
|
||||
fun calculateValue(expression: UExpression): List<PartHolder>? {
|
||||
if (!isString(expression)) return null
|
||||
return tryJoin(recursiveCalculateValue(expression, Context(depth = 10, maxParts = 20)))
|
||||
val sourcePsi = expression.sourcePsi ?: return null
|
||||
val project = sourcePsi.project
|
||||
return CachedValuesManager.getManager(project).getCachedValue(sourcePsi, CachedValueProvider {
|
||||
return@CachedValueProvider CachedValueProvider.Result.create(
|
||||
tryJoin(recursiveCalculateValue(sourcePsi.toUElementOfType<UExpression>(), Context(depth = 10, maxParts = 20))),
|
||||
PsiModificationTracker.MODIFICATION_COUNT)
|
||||
})
|
||||
}
|
||||
|
||||
private fun recursiveCalculateValue(expression: UExpression?,
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.intellij.jvm.analysis.internal.testFramework.logging
|
||||
|
||||
import com.intellij.codeInspection.logging.LoggingSimilarMessageInspection
|
||||
|
||||
abstract class LoggingSimilarMessageInspectionTestBase : LoggingInspectionTestBase() {
|
||||
override val inspection = LoggingSimilarMessageInspection()
|
||||
}
|
||||
@@ -0,0 +1,501 @@
|
||||
package com.intellij.codeInspection.tests.java.logging
|
||||
|
||||
import com.intellij.jvm.analysis.internal.testFramework.logging.LoggingSimilarMessageInspectionTestBase
|
||||
import com.intellij.jvm.analysis.testFramework.JvmLanguage
|
||||
|
||||
class JavaLoggingSimilarMessageInspectionTest : LoggingSimilarMessageInspectionTestBase() {
|
||||
|
||||
fun `test equals log4j2`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.apache.logging.log4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
|
||||
private static void request1(String i) {
|
||||
String msg = "log messages: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
String msg = "log messages: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun `test not completed log4j2`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.apache.logging.log4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
|
||||
private static void request1(String i) {
|
||||
String msg = "{}" + i;
|
||||
LOG.info(msg);
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
String msg = "{}" + i;
|
||||
LOG.info(msg);
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun `test not completed 2 log4j2`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.apache.logging.log4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
|
||||
private static void request1(String i) {
|
||||
String msg = "{} {}";
|
||||
LOG.info(msg);
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
String msg = "{} {}";
|
||||
LOG.info(msg);
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun `test many equals log4j2`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.apache.logging.log4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
|
||||
private static void request1(String i) {
|
||||
String msg = "log messages2: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
String msg = "log messages: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request3(int i) {
|
||||
String msg = "log messages2: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request4(int i) {
|
||||
String msg = "log messages: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request5(int i) {
|
||||
String msg = "log messages: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request6(int i) {
|
||||
String msg = "log messages: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request7(int i) {
|
||||
String msg = "log messages: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request8(int i) {
|
||||
String msg = "log messages: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request9(int i) {
|
||||
String msg = "log messages: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request10(int i) {
|
||||
String msg = "log messages: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun `test equals slf4j`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.slf4j.*;
|
||||
class Logging {
|
||||
private static Logger LOG = LoggerFactory.getLogger(Logging.class);
|
||||
|
||||
private static void request1(String i) {
|
||||
String msg = "log messages: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
String msg = "log messages: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
|
||||
fun `test setMessage equals slf4j`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.slf4j.*;
|
||||
class Logging {
|
||||
private static Logger LOG = LoggerFactory.getLogger(Logging.class);
|
||||
|
||||
private static void request1(String i) {
|
||||
String msg = "log messages: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
String msg = "log messages: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun `test not equals level slf4j`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.slf4j.*;
|
||||
import org.slf4j.spi.*;
|
||||
class X {
|
||||
|
||||
void foo() {
|
||||
Logger logger = LoggerFactory.getLogger(X.class);
|
||||
|
||||
<weak_warning descr="Similar log messages">logger.atError()
|
||||
.setMessage("aaa {}")
|
||||
.log()</weak_warning>;
|
||||
|
||||
<weak_warning descr="Similar log messages">logger.atError()
|
||||
.setMessage("aaa 2{}")
|
||||
.log()</weak_warning>;
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun `test not equals log4j2`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.apache.logging.log4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
|
||||
private static void request1(String i) {
|
||||
String msg = "log 2 messages: " + i;
|
||||
LOG.info(msg);
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
String msg = "log messages: " + i;
|
||||
LOG.info(msg);
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun `test not equals end log4j2`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.apache.logging.log4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
|
||||
private static void request1(String i) {
|
||||
String msg = i + ": log 2 messages";
|
||||
LOG.info(msg);
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
String msg = i + ": log messages";
|
||||
LOG.info(msg);
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun `test endWith log4j2`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.apache.logging.log4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
|
||||
private static void request1(String i) {
|
||||
String msg = i + "2: log messages";
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
String msg = i + ": log messages";
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun `test endWith2 log4j2`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.apache.logging.log4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
|
||||
private static void request1(String i) {
|
||||
String msg = i + ": log messages";
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
String msg = i + "2: log messages";
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun `test startWith log4j2`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.apache.logging.log4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
|
||||
private static void request1(String i) {
|
||||
String msg = "log messages" + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
String msg = "log messages2" + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun `test startWith 2 log4j2`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.apache.logging.log4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
|
||||
private static void request1(String i) {
|
||||
String msg = "log messages2" + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
String msg = "log messages" + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun `test equals end log4j2`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.apache.logging.log4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
|
||||
private static void request1(String i) {
|
||||
String msg = i + ": log messages";
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
String msg = i + ": log messages";
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun `test many equals end log4j2 without highlighting`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.apache.logging.log4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
|
||||
private static void request1(String i) {
|
||||
String msg = i + ": log messages";
|
||||
LOG.info(msg);
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
String msg = i + ": log messages";
|
||||
LOG.info(msg);
|
||||
}
|
||||
private static void request3(int i) {
|
||||
String msg = i + ": log messages";
|
||||
LOG.info(msg);
|
||||
}
|
||||
private static void request4(int i) {
|
||||
String msg = i + ": log messages";
|
||||
LOG.info(msg);
|
||||
}
|
||||
private static void request5(int i) {
|
||||
String msg = i + ": log messages";
|
||||
LOG.info(msg);
|
||||
}
|
||||
private static void request6(int i) {
|
||||
String msg = i + ": log messages";
|
||||
LOG.info(msg);
|
||||
}
|
||||
private static void request7(int i) {
|
||||
String msg = i + ": log messages";
|
||||
LOG.info(msg);
|
||||
}
|
||||
private static void request8(int i) {
|
||||
String msg = i + ": log messages";
|
||||
LOG.info(msg);
|
||||
}
|
||||
private static void request9(int i) {
|
||||
String msg = i + ": log messages";
|
||||
LOG.info(msg);
|
||||
}
|
||||
|
||||
private static void request10(int i) {
|
||||
String msg = i + ": log messages";
|
||||
LOG.info(msg);
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun `test equals middle log4j2`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.apache.logging.log4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
|
||||
private static void request1(String i) {
|
||||
String msg = i + ": log messages: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
String msg = i + ": log messages: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun `test equals middle contains log4j2`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.apache.logging.log4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
|
||||
private static void request1(String i) {
|
||||
String msg = i + ": log messages: 2" + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
String msg = i + ": log messages: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun `test equals middle contains 2 log4j2`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.apache.logging.log4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
|
||||
private static void request1(String i) {
|
||||
String msg = i + ": log messages: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
String msg = i + ": log messages: 2" + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun `test equals middle contains 3 log4j2`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.apache.logging.log4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
|
||||
private static void request1(String i) {
|
||||
String msg = i + "2: log messages: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
String msg = i + ": log messages:" + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun `test equals middle contains 4 log4j2`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.apache.logging.log4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
|
||||
private static void request1(String i) {
|
||||
String msg = i + ": log messages:" + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
String msg = i + "2: log messages:" + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info(msg)</weak_warning>;
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun `test not equals middle log4j2`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.apache.logging.log4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
|
||||
private static void request1(String i) {
|
||||
String msg = i + ": log messages: " + i;
|
||||
LOG.info(msg);
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
String msg = i + ": log 2 messages: " + i;
|
||||
LOG.info(msg);
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun `test equals log4j2 with placeholders`() {
|
||||
myFixture.testHighlighting(JvmLanguage.JAVA, """
|
||||
import org.apache.logging.log4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
|
||||
private static void request1(String i) {
|
||||
<weak_warning descr="Similar log messages">LOG.info("log messages: ", i)</weak_warning>;
|
||||
}
|
||||
|
||||
private static void request2(int i) {
|
||||
String msg = "log messages: " + i;
|
||||
<weak_warning descr="Similar log messages">LOG.info("log messages: ", i)</weak_warning>;
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.intellij.codeInspection.tests.kotlin.logging
|
||||
|
||||
import com.intellij.jvm.analysis.internal.testFramework.logging.LoggingSimilarMessageInspectionTestBase
|
||||
import com.intellij.jvm.analysis.testFramework.JvmLanguage
|
||||
|
||||
class KotlinLoggingSimilarMessageInspectionTest : LoggingSimilarMessageInspectionTestBase() {
|
||||
|
||||
fun `test equals log4j2`() {
|
||||
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import org.apache.logging.log4j.Logger
|
||||
|
||||
internal class Logging {
|
||||
private val logger: Logger = LogManager.getLogger()
|
||||
|
||||
private fun request1(i: String) {
|
||||
val msg = "log messages: {}"
|
||||
logger.<weak_warning descr="Similar log messages">info(msg, i)</weak_warning>
|
||||
}
|
||||
|
||||
private fun request2(i: Int) {
|
||||
val msg = "log messages: {}"
|
||||
logger.<weak_warning descr="Similar log messages">info(msg, i)</weak_warning>
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun `test equals slf4j`() {
|
||||
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
internal class Logging {
|
||||
private val LOG: Logger = LoggerFactory.getLogger(Logging::class.<error descr="[UNRESOLVED_REFERENCE] Unresolved reference: java">java</error>)
|
||||
|
||||
private fun request1(i: String) {
|
||||
val msg = "log messages: {}"
|
||||
LOG.<weak_warning descr="Similar log messages">info(msg, i)</weak_warning>
|
||||
LOG.info("1" + msg, i)
|
||||
}
|
||||
|
||||
private fun request2(i: Int) {
|
||||
val msg = "log messages: {}"
|
||||
LOG.<weak_warning descr="Similar log messages">info(msg, i)</weak_warning>
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user