Skip to content

Commit b0f7eee

Browse files
feat: Add PMD analysis support and enhance binary path processing
1 parent 763be82 commit b0f7eee

File tree

4 files changed

+118
-1
lines changed

4 files changed

+118
-1
lines changed

cmd/analyze.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,16 @@ func runTrivyAnalysis(workDirectory string, pathsToCheck []string, outputFile st
203203
}
204204
}
205205

206+
func runPmdAnalysis(workDirectory string, pathsToCheck []string, outputFile string, outputFormat string) {
207+
pmd := config.Config.Tools()["pmd"]
208+
pmdBinary := pmd.Binaries["pmd"]
209+
210+
err := tools.RunPmd(workDirectory, pmdBinary, pathsToCheck, outputFile, outputFormat)
211+
if err != nil {
212+
log.Fatalf("Error running PMD: %v", err)
213+
}
214+
}
215+
206216
var analyzeCmd = &cobra.Command{
207217
Use: "analyze",
208218
Short: "Runs all linters.",
@@ -226,6 +236,8 @@ var analyzeCmd = &cobra.Command{
226236
runEslintAnalysis(workDirectory, args, autoFix, outputFile, outputFormat)
227237
case "trivy":
228238
runTrivyAnalysis(workDirectory, args, outputFile, outputFormat)
239+
case "pmd":
240+
runPmdAnalysis(workDirectory, args, outputFile, outputFormat)
229241
case "":
230242
log.Fatal("You need to specify a tool to run analysis with, e.g., '--tool eslint'")
231243
default:

plugins/tool-utils.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,23 @@ func ProcessTools(configs []ToolConfig, toolDir string) (map[string]*ToolInfo, e
174174

175175
// Process binary paths
176176
for _, binary := range pluginConfig.Binaries {
177-
binaryPath := path.Join(installDir, binary.Path)
177+
// Process template variables in binary path
178+
tmpl, err := template.New("binary_path").Parse(binary.Path)
179+
if err != nil {
180+
return nil, fmt.Errorf("error parsing binary path template for %s: %w", config.Name, err)
181+
}
182+
183+
var buf bytes.Buffer
184+
err = tmpl.Execute(&buf, struct {
185+
Version string
186+
}{
187+
Version: config.Version,
188+
})
189+
if err != nil {
190+
return nil, fmt.Errorf("error executing binary path template for %s: %w", config.Name, err)
191+
}
192+
193+
binaryPath := path.Join(installDir, buf.String())
178194
info.Binaries[binary.Name] = binaryPath
179195
}
180196

tools/pmdRunner.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package tools
2+
3+
import (
4+
"os"
5+
"os/exec"
6+
)
7+
8+
// RunPmd executes PMD static code analyzer with the specified options
9+
func RunPmd(repositoryToAnalyseDirectory string, pmdBinary string, pathsToCheck []string, outputFile string, outputFormat string) error {
10+
cmd := exec.Command(pmdBinary, "check")
11+
12+
// Add format options
13+
if outputFormat == "sarif" {
14+
cmd.Args = append(cmd.Args, "--format", "sarif")
15+
}
16+
17+
if outputFile != "" {
18+
cmd.Args = append(cmd.Args, "--report-file", outputFile)
19+
}
20+
21+
// Add specific targets or use current directory
22+
if len(pathsToCheck) > 0 {
23+
cmd.Args = append(cmd.Args, pathsToCheck...)
24+
} else {
25+
cmd.Args = append(cmd.Args, ".")
26+
}
27+
28+
cmd.Dir = repositoryToAnalyseDirectory
29+
cmd.Stderr = os.Stderr
30+
cmd.Stdout = os.Stdout
31+
32+
return cmd.Run()
33+
}

tools/pmdRunner_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package tools
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"os"
7+
"path/filepath"
8+
"strings"
9+
"testing"
10+
11+
"github.com/stretchr/testify/assert"
12+
)
13+
14+
func TestRunPmdToFile(t *testing.T) {
15+
homeDirectory, err := os.UserHomeDir()
16+
if err != nil {
17+
log.Fatal(err.Error())
18+
}
19+
currentDirectory, err := os.Getwd()
20+
if err != nil {
21+
log.Fatal(err.Error())
22+
}
23+
24+
testDirectory := "testdata/repositories/pmd"
25+
tempResultFile := filepath.Join(os.TempDir(), "pmd.sarif")
26+
defer os.Remove(tempResultFile)
27+
28+
repositoryToAnalyze := filepath.Join(testDirectory, "src")
29+
30+
pmdBinary := filepath.Join(homeDirectory, ".cache/codacy/tools/[email protected]/pmd-bin-7.12.0/bin/pmd")
31+
32+
err = RunPmd(repositoryToAnalyze, pmdBinary, nil, tempResultFile, "sarif")
33+
if err != nil {
34+
t.Fatalf("Failed to run PMD: %v", err)
35+
}
36+
37+
// Check if the output file was created
38+
obtainedSarifBytes, err := os.ReadFile(tempResultFile)
39+
if err != nil {
40+
t.Fatalf("Failed to read output file: %v", err)
41+
}
42+
obtainedSarif := string(obtainedSarifBytes)
43+
filePrefix := "file://" + currentDirectory + "/"
44+
fmt.Println(filePrefix)
45+
actualSarif := strings.ReplaceAll(obtainedSarif, filePrefix, "")
46+
47+
// Read the expected SARIF
48+
expectedSarifFile := filepath.Join(testDirectory, "expected.sarif")
49+
expectedSarifBytes, err := os.ReadFile(expectedSarifFile)
50+
if err != nil {
51+
log.Fatal(err)
52+
}
53+
expectedSarif := strings.TrimSpace(string(expectedSarifBytes))
54+
55+
assert.Equal(t, expectedSarif, actualSarif, "output did not match expected")
56+
}

0 commit comments

Comments
 (0)