diff --git a/plugins/kotlin/base/resources/resources-en/messages/KotlinBundle.properties b/plugins/kotlin/base/resources/resources-en/messages/KotlinBundle.properties
index d7167284d9dd..a091a8866ec5 100644
--- a/plugins/kotlin/base/resources/resources-en/messages/KotlinBundle.properties
+++ b/plugins/kotlin/base/resources/resources-en/messages/KotlinBundle.properties
@@ -2646,6 +2646,12 @@ array.hash.code.problem.descriptor='hashCode()' called on array
replace.with.content.hash.code=Replace with 'contentHashCode()'
replace.with.content.deep.hash.code=Replace with 'contentDeepHashCode()'
+inspection.array.to.string.display.name='toString()' called on array
+array.to.string.problem.descriptor='toString()' called on array
+array.implicit.to.string.problem.descriptor=Implicit 'toString()' called on array
+replace.with.content.to.string=Replace with 'contentToString()'
+replace.with.content.deep.to.string=Replace with 'contentDeepToString()'
+
inspection.string.referential.equality.display.name=String compared with referential equality
string.comparison.using.referential.equality.triple.equals=String comparison using '===' instead of '=='
string.comparison.using.referential.equality.triple.not.equals=String comparison using '!==' instead of '!='
diff --git a/plugins/kotlin/code-insight/descriptions/resources-en/inspectionDescriptions/KotlinArrayToString.html b/plugins/kotlin/code-insight/descriptions/resources-en/inspectionDescriptions/KotlinArrayToString.html
new file mode 100644
index 000000000000..e08cf527a08f
--- /dev/null
+++ b/plugins/kotlin/code-insight/descriptions/resources-en/inspectionDescriptions/KotlinArrayToString.html
@@ -0,0 +1,54 @@
+
+
+Calling toString() on an array returns the address of the object in memory,
+ not a string representation of the array's contents. This is almost never what you want.
+To get a string representation of an array correctly, use:
+
+ contentToString() for linear arrays
+ contentDeepToString() for multidimensional arrays
+
+Example (explicit toString):
+
+ fun main() {
+ val a = arrayOf(1, 2, 3)
+ val s = a.toString() // incorrect
+ }
+
+After the quick-fix is applied:
+
+ fun main() {
+ val a = arrayOf(1, 2, 3)
+ val s = a.contentToString() // correct
+ }
+
+Example (implicit toString in string template):
+
+ fun main() {
+ val a = arrayOf(1, 2, 3)
+ println("Array: $a") // incorrect - prints address
+ }
+
+After the quick-fix is applied:
+
+ fun main() {
+ val a = arrayOf(1, 2, 3)
+ println("Array: ${a.contentToString()}") // correct - prints [1, 2, 3]
+ }
+
+Example (multidimensional array):
+
+ fun main() {
+ val a2d = arrayOf(arrayOf(1, 2), arrayOf(3, 4))
+ val s = a2d.toString() // incorrect
+ }
+
+After the quick-fix is applied:
+
+ fun main() {
+ val a2d = arrayOf(arrayOf(1, 2), arrayOf(3, 4))
+ val s = a2d.contentDeepToString() // correct - prints [[1, 2], [3, 4]]
+ }
+
+
+
+
diff --git a/plugins/kotlin/code-insight/inspections-k2/resources/intellij.kotlin.codeInsight.inspections.xml b/plugins/kotlin/code-insight/inspections-k2/resources/intellij.kotlin.codeInsight.inspections.xml
index f619c73cf23c..3cae9281321a 100644
--- a/plugins/kotlin/code-insight/inspections-k2/resources/intellij.kotlin.codeInsight.inspections.xml
+++ b/plugins/kotlin/code-insight/inspections-k2/resources/intellij.kotlin.codeInsight.inspections.xml
@@ -388,6 +388,14 @@
language="kotlin"
key="inspection.array.hash.code.display.name" bundle="messages.KotlinBundle"/>
+
+
= setOf("append", "print", "println")
+private val TO_STRING_CALLABLE_ID = CallableId(StandardClassIds.Any, Name.identifier("toString"))
+
+// This also handles Kotlin typealiases to Java underlying types
+private val IMPLICIT_TO_STRING_CALLABLE_IDS: Set = setOf(
+ CallableId(ClassId.topLevel(FqName("java.lang.StringBuilder")), Name.identifier("append")),
+ CallableId(ClassId.topLevel(FqName("java.lang.StringBuffer")), Name.identifier("append")),
+ CallableId(ClassId.topLevel(FqName("java.io.PrintStream")), Name.identifier("print")),
+ CallableId(ClassId.topLevel(FqName("java.io.PrintStream")), Name.identifier("println")),
+ CallableId(ClassId.topLevel(FqName("java.io.PrintWriter")), Name.identifier("print")),
+ CallableId(ClassId.topLevel(FqName("java.io.PrintWriter")), Name.identifier("println")),
+ CallableId(FqName("kotlin.io"), Name.identifier("print")),
+ CallableId(FqName("kotlin.io"), Name.identifier("println"))
+)
+
+internal class KotlinArrayToStringInspection : KotlinApplicableInspectionBase() {
+ data class Context(val isNestedArray: Boolean, val isImplicitConversion: Boolean)
+
+ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): KtVisitorVoid = object : KtVisitorVoid() {
+ override fun visitQualifiedExpression(expression: KtQualifiedExpression) {
+ visitTargetElement(expression, holder, isOnTheFly)
+ }
+
+ override fun visitBinaryExpression(expression: KtBinaryExpression) {
+ visitTargetElement(expression, holder, isOnTheFly)
+ }
+
+ override fun visitCallExpression(expression: KtCallExpression) {
+ visitTargetElement(expression, holder, isOnTheFly)
+ }
+
+ override fun visitStringTemplateEntry(entry: KtStringTemplateEntry) {
+ if (entry is KtStringTemplateEntryWithExpression) {
+ entry.expression?.let { visitTargetElement(it, holder, isOnTheFly) }
+ }
+ }
+ }
+
+ override fun isApplicableByPsi(element: KtExpression): Boolean {
+ return when (element) {
+ is KtQualifiedExpression -> {
+ val callExpression = element.selectorExpression as? KtCallExpression ?: return false
+ if (callExpression.valueArguments.isNotEmpty()) return false
+ val calleeName = callExpression.calleeExpression?.text ?: return false
+ calleeName == "toString"
+ }
+
+ is KtBinaryExpression -> {
+ element.operationReference.text == "+"
+ }
+
+ is KtCallExpression -> {
+ val calleeName = element.getCallNameExpression()?.text ?: return false
+ calleeName in IMPLICIT_TO_STRING_METHOD_NAMES
+ }
+
+ else -> {
+ // Check if this is inside a string template
+ val parent = element.parent
+ parent is KtBlockStringTemplateEntry || parent is KtSimpleNameStringTemplateEntry
+ }
+ }
+ }
+
+ override fun KaSession.prepareContext(element: KtExpression): Context? {
+ return when (element) {
+ is KtQualifiedExpression -> {
+ val receiverType = element.receiverExpression.expressionType ?: return null
+ if (!receiverType.isArrayOrPrimitiveArray) return null
+ val callExpression = element.selectorExpression as? KtCallExpression ?: return null
+ val call = callExpression.resolveToCall()?.successfulFunctionCallOrNull() ?: return null
+ val functionSymbol = call.symbol as? KaNamedFunctionSymbol ?: return null
+ if (functionSymbol.callableId != TO_STRING_CALLABLE_ID) return null
+
+ Context(receiverType.isNestedArray, isImplicitConversion = false)
+ }
+
+ is KtBinaryExpression -> {
+ // String concatenation only works as String + Any (not Any + String)
+ if (element.left?.expressionType?.isStringType != true) return null
+ val rightType = element.right?.expressionType ?: return null
+ if (!rightType.isArrayOrPrimitiveArray) return null
+
+ Context(rightType.isNestedArray, isImplicitConversion = true)
+ }
+
+ is KtCallExpression -> {
+ val call = element.resolveToCall()?.successfulFunctionCallOrNull() ?: return null
+ val functionSymbol = call.symbol as? KaNamedFunctionSymbol ?: return null
+ val callableId = functionSymbol.callableId ?: return null
+ if (callableId !in IMPLICIT_TO_STRING_CALLABLE_IDS) return null
+
+ val arguments = element.valueArguments
+ if (arguments.size != 1) return null
+ val argType = arguments[0].getArgumentExpression()?.expressionType ?: return null
+ if (!argType.isArrayOrPrimitiveArray) return null
+
+ Context(argType.isNestedArray, isImplicitConversion = true)
+ }
+
+ else -> {
+ val parent = element.parent
+ if (parent !is KtBlockStringTemplateEntry && parent !is KtSimpleNameStringTemplateEntry) return null
+ val expressionType = element.expressionType ?: return null
+ if (!expressionType.isArrayOrPrimitiveArray) return null
+
+ Context(expressionType.isNestedArray, isImplicitConversion = true)
+ }
+ }
+ }
+
+ override fun getApplicableRanges(element: KtExpression): List {
+ return when (element) {
+ is KtQualifiedExpression -> {
+ val selectorExpression = element.selectorExpression ?: return emptyList()
+ ApplicabilityRange.single(element) { selectorExpression }
+ }
+
+ is KtBinaryExpression -> {
+ ApplicabilityRange.single(element) { element.operationReference }
+ }
+
+ is KtCallExpression -> {
+ val calleeExpression = element.getCallNameExpression() ?: return emptyList()
+ ApplicabilityRange.single(element) { calleeExpression }
+ }
+
+ else -> {
+ // For string templates, highlight the entire expression
+ ApplicabilityRange.single(element) { element }
+ }
+ }
+ }
+
+ override fun InspectionManager.createProblemDescriptor(
+ element: KtExpression,
+ context: Context,
+ rangeInElement: TextRange?,
+ onTheFly: Boolean
+ ): ProblemDescriptor {
+ val message = if (context.isImplicitConversion) {
+ KotlinBundle.message("array.implicit.to.string.problem.descriptor")
+ } else {
+ KotlinBundle.message("array.to.string.problem.descriptor")
+ }
+
+ val fixes = if (context.isNestedArray) {
+ arrayOf(ReplaceWithContentToStringFix(), ReplaceWithContentDeepToStringFix())
+ } else {
+ arrayOf(ReplaceWithContentToStringFix())
+ }
+
+ return createProblemDescriptor(
+ /* psiElement = */ element,
+ /* rangeInElement = */ rangeInElement,
+ /* descriptionTemplate = */ message,
+ /* highlightType = */ ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
+ /* onTheFly = */ onTheFly,
+ /* ...fixes = */ *fixes
+ )
+ }
+}
+
+private class ReplaceWithContentToStringFix : KotlinModCommandQuickFix() {
+ override fun getFamilyName(): @IntentionFamilyName String =
+ KotlinBundle.message("replace.with.content.to.string")
+
+ override fun applyFix(project: Project, element: KtExpression, updater: ModPsiUpdater) {
+ replaceWithArrayContentMethod(project, element, methodName = "contentToString")
+ }
+}
+
+private class ReplaceWithContentDeepToStringFix : KotlinModCommandQuickFix(), HighPriorityAction {
+ override fun getFamilyName(): @IntentionFamilyName String =
+ KotlinBundle.message("replace.with.content.deep.to.string")
+
+ override fun applyFix(project: Project, element: KtExpression, updater: ModPsiUpdater) {
+ replaceWithArrayContentMethod(project, element, methodName = "contentDeepToString")
+ }
+}
+
+private fun replaceWithArrayContentMethod(project: Project, element: KtExpression, methodName: String) {
+ val psiFactory = KtPsiFactory(project)
+ when (element) {
+ is KtQualifiedExpression -> {
+ val receiver = element.receiverExpression
+ val operator = element.operationSign.value // . or ?.
+ val newExpression = psiFactory.createExpressionByPattern("$0$operator$methodName()", receiver)
+ element.replace(newExpression)
+ }
+
+ is KtBinaryExpression -> {
+ val left = element.left ?: return
+ val right = element.right ?: return
+ // Only string + array pattern is valid for string concatenation
+ val newExpression = psiFactory.createExpressionByPattern("$0 + $1.$methodName()", left, right)
+ element.replace(newExpression)
+ }
+
+ is KtCallExpression -> {
+ val calleeName = element.getCallNameExpression()?.text ?: return
+ when (calleeName) {
+ "append" -> {
+ // receiver.append(array) -> receiver.append(array.contentToString())
+ val receiver = element.parent as? KtDotQualifiedExpression
+ if (receiver != null) {
+ val receiverExpr = receiver.receiverExpression
+ val argument = element.valueArguments.firstOrNull()?.getArgumentExpression() ?: return
+ val operator = receiver.operationSign.value
+ val newExpression = psiFactory.createExpressionByPattern(
+ "$0${operator}$calleeName($1.$methodName())",
+ receiverExpr,
+ argument
+ )
+ receiver.replace(newExpression)
+ } else {
+ // Just append(array) without receiver -> append(array.contentToString())
+ val argument = element.valueArguments.firstOrNull()?.getArgumentExpression() ?: return
+ val newExpression = psiFactory.createExpressionByPattern("$calleeName($0.$methodName())", argument)
+ element.replace(newExpression)
+ }
+ }
+
+ "print", "println" -> {
+ // print(array) -> print(array.contentToString())
+ val argument = element.valueArguments.firstOrNull()?.getArgumentExpression() ?: return
+ val newExpression = psiFactory.createExpressionByPattern("$calleeName($0.$methodName())", argument)
+ element.replace(newExpression)
+ }
+ }
+ }
+
+ else -> {
+ // String template
+ val parent = element.parent
+ when (parent) {
+ is KtBlockStringTemplateEntry -> {
+ // "${array}" -> "${array.contentToString()}"
+ val newExpression = psiFactory.createExpressionByPattern("$0.$methodName()", element)
+ element.replace(newExpression)
+ }
+ is KtSimpleNameStringTemplateEntry -> {
+ // "$array" -> "${array.contentToString()}"
+ val newExpression = psiFactory.createExpressionByPattern("$0.$methodName()", element)
+ val newEntry = psiFactory.createBlockStringTemplateEntry(newExpression)
+ parent.replace(newEntry)
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2LocalInspectionTestGenerated.java b/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2LocalInspectionTestGenerated.java
index 5ad38e472cb5..8475d6945d09 100644
--- a/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2LocalInspectionTestGenerated.java
+++ b/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2LocalInspectionTestGenerated.java
@@ -4353,6 +4353,115 @@ public abstract class K2LocalInspectionTestGenerated extends AbstractK2LocalInsp
}
}
+ @RunWith(JUnit3RunnerWithInners.class)
+ @TestMetadata("../../../idea/tests/testData/inspectionsLocal/arrayToString")
+ public static class ArrayToString extends AbstractK2LocalInspectionTest {
+ @java.lang.Override
+ @org.jetbrains.annotations.NotNull
+ public final KotlinPluginMode getPluginMode() {
+ return KotlinPluginMode.K2;
+ }
+
+ private void runTest(String testDataFilePath) throws Exception {
+ KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
+ }
+
+ @TestMetadata("genericTypeArray.kt")
+ public void testGenericTypeArray() throws Exception {
+ runTest("../../../idea/tests/testData/inspectionsLocal/arrayToString/genericTypeArray.kt");
+ }
+
+ @TestMetadata("implicitNestedArrayConcatenation.kt")
+ public void testImplicitNestedArrayConcatenation() throws Exception {
+ runTest("../../../idea/tests/testData/inspectionsLocal/arrayToString/implicitNestedArrayConcatenation.kt");
+ }
+
+ @TestMetadata("implicitStringConcatenation.kt")
+ public void testImplicitStringConcatenation() throws Exception {
+ runTest("../../../idea/tests/testData/inspectionsLocal/arrayToString/implicitStringConcatenation.kt");
+ }
+
+ @TestMetadata("intArray.kt")
+ public void testIntArray() throws Exception {
+ runTest("../../../idea/tests/testData/inspectionsLocal/arrayToString/intArray.kt");
+ }
+
+ @TestMetadata("multidimensionalArrayContentDeepToString.kt")
+ public void testMultidimensionalArrayContentDeepToString() throws Exception {
+ runTest("../../../idea/tests/testData/inspectionsLocal/arrayToString/multidimensionalArrayContentDeepToString.kt");
+ }
+
+ @TestMetadata("multidimensionalArrayContentToString.kt")
+ public void testMultidimensionalArrayContentToString() throws Exception {
+ runTest("../../../idea/tests/testData/inspectionsLocal/arrayToString/multidimensionalArrayContentToString.kt");
+ }
+
+ @TestMetadata("noInspection.kt")
+ public void testNoInspection() throws Exception {
+ runTest("../../../idea/tests/testData/inspectionsLocal/arrayToString/noInspection.kt");
+ }
+
+ @TestMetadata("nullableArray.kt")
+ public void testNullableArray() throws Exception {
+ runTest("../../../idea/tests/testData/inspectionsLocal/arrayToString/nullableArray.kt");
+ }
+
+ @TestMetadata("printArray.kt")
+ public void testPrintArray() throws Exception {
+ runTest("../../../idea/tests/testData/inspectionsLocal/arrayToString/printArray.kt");
+ }
+
+ @TestMetadata("printlnArray.kt")
+ public void testPrintlnArray() throws Exception {
+ runTest("../../../idea/tests/testData/inspectionsLocal/arrayToString/printlnArray.kt");
+ }
+
+ @TestMetadata("printlnNestedArray.kt")
+ public void testPrintlnNestedArray() throws Exception {
+ runTest("../../../idea/tests/testData/inspectionsLocal/arrayToString/printlnNestedArray.kt");
+ }
+
+ @TestMetadata("simpleArray.kt")
+ public void testSimpleArray() throws Exception {
+ runTest("../../../idea/tests/testData/inspectionsLocal/arrayToString/simpleArray.kt");
+ }
+
+ @TestMetadata("stringBufferAppend.kt")
+ public void testStringBufferAppend() throws Exception {
+ runTest("../../../idea/tests/testData/inspectionsLocal/arrayToString/stringBufferAppend.kt");
+ }
+
+ @TestMetadata("stringBuilderAppend.kt")
+ public void testStringBuilderAppend() throws Exception {
+ runTest("../../../idea/tests/testData/inspectionsLocal/arrayToString/stringBuilderAppend.kt");
+ }
+
+ @TestMetadata("stringBuilderAppendNestedArray.kt")
+ public void testStringBuilderAppendNestedArray() throws Exception {
+ runTest("../../../idea/tests/testData/inspectionsLocal/arrayToString/stringBuilderAppendNestedArray.kt");
+ }
+
+ @TestMetadata("stringTemplate.kt")
+ public void testStringTemplate() throws Exception {
+ runTest("../../../idea/tests/testData/inspectionsLocal/arrayToString/stringTemplate.kt");
+ }
+
+ @TestMetadata("stringTemplateNestedArray.kt")
+ public void testStringTemplateNestedArray() throws Exception {
+ runTest("../../../idea/tests/testData/inspectionsLocal/arrayToString/stringTemplateNestedArray.kt");
+ }
+
+ @TestMetadata("stringTemplateSimpleName.kt")
+ public void testStringTemplateSimpleName() throws Exception {
+ runTest("../../../idea/tests/testData/inspectionsLocal/arrayToString/stringTemplateSimpleName.kt");
+ }
+
+ @TestMetadata("varargParameter.kt")
+ public void testVarargParameter() throws Exception {
+ runTest("../../../idea/tests/testData/inspectionsLocal/arrayToString/varargParameter.kt");
+ }
+ }
+
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("../../../idea/tests/testData/inspectionsLocal/stringReferentialEquality")
public static class StringReferentialEquality extends AbstractK2LocalInspectionTest {
diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
index c37b3e15d32f..1ba5cbf1c370 100644
--- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
+++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
@@ -192,6 +192,115 @@ public abstract class LocalInspectionTestGenerated extends AbstractLocalInspecti
}
}
+ @RunWith(JUnit3RunnerWithInners.class)
+ @TestMetadata("testData/inspectionsLocal/arrayToString")
+ public static class ArrayToString extends AbstractLocalInspectionTest {
+ @java.lang.Override
+ @org.jetbrains.annotations.NotNull
+ public final KotlinPluginMode getPluginMode() {
+ return KotlinPluginMode.K1;
+ }
+
+ private void runTest(String testDataFilePath) throws Exception {
+ KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
+ }
+
+ @TestMetadata("genericTypeArray.kt")
+ public void testGenericTypeArray() throws Exception {
+ runTest("testData/inspectionsLocal/arrayToString/genericTypeArray.kt");
+ }
+
+ @TestMetadata("implicitNestedArrayConcatenation.kt")
+ public void testImplicitNestedArrayConcatenation() throws Exception {
+ runTest("testData/inspectionsLocal/arrayToString/implicitNestedArrayConcatenation.kt");
+ }
+
+ @TestMetadata("implicitStringConcatenation.kt")
+ public void testImplicitStringConcatenation() throws Exception {
+ runTest("testData/inspectionsLocal/arrayToString/implicitStringConcatenation.kt");
+ }
+
+ @TestMetadata("intArray.kt")
+ public void testIntArray() throws Exception {
+ runTest("testData/inspectionsLocal/arrayToString/intArray.kt");
+ }
+
+ @TestMetadata("multidimensionalArrayContentDeepToString.kt")
+ public void testMultidimensionalArrayContentDeepToString() throws Exception {
+ runTest("testData/inspectionsLocal/arrayToString/multidimensionalArrayContentDeepToString.kt");
+ }
+
+ @TestMetadata("multidimensionalArrayContentToString.kt")
+ public void testMultidimensionalArrayContentToString() throws Exception {
+ runTest("testData/inspectionsLocal/arrayToString/multidimensionalArrayContentToString.kt");
+ }
+
+ @TestMetadata("noInspection.kt")
+ public void testNoInspection() throws Exception {
+ runTest("testData/inspectionsLocal/arrayToString/noInspection.kt");
+ }
+
+ @TestMetadata("nullableArray.kt")
+ public void testNullableArray() throws Exception {
+ runTest("testData/inspectionsLocal/arrayToString/nullableArray.kt");
+ }
+
+ @TestMetadata("printArray.kt")
+ public void testPrintArray() throws Exception {
+ runTest("testData/inspectionsLocal/arrayToString/printArray.kt");
+ }
+
+ @TestMetadata("printlnArray.kt")
+ public void testPrintlnArray() throws Exception {
+ runTest("testData/inspectionsLocal/arrayToString/printlnArray.kt");
+ }
+
+ @TestMetadata("printlnNestedArray.kt")
+ public void testPrintlnNestedArray() throws Exception {
+ runTest("testData/inspectionsLocal/arrayToString/printlnNestedArray.kt");
+ }
+
+ @TestMetadata("simpleArray.kt")
+ public void testSimpleArray() throws Exception {
+ runTest("testData/inspectionsLocal/arrayToString/simpleArray.kt");
+ }
+
+ @TestMetadata("stringBufferAppend.kt")
+ public void testStringBufferAppend() throws Exception {
+ runTest("testData/inspectionsLocal/arrayToString/stringBufferAppend.kt");
+ }
+
+ @TestMetadata("stringBuilderAppend.kt")
+ public void testStringBuilderAppend() throws Exception {
+ runTest("testData/inspectionsLocal/arrayToString/stringBuilderAppend.kt");
+ }
+
+ @TestMetadata("stringBuilderAppendNestedArray.kt")
+ public void testStringBuilderAppendNestedArray() throws Exception {
+ runTest("testData/inspectionsLocal/arrayToString/stringBuilderAppendNestedArray.kt");
+ }
+
+ @TestMetadata("stringTemplate.kt")
+ public void testStringTemplate() throws Exception {
+ runTest("testData/inspectionsLocal/arrayToString/stringTemplate.kt");
+ }
+
+ @TestMetadata("stringTemplateNestedArray.kt")
+ public void testStringTemplateNestedArray() throws Exception {
+ runTest("testData/inspectionsLocal/arrayToString/stringTemplateNestedArray.kt");
+ }
+
+ @TestMetadata("stringTemplateSimpleName.kt")
+ public void testStringTemplateSimpleName() throws Exception {
+ runTest("testData/inspectionsLocal/arrayToString/stringTemplateSimpleName.kt");
+ }
+
+ @TestMetadata("varargParameter.kt")
+ public void testVarargParameter() throws Exception {
+ runTest("testData/inspectionsLocal/arrayToString/varargParameter.kt");
+ }
+ }
+
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("testData/inspectionsLocal/booleanLiteralArgument")
public static class BooleanLiteralArgument extends AbstractLocalInspectionTest {
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/.k2Inspection b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/.k2Inspection
new file mode 100644
index 000000000000..89dbd6949322
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/.k2Inspection
@@ -0,0 +1 @@
+org.jetbrains.kotlin.idea.k2.codeinsight.inspections.KotlinArrayToStringInspection
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/genericTypeArray.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/genericTypeArray.kt
new file mode 100644
index 000000000000..9d0ca8d1b199
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/genericTypeArray.kt
@@ -0,0 +1,8 @@
+// PROBLEM: 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun stringifyArray(arr: Array): String {
+ return arr.toString()
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/genericTypeArray.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/genericTypeArray.kt.after
new file mode 100644
index 000000000000..a24c9814b1de
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/genericTypeArray.kt.after
@@ -0,0 +1,8 @@
+// PROBLEM: 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun stringifyArray(arr: Array): String {
+ return arr.contentToString()
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/implicitNestedArrayConcatenation.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/implicitNestedArrayConcatenation.kt
new file mode 100644
index 000000000000..10466fd6f315
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/implicitNestedArrayConcatenation.kt
@@ -0,0 +1,9 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentDeepToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = arrayOf(arrayOf(1, 2), arrayOf(3, 4))
+ val result = "Nested: " + arr
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/implicitNestedArrayConcatenation.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/implicitNestedArrayConcatenation.kt.after
new file mode 100644
index 000000000000..19ac669265b0
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/implicitNestedArrayConcatenation.kt.after
@@ -0,0 +1,9 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentDeepToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = arrayOf(arrayOf(1, 2), arrayOf(3, 4))
+ val result = "Nested: " + arr.contentDeepToString()
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/implicitStringConcatenation.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/implicitStringConcatenation.kt
new file mode 100644
index 000000000000..0b23d163617e
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/implicitStringConcatenation.kt
@@ -0,0 +1,9 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = arrayOf(1, 2, 3)
+ val result = "Array: " + arr
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/implicitStringConcatenation.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/implicitStringConcatenation.kt.after
new file mode 100644
index 000000000000..2739d828e608
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/implicitStringConcatenation.kt.after
@@ -0,0 +1,9 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = arrayOf(1, 2, 3)
+ val result = "Array: " + arr.contentToString()
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/intArray.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/intArray.kt
new file mode 100644
index 000000000000..d13c9cc5fb73
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/intArray.kt
@@ -0,0 +1,9 @@
+// PROBLEM: 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val a1 = intArrayOf(1, 2, 3)
+ val s = a1.toString()
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/intArray.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/intArray.kt.after
new file mode 100644
index 000000000000..7c614bc76363
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/intArray.kt.after
@@ -0,0 +1,9 @@
+// PROBLEM: 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val a1 = intArrayOf(1, 2, 3)
+ val s = a1.contentToString()
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/multidimensionalArrayContentDeepToString.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/multidimensionalArrayContentDeepToString.kt
new file mode 100644
index 000000000000..1f57cf6f6ba4
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/multidimensionalArrayContentDeepToString.kt
@@ -0,0 +1,10 @@
+// PROBLEM: 'toString()' called on array
+// FIX: Replace with 'contentDeepToString()'
+// PRIORITY: HIGH
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val a2d = arrayOf(arrayOf(1, 2), arrayOf(3, 4))
+ val s = a2d.toString()
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/multidimensionalArrayContentDeepToString.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/multidimensionalArrayContentDeepToString.kt.after
new file mode 100644
index 000000000000..a8cf21bd216b
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/multidimensionalArrayContentDeepToString.kt.after
@@ -0,0 +1,10 @@
+// PROBLEM: 'toString()' called on array
+// FIX: Replace with 'contentDeepToString()'
+// PRIORITY: HIGH
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val a2d = arrayOf(arrayOf(1, 2), arrayOf(3, 4))
+ val s = a2d.contentDeepToString()
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/multidimensionalArrayContentToString.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/multidimensionalArrayContentToString.kt
new file mode 100644
index 000000000000..6e36e7e6559a
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/multidimensionalArrayContentToString.kt
@@ -0,0 +1,9 @@
+// PROBLEM: 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val a2d = arrayOf(arrayOf(1, 2), arrayOf(3, 4))
+ val s = a2d.toString()
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/multidimensionalArrayContentToString.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/multidimensionalArrayContentToString.kt.after
new file mode 100644
index 000000000000..4acbd3c01bd3
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/multidimensionalArrayContentToString.kt.after
@@ -0,0 +1,9 @@
+// PROBLEM: 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val a2d = arrayOf(arrayOf(1, 2), arrayOf(3, 4))
+ val s = a2d.contentToString()
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/noInspection.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/noInspection.kt
new file mode 100644
index 000000000000..597ae395bb4f
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/noInspection.kt
@@ -0,0 +1,8 @@
+// PROBLEM: none
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val notArray = "test"
+ val s = notArray.toString()
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/nullableArray.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/nullableArray.kt
new file mode 100644
index 000000000000..63f734e2cfe5
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/nullableArray.kt
@@ -0,0 +1,9 @@
+// PROBLEM: 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr: IntArray? = intArrayOf(1, 2, 3)
+ val s = arr?.toString()
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/nullableArray.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/nullableArray.kt.after
new file mode 100644
index 000000000000..cab5d6cc702c
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/nullableArray.kt.after
@@ -0,0 +1,9 @@
+// PROBLEM: 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr: IntArray? = intArrayOf(1, 2, 3)
+ val s = arr?.contentToString()
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/printArray.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/printArray.kt
new file mode 100644
index 000000000000..49c9509ad86d
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/printArray.kt
@@ -0,0 +1,9 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = arrayOf("a", "b", "c")
+ print(arr)
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/printArray.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/printArray.kt.after
new file mode 100644
index 000000000000..60c457c9845b
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/printArray.kt.after
@@ -0,0 +1,9 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = arrayOf("a", "b", "c")
+ print(arr.contentToString())
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/printlnArray.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/printlnArray.kt
new file mode 100644
index 000000000000..da4f5a1b5566
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/printlnArray.kt
@@ -0,0 +1,9 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = doubleArrayOf(1.0, 2.0, 3.0)
+ println(arr)
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/printlnArray.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/printlnArray.kt.after
new file mode 100644
index 000000000000..01f28327210f
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/printlnArray.kt.after
@@ -0,0 +1,9 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = doubleArrayOf(1.0, 2.0, 3.0)
+ println(arr.contentToString())
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/printlnNestedArray.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/printlnNestedArray.kt
new file mode 100644
index 000000000000..f3eaa17376e7
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/printlnNestedArray.kt
@@ -0,0 +1,9 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentDeepToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = arrayOf(intArrayOf(1, 2), intArrayOf(3, 4))
+ println(arr)
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/printlnNestedArray.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/printlnNestedArray.kt.after
new file mode 100644
index 000000000000..c513995f35c5
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/printlnNestedArray.kt.after
@@ -0,0 +1,9 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentDeepToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = arrayOf(intArrayOf(1, 2), intArrayOf(3, 4))
+ println(arr.contentDeepToString())
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/simpleArray.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/simpleArray.kt
new file mode 100644
index 000000000000..670a65f92885
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/simpleArray.kt
@@ -0,0 +1,9 @@
+// PROBLEM: 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val a = arrayOf(1, 2, 3)
+ val s = a.toString()
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/simpleArray.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/simpleArray.kt.after
new file mode 100644
index 000000000000..e4a4a5d172f7
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/simpleArray.kt.after
@@ -0,0 +1,9 @@
+// PROBLEM: 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val a = arrayOf(1, 2, 3)
+ val s = a.contentToString()
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringBufferAppend.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringBufferAppend.kt
new file mode 100644
index 000000000000..70623050b72f
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringBufferAppend.kt
@@ -0,0 +1,10 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = intArrayOf(1, 2, 3)
+ val sb = StringBuffer()
+ sb.append(arr)
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringBufferAppend.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringBufferAppend.kt.after
new file mode 100644
index 000000000000..641a325bb059
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringBufferAppend.kt.after
@@ -0,0 +1,10 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = intArrayOf(1, 2, 3)
+ val sb = StringBuffer()
+ sb.append(arr.contentToString())
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringBuilderAppend.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringBuilderAppend.kt
new file mode 100644
index 000000000000..7b85a1eadaf3
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringBuilderAppend.kt
@@ -0,0 +1,10 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = arrayOf(1, 2, 3)
+ val sb = StringBuilder()
+ sb.append(arr)
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringBuilderAppend.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringBuilderAppend.kt.after
new file mode 100644
index 000000000000..0ae37676d86a
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringBuilderAppend.kt.after
@@ -0,0 +1,10 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = arrayOf(1, 2, 3)
+ val sb = StringBuilder()
+ sb.append(arr.contentToString())
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringBuilderAppendNestedArray.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringBuilderAppendNestedArray.kt
new file mode 100644
index 000000000000..c0d4412c18fe
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringBuilderAppendNestedArray.kt
@@ -0,0 +1,10 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentDeepToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = arrayOf(arrayOf(1, 2), arrayOf(3, 4))
+ val sb = StringBuilder()
+ sb.append(arr)
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringBuilderAppendNestedArray.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringBuilderAppendNestedArray.kt.after
new file mode 100644
index 000000000000..e917d5ee4c56
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringBuilderAppendNestedArray.kt.after
@@ -0,0 +1,10 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentDeepToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = arrayOf(arrayOf(1, 2), arrayOf(3, 4))
+ val sb = StringBuilder()
+ sb.append(arr.contentDeepToString())
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringTemplate.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringTemplate.kt
new file mode 100644
index 000000000000..4656c553c040
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringTemplate.kt
@@ -0,0 +1,9 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = arrayOf(1, 2, 3)
+ val result = "Array: ${arr}"
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringTemplate.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringTemplate.kt.after
new file mode 100644
index 000000000000..b304cbec0ab9
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringTemplate.kt.after
@@ -0,0 +1,9 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = arrayOf(1, 2, 3)
+ val result = "Array: ${arr.contentToString()}"
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringTemplateNestedArray.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringTemplateNestedArray.kt
new file mode 100644
index 000000000000..2d3e796c09ab
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringTemplateNestedArray.kt
@@ -0,0 +1,9 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentDeepToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = arrayOf(arrayOf("a", "b"), arrayOf("c", "d"))
+ val result = "Nested: ${arr}"
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringTemplateNestedArray.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringTemplateNestedArray.kt.after
new file mode 100644
index 000000000000..32369ffb4b4e
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringTemplateNestedArray.kt.after
@@ -0,0 +1,9 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentDeepToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = arrayOf(arrayOf("a", "b"), arrayOf("c", "d"))
+ val result = "Nested: ${arr.contentDeepToString()}"
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringTemplateSimpleName.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringTemplateSimpleName.kt
new file mode 100644
index 000000000000..d3862d9ed4f4
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringTemplateSimpleName.kt
@@ -0,0 +1,9 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = arrayOf(1, 2, 3)
+ val result = "Array: $arr"
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringTemplateSimpleName.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringTemplateSimpleName.kt.after
new file mode 100644
index 000000000000..b304cbec0ab9
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/stringTemplateSimpleName.kt.after
@@ -0,0 +1,9 @@
+// PROBLEM: Implicit 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun main() {
+ val arr = arrayOf(1, 2, 3)
+ val result = "Array: ${arr.contentToString()}"
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/varargParameter.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/varargParameter.kt
new file mode 100644
index 000000000000..6787bb95f2f5
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/varargParameter.kt
@@ -0,0 +1,9 @@
+// PROBLEM: 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun printItems(vararg items: Int) {
+ val s = items.toString()
+ println(s)
+}
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/varargParameter.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/varargParameter.kt.after
new file mode 100644
index 000000000000..b3c99ad704a0
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/arrayToString/varargParameter.kt.after
@@ -0,0 +1,9 @@
+// PROBLEM: 'toString()' called on array
+// FIX: Replace with 'contentToString()'
+// IGNORE_K1
+// WITH_STDLIB
+
+fun printItems(vararg items: Int) {
+ val s = items.contentToString()
+ println(s)
+}
diff --git a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/codeinsight/GenerateK2InspectionTests.kt b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/codeinsight/GenerateK2InspectionTests.kt
index f581ab7ec3b9..d36ddba80d37 100644
--- a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/codeinsight/GenerateK2InspectionTests.kt
+++ b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/codeinsight/GenerateK2InspectionTests.kt
@@ -60,6 +60,7 @@ internal fun MutableTWorkspace.generateK2InspectionTests() {
model("${idea}/inspectionsLocal/redundantRequireNotNullCall")
model("${idea}/inspectionsLocal/suspiciousCallOnCollectionToAddOrRemovePath")
model("${idea}/inspectionsLocal/arrayHashCode")
+ model("${idea}/inspectionsLocal/arrayToString")
model("${idea}/inspectionsLocal/stringReferentialEquality")
model("${idea}/inspectionsLocal/suspiciousCascadingIf")
model("${idea}/inspectionsLocal/equalsOrHashCode")