Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added AvoidSimpleDateFormat for Kotlin #294

Merged
merged 2 commits into from Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 43 additions & 0 deletions src/main/resources/category/kotlin/common.xml
Expand Up @@ -133,4 +133,47 @@ class Foo {
</example>
</rule>

<rule name="AvoidSimpleDateFormat"
class="net.sourceforge.pmd.lang.rule.XPathRule"
dfa="false"
language="kotlin"
message="SimpleDateFormat is used. Since it is thread-unsafe, it needs expensive recreation."
typeResolution="true"
externalInfoUrl="${doc_root}/JavaCodePerformance.md#idtf01">
<description>Problem: java.util.SimpleDateFormat is thread-unsafe. The usual solution is to create a new one when needed in a method. Creating SimpleDateFormat is relatively expensive. &#13;
Solution: Use java.time.DateTimeFormatter. These classes are immutable, thus thread-safe and can be made static.
(jpinpoint-rules)</description>
<priority>2</priority>
<properties>
<property name="tag" value="jpinpoint-rule" type="String" description="for-sonar"/>
<property name="version" value="3.1"/>
<property name="xpath">
<value><![CDATA[
(: check if java.text imports exists as filter for same named classes in other packages :)
//ImportHeader[.//T-Identifier[@Text='java'] and .//T-Identifier[@Text='text']][1]/../..

(: if used in setDateFormat function, allow if jackson ObjectMapper or XmlMapper is used :)
//ClassMemberDeclaration//SimpleIdentifier//T-Identifier[(@Text="SimpleDateFormat")
stokpop marked this conversation as resolved.
Show resolved Hide resolved
and not (ancestor::ClassMemberDeclaration//T-Identifier[@Text="setDateFormat"]
and //ImportHeader[.//T-Identifier[@Text='fasterxml'] and .//T-Identifier[@Text='jackson']]
)
]
]]></value>
</property>
</properties>
<example><![CDATA[
import java.text.SimpleDateFormat
import java.util.*

class Foo {
private fun toKey(calcDate: Date): String {
val formatter = SimpleDateFormat("yyyy-MM-dd") //bad
return formatter.format(calcDate)
}
}
]]>
</example>
</rule>


</ruleset>
@@ -0,0 +1,6 @@
package com.jpinpoint.perf.lang.kotlin.ruleset.common;

import net.sourceforge.pmd.testframework.PmdRuleTst;

public class AvoidSimpleDateFormatTest extends PmdRuleTst {
}
@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<test-data
xmlns="http://pmd.sourceforge.net/rule-tests"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd">
<test-code>
<description>violation: Avoid the use of SimpleDateFormat</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>6</expected-linenumbers>
<code><![CDATA[
import java.text.SimpleDateFormat
import java.util.*

class Foo {
private fun toKey(rekenDatum: Date): String {
val formatter = SimpleDateFormat("yyyy-MM-dd") //bad
return formatter.format(rekenDatum)
}
}
]]></code>
</test-code>
<test-code>
<description>no violation: SimpleDateFormat is allowed in Jackon's ObjectMapper</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.dataformat.xml.XmlMapper
import java.text.SimpleDateFormat

object Foo {
private val OBJECT_MAPPER = createObjectMapper()
private val XML_MAPPER: XmlMapper
private val unknown: Unknown = createUnknownObject()

init {
XML_MAPPER = XmlMapper()
val df = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss") // good, used in XmlMapper
XML_MAPPER.setDateFormat(df)
}

private fun createObjectMapper(): ObjectMapper {
val mapper = ObjectMapper()
mapper.setDateFormat(SimpleDateFormat("yyyy-MM-dd")) // good, used in ObjectMapper
return mapper
}

}
]]></code>
</test-code>
<test-code>
<description>violation: SimpleDateFormat is not allowed in non XmlMapper or ObjectMapper</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>8</expected-linenumbers>
<code><![CDATA[
import java.text.SimpleDateFormat

object Foo {
private val unknown: Unknown = createUnknownObject()

private fun createUnknownObject(): Unknown {
val unknown: Unknown = Unknown()
unknown.setDateFormat(SimpleDateFormat("yyyy-MM-dd")) // bad, used in unknown object
return unknown
}
}
]]></code>
</test-code>
</test-data>