From e51bcf6c0292f8ca1548f703125b423d50eadeac Mon Sep 17 00:00:00 2001 From: Alexander Drugakov Date: Mon, 18 Dec 2023 16:10:02 +0300 Subject: [PATCH] Fixed duplicate `@property` generation for parameter with ' in name (#1873) ### What's done: - fixed bug. - added fix tests. Closes #1719 --- .../rules/chapter2/kdoc/KdocComments.kt | 53 ++++++++----------- .../kdoc/ConstructorCommentExpected.kt | 13 +++++ .../kdoc/ConstructorCommentNoKDocExpected.kt | 9 ++++ .../kdoc/ConstructorCommentNoKDocTest.kt | 5 ++ .../ConstructorCommentPropertiesExpected.kt | 9 ++++ .../kdoc/ConstructorCommentPropertiesTest.kt | 8 +++ .../paragraph2/kdoc/ConstructorCommentTest.kt | 10 ++++ 7 files changed, 76 insertions(+), 31 deletions(-) diff --git a/diktat-rules/src/main/kotlin/com/saveourtool/diktat/ruleset/rules/chapter2/kdoc/KdocComments.kt b/diktat-rules/src/main/kotlin/com/saveourtool/diktat/ruleset/rules/chapter2/kdoc/KdocComments.kt index e9f9ad7706..9dc43f5ca3 100644 --- a/diktat-rules/src/main/kotlin/com/saveourtool/diktat/ruleset/rules/chapter2/kdoc/KdocComments.kt +++ b/diktat-rules/src/main/kotlin/com/saveourtool/diktat/ruleset/rules/chapter2/kdoc/KdocComments.kt @@ -184,10 +184,8 @@ class KdocComments(configRules: List) : DiktatRule( kdocBeforeClass: ASTNode, isParamTagNeeded: Boolean ) { - val parameterName = node.findChildByType(IDENTIFIER)!!.text - val parameterTagInClassKdoc = kdocBeforeClass - .kDocTags() - .firstOrNull { (it.knownTag == KDocKnownTag.PARAM || it.knownTag == KDocKnownTag.PROPERTY) && it.getSubjectName() == parameterName } + val parameterName = getParameterName(node) + val parameterTagInClassKdoc = findParameterTagInClassKdoc(kdocBeforeClass, parameterName) parameterTagInClassKdoc?.let { val correctTag = if (isParamTagNeeded) KDocKnownTag.PARAM else KDocKnownTag.PROPERTY @@ -303,7 +301,7 @@ class KdocComments(configRules: List) : DiktatRule( @Suppress("UnsafeCallOnNullableType") private fun createKdocBasicKdoc(node: ASTNode, isParamTagNeeded: Boolean) { if (isNeedToWarn(node, isParamTagNeeded)) { - val parameterName = node.findChildByType(IDENTIFIER)!!.text + val parameterName = getParameterName(node) val warningText = if (isParamTagNeeded) "add param <$parameterName> to KDoc" else "add property <$parameterName> to KDoc" KDOC_NO_CONSTRUCTOR_PROPERTY.warnAndFix(configRules, emitWarn, isFixMode, warningText, node.startOffset, node) { @@ -324,7 +322,7 @@ class KdocComments(configRules: List) : DiktatRule( isParamTagNeeded: Boolean ) { if (isNeedToWarn(node, isParamTagNeeded)) { - val parameterName = node.findChildByType(IDENTIFIER)!!.text + val parameterName = getParameterName(node) val classNode = node.parent { it.elementType == CLASS }!! // if property or parameter is documented with KDoc, which has a tag inside, then it can contain some additional more @@ -334,7 +332,8 @@ class KdocComments(configRules: List) : DiktatRule( val warningText = if (isParamTagNeeded) "add comment for param <$parameterName> to KDoc" else "add comment for property <$parameterName> to KDoc" KDOC_NO_CONSTRUCTOR_PROPERTY_WITH_COMMENT.warnOnlyOrWarnAndFix(configRules, emitWarn, warningText, prevComment.startOffset, node, isFixable, isFixMode) { - val newKdocText = createClassKdocTextFromComment(prevComment, parameterName, isParamTagNeeded) + val paramOrPropertyTagText = if (isParamTagNeeded) "@param" else "@property" + val newKdocText = createClassKdocTextFromComment(prevComment, parameterName, paramOrPropertyTagText) val newKdoc = KotlinParser().createNode(newKdocText).findChildByType(KDOC)!! classNode.addChild(PsiWhiteSpaceImpl("\n"), classNode.firstChildNode) @@ -347,23 +346,11 @@ class KdocComments(configRules: List) : DiktatRule( private fun createClassKdocTextFromComment( prevComment: ASTNode, parameterName: String, - isParamTagNeeded: Boolean + paramOrPropertyTagText: String ) = when (prevComment.elementType) { - KDOC -> if (isParamTagNeeded) { - "/**\n * @param $parameterName${createClassKdocTextFromKdocComment(prevComment)}\n */" - } else { - "/**\n * @property $parameterName${createClassKdocTextFromKdocComment(prevComment)}\n */" - } - EOL_COMMENT -> if (isParamTagNeeded) { - "/**\n * @param $parameterName ${createClassKdocTextFromEolComment(prevComment)}\n */" - } else { - "/**\n * @property $parameterName ${createClassKdocTextFromEolComment(prevComment)}\n */" - } - else -> if (isParamTagNeeded) { - "/**\n * @param $parameterName${createClassKdocTextFromBlockComment(prevComment)}\n */" - } else { - "/**\n * @property $parameterName${createClassKdocTextFromBlockComment(prevComment)}\n */" - } + KDOC -> "/**\n * $paramOrPropertyTagText $parameterName${createClassKdocTextFromKdocComment(prevComment)}\n */" + EOL_COMMENT -> "/**\n * $paramOrPropertyTagText $parameterName ${createClassKdocTextFromEolComment(prevComment)}\n */" + else -> "/**\n * $paramOrPropertyTagText $parameterName${createClassKdocTextFromBlockComment(prevComment)}\n */" } private fun createClassKdocTextFromKdocComment(prevComment: ASTNode) = @@ -401,10 +388,8 @@ class KdocComments(configRules: List) : DiktatRule( prevComment: ASTNode, isParamTagNeeded: Boolean ) { - val parameterName = node.findChildByType(IDENTIFIER)!!.text - val parameterTagInClassKdoc = kdocBeforeClass - .kDocTags() - .firstOrNull { (it.knownTag == KDocKnownTag.PARAM || it.knownTag == KDocKnownTag.PROPERTY) && it.getSubjectName() == parameterName } + val parameterName = getParameterName(node) + val parameterTagInClassKdoc = findParameterTagInClassKdoc(kdocBeforeClass, parameterName) val parameterInClassKdoc = parameterTagInClassKdoc?.node val commentText = if (prevComment.elementType == KDOC) { @@ -456,10 +441,8 @@ class KdocComments(configRules: List) : DiktatRule( prevComment: ASTNode, isParamTagNeeded: Boolean ) { - val parameterName = node.findChildByType(IDENTIFIER)!!.text - val parameterTagInClassKdoc = kdocBeforeClass - .kDocTags() - .firstOrNull { (it.knownTag == KDocKnownTag.PARAM || it.knownTag == KDocKnownTag.PROPERTY) && it.getSubjectName() == parameterName } + val parameterName = getParameterName(node) + val parameterTagInClassKdoc = findParameterTagInClassKdoc(kdocBeforeClass, parameterName) val parameterInClassKdoc = parameterTagInClassKdoc?.node val (isHasWrongTag, warningText) = checkWrongTagAndMakeWarningText(parameterTagInClassKdoc, parameterName, isParamTagNeeded) @@ -500,6 +483,14 @@ class KdocComments(configRules: List) : DiktatRule( } } + @Suppress("UnsafeCallOnNullableType") + private fun getParameterName(node: ASTNode) = node.findChildByType(IDENTIFIER)!!.text.replace("`", "") + + private fun findParameterTagInClassKdoc(kdocBeforeClass: ASTNode, parameterName: String) = + kdocBeforeClass + .kDocTags() + .firstOrNull { (it.knownTag == KDocKnownTag.PARAM || it.knownTag == KDocKnownTag.PROPERTY) && it.getSubjectName() == parameterName } + private fun checkWrongTagAndMakeWarningText( parameterTagInClassKdoc: KDocTag?, parameterName: String, diff --git a/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentExpected.kt b/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentExpected.kt index 94116b484f..bb17335968 100644 --- a/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentExpected.kt +++ b/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentExpected.kt @@ -309,3 +309,16 @@ class A constructor( */ paramAddr: String, ) : B(), C

