Skip to content

Commit a685a55

Browse files
committed
pmd configuration
1 parent 8bc9720 commit a685a55

10 files changed

Lines changed: 521 additions & 55 deletions

File tree

.codacy/codacy.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ runtimes:
44
tools:
55
- eslint@9.3.0
66
- trivy@0.59.1
7-
- pmd@7.12.0
87
- pylint@3.3.6
8+
- pmd@6.55.0

cmd/init.go

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ var initCmd = &cobra.Command{
5555
}
5656

5757
func createConfigurationFile(tools []tools.Tool) error {
58-
5958
configFile, err := os.Create(config.Config.ProjectConfigFile())
6059
defer configFile.Close()
6160
if err != nil {
@@ -76,6 +75,7 @@ func configFileTemplate(tools []tools.Tool) string {
7675
eslintVersion := "9.3.0"
7776
trivyVersion := "0.59.1" // Latest stable version
7877
pylintVersion := "3.3.6"
78+
pmdVersion := "6.55.0"
7979

8080
for _, tool := range tools {
8181
if tool.Uuid == "f8b29663-2cb2-498d-b923-a10c6a8c05cd" {
@@ -87,6 +87,9 @@ func configFileTemplate(tools []tools.Tool) string {
8787
if tool.Uuid == "31677b6d-4ae0-4f56-8041-606a8d7a8e61" {
8888
pylintVersion = tool.Version
8989
}
90+
if tool.Uuid == "9ed24812-b6ee-4a58-9004-0ed183c45b8f" {
91+
pmdVersion = tool.Version
92+
}
9093
}
9194

9295
return fmt.Sprintf(`runtimes:
@@ -96,11 +99,11 @@ tools:
9699
- eslint@%s
97100
- trivy@%s
98101
- pylint@%s
99-
`, eslintVersion, trivyVersion, pylintVersion)
102+
- pmd@%s
103+
`, eslintVersion, trivyVersion, pylintVersion, pmdVersion)
100104
}
101105

102106
func buildRepositoryConfigurationFiles(token string) error {
103-
104107
fmt.Println("Building project configuration files ...")
105108
fmt.Println("Fetching project configuration from codacy ...")
106109

@@ -163,24 +166,38 @@ func buildRepositoryConfigurationFiles(token string) error {
163166
log.Fatal(err)
164167
}
165168

166-
// Create Trivy configuration after processing ESLint
169+
// Trivy configuration
167170
trivyApiConfiguration := extractTrivyConfiguration(apiToolConfigurations)
168171
if trivyApiConfiguration != nil {
169-
// Create trivy.yaml file based on API configuration
170172
err = createTrivyConfigFile(*trivyApiConfiguration)
171173
if err != nil {
172174
log.Fatal(err)
173175
}
174176
fmt.Println("Trivy configuration created based on Codacy settings")
175177
} else {
176-
// Create default trivy.yaml if no configuration from API
177178
err = createDefaultTrivyConfigFile()
178179
if err != nil {
179180
log.Fatal(err)
180181
}
181182
fmt.Println("Default Trivy configuration created")
182183
}
183184

185+
// PMD configuration
186+
pmdApiConfiguration := extractPMDConfiguration(apiToolConfigurations)
187+
if pmdApiConfiguration != nil {
188+
err = createPMDConfigFile(*pmdApiConfiguration)
189+
if err != nil {
190+
log.Fatal(err)
191+
}
192+
fmt.Println("PMD configuration created based on Codacy settings")
193+
} else {
194+
err = createDefaultPMDConfigFile()
195+
if err != nil {
196+
log.Fatal(err)
197+
}
198+
fmt.Println("Default PMD configuration created")
199+
}
200+
184201
return nil
185202
}
186203

@@ -239,6 +256,29 @@ func extractTrivyConfiguration(toolConfigurations []CodacyToolConfiguration) *Co
239256
return nil
240257
}
241258

259+
// Add PMD-specific functions
260+
func extractPMDConfiguration(toolConfigurations []CodacyToolConfiguration) *CodacyToolConfiguration {
261+
const PMDUUID = "9ed24812-b6ee-4a58-9004-0ed183c45b8f"
262+
for _, toolConfiguration := range toolConfigurations {
263+
if toolConfiguration.Uuid == PMDUUID {
264+
return &toolConfiguration
265+
}
266+
}
267+
return nil
268+
}
269+
270+
func createPMDConfigFile(config CodacyToolConfiguration) error {
271+
pmdDomainConfiguration := convertAPIToolConfigurationToDomain(config)
272+
pmdConfigurationString := tools.CreatePmdConfig(pmdDomainConfiguration)
273+
return os.WriteFile("pmd-ruleset.xml", []byte(pmdConfigurationString), 0644)
274+
}
275+
276+
func createDefaultPMDConfigFile() error {
277+
emptyConfig := tools.ToolConfiguration{}
278+
content := tools.CreatePmdConfig(emptyConfig)
279+
return os.WriteFile("pmd-ruleset.xml", []byte(content), 0644)
280+
}
281+
242282
type CodacyToolConfiguration struct {
243283
Uuid string `json:"uuid"`
244284
IsEnabled bool `json:"isEnabled"`

plugins/tools/pmd/plugin.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
name: pmd
22
description: PMD - An extensible cross-language static code analyzer
33
download:
4-
url_template: https://github.com/pmd/pmd/releases/download/pmd_releases%2F{{.Version}}/pmd-dist-{{.Version}}-bin.zip
5-
file_name_template: pmd-dist-{{.Version}}-bin.zip
4+
url_template: "https://github.com/pmd/pmd/releases/download/pmd_releases%2F{{.Version}}/pmd-bin-{{.Version}}.zip"
5+
file_name_template: pmd-bin-{{.Version}}
66
extension:
77
default: .zip
88
binaries:
99
- name: pmd
10-
path: pmd-bin-{{.Version}}/bin/pmd
10+
path: pmd-bin-{{.Version}}/bin/run.sh

tools/pmd/default-ruleset.xml

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ruleset name="Default PMD Ruleset"
3+
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
6+
7+
<description>Default PMD ruleset with commonly used rules</description>
8+
9+
<!-- Java Best Practices -->
10+
<rule ref="category/java/bestpractices.xml/AvoidReassigningParameters"/>
11+
<rule ref="category/java/bestpractices.xml/CheckResultSet"/>
12+
<rule ref="category/java/bestpractices.xml/JUnitTestsShouldIncludeAssert"/>
13+
<rule ref="category/java/bestpractices.xml/OneDeclarationPerLine"/>
14+
<rule ref="category/java/bestpractices.xml/SwitchStmtsShouldHaveDefault"/>
15+
<rule ref="category/java/bestpractices.xml/UnusedImports"/>
16+
<rule ref="category/java/bestpractices.xml/UnusedLocalVariable"/>
17+
<rule ref="category/java/bestpractices.xml/UnusedPrivateField"/>
18+
<rule ref="category/java/bestpractices.xml/UnusedPrivateMethod"/>
19+
20+
<!-- Java Code Style -->
21+
<rule ref="category/java/codestyle.xml/ClassNamingConventions">
22+
<properties>
23+
<property name="classPattern" value="[A-Z][a-zA-Z0-9]*"/>
24+
<property name="abstractClassPattern" value="Abstract[A-Z][a-zA-Z0-9]*"/>
25+
<property name="interfacePattern" value="[A-Z][a-zA-Z0-9]*"/>
26+
<property name="enumPattern" value="[A-Z][a-zA-Z0-9]*"/>
27+
<property name="annotationPattern" value="[A-Z][a-zA-Z0-9]*"/>
28+
</properties>
29+
</rule>
30+
<rule ref="category/java/codestyle.xml/MethodNamingConventions">
31+
<properties>
32+
<property name="methodPattern" value="[a-z][a-zA-Z0-9]*"/>
33+
<property name="staticPattern" value="[a-z][a-zA-Z0-9]*"/>
34+
<property name="nativePattern" value="[a-z][a-zA-Z0-9]*"/>
35+
</properties>
36+
</rule>
37+
<rule ref="category/java/codestyle.xml/DefaultPackage"/>
38+
<rule ref="category/java/codestyle.xml/DontImportJavaLang"/>
39+
<rule ref="category/java/codestyle.xml/ExtendsObject"/>
40+
<rule ref="category/java/codestyle.xml/FieldDeclarationsShouldBeAtStartOfClass"/>
41+
<rule ref="category/java/codestyle.xml/GenericsNaming"/>
42+
<rule ref="category/java/codestyle.xml/NoPackage"/>
43+
<rule ref="category/java/codestyle.xml/PackageCase"/>
44+
45+
<!-- Java Design -->
46+
<rule ref="category/java/design.xml/AvoidThrowingNullPointerException"/>
47+
<rule ref="category/java/design.xml/AvoidThrowingRawExceptionTypes"/>
48+
<rule ref="category/java/design.xml/CollapsibleIfStatements"/>
49+
<rule ref="category/java/design.xml/ExcessiveClassLength">
50+
<properties>
51+
<property name="minimum" value="1000"/>
52+
</properties>
53+
</rule>
54+
<rule ref="category/java/design.xml/ExcessiveMethodLength">
55+
<properties>
56+
<property name="minimum" value="50"/>
57+
</properties>
58+
</rule>
59+
<rule ref="category/java/design.xml/ExcessiveParameterList">
60+
<properties>
61+
<property name="minimum" value="10"/>
62+
</properties>
63+
</rule>
64+
<rule ref="category/java/design.xml/SimplifyBooleanReturns"/>
65+
<rule ref="category/java/design.xml/SimplifyBooleanExpressions"/>
66+
67+
<!-- Java Error Prone -->
68+
<rule ref="category/java/errorprone.xml/AvoidBranchingStatementAsLastInLoop"/>
69+
<rule ref="category/java/errorprone.xml/AvoidDecimalLiteralsInBigDecimalConstructor"/>
70+
<rule ref="category/java/errorprone.xml/AvoidMultipleUnaryOperators"/>
71+
<rule ref="category/java/errorprone.xml/AvoidCallingFinalize"/>
72+
<rule ref="category/java/errorprone.xml/EmptyIfStmt"/>
73+
<rule ref="category/java/errorprone.xml/EmptyTryBlock"/>
74+
<rule ref="category/java/errorprone.xml/EmptyFinallyBlock"/>
75+
<rule ref="category/java/errorprone.xml/EmptyWhileStmt"/>
76+
<rule ref="category/java/errorprone.xml/CompareObjectsWithEquals"/>
77+
<rule ref="category/java/errorprone.xml/UseEqualsToCompareStrings"/>
78+
79+
<!-- Java Performance -->
80+
<rule ref="category/java/performance.xml/BooleanInstantiation"/>
81+
<rule ref="category/java/performance.xml/StringInstantiation"/>
82+
<rule ref="category/java/performance.xml/StringToString"/>
83+
<rule ref="category/java/performance.xml/UseStringBufferLength"/>
84+
85+
<!-- Java Documentation -->
86+
<rule ref="category/java/documentation.xml/UncommentedEmptyMethodBody"/>
87+
88+
<!-- JavaScript Best Practices -->
89+
<rule ref="category/ecmascript/bestpractices.xml/AvoidWithStatement"/>
90+
<rule ref="category/ecmascript/bestpractices.xml/ConsistentReturn"/>
91+
<rule ref="category/ecmascript/bestpractices.xml/UseBaseWithParseInt"/>
92+
93+
<!-- JSP Design -->
94+
<rule ref="category/jsp/design.xml/NoInlineScript"/>
95+
<rule ref="category/jsp/design.xml/NoInlineStyleInformation"/>
96+
<rule ref="category/jsp/design.xml/NoScriptlets"/>
97+
98+
<!-- XML Error Prone -->
99+
<rule ref="category/xml/errorprone.xml/MistypedCDATASection"/>
100+
101+
</ruleset>

tools/pmdConfigCreator.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package tools
2+
3+
import (
4+
_ "embed"
5+
"fmt"
6+
"strings"
7+
)
8+
9+
//go:embed pmd/default-ruleset.xml
10+
var defaultPMDRuleset string
11+
12+
func CreatePmdConfig(configuration ToolConfiguration) string {
13+
// If no patterns provided, return the default ruleset
14+
if len(configuration.PatternsConfiguration) == 0 {
15+
return defaultPMDRuleset
16+
}
17+
18+
var contentBuilder strings.Builder
19+
20+
// Write XML header and ruleset opening with correct name
21+
contentBuilder.WriteString("<?xml version=\"1.0\"?>\n")
22+
contentBuilder.WriteString("<ruleset name=\"Codacy PMD Ruleset\"\n")
23+
contentBuilder.WriteString(" xmlns=\"http://pmd.sourceforge.net/ruleset/2.0.0\"\n")
24+
contentBuilder.WriteString(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n")
25+
contentBuilder.WriteString(" xsi:schemaLocation=\"http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd\">\n\n")
26+
27+
// Process patterns from configuration
28+
for _, pattern := range configuration.PatternsConfiguration {
29+
// Check if pattern is enabled
30+
patternEnabled := true
31+
var properties []string
32+
33+
for _, param := range pattern.ParamenterConfigurations {
34+
if param.Name == "enabled" && param.Value == "false" {
35+
patternEnabled = false
36+
break
37+
} else if param.Name != "enabled" {
38+
// Store non-enabled parameters for properties
39+
properties = append(properties, fmt.Sprintf(" <property name=\"%s\" value=\"%s\"/>", param.Name, param.Value))
40+
}
41+
}
42+
43+
if patternEnabled {
44+
// Convert pattern ID to correct PMD path format
45+
// e.g., "java/codestyle/AtLeastOneConstructor" -> "category/java/codestyle.xml/AtLeastOneConstructor"
46+
parts := strings.Split(pattern.PatternId, "/")
47+
if len(parts) >= 2 {
48+
category := parts[len(parts)-2]
49+
rule := parts[len(parts)-1]
50+
contentBuilder.WriteString(fmt.Sprintf(" <rule ref=\"category/java/%s.xml/%s\"", category, rule))
51+
52+
// Add properties if any exist
53+
if len(properties) > 0 {
54+
contentBuilder.WriteString(">\n <properties>\n")
55+
for _, prop := range properties {
56+
contentBuilder.WriteString(prop + "\n")
57+
}
58+
contentBuilder.WriteString(" </properties>\n </rule>\n")
59+
} else {
60+
contentBuilder.WriteString("/>\n")
61+
}
62+
}
63+
}
64+
}
65+
66+
contentBuilder.WriteString("</ruleset>")
67+
return contentBuilder.String()
68+
}

0 commit comments

Comments
 (0)