pmdtester 1.0.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ci/build.sh +99 -0
- data/.ci/inc/fetch_ci_scripts.bash +19 -0
- data/.ci/manual-integration-tests.sh +37 -0
- data/.github/workflows/build.yml +55 -0
- data/.github/workflows/manual-integration-tests.yml +43 -0
- data/.gitignore +9 -0
- data/.hoerc +1 -1
- data/.rubocop.yml +9 -2
- data/.ruby-version +1 -0
- data/History.md +79 -0
- data/Manifest.txt +28 -9
- data/README.rdoc +59 -33
- data/Rakefile +7 -5
- data/config/all-java.xml +1 -1
- data/config/design.xml +1 -1
- data/config/project-list.xml +8 -7
- data/config/projectlist_1_0_0.xsd +2 -1
- data/config/projectlist_1_1_0.xsd +31 -0
- data/config/projectlist_1_2_0.xsd +39 -0
- data/lib/pmdtester.rb +8 -7
- data/lib/pmdtester/builders/liquid_renderer.rb +130 -0
- data/lib/pmdtester/builders/pmd_report_builder.rb +107 -79
- data/lib/pmdtester/builders/project_builder.rb +105 -0
- data/lib/pmdtester/builders/project_hasher.rb +128 -0
- data/lib/pmdtester/builders/rule_set_builder.rb +96 -47
- data/lib/pmdtester/builders/simple_progress_logger.rb +4 -4
- data/lib/pmdtester/builders/summary_report_builder.rb +63 -131
- data/lib/pmdtester/collection_by_file.rb +55 -0
- data/lib/pmdtester/parsers/options.rb +24 -0
- data/lib/pmdtester/parsers/pmd_report_document.rb +72 -28
- data/lib/pmdtester/parsers/projects_parser.rb +2 -4
- data/lib/pmdtester/pmd_branch_detail.rb +35 -19
- data/lib/pmdtester/pmd_configerror.rb +23 -24
- data/lib/pmdtester/pmd_error.rb +34 -34
- data/lib/pmdtester/pmd_report_detail.rb +10 -13
- data/lib/pmdtester/pmd_tester_utils.rb +58 -0
- data/lib/pmdtester/pmd_violation.rb +66 -28
- data/lib/pmdtester/project.rb +42 -56
- data/lib/pmdtester/report_diff.rb +203 -109
- data/lib/pmdtester/resource_locator.rb +4 -0
- data/lib/pmdtester/runner.rb +67 -64
- data/pmdtester.gemspec +28 -37
- data/resources/_includes/diff_pill_row.html +6 -0
- data/resources/css/bootstrap.min.css +7 -0
- data/resources/css/datatables.min.css +36 -0
- data/resources/css/pmd-tester.css +132 -0
- data/resources/js/bootstrap.min.js +7 -0
- data/resources/js/code-snippets.js +73 -0
- data/resources/js/datatables.min.js +726 -0
- data/resources/js/jquery-3.2.1.slim.min.js +4 -0
- data/resources/js/jquery.min.js +2 -0
- data/resources/js/popper.min.js +5 -0
- data/resources/js/project-report.js +137 -0
- data/resources/project_diff_report.html +214 -0
- data/resources/project_index.html +113 -0
- data/resources/project_pmd_report.html +186 -0
- metadata +73 -25
- data/.travis.yml +0 -40
- data/lib/pmdtester/builders/diff_builder.rb +0 -31
- data/lib/pmdtester/builders/diff_report/configerrors.rb +0 -50
- data/lib/pmdtester/builders/diff_report/errors.rb +0 -71
- data/lib/pmdtester/builders/diff_report/violations.rb +0 -77
- data/lib/pmdtester/builders/diff_report_builder.rb +0 -99
- data/lib/pmdtester/builders/html_report_builder.rb +0 -56
- data/resources/css/maven-base.css +0 -155
- data/resources/css/maven-theme.css +0 -171
data/README.rdoc
CHANGED
@@ -4,7 +4,9 @@ home :: https://pmd.github.io
|
|
4
4
|
code :: https://github.com/pmd/pmd-regression-tester
|
5
5
|
bugs :: https://github.com/pmd/pmd-regression-tester/issues
|
6
6
|
|
7
|
-
build-status :: {<img src="https://
|
7
|
+
build-status :: {<img src="https://github.com/pmd/pmd-regression-tester/workflows/build/badge.svg?branch=master" alt="Build Status" />}[https://github.com/pmd/pmd-regression-tester/actions?query=workflow%3Abuild]
|
8
|
+
|
9
|
+
gem-version :: {<img src="https://badge.fury.io/rb/pmdtester.svg" alt="Gem Version" />}[https://rubygems.org/gems/pmdtester]
|
8
10
|
|
9
11
|
== DESCRIPTION:
|
10
12
|
|
@@ -18,26 +20,30 @@ on a list of standard projects(Spring Framework, Hibernate, Solr, etc.)
|
|
18
20
|
== SYNOPSIS:
|
19
21
|
|
20
22
|
=== Options:
|
21
|
-
-r, --local-git-repo
|
22
|
-
-b, --base-branch
|
23
|
-
-p, --patch-branch
|
24
|
-
-bc, --base-config
|
25
|
-
-pc, --patch-config
|
26
|
-
-c, --config
|
27
|
-
-l, --list-of-project
|
28
|
-
-m, --mode
|
23
|
+
-r, --local-git-repo path to the local PMD repository
|
24
|
+
-b, --base-branch name of the base branch in local PMD repository
|
25
|
+
-p, --patch-branch name of the patch branch in local PMD repository
|
26
|
+
-bc, --base-config path to the base PMD configuration file
|
27
|
+
-pc, --patch-config path to the patch PMD configuration file
|
28
|
+
-c, --config path to the base and patch PMD configuration file
|
29
|
+
-l, --list-of-project path to the file which contains the list of standard projects
|
30
|
+
-m, --mode the mode of the tool: 'local', 'online' or 'single'
|
29
31
|
single: Set this option to 'single' if your patch branch contains changes
|
30
32
|
for any option that can't work on master/base branch
|
31
33
|
online: Set this option to 'online' if you want to download
|
32
34
|
the PMD report of master/base branch rather than generating it locally
|
33
35
|
local: Default option is 'local', PMD reports for the base and patch branches are generated locally.
|
34
36
|
|
35
|
-
-t, --threads
|
36
|
-
-f, --html-flag
|
37
|
-
-a, --auto-gen-config
|
38
|
-
-
|
39
|
-
-
|
40
|
-
-
|
37
|
+
-t, --threads Sets the number of threads used by PMD. Set threads to 0 to disable multi-threading processing.
|
38
|
+
-f, --html-flag whether to not generate the html diff report in single mode
|
39
|
+
-a, --auto-gen-config whether to generate configurations automatically based on branch differences,this option only works in online and local mode
|
40
|
+
--filter-with-patch-config whether to use patch config to filter baseline result as if --auto-gen-config has been used. This option only works in online mode.
|
41
|
+
--keep-reports whether to keep old reports and skip running PMD again if possible
|
42
|
+
-d, --debug whether change log level to DEBUG to see more information
|
43
|
+
--error-recovery enable error recovery mode when executing PMD. Might help to analyze errors.
|
44
|
+
--baseline-download-url download url prefix from where to download the baseline in online mode
|
45
|
+
-v, --version
|
46
|
+
-h, --help
|
41
47
|
|
42
48
|
=== Quick start
|
43
49
|
|
@@ -60,19 +66,24 @@ The tool creates the following folders:
|
|
60
66
|
│ ├── PROJECT_NAME_1
|
61
67
|
│ ├── ......
|
62
68
|
│ └── PROJECT_NAME_n
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
69
|
+
├── reports
|
70
|
+
│ ├── BASE_BRANCH_NAME <- the base baseline is placed here
|
71
|
+
│ ├── PATCH_BRANCH_NAME <- the patch baseline is placed here
|
72
|
+
│ └── diff
|
73
|
+
│ ├── index.html <- the summary report of diff reports
|
74
|
+
│ ├── base_config.xml <- pmd config from the base branch
|
75
|
+
│ ├── patch_config.xml <- pmd config from the patch branch
|
76
|
+
│ ├── css <- css resources are placed here
|
77
|
+
│ ├── js <- js resources
|
78
|
+
│ ├── PROJECT_NAME_1
|
79
|
+
│ │ ├── project_data.js <- contains the violations as js/json
|
80
|
+
│ │ └── index.html <- the diff report of PROJECT_1
|
81
|
+
│ ├── .......
|
82
|
+
│ └── PROJECT_NAME_n
|
83
|
+
│ ├── project_data.js <- contains the violations as js/json
|
84
|
+
│ └── index.xml <- the diff report of PROJECT_N
|
85
|
+
├── pmd-bin-<version>-<branch_name>-<sha1> <- cached pmd builds that are reused
|
86
|
+
└── pmd-bin-....
|
76
87
|
|
77
88
|
==== The baseline format
|
78
89
|
branch_name
|
@@ -90,14 +101,16 @@ The tool creates the following folders:
|
|
90
101
|
|
91
102
|
== REQUIREMENTS:
|
92
103
|
|
93
|
-
* Ruby 2.
|
104
|
+
* Ruby 2.7 or higher
|
94
105
|
|
95
106
|
=== Runtime dependency
|
96
107
|
|
97
|
-
nokogiri
|
108
|
+
nokogiri >= 1.11.0.rc4
|
98
109
|
slop ~> 4.6
|
99
110
|
differ ~> 0.1
|
100
111
|
rufus-scheduler ~> 3.5
|
112
|
+
logger-colors ~> 1.0
|
113
|
+
liquid >= 4.0
|
101
114
|
|
102
115
|
=== Development dependency
|
103
116
|
|
@@ -122,11 +135,24 @@ The tool creates the following folders:
|
|
122
135
|
bundle install # once
|
123
136
|
bundle exec rake verify # run this command before commit your changes
|
124
137
|
bundle exec pmdtester ... # run this to directly execute pmdtester from source
|
138
|
+
|
139
|
+
Run a single test class, e.g.:
|
140
|
+
bundle exec ruby -I test test/test_diff_report_builder.rb
|
141
|
+
|
142
|
+
Run a single test, e.g.:
|
143
|
+
bundle exec ruby -I test test/test_diff_report_builder.rb -n test_diff_report_builder
|
125
144
|
|
126
145
|
=== Releasing
|
127
146
|
|
128
147
|
* Update +History.md+ (version and date)
|
129
148
|
* Update +lib/pmdtester.rb+ (version)
|
130
|
-
*
|
131
|
-
*
|
132
|
-
|
149
|
+
* Run "bundle exec rake verify" and add new +pmdtester.gemspec+ (new version)
|
150
|
+
* Commit ("Prepare release x.y.z").
|
151
|
+
* Tag this commit ("git tag vx.y.z").
|
152
|
+
* Update History.md and lib/pmdtester.rb for the next development version,
|
153
|
+
run again "bundle exec rake verify"
|
154
|
+
* Commit ("Prepare next development version x.y.z-SNAPSHOT").
|
155
|
+
* Push to master.
|
156
|
+
* Push the tag. Github Actions will build and publish the new gem
|
157
|
+
* A github release is automatically created, verify it on https://github.com/pmd/pmd-regression-tester/releases
|
158
|
+
* To make pmd's main CI use the new version (in [pmd/pmd](https://github.com/pmd/pmd/)), go to the root directory and run `bundle lock --update`. Commit these changes.
|
data/Rakefile
CHANGED
@@ -14,12 +14,14 @@ Hoe.plugin :git
|
|
14
14
|
hoe = Hoe.spec 'pmdtester' do
|
15
15
|
self.version = PmdTester::VERSION
|
16
16
|
|
17
|
-
developer 'Andreas Dangel', 'andreas.dangel@
|
17
|
+
developer 'Andreas Dangel', 'andreas.dangel@pmd-code.org'
|
18
18
|
developer 'Binguo Bao', 'djydewang@gmail.com'
|
19
|
+
developer 'Clément Fournier', 'clement.fournier76@gmail.com'
|
19
20
|
|
20
|
-
self.clean_globs = %w[target/reports/**/* target/test/**/* Gemfile.lock]
|
21
|
-
self.extra_deps += [['nokogiri', '
|
22
|
-
['rufus-scheduler', '~> 3.5']]
|
21
|
+
self.clean_globs = %w[target/reports/**/* target/test/**/* target/dynamic-config.xml Gemfile.lock]
|
22
|
+
self.extra_deps += [['nokogiri', '>= 1.11.0.rc4'], ['slop', '~> 4.6'], ['differ', '~> 0.1'],
|
23
|
+
['rufus-scheduler', '~> 3.5'], ['logger-colors', '~> 1.0'],
|
24
|
+
['liquid', '>= 4.0']]
|
23
25
|
self.extra_dev_deps += [
|
24
26
|
['hoe-bundler', '~> 1.5'],
|
25
27
|
['hoe-git', '~> 1.6'],
|
@@ -30,7 +32,7 @@ hoe = Hoe.spec 'pmdtester' do
|
|
30
32
|
['test-unit', '~> 3.2'],
|
31
33
|
['rdoc', ['>= 4.0', '< 7']]
|
32
34
|
]
|
33
|
-
spec_extras[:required_ruby_version] = '>= 2.
|
35
|
+
spec_extras[:required_ruby_version] = '>= 2.7'
|
34
36
|
|
35
37
|
license 'BSD-2-Clause'
|
36
38
|
end
|
data/config/all-java.xml
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
<ruleset name="All Java Rules"
|
4
4
|
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
|
5
5
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
6
|
-
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0
|
6
|
+
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
|
7
7
|
<description>Every Java Rule in PMD</description>
|
8
8
|
|
9
9
|
<rule ref="category/java/bestpractices.xml" />
|
data/config/design.xml
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
<ruleset name="Design"
|
4
4
|
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
|
5
5
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
6
|
-
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0
|
6
|
+
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
|
7
7
|
|
8
8
|
<description>
|
9
9
|
The Design ruleset contains rules that flag suboptimal code implementations. Alternate approaches
|
data/config/project-list.xml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
<?xml version="1.0"?>
|
2
2
|
|
3
3
|
<projectlist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
4
|
-
xsi:noNamespaceSchemaLocation="
|
4
|
+
xsi:noNamespaceSchemaLocation="projectlist_1_2_0.xsd">
|
5
5
|
<description>Standard Projects</description>
|
6
6
|
|
7
7
|
<project>
|
@@ -20,10 +20,11 @@ xsi:noNamespaceSchemaLocation="projectlist_1_0_0.xsd">
|
|
20
20
|
<tag>v5.0.6.RELEASE</tag>
|
21
21
|
</project>
|
22
22
|
|
23
|
-
|
24
|
-
<name>
|
25
|
-
<type>
|
26
|
-
<connection>
|
27
|
-
<
|
28
|
-
|
23
|
+
<project>
|
24
|
+
<name>openjdk-11</name>
|
25
|
+
<type>git</type>
|
26
|
+
<connection>https://github.com/openjdk/jdk</connection>
|
27
|
+
<tag>jdk-11+28</tag>
|
28
|
+
<src-subpath>src/java.base</src-subpath>
|
29
|
+
</project>
|
29
30
|
</projectlist>
|
@@ -1,4 +1,5 @@
|
|
1
1
|
<?xml version="1.0" ?>
|
2
|
+
<!-- version 1.0.0 -->
|
2
3
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
3
4
|
<xs:element name="projectlist">
|
4
5
|
<xs:complexType>
|
@@ -25,4 +26,4 @@
|
|
25
26
|
<xs:element name="exclude-pattern" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
|
26
27
|
</xs:sequence>
|
27
28
|
</xs:complexType>
|
28
|
-
</xs:schema>
|
29
|
+
</xs:schema>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<?xml version="1.0" ?>
|
2
|
+
<!-- version 1.1.0 -->
|
3
|
+
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
4
|
+
<xs:element name="projectlist">
|
5
|
+
<xs:complexType>
|
6
|
+
<xs:sequence>
|
7
|
+
<xs:element name="description" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
8
|
+
<xs:element name="project" type="project" minOccurs="1" maxOccurs="unbounded"/>
|
9
|
+
</xs:sequence>
|
10
|
+
</xs:complexType>
|
11
|
+
</xs:element>
|
12
|
+
<xs:complexType name="project">
|
13
|
+
<xs:sequence>
|
14
|
+
<xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
15
|
+
<xs:element name="type" minOccurs="1" maxOccurs="1">
|
16
|
+
<xs:simpleType>
|
17
|
+
<xs:restriction base="xs:string">
|
18
|
+
<xs:enumeration value="git"/>
|
19
|
+
<xs:enumeration value="hg"/>
|
20
|
+
</xs:restriction>
|
21
|
+
</xs:simpleType>
|
22
|
+
</xs:element>
|
23
|
+
<xs:element name="connection" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
24
|
+
<xs:element name="webview-url" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
25
|
+
<xs:element name="tag" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
26
|
+
<xs:element name="exclude-pattern" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
|
27
|
+
<xs:element name="build-command" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
28
|
+
<xs:element name="auxclasspath-command" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
29
|
+
</xs:sequence>
|
30
|
+
</xs:complexType>
|
31
|
+
</xs:schema>
|
@@ -0,0 +1,39 @@
|
|
1
|
+
<?xml version="1.0" ?>
|
2
|
+
<!-- version 1.1.0 -->
|
3
|
+
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
4
|
+
<xs:element name="projectlist">
|
5
|
+
<xs:complexType>
|
6
|
+
<xs:sequence>
|
7
|
+
<xs:element name="description" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
8
|
+
<xs:element name="project" type="project" minOccurs="1" maxOccurs="unbounded"/>
|
9
|
+
</xs:sequence>
|
10
|
+
</xs:complexType>
|
11
|
+
</xs:element>
|
12
|
+
<xs:complexType name="project">
|
13
|
+
<xs:sequence>
|
14
|
+
<xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
15
|
+
<xs:element name="type" minOccurs="1" maxOccurs="1">
|
16
|
+
<xs:simpleType>
|
17
|
+
<xs:restriction base="xs:string">
|
18
|
+
<xs:enumeration value="git"/>
|
19
|
+
</xs:restriction>
|
20
|
+
</xs:simpleType>
|
21
|
+
</xs:element>
|
22
|
+
<xs:element name="connection" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
23
|
+
<xs:element name="webview-url" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
24
|
+
<xs:element name="tag" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
25
|
+
<xs:element name="src-subpath" type="xs:string" minOccurs="0" maxOccurs="1" default=".">
|
26
|
+
<xs:annotation>
|
27
|
+
<xs:documentation>
|
28
|
+
Value of the -dir option for the PMD run.
|
29
|
+
The value must be a directory path relative to the root directory of the clone.
|
30
|
+
Defaults to just '.', ie the entire directory.
|
31
|
+
</xs:documentation>
|
32
|
+
</xs:annotation>
|
33
|
+
</xs:element>
|
34
|
+
<xs:element name="exclude-pattern" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
|
35
|
+
<xs:element name="build-command" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
36
|
+
<xs:element name="auxclasspath-command" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
37
|
+
</xs:sequence>
|
38
|
+
</xs:complexType>
|
39
|
+
</xs:schema>
|
data/lib/pmdtester.rb
CHANGED
@@ -1,12 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'logger'
|
4
|
+
require 'logger/colors'
|
4
5
|
|
5
6
|
require_relative 'pmdtester/cmd'
|
7
|
+
require_relative 'pmdtester/collection_by_file'
|
6
8
|
require_relative 'pmdtester/pmd_branch_detail'
|
7
9
|
require_relative 'pmdtester/pmd_configerror'
|
8
10
|
require_relative 'pmdtester/pmd_error'
|
9
11
|
require_relative 'pmdtester/pmd_report_detail'
|
12
|
+
require_relative 'pmdtester/pmd_tester_utils'
|
10
13
|
require_relative 'pmdtester/pmd_violation'
|
11
14
|
require_relative 'pmdtester/project'
|
12
15
|
require_relative 'pmdtester/report_diff'
|
@@ -14,13 +17,10 @@ require_relative 'pmdtester/resource_locator'
|
|
14
17
|
require_relative 'pmdtester/runner'
|
15
18
|
|
16
19
|
require_relative 'pmdtester/builders/simple_progress_logger'
|
17
|
-
require_relative 'pmdtester/builders/
|
18
|
-
require_relative 'pmdtester/builders/
|
19
|
-
require_relative 'pmdtester/builders/diff_report/violations'
|
20
|
-
require_relative 'pmdtester/builders/diff_report/configerrors'
|
21
|
-
require_relative 'pmdtester/builders/diff_report/errors'
|
22
|
-
require_relative 'pmdtester/builders/diff_report_builder'
|
20
|
+
require_relative 'pmdtester/builders/project_builder'
|
21
|
+
require_relative 'pmdtester/builders/project_hasher'
|
23
22
|
require_relative 'pmdtester/builders/pmd_report_builder'
|
23
|
+
require_relative 'pmdtester/builders/liquid_renderer'
|
24
24
|
require_relative 'pmdtester/builders/rule_set_builder'
|
25
25
|
require_relative 'pmdtester/builders/summary_report_builder'
|
26
26
|
|
@@ -32,9 +32,10 @@ require_relative 'pmdtester/parsers/projects_parser'
|
|
32
32
|
# and unexpected behaviors will not be introduced to PMD project
|
33
33
|
# after fixing an issue and new rules can work as expected.
|
34
34
|
module PmdTester
|
35
|
-
VERSION = '1.
|
35
|
+
VERSION = '1.2.0'
|
36
36
|
BASE = 'base'
|
37
37
|
PATCH = 'patch'
|
38
|
+
PR_NUM_ENV_VAR = 'PMD_CI_PULL_REQUEST_NUMBER' # see PmdBranchDetail
|
38
39
|
|
39
40
|
def logger
|
40
41
|
PmdTester.logger
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'liquid'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
module PmdTester
|
7
|
+
# A module to include in classes that use a Liquid template
|
8
|
+
# to generate content.
|
9
|
+
module LiquidRenderer
|
10
|
+
include PmdTester
|
11
|
+
|
12
|
+
def render_liquid(template_path, env)
|
13
|
+
to_render = File.read(ResourceLocator.resource(template_path))
|
14
|
+
includes = Liquid::LocalFileSystem.new(ResourceLocator.resource('_includes'), '%s.html')
|
15
|
+
Liquid::Template.file_system = includes
|
16
|
+
template = Liquid::Template.parse(to_render, error_mode: :strict)
|
17
|
+
template.render!(env, { strict_variables: true })
|
18
|
+
end
|
19
|
+
|
20
|
+
def render_and_write(template_path, target_file, env)
|
21
|
+
write_file(target_file, render_liquid(template_path, env))
|
22
|
+
end
|
23
|
+
|
24
|
+
def write_file(target_file, contents)
|
25
|
+
dir = File.dirname(target_file)
|
26
|
+
FileUtils.mkdir_p(dir) unless File.directory?(dir)
|
27
|
+
|
28
|
+
index = File.new(target_file, 'w')
|
29
|
+
index&.puts contents # may be nil when stubbing
|
30
|
+
logger&.info "Written #{target_file}"
|
31
|
+
ensure
|
32
|
+
index&.close
|
33
|
+
end
|
34
|
+
|
35
|
+
def copy_resource(dir, to_root)
|
36
|
+
src = ResourceLocator.resource(dir)
|
37
|
+
dest = "#{to_root}/#{dir}"
|
38
|
+
FileUtils.copy_entry(src, dest)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Renders the index of a project diff report.
|
43
|
+
class LiquidProjectRenderer
|
44
|
+
include PmdTester
|
45
|
+
include ProjectHasher
|
46
|
+
include LiquidRenderer
|
47
|
+
|
48
|
+
def write_project_index(project, root)
|
49
|
+
liquid_env = {
|
50
|
+
'diff' => report_diff_to_h(project.report_diff),
|
51
|
+
'error_diffs' => errors_to_h(project),
|
52
|
+
'configerror_diffs' => configerrors_to_h(project),
|
53
|
+
'project_name' => project.name
|
54
|
+
}
|
55
|
+
|
56
|
+
# Renders index.html using liquid
|
57
|
+
write_file("#{root}/index.html", render_liquid('project_diff_report.html', liquid_env))
|
58
|
+
# generate array of violations in json
|
59
|
+
write_file("#{root}/project_data.js", dump_violations_json(project))
|
60
|
+
# copy original pmd reports
|
61
|
+
copy_file("#{root}/base_pmd_report.xml", project.report_diff.base_report.file)
|
62
|
+
copy_file("#{root}/patch_pmd_report.xml", project.report_diff.patch_report.file)
|
63
|
+
# render full pmd reports
|
64
|
+
write_file("#{root}/base_pmd_report.html",
|
65
|
+
render_liquid('project_pmd_report.html', pmd_report_liquid_env(project, BASE)))
|
66
|
+
write_file("#{root}/base_data.js", dump_violations_json(project, BASE))
|
67
|
+
write_file("#{root}/patch_pmd_report.html",
|
68
|
+
render_liquid('project_pmd_report.html', pmd_report_liquid_env(project, PATCH)))
|
69
|
+
write_file("#{root}/patch_data.js", dump_violations_json(project, PATCH))
|
70
|
+
end
|
71
|
+
|
72
|
+
def dump_violations_json(project, branch = 'diff')
|
73
|
+
violations_by_file = if branch == BASE
|
74
|
+
project.report_diff.base_report.violations_by_file.to_h
|
75
|
+
elsif branch == PATCH
|
76
|
+
project.report_diff.patch_report.violations_by_file.to_h
|
77
|
+
else
|
78
|
+
project.report_diff.violation_diffs_by_file
|
79
|
+
end
|
80
|
+
|
81
|
+
h = {
|
82
|
+
'source_link_base' => project.webview_url,
|
83
|
+
'source_link_template' => link_template(project),
|
84
|
+
**violations_to_hash(project, violations_by_file, branch == 'diff')
|
85
|
+
}
|
86
|
+
|
87
|
+
project_data = JSON.fast_generate(h, indent: ' ', object_nl: "\n", array_nl: "\n")
|
88
|
+
"let project = #{project_data}"
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def copy_file(target_file, source_file)
|
94
|
+
if File.exist? source_file
|
95
|
+
FileUtils.cp(source_file, target_file)
|
96
|
+
logger&.info "Written #{target_file}"
|
97
|
+
else
|
98
|
+
logger&.warn "File #{source_file} not found"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def pmd_report_liquid_env(project, branch)
|
103
|
+
report = if branch == BASE
|
104
|
+
project.report_diff.base_report
|
105
|
+
else
|
106
|
+
project.report_diff.patch_report
|
107
|
+
end
|
108
|
+
{
|
109
|
+
'project_name' => project.name,
|
110
|
+
'branch' => branch,
|
111
|
+
'report' => report_to_h(project, report)
|
112
|
+
}
|
113
|
+
end
|
114
|
+
|
115
|
+
def report_to_h(project, report)
|
116
|
+
{
|
117
|
+
'violation_counts' => report.violations_by_file.total_size,
|
118
|
+
'error_counts' => report.errors_by_file.total_size,
|
119
|
+
'configerror_counts' => report.configerrors_by_rule.values.flatten.length,
|
120
|
+
|
121
|
+
'execution_time' => PmdReportDetail.convert_seconds(report.exec_time),
|
122
|
+
'timestamp' => report.timestamp,
|
123
|
+
|
124
|
+
'rules' => report.rule_summaries,
|
125
|
+
'errors' => report.errors_by_file.all_values.map { |e| error_to_hash(e, project) },
|
126
|
+
'configerrors' => report.configerrors_by_rule.values.flatten.map { |e| configerror_to_hash(e) }
|
127
|
+
}
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|