Skip to content

Commit

Permalink
Fixed duplicate @property generation for parameter with ' in name (#…
Browse files Browse the repository at this point in the history
…1873)

### What's done:
- fixed bug.
- added fix tests.

Closes #1719
  • Loading branch information
DrAlexD authored Dec 18, 2023
1 parent beb9960 commit e51bcf6
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,8 @@ class KdocComments(configRules: List<RulesConfig>) : 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
Expand Down Expand Up @@ -303,7 +301,7 @@ class KdocComments(configRules: List<RulesConfig>) : 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) {
Expand All @@ -324,7 +322,7 @@ class KdocComments(configRules: List<RulesConfig>) : 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
Expand All @@ -334,7 +332,8 @@ class KdocComments(configRules: List<RulesConfig>) : 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)
Expand All @@ -347,23 +346,11 @@ class KdocComments(configRules: List<RulesConfig>) : 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) =
Expand Down Expand Up @@ -401,10 +388,8 @@ class KdocComments(configRules: List<RulesConfig>) : 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) {
Expand Down Expand Up @@ -456,10 +441,8 @@ class KdocComments(configRules: List<RulesConfig>) : 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)
Expand Down Expand Up @@ -500,6 +483,14 @@ class KdocComments(configRules: List<RulesConfig>) : 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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,3 +309,16 @@ class A<K : Any, P: Any, G: Any> constructor(
*/
paramAddr: String,
) : B<K>(), C<P>, D<G> {}

/**
* kdoc
* class
* comment
*
* @property as
* @property keyAs
*/
actual annotation class JsonSerialize(
actual val `as`: KClass<*>,
actual val keyAs: KClass<*>,
)
Original file line number Diff line number Diff line change
Expand Up @@ -238,3 +238,12 @@ class A<K : Any, P: Any, G: Any> constructor(
*/
paramAddr: String,
) : B<K>(), C<P>, D<G> {}

/**
* @property as
* @property keyAs
*/
actual annotation class JsonSerialize(
actual val `as`: KClass<*>,
actual val keyAs: KClass<*>,
)
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,8 @@ class A<K : Any, P: Any, G: Any> constructor(
*/
paramAddr: String,
) : B<K>(), C<P>, D<G> {}

actual annotation class JsonSerialize(
actual val `as`: KClass<*>,
actual val keyAs: KClass<*>,
)
Original file line number Diff line number Diff line change
Expand Up @@ -263,3 +263,12 @@ class A<K : Any, P: Any, G: Any> constructor(
*/
paramAddr: String,
) : B<K>(), C<P>, D<G> {}

/**
* @property keyAs
* @property as
*/
actual annotation class JsonSerialize(
actual val `as`: KClass<*>,
actual val keyAs: KClass<*>,
)
Original file line number Diff line number Diff line change
Expand Up @@ -289,3 +289,11 @@ class A<K : Any, P: Any, G: Any> constructor(
*/
paramAddr: String,
) : B<K>(), C<P>, D<G> {}

/**
* @property keyAs
*/
actual annotation class JsonSerialize(
actual val `as`: KClass<*>,
actual val keyAs: KClass<*>,
)
Original file line number Diff line number Diff line change
Expand Up @@ -308,3 +308,13 @@ class A<K : Any, P: Any, G: Any> constructor(
*/
paramAddr: String,
) : B<K>(), C<P>, D<G> {}

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

0 comments on commit e51bcf6

Please sign in to comment.