Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .codacy/codacy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ tools:
- eslint@9.3.0
- trivy@0.59.1
- pylint@3.3.6
- pmd@7.12.0
- pmd@6.55.0
59 changes: 49 additions & 10 deletions cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@
}

func createConfigurationFile(tools []tools.Tool) error {

configFile, err := os.Create(config.Config.ProjectConfigFile())
defer configFile.Close()
if err != nil {
Expand All @@ -86,7 +85,8 @@
eslintVersion := "9.3.0"
trivyVersion := "0.59.1" // Latest stable version
pylintVersion := "3.3.6"
pmdVersion := "7.12.0"
pmdVersion := "6.55.0"

for _, tool := range tools {
if tool.Uuid == "f8b29663-2cb2-498d-b923-a10c6a8c05cd" {
eslintVersion = tool.Version
Expand All @@ -97,6 +97,9 @@
if tool.Uuid == "31677b6d-4ae0-4f56-8041-606a8d7a8e61" {
pylintVersion = tool.Version
}
if tool.Uuid == "9ed24812-b6ee-4a58-9004-0ed183c45b8f" {
pmdVersion = tool.Version
}
}

return fmt.Sprintf(`runtimes:
Expand All @@ -111,7 +114,6 @@
}

func buildRepositoryConfigurationFiles(token string) error {

fmt.Println("Building project configuration files ...")
fmt.Println("Fetching project configuration from codacy ...")

Expand Down Expand Up @@ -174,24 +176,38 @@
log.Fatal(err)
}

// Create Trivy configuration after processing ESLint
// Trivy configuration
trivyApiConfiguration := extractTrivyConfiguration(apiToolConfigurations)
if trivyApiConfiguration != nil {
// Create trivy.yaml file based on API configuration
err = createTrivyConfigFile(*trivyApiConfiguration)
if err != nil {
log.Fatal(err)
}
fmt.Println("Trivy configuration created based on Codacy settings")
} else {
// Create default trivy.yaml if no configuration from API
err = createDefaultTrivyConfigFile()
if err != nil {
log.Fatal(err)
}
fmt.Println("Default Trivy configuration created")
}

// PMD configuration
pmdApiConfiguration := extractPMDConfiguration(apiToolConfigurations)

Check notice on line 196 in cmd/init.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cmd/init.go#L196

var pmdApiConfiguration should be pmdAPIConfiguration
if pmdApiConfiguration != nil {
err = createPMDConfigFile(*pmdApiConfiguration)
if err != nil {
log.Fatal(err)
}
fmt.Println("PMD configuration created based on Codacy settings")
} else {
err = createDefaultPMDConfigFile()
if err != nil {
log.Fatal(err)
}
fmt.Println("Default PMD configuration created")
}

return nil
}

Expand All @@ -211,8 +227,8 @@
patterns = append(
patterns,
tools.PatternConfiguration{
PatternId: pattern.InternalId,
ParamenterConfigurations: parameters,
PatternId: pattern.InternalId,
ParameterConfigurations: parameters,
},
)
}
Expand Down Expand Up @@ -250,6 +266,29 @@
return nil
}

// Add PMD-specific functions
func extractPMDConfiguration(toolConfigurations []CodacyToolConfiguration) *CodacyToolConfiguration {
const PMDUUID = "9ed24812-b6ee-4a58-9004-0ed183c45b8f"
for _, toolConfiguration := range toolConfigurations {
if toolConfiguration.Uuid == PMDUUID {
return &toolConfiguration
}
}
return nil
}

func createPMDConfigFile(config CodacyToolConfiguration) error {
pmdDomainConfiguration := convertAPIToolConfigurationToDomain(config)
pmdConfigurationString := tools.CreatePmdConfig(pmdDomainConfiguration)
return os.WriteFile("pmd-ruleset.xml", []byte(pmdConfigurationString), 0644)

Check warning on line 283 in cmd/init.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cmd/init.go#L283

The application was found setting file permissions to overly permissive values.
}

func createDefaultPMDConfigFile() error {
emptyConfig := tools.ToolConfiguration{}
content := tools.CreatePmdConfig(emptyConfig)
return os.WriteFile("pmd-ruleset.xml", []byte(content), 0644)

Check warning on line 289 in cmd/init.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cmd/init.go#L289

The application was found setting file permissions to overly permissive values.
}

type CodacyToolConfiguration struct {
Uuid string `json:"uuid"`
IsEnabled bool `json:"isEnabled"`
Expand Down Expand Up @@ -306,8 +345,8 @@
patterns = append(
patterns,
tools.PatternConfiguration{
PatternId: pattern.InternalId,
ParamenterConfigurations: parameters,
PatternId: pattern.InternalId,
ParameterConfigurations: parameters,
},
)
}
Expand Down
6 changes: 3 additions & 3 deletions plugins/tools/pmd/plugin.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
name: pmd
description: PMD - An extensible cross-language static code analyzer
download:
url_template: https://github.com/pmd/pmd/releases/download/pmd_releases%2F{{.Version}}/pmd-dist-{{.Version}}-bin.zip
file_name_template: pmd-dist-{{.Version}}-bin.zip
url_template: "https://github.com/pmd/pmd/releases/download/pmd_releases%2F{{.Version}}/pmd-bin-{{.Version}}.zip"
file_name_template: pmd-bin-{{.Version}}
extension:
default: .zip
binaries:
- name: pmd
path: pmd-bin-{{.Version}}/bin/pmd
path: pmd-bin-{{.Version}}/bin/run.sh
4 changes: 2 additions & 2 deletions tools/ToolConfigurationStruct.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ type PatternParameterConfiguration struct {
}

type PatternConfiguration struct {
PatternId string
ParamenterConfigurations []PatternParameterConfiguration
PatternId string
ParameterConfigurations []PatternParameterConfiguration
}

type ToolConfiguration struct {
Expand Down
4 changes: 2 additions & 2 deletions tools/eslintConfigCreator.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ func CreateEslintConfig(configuration ToolConfiguration) string {

parametersString := ""

for _, parameter := range patternConfiguration.ParamenterConfigurations {
for _, parameter := range patternConfiguration.ParameterConfigurations {
if parameter.Name == "unnamedParam" {
parametersString += quoteWhenIsNotJson(parameter.Value)
}
}

// build named parameters json object
namedParametersString := ""
for _, parameter := range patternConfiguration.ParamenterConfigurations {
for _, parameter := range patternConfiguration.ParameterConfigurations {

if parameter.Name != "unnamedParam" {
if len(namedParametersString) == 0 {
Expand Down
6 changes: 3 additions & 3 deletions tools/eslintConfigCreator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func TestCreateEslintConfigUnnamedParam(t *testing.T) {
PatternsConfiguration: []PatternConfiguration{
{
PatternId: "ESLint8_semi",
ParamenterConfigurations: []PatternParameterConfiguration{
ParameterConfigurations: []PatternParameterConfiguration{
{
Name: "unnamedParam",
Value: "never",
Expand All @@ -70,7 +70,7 @@ func TestCreateEslintConfigNamedParam(t *testing.T) {
PatternsConfiguration: []PatternConfiguration{
{
PatternId: "consistent-return",
ParamenterConfigurations: []PatternParameterConfiguration{
ParameterConfigurations: []PatternParameterConfiguration{
{
Name: "treatUndefinedAsUnspecified",
Value: "false",
Expand All @@ -94,7 +94,7 @@ func TestCreateEslintConfigUnnamedAndNamedParam(t *testing.T) {
PatternsConfiguration: []PatternConfiguration{
{
PatternId: "consistent-return",
ParamenterConfigurations: []PatternParameterConfiguration{
ParameterConfigurations: []PatternParameterConfiguration{
{
Name: "treatUndefinedAsUnspecified",
Value: "false",
Expand Down
101 changes: 101 additions & 0 deletions tools/pmd/default-ruleset.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="Default PMD Ruleset"
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">

<description>Default PMD ruleset with commonly used rules</description>

<!-- Java Best Practices -->
<rule ref="category/java/bestpractices.xml/AvoidReassigningParameters"/>
<rule ref="category/java/bestpractices.xml/CheckResultSet"/>
<rule ref="category/java/bestpractices.xml/JUnitTestsShouldIncludeAssert"/>
<rule ref="category/java/bestpractices.xml/OneDeclarationPerLine"/>
<rule ref="category/java/bestpractices.xml/SwitchStmtsShouldHaveDefault"/>
<rule ref="category/java/bestpractices.xml/UnusedImports"/>
<rule ref="category/java/bestpractices.xml/UnusedLocalVariable"/>
<rule ref="category/java/bestpractices.xml/UnusedPrivateField"/>
<rule ref="category/java/bestpractices.xml/UnusedPrivateMethod"/>

<!-- Java Code Style -->
<rule ref="category/java/codestyle.xml/ClassNamingConventions">
<properties>
<property name="classPattern" value="[A-Z][a-zA-Z0-9]*"/>
<property name="abstractClassPattern" value="Abstract[A-Z][a-zA-Z0-9]*"/>
<property name="interfacePattern" value="[A-Z][a-zA-Z0-9]*"/>
<property name="enumPattern" value="[A-Z][a-zA-Z0-9]*"/>
<property name="annotationPattern" value="[A-Z][a-zA-Z0-9]*"/>
</properties>
</rule>
<rule ref="category/java/codestyle.xml/MethodNamingConventions">
<properties>
<property name="methodPattern" value="[a-z][a-zA-Z0-9]*"/>
<property name="staticPattern" value="[a-z][a-zA-Z0-9]*"/>
<property name="nativePattern" value="[a-z][a-zA-Z0-9]*"/>
</properties>
</rule>
<rule ref="category/java/codestyle.xml/DefaultPackage"/>
<rule ref="category/java/codestyle.xml/DontImportJavaLang"/>
<rule ref="category/java/codestyle.xml/ExtendsObject"/>
<rule ref="category/java/codestyle.xml/FieldDeclarationsShouldBeAtStartOfClass"/>
<rule ref="category/java/codestyle.xml/GenericsNaming"/>
<rule ref="category/java/codestyle.xml/NoPackage"/>
<rule ref="category/java/codestyle.xml/PackageCase"/>

<!-- Java Design -->
<rule ref="category/java/design.xml/AvoidThrowingNullPointerException"/>
<rule ref="category/java/design.xml/AvoidThrowingRawExceptionTypes"/>
<rule ref="category/java/design.xml/CollapsibleIfStatements"/>
<rule ref="category/java/design.xml/ExcessiveClassLength">
<properties>
<property name="minimum" value="1000"/>
</properties>
</rule>
<rule ref="category/java/design.xml/ExcessiveMethodLength">
<properties>
<property name="minimum" value="50"/>
</properties>
</rule>
<rule ref="category/java/design.xml/ExcessiveParameterList">
<properties>
<property name="minimum" value="10"/>
</properties>
</rule>
<rule ref="category/java/design.xml/SimplifyBooleanReturns"/>
<rule ref="category/java/design.xml/SimplifyBooleanExpressions"/>

<!-- Java Error Prone -->
<rule ref="category/java/errorprone.xml/AvoidBranchingStatementAsLastInLoop"/>
<rule ref="category/java/errorprone.xml/AvoidDecimalLiteralsInBigDecimalConstructor"/>
<rule ref="category/java/errorprone.xml/AvoidMultipleUnaryOperators"/>
<rule ref="category/java/errorprone.xml/AvoidCallingFinalize"/>
<rule ref="category/java/errorprone.xml/EmptyIfStmt"/>
<rule ref="category/java/errorprone.xml/EmptyTryBlock"/>
<rule ref="category/java/errorprone.xml/EmptyFinallyBlock"/>
<rule ref="category/java/errorprone.xml/EmptyWhileStmt"/>
<rule ref="category/java/errorprone.xml/CompareObjectsWithEquals"/>
<rule ref="category/java/errorprone.xml/UseEqualsToCompareStrings"/>

<!-- Java Performance -->
<rule ref="category/java/performance.xml/BooleanInstantiation"/>
<rule ref="category/java/performance.xml/StringInstantiation"/>
<rule ref="category/java/performance.xml/StringToString"/>
<rule ref="category/java/performance.xml/UseStringBufferLength"/>

<!-- Java Documentation -->
<rule ref="category/java/documentation.xml/UncommentedEmptyMethodBody"/>

<!-- JavaScript Best Practices -->
<rule ref="category/ecmascript/bestpractices.xml/AvoidWithStatement"/>
<rule ref="category/ecmascript/bestpractices.xml/ConsistentReturn"/>
<rule ref="category/ecmascript/bestpractices.xml/UseBaseWithParseInt"/>

<!-- JSP Design -->
<rule ref="category/jsp/design.xml/NoInlineScript"/>
<rule ref="category/jsp/design.xml/NoInlineStyleInformation"/>
<rule ref="category/jsp/design.xml/NoScriptlets"/>

<!-- XML Error Prone -->
<rule ref="category/xml/errorprone.xml/MistypedCDATASection"/>

</ruleset>
68 changes: 68 additions & 0 deletions tools/pmdConfigCreator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package tools

import (
_ "embed"
"fmt"
"strings"
)

//go:embed pmd/default-ruleset.xml
var defaultPMDRuleset string

func CreatePmdConfig(configuration ToolConfiguration) string {

Check failure on line 12 in tools/pmdConfigCreator.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tools/pmdConfigCreator.go#L12

Method CreatePmdConfig has a cyclomatic complexity of 12 (limit is 10)

Check notice on line 12 in tools/pmdConfigCreator.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tools/pmdConfigCreator.go#L12

exported function CreatePmdConfig should have comment or be unexported
// If no patterns provided, return the default ruleset
if len(configuration.PatternsConfiguration) == 0 {
return defaultPMDRuleset
}

var contentBuilder strings.Builder

// Write XML header and ruleset opening with correct name
contentBuilder.WriteString("<?xml version=\"1.0\"?>\n")
contentBuilder.WriteString("<ruleset name=\"Codacy PMD Ruleset\"\n")
contentBuilder.WriteString(" xmlns=\"http://pmd.sourceforge.net/ruleset/2.0.0\"\n")
contentBuilder.WriteString(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n")
contentBuilder.WriteString(" xsi:schemaLocation=\"http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd\">\n\n")

// Process patterns from configuration
for _, pattern := range configuration.PatternsConfiguration {
// Check if pattern is enabled
patternEnabled := true
var properties []string

for _, param := range pattern.ParameterConfigurations {
if param.Name == "enabled" && param.Value == "false" {
patternEnabled = false
break
} else if param.Name != "enabled" {
// Store non-enabled parameters for properties
properties = append(properties, fmt.Sprintf(" <property name=\"%s\" value=\"%s\"/>", param.Name, param.Value))
}
}

if patternEnabled {
// Convert pattern ID to correct PMD path format
// e.g., "java/codestyle/AtLeastOneConstructor" -> "category/java/codestyle.xml/AtLeastOneConstructor"
parts := strings.Split(pattern.PatternId, "/")
if len(parts) >= 2 {
category := parts[len(parts)-2]
rule := parts[len(parts)-1]
contentBuilder.WriteString(fmt.Sprintf(" <rule ref=\"category/java/%s.xml/%s\"", category, rule))

// Add properties if any exist
if len(properties) > 0 {
contentBuilder.WriteString(">\n <properties>\n")
for _, prop := range properties {
contentBuilder.WriteString(prop + "\n")
}
contentBuilder.WriteString(" </properties>\n </rule>\n")
} else {
contentBuilder.WriteString("/>\n")
}
}
}
}

contentBuilder.WriteString("</ruleset>")
return contentBuilder.String()
}
Loading