Skip to content

Commit

Permalink
Merge pull request #290 from jborgers/kotlin/AvoidInMemoryStreamingDe…
Browse files Browse the repository at this point in the history
…faultContructor

Kotlin rule completion AvoidInMemoryStreamingDefaultConstructor
  • Loading branch information
stokpop committed Mar 1, 2024
2 parents 14f736c + 2aeb189 commit d858c47
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 22 deletions.
8 changes: 4 additions & 4 deletions docs/EvaluateRulesForKotlin.md
Expand Up @@ -11,12 +11,12 @@ Evaluation of Java PMD rules for use as Kotlin rules
| 5. | | AvoidImplicitlyRecompilingRegex | Yes | High | Yes | High | Not found | Kotlin has own String/regex, also occurs here? support both? |
| 6. | JB-1 | AvoidInMemoryStreamingDefaultConstructor | Yes | Low | Yes | High | Not found | Kotlin types? -> No |
| 7. | | AvoidMultipleConcatStatements | Yes | Medium | Yes | High | Not found | How concat in Kotlin? Seems like Java |
| 8. | | AvoidRecompilingPatterns | Yes | Low/Medium | Yes | High | Not found | Kotlin version? |
| 9. | | AvoidRecompilingXPathExpression | Yes | Low | Yes | Medium/High | Not found | Good example ThreadLocal in Kotlin? |
| 8. | PP-3 | AvoidRecompilingPatterns | Yes | Low/Medium | Yes | High | Not found | Kotlin version? |
| 9. | JB-3 | AvoidRecompilingXPathExpression | Yes | Low | Yes | Medium/High | Not found | Good example ThreadLocal in Kotlin? |
| 10. | | AvoidRecreatingDateTimeFormatter | Yes | Medium | Yes | High | Not found | - |
| 11. | | AvoidReflectionInToStringAndHashCode | Yes | Low/Medium | Yes | Low/Medium | Not found | - |
| 12. | | AvoidSimpleDateFormat | Yes | Low | Yes | Medium | Not found | |
| 13. | | AvoidStringBuffer | Yes | Low | Yes | Low/Medium | Not found | |
| 12. | PP-2 | AvoidSimpleDateFormat | Yes | Low | Yes | Medium | Not found | |
| 13. | JB-2 | AvoidStringBuffer | Yes | Low | Yes | Low/Medium | Not found | |
| 14. | | AvoidUnconditionalBuiltLogStrings | Yes | High | Yes | Medium | Not found | |
| 15. | | AvoidWideScopeXPathExpression | Yes | Low | Yes | Medium | Not found | |
| 16. | | AvoidXPathAPIUsage | Yes | Low | Yes | Medium | Not found | remove VTD reference?, seems old, better alternatives? |
Expand Down
10 changes: 5 additions & 5 deletions pom.xml
Expand Up @@ -15,8 +15,8 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>6.0.9</spring.version>
<pmd.version>6.55.0</pmd.version>
<pmd.kotlin.version>7.0.0-SNAPSHOT</pmd.kotlin.version>
<!--pmd.version>6.55.0</pmd.version>
<pmd.kotlin.version>7.0.0-rc4</pmd.kotlin.version-->
</properties>

