diff --git a/platform/platform-api/src/com/intellij/ide/HelpTooltip.kt b/platform/platform-api/src/com/intellij/ide/HelpTooltip.kt
index 07dba95bd40d..68bcf869a39d 100644
--- a/platform/platform-api/src/com/intellij/ide/HelpTooltip.kt
+++ b/platform/platform-api/src/com/intellij/ide/HelpTooltip.kt
@@ -13,5 +13,6 @@ import javax.swing.JComponent
* prefer using [HtmlChunk.text] to avoid accidental HTML injections.
*/
fun JComponent.setToolTipText(html: HtmlChunk?) {
+ @Suppress("UseHtmlChunkToolTip")
this.toolTipText = html?.toString()
}
\ No newline at end of file
diff --git a/plugins/devkit/devkit-core/resources/inspectionDescriptions/UseHtmlChunkToolTip.html b/plugins/devkit/devkit-core/resources/inspectionDescriptions/UseHtmlChunkToolTip.html
new file mode 100644
index 000000000000..08d75307fbb9
--- /dev/null
+++ b/plugins/devkit/devkit-core/resources/inspectionDescriptions/UseHtmlChunkToolTip.html
@@ -0,0 +1,23 @@
+
+
+Reports usages of JComponent.setToolTipText(String).
+
+ Passing raw strings may cause accidental HTML injections because IntelliJ Platform interprets HTML markup when renders the tooltip text.
+ com.intellij.ide.HelpTooltipKt.setToolTipText(HtmlChunk) should be used instead of
+ JComponent.setToolTipText(String).
+ Use HtmlChunk.text() to safely escape text, especially in cases when text can contain user input
+ or project content (for example, file names).
+ Or use HtmlChunk.raw() if the tooltip supposes to contain HTML.
+
+
+ Example:
+
+
+// Bad — raw string may contain HTML injection:
+component.setToolTipText(text)
+
+// Good — text is escaped:
+component.setToolTipText(HtmlChunk.text(text))
+
+
+
\ No newline at end of file
diff --git a/plugins/devkit/devkit-core/resources/intellij.devkit.core.xml b/plugins/devkit/devkit-core/resources/intellij.devkit.core.xml
index b570c596b028..c8164008ca41 100644
--- a/plugins/devkit/devkit-core/resources/intellij.devkit.core.xml
+++ b/plugins/devkit/devkit-core/resources/intellij.devkit.core.xml
@@ -253,6 +253,12 @@
enabledByDefault="true" level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.UseIntelliJVirtualThreadsInspection"
key="inspection.use.intellij.virtual.threads.display.name"/>
+
+
@@ -830,6 +839,12 @@
+
+
+
diff --git a/plugins/devkit/devkit-core/resources/messages/DevKitBundle.properties b/plugins/devkit/devkit-core/resources/messages/DevKitBundle.properties
index d884546240df..0a1e0387874a 100644
--- a/plugins/devkit/devkit-core/resources/messages/DevKitBundle.properties
+++ b/plugins/devkit/devkit-core/resources/messages/DevKitBundle.properties
@@ -850,6 +850,11 @@ inspection.use.intellij.virtual.threads.display.name=Use 'IntelliJVirtualThreads
inspection.use.intellij.virtual.threads.message=Use 'IntelliJVirtualThreads.ofVirtual()' instead of 'Thread.ofVirtual()'
inspection.use.intellij.virtual.threads.fix.family.name=Replace with 'IntelliJVirtualThreads.ofVirtual()'
+inspection.use.html.chunk.tooltip.display.name=Use 'setToolTipText(HtmlChunk)' to avoid HTML injections
+inspections.use.html.chunk.tooltip.message='JComponent.setToolTipText(String)' used instead of safe 'setToolTipText(HtmlChunk)'
+inspections.use.html.chunk.tooltip.fix.wrap.text.family.name=Wrap with 'HtmlChunk.text()'
+inspections.use.html.chunk.tooltip.fix.wrap.raw.family.name=Wrap with 'HtmlChunk.raw()'
+
category.platform.title=IntelliJ Platform
category.platform.description=APIs provided by IntelliJ Platform modules
category.plugins.title=Plugins
diff --git a/plugins/devkit/devkit-core/src/inspections/UseHtmlChunkToolTipInspection.kt b/plugins/devkit/devkit-core/src/inspections/UseHtmlChunkToolTipInspection.kt
new file mode 100644
index 000000000000..31e7b880ee10
--- /dev/null
+++ b/plugins/devkit/devkit-core/src/inspections/UseHtmlChunkToolTipInspection.kt
@@ -0,0 +1,85 @@
+// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package org.jetbrains.idea.devkit.inspections
+
+import com.intellij.codeInspection.LocalQuickFix
+import com.intellij.codeInspection.ProblemsHolder
+import com.intellij.psi.CommonClassNames
+import com.intellij.psi.PsiElementVisitor
+import com.intellij.psi.PsiMethod
+import com.intellij.psi.util.InheritanceUtil
+import com.intellij.uast.UastHintedVisitorAdapter
+import org.jetbrains.idea.devkit.DevKitBundle
+import org.jetbrains.idea.devkit.inspections.quickfix.UseHtmlChunkToolTipFixProviders
+import org.jetbrains.uast.UBinaryExpression
+import org.jetbrains.uast.UCallExpression
+import org.jetbrains.uast.UElement
+import org.jetbrains.uast.UExpression
+import org.jetbrains.uast.ULiteralExpression
+import org.jetbrains.uast.UastBinaryOperator
+import org.jetbrains.uast.visitor.AbstractUastNonRecursiveVisitor
+
+/**
+ * Reports usages of [javax.swing.JComponent.setToolTipText] with a [String] argument
+ * and suggests using [com.intellij.ide.setToolTipText] to prevent accidental HTML injections.
+ *
+ * Detects both explicit method calls (`comp.setToolTipText(text)`) and
+ * Kotlin property-style setters (`comp.toolTipText = text`).
+ */
+internal class UseHtmlChunkToolTipInspection : DevKitUastInspectionBase() {
+ override fun isAllowed(holder: ProblemsHolder): Boolean {
+ return DevKitInspectionUtil.isAllowed(holder.file) &&
+ DevKitInspectionUtil.isClassAvailable(holder, HTML_CHUNK_FQN) &&
+ DevKitInspectionUtil.isClassAvailable(holder, HELP_TOOLTIP_KT_FQN)
+ }
+
+ override fun buildInternalVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
+ return UastHintedVisitorAdapter.create(holder.file.language, object : AbstractUastNonRecursiveVisitor() {
+ override fun visitCallExpression(node: UCallExpression): Boolean {
+ if (node.methodName != SET_TIP_TEXT_METHOD_NAME) return super.visitCallExpression(node)
+ val method = node.resolve() ?: return super.visitCallExpression(node)
+ if (!isSetToolTipTextOnJComponent(method)) return super.visitCallExpression(node)
+ if (isNullLiteral(node.valueArguments.firstOrNull())) return super.visitCallExpression(node)
+
+ val psi = node.sourcePsi ?: return super.visitCallExpression(node)
+ registerProblem(psi)
+ return super.visitCallExpression(node)
+ }
+
+ override fun visitBinaryExpression(node: UBinaryExpression): Boolean {
+ if (node.operator != UastBinaryOperator.ASSIGN) return super.visitBinaryExpression(node)
+ val method = node.resolveOperator() ?: return super.visitBinaryExpression(node)
+ if (method.name != SET_TIP_TEXT_METHOD_NAME) return super.visitBinaryExpression(node)
+ if (!isSetToolTipTextOnJComponent(method)) return super.visitBinaryExpression(node)
+ if (isNullLiteral(node.rightOperand)) return super.visitBinaryExpression(node)
+
+ val psi = node.sourcePsi ?: return super.visitBinaryExpression(node)
+ registerProblem(psi)
+ return super.visitBinaryExpression(node)
+ }
+
+ private fun registerProblem(psi: com.intellij.psi.PsiElement) {
+ val fixProvider = UseHtmlChunkToolTipFixProviders.forLanguage(psi.language)
+ val fixes = fixProvider?.createFixes(psi) ?: LocalQuickFix.EMPTY_ARRAY
+ holder.registerProblem(psi, DevKitBundle.message("inspections.use.html.chunk.tooltip.message"), *fixes)
+ }
+ }, HINTS)
+ }
+}
+
+private const val SET_TIP_TEXT_METHOD_NAME = "setToolTipText"
+private const val JCOMPONENT_FQN = "javax.swing.JComponent"
+private const val HTML_CHUNK_FQN = "com.intellij.openapi.util.text.HtmlChunk"
+private const val HELP_TOOLTIP_KT_FQN = "com.intellij.ide.HelpTooltipKt"
+
+private val HINTS: Array> = arrayOf(UCallExpression::class.java, UBinaryExpression::class.java)
+
+private fun isNullLiteral(expr: UExpression?): Boolean {
+ return expr is ULiteralExpression && expr.isNull
+}
+
+private fun isSetToolTipTextOnJComponent(method: PsiMethod): Boolean {
+ val clazz = method.containingClass ?: return false
+ if (!InheritanceUtil.isInheritor(clazz, JCOMPONENT_FQN)) return false
+ val params = method.parameterList.parameters
+ return params.size == 1 && params[0].type.canonicalText == CommonClassNames.JAVA_LANG_STRING
+}
diff --git a/plugins/devkit/devkit-core/src/inspections/quickfix/UseHtmlChunkToolTipFixProvider.kt b/plugins/devkit/devkit-core/src/inspections/quickfix/UseHtmlChunkToolTipFixProvider.kt
new file mode 100644
index 000000000000..e1ec72b30741
--- /dev/null
+++ b/plugins/devkit/devkit-core/src/inspections/quickfix/UseHtmlChunkToolTipFixProvider.kt
@@ -0,0 +1,65 @@
+// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package org.jetbrains.idea.devkit.inspections.quickfix
+
+import com.intellij.codeInsight.intention.PriorityAction
+import com.intellij.codeInsight.intention.PriorityAction.Priority
+import com.intellij.codeInspection.LocalQuickFix
+import com.intellij.codeInspection.ProblemDescriptor
+import com.intellij.codeInspection.util.IntentionFamilyName
+import com.intellij.lang.LanguageExtension
+import com.intellij.openapi.extensions.ExtensionPointName
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.util.IntellijInternalApi
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiElementFactory
+import com.intellij.psi.PsiMethodCallExpression
+import com.intellij.psi.codeStyle.JavaCodeStyleManager
+import org.jetbrains.annotations.ApiStatus
+import org.jetbrains.idea.devkit.DevKitBundle
+
+private val EP_NAME = ExtensionPointName.create("DevKit.lang.useHtmlChunkToolTipFixProvider")
+
+internal object UseHtmlChunkToolTipFixProviders : LanguageExtension(EP_NAME.name)
+
+@IntellijInternalApi
+@ApiStatus.Internal
+interface UseHtmlChunkToolTipFixProvider {
+ fun createFixes(element: PsiElement): Array
+}
+
+private const val SET_TOOLTIP_TEXT_METHOD_FQN = "com.intellij.ide.HelpTooltipKt.setToolTipText"
+private const val HTML_CHUNK_FQN = "com.intellij.openapi.util.text.HtmlChunk"
+
+internal class JavaUseHtmlChunkToolTipFixProvider : UseHtmlChunkToolTipFixProvider {
+ override fun createFixes(element: PsiElement): Array {
+ return arrayOf(
+ JavaWrapWithHtmlChunkFix("text", "inspections.use.html.chunk.tooltip.fix.wrap.text.family.name", Priority.TOP),
+ JavaWrapWithHtmlChunkFix("raw", "inspections.use.html.chunk.tooltip.fix.wrap.raw.family.name", Priority.HIGH),
+ )
+ }
+}
+
+/**
+ * Replaces `comp.setToolTipText(arg)` with `HelpTooltipKt.setToolTipText(comp, HtmlChunk.text/raw(arg))`.
+ */
+private class JavaWrapWithHtmlChunkFix(
+ private val wrapMethodName: String,
+ private val familyNameKey: String,
+ private val fixPriority: Priority,
+) : LocalQuickFix, PriorityAction {
+ override fun getPriority(): Priority = fixPriority
+
+ @IntentionFamilyName
+ override fun getFamilyName(): String = DevKitBundle.message(familyNameKey)
+
+ override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
+ val callExpr = descriptor.psiElement as? PsiMethodCallExpression ?: return
+ val qualifierExpr = callExpr.methodExpression.qualifierExpression ?: return
+ val arg = callExpr.argumentList.expressions.firstOrNull() ?: return
+
+ val newText = "$SET_TOOLTIP_TEXT_METHOD_FQN(${qualifierExpr.text}, $HTML_CHUNK_FQN.$wrapMethodName(${arg.text}))"
+ val newExpr = PsiElementFactory.getInstance(project).createExpressionFromText(newText, callExpr)
+ val replaced = callExpr.replace(newExpr)
+ JavaCodeStyleManager.getInstance(project).shortenClassReferences(replaced)
+ }
+}
diff --git a/plugins/devkit/devkit-java-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithString.java b/plugins/devkit/devkit-java-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithString.java
new file mode 100644
index 000000000000..2f1bf3bfbc28
--- /dev/null
+++ b/plugins/devkit/devkit-java-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithString.java
@@ -0,0 +1,11 @@
+import javax.swing.*;
+
+class SetToolTipTextWithString {
+ void test(JComponent comp) {
+ comp.setToolTipText("hello");
+ comp.setToolTipText(getString());
+ comp.setToolTipText(null);
+ }
+
+ String getString() { return ""; }
+}
diff --git a/plugins/devkit/devkit-java-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFix.java b/plugins/devkit/devkit-java-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFix.java
new file mode 100644
index 000000000000..838dbd0c2f69
--- /dev/null
+++ b/plugins/devkit/devkit-java-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFix.java
@@ -0,0 +1,7 @@
+import javax.swing.*;
+
+class SetToolTipTextWithStringFix {
+ void test(JComponent comp) {
+ comp.setToolTipText("hello");
+ }
+}
diff --git a/plugins/devkit/devkit-java-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFixRaw.java b/plugins/devkit/devkit-java-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFixRaw.java
new file mode 100644
index 000000000000..d00e7a357ab1
--- /dev/null
+++ b/plugins/devkit/devkit-java-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFixRaw.java
@@ -0,0 +1,7 @@
+import javax.swing.*;
+
+class SetToolTipTextWithStringFixRaw {
+ void test(JComponent comp) {
+ comp.setToolTipText("hello");
+ }
+}
diff --git a/plugins/devkit/devkit-java-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFixRaw_after.java b/plugins/devkit/devkit-java-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFixRaw_after.java
new file mode 100644
index 000000000000..f8e0302fbf95
--- /dev/null
+++ b/plugins/devkit/devkit-java-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFixRaw_after.java
@@ -0,0 +1,10 @@
+import com.intellij.ide.HelpTooltipKt;
+import com.intellij.openapi.util.text.HtmlChunk;
+
+import javax.swing.*;
+
+class SetToolTipTextWithStringFixRaw {
+ void test(JComponent comp) {
+ HelpTooltipKt.setToolTipText(comp, HtmlChunk.raw("hello"));
+ }
+}
diff --git a/plugins/devkit/devkit-java-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFix_after.java b/plugins/devkit/devkit-java-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFix_after.java
new file mode 100644
index 000000000000..99607b954736
--- /dev/null
+++ b/plugins/devkit/devkit-java-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFix_after.java
@@ -0,0 +1,10 @@
+import com.intellij.ide.HelpTooltipKt;
+import com.intellij.openapi.util.text.HtmlChunk;
+
+import javax.swing.*;
+
+class SetToolTipTextWithStringFix {
+ void test(JComponent comp) {
+ HelpTooltipKt.setToolTipText(comp, HtmlChunk.text("hello"));
+ }
+}
diff --git a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/UseHtmlChunkToolTipInspectionTest.kt b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/UseHtmlChunkToolTipInspectionTest.kt
new file mode 100644
index 000000000000..f01229eefbf3
--- /dev/null
+++ b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/UseHtmlChunkToolTipInspectionTest.kt
@@ -0,0 +1,27 @@
+// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package org.jetbrains.idea.devkit.inspections
+
+import com.intellij.testFramework.TestDataPath
+import org.jetbrains.idea.devkit.DevkitJavaTestsUtil
+import org.jetbrains.idea.devkit.inspections.quickfix.UseHtmlChunkToolTipInspectionTestBase
+
+@TestDataPath($$"$CONTENT_ROOT/testData/inspections/useHtmlChunkToolTip")
+class UseHtmlChunkToolTipInspectionTest : UseHtmlChunkToolTipInspectionTestBase() {
+ override fun getBasePath(): String {
+ return DevkitJavaTestsUtil.TESTDATA_PATH + "inspections/useHtmlChunkToolTip"
+ }
+
+ override fun getFileExtension(): String = "java"
+
+ fun testSetToolTipTextWithString() {
+ doTest()
+ }
+
+ fun testSetToolTipTextWithStringFix() {
+ doTest("Wrap with 'HtmlChunk.text()'")
+ }
+
+ fun testSetToolTipTextWithStringFixRaw() {
+ doTest("Wrap with 'HtmlChunk.raw()'")
+ }
+}
diff --git a/plugins/devkit/devkit-kotlin-fir-tests/testSrc/org/jetbrains/idea/devkit/k2/inspections/KtUseHtmlChunkToolTipInspectionTest.kt b/plugins/devkit/devkit-kotlin-fir-tests/testSrc/org/jetbrains/idea/devkit/k2/inspections/KtUseHtmlChunkToolTipInspectionTest.kt
new file mode 100644
index 000000000000..5c481b42b3ed
--- /dev/null
+++ b/plugins/devkit/devkit-kotlin-fir-tests/testSrc/org/jetbrains/idea/devkit/k2/inspections/KtUseHtmlChunkToolTipInspectionTest.kt
@@ -0,0 +1,52 @@
+// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package org.jetbrains.idea.devkit.k2.inspections
+
+import com.intellij.testFramework.TestDataPath
+import org.jetbrains.idea.devkit.inspections.quickfix.UseHtmlChunkToolTipInspectionTestBase
+import org.jetbrains.idea.devkit.kotlin.DevkitKtTestsUtil
+import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginMode
+import org.jetbrains.kotlin.idea.test.ExpectedPluginModeProvider
+import org.jetbrains.kotlin.idea.test.setUpWithKotlinPlugin
+
+@TestDataPath("\$CONTENT_ROOT/testData/inspections/useHtmlChunkToolTip")
+class KtUseHtmlChunkToolTipInspectionTest : UseHtmlChunkToolTipInspectionTestBase(), ExpectedPluginModeProvider {
+ override val pluginMode: KotlinPluginMode = KotlinPluginMode.K2
+
+ override fun setUp() {
+ setUpWithKotlinPlugin { super.setUp() }
+ }
+
+ override fun getBasePath(): String {
+ return DevkitKtTestsUtil.TESTDATA_PATH + "inspections/useHtmlChunkToolTip"
+ }
+
+ override fun getFileExtension(): String = "kt"
+
+ override fun addSetToolTipTextExtensionStub() {
+ myFixture.addFileToProject(
+ "src/com/intellij/ide/HelpTooltip.kt",
+ """
+ package com.intellij.ide
+ import javax.swing.JComponent
+ import com.intellij.openapi.util.text.HtmlChunk
+ fun JComponent.setToolTipText(html: HtmlChunk?) {}
+ """.trimIndent()
+ )
+ }
+
+ fun testSetToolTipTextWithString() {
+ doTest()
+ }
+
+ fun testSetToolTipTextWithStringFix() {
+ doTest("Wrap with 'HtmlChunk.text()'")
+ }
+
+ fun testSetToolTipTextWithStringFixRaw() {
+ doTest("Wrap with 'HtmlChunk.raw()'")
+ }
+
+ fun testSetToolTipTextPropertyStyleFix() {
+ doTest("Wrap with 'HtmlChunk.text()'")
+ }
+}
diff --git a/plugins/devkit/devkit-kotlin-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextPropertyStyleFix.kt b/plugins/devkit/devkit-kotlin-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextPropertyStyleFix.kt
new file mode 100644
index 000000000000..6288da182f37
--- /dev/null
+++ b/plugins/devkit/devkit-kotlin-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextPropertyStyleFix.kt
@@ -0,0 +1,9 @@
+@file:Suppress("MISSING_DEPENDENCY_SUPERCLASS") // mockSDK misses some superclasses
+
+import javax.swing.JComponent
+
+class SetToolTipTextPropertyStyleFix {
+ fun test(comp: JComponent) {
+ comp.toolTipText = "hello"
+ }
+}
diff --git a/plugins/devkit/devkit-kotlin-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextPropertyStyleFix_after.kt b/plugins/devkit/devkit-kotlin-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextPropertyStyleFix_after.kt
new file mode 100644
index 000000000000..c4182bd48d23
--- /dev/null
+++ b/plugins/devkit/devkit-kotlin-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextPropertyStyleFix_after.kt
@@ -0,0 +1,11 @@
+@file:Suppress("MISSING_DEPENDENCY_SUPERCLASS") // mockSDK misses some superclasses
+
+import com.intellij.ide.setToolTipText
+import com.intellij.openapi.util.text.HtmlChunk
+import javax.swing.JComponent
+
+class SetToolTipTextPropertyStyleFix {
+ fun test(comp: JComponent) {
+ comp.setToolTipText(HtmlChunk.text("hello"))
+ }
+}
diff --git a/plugins/devkit/devkit-kotlin-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithString.kt b/plugins/devkit/devkit-kotlin-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithString.kt
new file mode 100644
index 000000000000..3ca3e310e965
--- /dev/null
+++ b/plugins/devkit/devkit-kotlin-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithString.kt
@@ -0,0 +1,15 @@
+@file:Suppress("MISSING_DEPENDENCY_SUPERCLASS") // mockSDK misses some superclasses
+
+import javax.swing.JComponent
+
+class SetToolTipTextWithString {
+ fun test(comp: JComponent) {
+ comp.setToolTipText("hello")
+ comp.setToolTipText(null)
+ comp.toolTipText = "hello"
+ comp.toolTipText = getString()
+ comp.toolTipText = null
+ }
+
+ fun getString(): String = ""
+}
diff --git a/plugins/devkit/devkit-kotlin-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFix.kt b/plugins/devkit/devkit-kotlin-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFix.kt
new file mode 100644
index 000000000000..f382c6f1dff8
--- /dev/null
+++ b/plugins/devkit/devkit-kotlin-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFix.kt
@@ -0,0 +1,9 @@
+@file:Suppress("MISSING_DEPENDENCY_SUPERCLASS") // mockSDK misses some superclasses
+
+import javax.swing.JComponent
+
+class SetToolTipTextWithStringFix {
+ fun test(comp: JComponent) {
+ comp.setToolTipText("hello")
+ }
+}
diff --git a/plugins/devkit/devkit-kotlin-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFixRaw.kt b/plugins/devkit/devkit-kotlin-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFixRaw.kt
new file mode 100644
index 000000000000..65460538e050
--- /dev/null
+++ b/plugins/devkit/devkit-kotlin-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFixRaw.kt
@@ -0,0 +1,9 @@
+@file:Suppress("MISSING_DEPENDENCY_SUPERCLASS") // mockSDK misses some superclasses
+
+import javax.swing.JComponent
+
+class SetToolTipTextWithStringFixRaw {
+ fun test(comp: JComponent) {
+ comp.setToolTipText("hello")
+ }
+}
diff --git a/plugins/devkit/devkit-kotlin-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFixRaw_after.kt b/plugins/devkit/devkit-kotlin-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFixRaw_after.kt
new file mode 100644
index 000000000000..f85cc3bac9a0
--- /dev/null
+++ b/plugins/devkit/devkit-kotlin-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFixRaw_after.kt
@@ -0,0 +1,11 @@
+@file:Suppress("MISSING_DEPENDENCY_SUPERCLASS") // mockSDK misses some superclasses
+
+import com.intellij.ide.setToolTipText
+import com.intellij.openapi.util.text.HtmlChunk
+import javax.swing.JComponent
+
+class SetToolTipTextWithStringFixRaw {
+ fun test(comp: JComponent) {
+ comp.setToolTipText(HtmlChunk.raw("hello"))
+ }
+}
diff --git a/plugins/devkit/devkit-kotlin-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFix_after.kt b/plugins/devkit/devkit-kotlin-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFix_after.kt
new file mode 100644
index 000000000000..a733c57eba02
--- /dev/null
+++ b/plugins/devkit/devkit-kotlin-tests/testData/inspections/useHtmlChunkToolTip/SetToolTipTextWithStringFix_after.kt
@@ -0,0 +1,11 @@
+@file:Suppress("MISSING_DEPENDENCY_SUPERCLASS") // mockSDK misses some superclasses
+
+import com.intellij.ide.setToolTipText
+import com.intellij.openapi.util.text.HtmlChunk
+import javax.swing.JComponent
+
+class SetToolTipTextWithStringFix {
+ fun test(comp: JComponent) {
+ comp.setToolTipText(HtmlChunk.text("hello"))
+ }
+}
diff --git a/plugins/devkit/devkit-tests/testSrc/org/jetbrains/idea/devkit/inspections/quickfix/UseHtmlChunkToolTipInspectionTestBase.kt b/plugins/devkit/devkit-tests/testSrc/org/jetbrains/idea/devkit/inspections/quickfix/UseHtmlChunkToolTipInspectionTestBase.kt
new file mode 100644
index 000000000000..8cdf98ea683c
--- /dev/null
+++ b/plugins/devkit/devkit-tests/testSrc/org/jetbrains/idea/devkit/inspections/quickfix/UseHtmlChunkToolTipInspectionTestBase.kt
@@ -0,0 +1,37 @@
+// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package org.jetbrains.idea.devkit.inspections.quickfix
+
+import org.jetbrains.idea.devkit.inspections.UseHtmlChunkToolTipInspection
+
+abstract class UseHtmlChunkToolTipInspectionTestBase : LightDevKitInspectionFixTestBase() {
+ @Throws(Exception::class)
+ override fun setUp() {
+ super.setUp()
+ myFixture.enableInspections(UseHtmlChunkToolTipInspection())
+ myFixture.addClass(
+ """package javax.swing;
+ |public class JComponent {
+ | public String getToolTipText() { return ""; }
+ | public void setToolTipText(String text) {}
+ |}""".trimMargin()
+ )
+ myFixture.addClass(
+ """package com.intellij.openapi.util.text;
+ |public class HtmlChunk {
+ | public static HtmlChunk text(String text) { return new HtmlChunk(); }
+ | public static HtmlChunk raw(String text) { return new HtmlChunk(); }
+ |}""".trimMargin()
+ )
+ myFixture.addClass(
+ """package com.intellij.ide;
+ |import javax.swing.JComponent;
+ |import com.intellij.openapi.util.text.HtmlChunk;
+ |public class HelpTooltipKt {
+ | public static void setToolTipText(JComponent comp, HtmlChunk html) {}
+ |}""".trimMargin()
+ )
+ addSetToolTipTextExtensionStub()
+ }
+
+ protected open fun addSetToolTipTextExtensionStub() {}
+}
diff --git a/plugins/devkit/intellij.kotlin.devkit/resources/intellij.kotlin.devkit.xml b/plugins/devkit/intellij.kotlin.devkit/resources/intellij.kotlin.devkit.xml
index d004fdebac81..cdb74e16b955 100644
--- a/plugins/devkit/intellij.kotlin.devkit/resources/intellij.kotlin.devkit.xml
+++ b/plugins/devkit/intellij.kotlin.devkit/resources/intellij.kotlin.devkit.xml
@@ -140,6 +140,9 @@
+
diff --git a/plugins/devkit/intellij.kotlin.devkit/src/inspections/KtUseHtmlChunkToolTipFixProvider.kt b/plugins/devkit/intellij.kotlin.devkit/src/inspections/KtUseHtmlChunkToolTipFixProvider.kt
new file mode 100644
index 000000000000..57afde6b7385
--- /dev/null
+++ b/plugins/devkit/intellij.kotlin.devkit/src/inspections/KtUseHtmlChunkToolTipFixProvider.kt
@@ -0,0 +1,80 @@
+// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package org.jetbrains.idea.devkit.kotlin.inspections
+
+import com.intellij.codeInsight.intention.PriorityAction
+import com.intellij.codeInsight.intention.PriorityAction.Priority
+import com.intellij.codeInspection.LocalQuickFix
+import com.intellij.codeInspection.ProblemDescriptor
+import com.intellij.codeInspection.util.IntentionFamilyName
+import com.intellij.openapi.project.Project
+import com.intellij.psi.PsiElement
+import org.jetbrains.idea.devkit.DevKitBundle
+import org.jetbrains.idea.devkit.inspections.quickfix.UseHtmlChunkToolTipFixProvider
+import org.jetbrains.kotlin.idea.base.codeInsight.ShortenReferencesFacility
+import org.jetbrains.kotlin.idea.base.psi.imports.addImport
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.psi.KtBinaryExpression
+import org.jetbrains.kotlin.psi.KtCallExpression
+import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.psi.KtPsiFactory
+
+internal class KtUseHtmlChunkToolTipFixProvider : UseHtmlChunkToolTipFixProvider {
+ override fun createFixes(element: PsiElement): Array {
+ return arrayOf(
+ KtWrapWithHtmlChunkFix("text", "inspections.use.html.chunk.tooltip.fix.wrap.text.family.name", Priority.TOP),
+ KtWrapWithHtmlChunkFix("raw", "inspections.use.html.chunk.tooltip.fix.wrap.raw.family.name", Priority.HIGH),
+ )
+ }
+}
+
+private const val HTML_CHUNK_FQN = "com.intellij.openapi.util.text.HtmlChunk"
+private val SET_TOOL_TIP_TEXT_EXTENSION_FQN = FqName("com.intellij.ide.setToolTipText")
+
+private class KtWrapWithHtmlChunkFix(
+ private val wrapMethodName: String,
+ private val familyNameKey: String,
+ private val fixPriority: Priority,
+) : LocalQuickFix, PriorityAction {
+ override fun getPriority(): Priority = fixPriority
+
+ @IntentionFamilyName
+ override fun getFamilyName(): String = DevKitBundle.message(familyNameKey)
+
+ override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
+ val element = descriptor.psiElement
+ val ktFile = element.containingFile as? KtFile ?: return
+ val psiFactory = KtPsiFactory(project)
+
+ // Case 1: Method call — comp.setToolTipText(arg)
+ val dotCall = element as? KtDotQualifiedExpression
+ ?: (element.parent as? KtDotQualifiedExpression)?.takeIf { it.selectorExpression is KtCallExpression }
+ if (dotCall != null) {
+ val call = dotCall.selectorExpression as? KtCallExpression ?: return
+ val receiverText = dotCall.receiverExpression.text
+ val argText = call.valueArguments.firstOrNull()?.getArgumentExpression()?.text ?: return
+ replaceAndShortenReferences(ktFile, psiFactory, dotCall, receiverText, argText)
+ return
+ }
+
+ // Case 2: Property assignment — comp.toolTipText = arg
+ val binaryExpr = element as? KtBinaryExpression ?: return
+ val left = binaryExpr.left as? KtDotQualifiedExpression ?: return
+ val receiverText = left.receiverExpression.text
+ val argText = binaryExpr.right?.text ?: return
+ replaceAndShortenReferences(ktFile, psiFactory, binaryExpr, receiverText, argText)
+ }
+
+ private fun replaceAndShortenReferences(
+ ktFile: KtFile,
+ psiFactory: KtPsiFactory,
+ nodeToReplace: PsiElement,
+ receiverText: String,
+ argText: String,
+ ) {
+ val newExpr = psiFactory.createExpression("$receiverText.setToolTipText($HTML_CHUNK_FQN.$wrapMethodName($argText))")
+ val replaced = nodeToReplace.replace(newExpr)
+ ShortenReferencesFacility.getInstance().shorten(replaced as org.jetbrains.kotlin.psi.KtElement)
+ ktFile.addImport(SET_TOOL_TIP_TEXT_EXTENSION_FQN)
+ }
+}