88 "strings"
99)
1010
11- //go:embed pmd/default-ruleset.xml
12- var defaultPMDRuleset string
13-
1411// Parameter represents a rule parameter
1512type Parameter struct {
1613 Name string
@@ -33,9 +30,14 @@ type RuleSet struct {
3330}
3431
3532// DeprecatedReferences maps deprecated pattern IDs to their new versions
36- var DeprecatedReferences = map [string ]string {
37- // Add deprecated pattern mappings here
38- // Example: "rulesets_java_design_ExcessiveClassLength": "category_java_design_ExcessiveClassLength",
33+ var DeprecatedReferences = map [string ]string {}
34+
35+ func CreatePmd6Config (configuration []domain.PatternConfiguration ) string {
36+ return createPmdConfigGeneric (configuration , pmd6Header , convertPatternIDToPMD , false )
37+ }
38+
39+ func CreatePmd7Config (configuration []domain.PatternConfiguration ) string {
40+ return createPmdConfigGeneric (configuration , pmd7Header , convertPatternIDToPMD , true )
3941}
4042
4143// prefixPatternID adds the appropriate prefix to a pattern ID
@@ -59,128 +61,74 @@ func prefixPatternID(patternID string) string {
5961 }
6062}
6163
62- // convertPatternIDToPMD converts a Codacy pattern ID to PMD format
63- func convertPatternIDToPMD (patternID string ) (string , error ) {
64- // Check if this is a deprecated pattern
64+ func convertPatternIDToPMD (patternID string , isPmd7 bool ) (string , error ) {
65+ // Normalize deprecated patterns
6566 if newID , ok := DeprecatedReferences [patternID ]; ok {
6667 patternID = newID
6768 }
6869
69- // Handle both formats:
70- // 1. "java/design/NPathComplexity"
71- // 2. "PMD_category_java_design_NPathComplexity"
72- // 3. "PMD_category_apex_security_ApexSharingViolations"
73- // 4. "PMD_category_plsql_errorprone_TO_TIMESTAMPWithoutDateFormat"
70+ // Normalize version-specific prefixes
71+ if isPmd7 {
72+ patternID = strings .TrimPrefix (patternID , "PMD7_" )
73+ } else {
74+ patternID = strings .TrimPrefix (patternID , "PMD_" )
75+ }
7476
7577 var parts []string
78+
79+ // Handle different ID formats
7680 if strings .Contains (patternID , "/" ) {
81+ // Already in path form: lang/category/rule
7782 parts = strings .Split (patternID , "/" )
83+ if len (parts ) < 3 {
84+ return "" , fmt .Errorf ("invalid PMD path pattern ID: %s" , patternID )
85+ }
86+ lang , category := parts [0 ], parts [1 ]
87+ rule := strings .Join (parts [2 :], "/" )
88+ return fmt .Sprintf ("rulesets/%s/%s.xml/%s" , lang , category , rule ), nil
89+ }
90+
91+ // Handle underscore-based Codacy pattern IDs
92+ parts = strings .Split (patternID , "_" )
93+ if isPmd7 {
94+ // Expect category_lang_category_rule
95+ if len (parts ) < 4 || parts [0 ] != "category" {
96+ return "" , fmt .Errorf ("invalid PMD 7 pattern ID: %s" , patternID )
97+ }
98+ lang := parts [1 ]
99+ category := parts [2 ]
100+ rule := strings .Join (parts [3 :], "_" )
101+ return fmt .Sprintf ("category/%s/%s.xml/%s" , lang , category , rule ), nil
78102 } else {
79- // Remove PMD_ prefix if present
80- id := strings .TrimPrefix (patternID , "PMD_" )
81- // Split by underscore and remove "category" if present
82- parts = strings .Split (id , "_" )
103+ // PMD 6: expect lang_category_rule
83104 if parts [0 ] == "category" {
84105 parts = parts [1 :]
85106 }
86- }
87-
88- if len (parts ) < 3 {
89- return "" , fmt .Errorf ("invalid pattern ID format: %s" , patternID )
90- }
91-
92- // Extract language, category, and rule
93- language := parts [0 ] // java, apex, etc.
94- category := parts [1 ] // design, security, etc.
95- rule := parts [2 ] // rule name
96-
97- // If there are more parts, combine them with the rule name
98- if len (parts ) > 3 {
99- rule = strings .Join (parts [2 :], "_" )
100- }
101-
102- return fmt .Sprintf ("category/%s/%s.xml/%s" , language , category , rule ), nil
103- }
104-
105- // convertPatternIDToPMD7 converts a Codacy pattern ID to PMD 7 format
106- func convertPatternIDToPMD7 (patternID string ) (string , error ) {
107- // Strip deprecated mappings
108- if newID , ok := DeprecatedReferences [patternID ]; ok {
109- patternID = newID
110- }
111-
112- // Remove "PMD7_" prefix if present
113- patternID = strings .TrimPrefix (patternID , "PMD7_" )
114-
115- // Now handle patternIDs like: category_java_bestpractices_UnusedLocalVariable
116- parts := strings .Split (patternID , "_" )
117-
118- if len (parts ) < 4 || parts [0 ] != "category" {
119- return "" , fmt .Errorf ("invalid PMD 7 pattern ID: %s" , patternID )
120- }
121-
122- lang := parts [1 ]
123- category := parts [2 ]
124- rule := strings .Join (parts [3 :], "_" )
125-
126- return fmt .Sprintf ("category/%s/%s.xml/%s" , lang , category , rule ), nil
127- }
128-
129- // generateRuleXML generates XML for a single rule
130- func generateRuleXML (rule Rule ) (string , error ) {
131- pmdRef , err := convertPatternIDToPMD (rule .PatternID )
132- if err != nil {
133- return "" , err
134- }
135-
136- if len (rule .Parameters ) == 0 {
137- return fmt .Sprintf (` <rule ref="%s"/>` , pmdRef ), nil
138- }
139-
140- // Generate rule with parameters
141- var params strings.Builder
142- for _ , param := range rule .Parameters {
143- // Skip enabled and version parameters, but include all others
144- if param .Name != "enabled" && param .Name != "version" {
145- params .WriteString (fmt .Sprintf (`
146- <property name="%s" value="%s"/>` , param .Name , param .Value ))
107+ if len (parts ) < 3 {
108+ return "" , fmt .Errorf ("invalid PMD 6 pattern ID: %s" , patternID )
147109 }
110+ lang := parts [0 ]
111+ category := parts [1 ]
112+ rule := strings .Join (parts [2 :], "_" )
113+ return fmt .Sprintf ("rulesets/%s/%s.xml/%s" , lang , category , rule ), nil
148114 }
149-
150- // If no parameters left after filtering, just output the rule without properties
151- if params .Len () == 0 {
152- return fmt .Sprintf (` <rule ref="%s"/>` , pmdRef ), nil
153- }
154-
155- result := fmt .Sprintf (` <rule ref="%s">
156- <properties>%s
157- </properties>
158- </rule>` , pmdRef , params .String ())
159-
160- return result , nil
161115}
162116
163- // Add PMD 7 header
164- var pmd7Header = `<?xml version="1.0" encoding="UTF-8"?>
165- <ruleset name="Codacy PMD 7 Ruleset"
166- xmlns="https://pmd.github.io/ruleset/2.0.0"
167- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
168- xsi:schemaLocation="https://pmd.github.io/ruleset/2.0.0 https://pmd.github.io/schemas/pmd-7.0.0.xsd">
169- <description>Codacy PMD 7 Ruleset</description>`
170-
171117// createPmdConfigGeneric abstracts the config creation for both PMD and PMD7
172118func createPmdConfigGeneric (
173119 configuration []domain.PatternConfiguration ,
174120 header string ,
175- convertPatternID func (string ) (string , error ),
121+ convertPatternID func (string , bool ) (string , error ),
176122 isPMD7 bool ,
177123) string {
178124 if len (configuration ) == 0 {
179125 // Fallback empty ruleset for PMD 7, or default for PMD 6
180126 if header == pmd7Header {
181127 return header + `</ruleset>`
182128 }
183- return defaultPMDRuleset
129+
130+ return pmd6Header + `</ruleset>`
131+
184132 }
185133
186134 var rules []Rule
@@ -235,7 +183,7 @@ func createPmdConfigGeneric(
235183 continue
236184 }
237185
238- ref , err := convertPatternID (rule .PatternID )
186+ ref , err := convertPatternID (rule .PatternID , isPMD7 )
239187 if err != nil {
240188 continue
241189 }
@@ -268,18 +216,17 @@ func createPmdConfigGeneric(
268216 return rulesetXML .String ()
269217}
270218
271- // CreatePmdConfig creates a PMD 6 configuration from the provided tool configuration
272- func CreatePmdConfig (configuration []domain.PatternConfiguration ) string {
273- return createPmdConfigGeneric (configuration , `<?xml version="1.0"?>
274- <ruleset name="Codacy PMD Ruleset"
275- xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
276- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
277- xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
278- <description>Codacy PMD Ruleset</description>
279-
280- ` , convertPatternIDToPMD , false )
281- }
219+ var pmd7Header = `<?xml version="1.0" encoding="UTF-8"?>
220+ <ruleset name="Codacy PMD 7 Ruleset"
221+ xmlns="https://pmd.github.io/ruleset/2.0.0"
222+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
223+ xsi:schemaLocation="https://pmd.github.io/ruleset/2.0.0 https://pmd.github.io/schemas/pmd-7.0.0.xsd">
224+ <description>Codacy PMD 7 Ruleset</description>`
282225
283- func CreatePmd7Config (configuration []domain.PatternConfiguration ) string {
284- return createPmdConfigGeneric (configuration , pmd7Header , convertPatternIDToPMD7 , true )
285- }
226+ var pmd6Header = `<?xml version="1.0"?>
227+ <ruleset name="Codacy PMD Ruleset"
228+ xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
229+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
230+ xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
231+ <description>Codacy PMD Ruleset</description>
232+ `
0 commit comments