<build>
Expand Down Expand Up @@ -193,9 +193,9 @@
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<!--properties>
<pmd.version>6.51.0</pmd.version>
</properties-->
<properties>
<pmd.version>6.55.0</pmd.version>
</properties>
<build>
<plugins>
<plugin>
Expand Down
9 changes: 5 additions & 4 deletions rulesets/java/jpinpoint-rules.xml
Expand Up @@ -300,9 +300,10 @@ VariableInitializer/Expression/PrimaryExpression/PrimaryPrefix/Literal[string-le
</properties>
</rule>

<rule name="AvoidInMemoryStreamingDefaultConstructor" class="net.sourceforge.pmd.lang.rule.XPathRule" dfa="false" language="java" message="Default capacity or smaller is used for ByteArrayOutputStream or StringWriter, it usually needs expensive expansions." typeResolution="true"
<rule name="AvoidInMemoryStreamingDefaultConstructor" class="net.sourceforge.pmd.lang.rule.XPathRule" dfa="false" language="java"
message="The default capacity or smaller is used for ByteArrayOutputStream or StringWriter, it usually needs expensive expansions." typeResolution="true"
externalInfoUrl="https://github.com/jborgers/PMD-jPinpoint-rules/tree/master/docs/JavaCodePerformance.md#isio01">
<description>The default constructor of ByteArrayOutputStream creates a 32 bytes initial capacity and for StringWriter 16 chars. Problem: Such a small buffer as capacity usually needs several expensive expansions.&#13;
<description>Problem: The default constructor of ByteArrayOutputStream creates a 32 bytes initial capacity and for StringWriter 16 chars. Problem: Such a small buffer as capacity usually needs several expensive expansions.&#13;
Solution: Presize the ByteArrayOutputStream or StringWriter with an initial capacity such that an expansion is not needed in most cases, typically much larger than 32, for instance 4096.
(jpinpoint-rules)</description>
<priority>2</priority>
Expand Down Expand Up @@ -721,12 +722,12 @@ ancestor::MethodDeclaration/MethodDeclarator/FormalParameters/FormalParameter/Va

<rule name="AvoidRecreatingSecurityProviders"
language="java"
message="Avoid re-creating security providers."
message="Avoid re-creating security providers, this is expensive."
class="net.sourceforge.pmd.lang.rule.XPathRule"
typeResolution="true"
externalInfoUrl="https://github.com/jborgers/PMD-jPinpoint-rules/tree/master/docs/JavaCodePerformance.md#iuosf01">
<description>Problem: Creating a security provider is expensive because of loading of algorithms and other classes. Additionally, it uses synchronized which leads to lock contention when used with multiple threads.
Solution: This only needs to happen once in the JVM lifetime, because once loaded, the provider is available from the Security class. Create the security provider only once: only in case it is nog available from the Security class, yet.
Solution: This only needs to happen once in the JVM lifetime, because once loaded, the provider is typically available from the Security class. Create the security provider only once: only in case it is nog available from the Security class, yet.
(jpinpoint-rules)</description>
<priority>2</priority>
<properties>
Expand Down
7 changes: 5 additions & 2 deletions rulesets/kotlin/jpinpoint-kotlin-rules.xml
Expand Up @@ -30,7 +30,10 @@
<property name="xpath">
<value><![CDATA[
//ImportHeader[.//T-Identifier[@Text='java'] and .//T-Identifier[@Text='io']]/ancestor::KotlinFile
//Expression//T-Identifier[@Text='ByteArrayOutputStream' or @Text='StringWriter']/../../../PostfixUnarySuffix//ValueArguments[not(ValueArgument)]/../../..
//Expression//T-Identifier[(@Text='ByteArrayOutputStream' and ../../../
PostfixUnarySuffix//ValueArguments[not(ValueArgument) or ValueArgument//T-IntegerLiteral[number(@Text)<=32]])
or (@Text='StringWriter' and ../../../
PostfixUnarySuffix//ValueArguments[not(ValueArgument) or ValueArgument//T-IntegerLiteral[number(@Text)<=16]])]
]]>
</value>
</property>
Expand All @@ -43,7 +46,7 @@ class AvoidInMemoryStreamingDefaultConstructor {
fun bad() {
var baos = ByteArrayOutputStream() //bad
val sw = StringWriter() //bad
baos = ByteArrayOutputStream(32) //bad - not larger than default // TODO
baos = ByteArrayOutputStream(32) //bad - not larger than default
}
fun good() {
val baos = ByteArrayOutputStream(8192) // 8 kiB
Expand Down
9 changes: 6 additions & 3 deletions src/main/resources/category/kotlin/common.xml
Expand Up @@ -20,8 +20,11 @@
<property name="version" value="3.1"/>
<property name="xpath">
<value><![CDATA[
//ImportHeader[.//T-Identifier[@Text='java'] and .//T-Identifier[@Text='io']]/ancestor::KotlinFile
//Expression//T-Identifier[@Text='ByteArrayOutputStream' or @Text='StringWriter']/../../../PostfixUnarySuffix//ValueArguments[not(ValueArgument)]/../../..
//ImportHeader[.//T-Identifier[@Text='java'] and .//T-Identifier[@Text='io']][1]/ancestor::KotlinFile
//Expression//T-Identifier[(@Text='ByteArrayOutputStream' and ../../../
PostfixUnarySuffix//ValueArguments[not(ValueArgument) or ValueArgument//T-IntegerLiteral[number(@Text)<=32]])
or (@Text='StringWriter' and ../../../
PostfixUnarySuffix//ValueArguments[not(ValueArgument) or ValueArgument//T-IntegerLiteral[number(@Text)<=16]])]
]]>
</value>
</property>
Expand All @@ -34,7 +37,7 @@ class AvoidInMemoryStreamingDefaultConstructor {
fun bad() {
var baos = ByteArrayOutputStream() //bad
val sw = StringWriter() //bad
baos = ByteArrayOutputStream(32) //bad - not larger than default // TODO
baos = ByteArrayOutputStream(32) //bad - not larger than default
}
fun good() {
val baos = ByteArrayOutputStream(8192) // 8 kiB
Expand Down
Expand Up @@ -25,20 +25,22 @@ class AvoidInMemoryStreamingDefaultConstructor {
</test-code>

<test-code>
<description>AvoidInMemoryStreamingDefaultConstructor - capacity not larger than default - TODO</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>6</expected-linenumbers>
<description>AvoidInMemoryStreamingDefaultConstructor - capacity not larger than default </description>
<expected-problems>2</expected-problems>
<expected-linenumbers>6,7</expected-linenumbers>
<code><![CDATA[
import java.io.ByteArrayOutputStream
import java.io.StringWriter
class AvoidInMemoryStreamingDefaultConstructor {
fun bad() {
baos = ByteArrayOutputStream(32) //bad - not larger than default
val baos = ByteArrayOutputStream(32) //bad - not larger than default
val sw = StringWriter(16) //bad - not larger than default
}
fun good() {
val baos = ByteArrayOutputStream(8192) // 8 kiB
val sw = StringWriter(2048)
val sw2 = StringWriter(17)
}
}
]]></code>
Expand Down

0 comments on commit d858c47

Please sign in to comment.