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

Kotlin rule completion AvoidInMemoryStreamingDefaultConstructor #290

Merged
merged 6 commits into from Mar 1, 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
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