, D {} + +/** + * kdoc + * class + * comment + * + * @property as + * @property keyAs + */ +actual annotation class JsonSerialize( + actual val `as`: KClass<*>, + actual val keyAs: KClass<*>, +) diff --git a/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentNoKDocExpected.kt b/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentNoKDocExpected.kt index 98f7e580cb..fb4c2740a2 100644 --- a/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentNoKDocExpected.kt +++ b/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentNoKDocExpected.kt @@ -238,3 +238,12 @@ class A constructor( */ paramAddr: String, ) : B(), C

, D {} + +/** + * @property as + * @property keyAs + */ +actual annotation class JsonSerialize( + actual val `as`: KClass<*>, + actual val keyAs: KClass<*>, +) diff --git a/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentNoKDocTest.kt b/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentNoKDocTest.kt index 29e57b34cd..7b262ef5ad 100644 --- a/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentNoKDocTest.kt +++ b/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentNoKDocTest.kt @@ -223,3 +223,8 @@ class A constructor( */ paramAddr: String, ) : B(), C

, D {} + +actual annotation class JsonSerialize( + actual val `as`: KClass<*>, + actual val keyAs: KClass<*>, +) diff --git a/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentPropertiesExpected.kt b/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentPropertiesExpected.kt index 7976c268c9..01b5afa976 100644 --- a/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentPropertiesExpected.kt +++ b/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentPropertiesExpected.kt @@ -263,3 +263,12 @@ class A constructor( */ paramAddr: String, ) : B(), C

, D {} + +/** + * @property keyAs + * @property as + */ +actual annotation class JsonSerialize( + actual val `as`: KClass<*>, + actual val keyAs: KClass<*>, +) diff --git a/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentPropertiesTest.kt b/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentPropertiesTest.kt index c1c69c8fce..62563bc7ae 100644 --- a/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentPropertiesTest.kt +++ b/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentPropertiesTest.kt @@ -289,3 +289,11 @@ class A constructor( */ paramAddr: String, ) : B(), C

, D {} + +/** + * @property keyAs + */ +actual annotation class JsonSerialize( + actual val `as`: KClass<*>, + actual val keyAs: KClass<*>, +) diff --git a/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentTest.kt b/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentTest.kt index 04b7a6cab4..86c27b144b 100644 --- a/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentTest.kt +++ b/diktat-rules/src/test/resources/test/paragraph2/kdoc/ConstructorCommentTest.kt @@ -308,3 +308,13 @@ class A constructor( */ paramAddr: String, ) : B(), C

, D {} + +/** + * kdoc + * class + * comment + */ +actual annotation class JsonSerialize( + actual val `as`: KClass<*>, + actual val keyAs: KClass<*>, +)