pmdtester 1.1.2 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.ci/build.sh +87 -55
- data/.ci/inc/fetch_ci_scripts.bash +19 -0
- data/.ci/manual-integration-tests.sh +31 -14
- data/.github/workflows/build.yml +26 -9
- data/.github/workflows/manual-integration-tests.yml +24 -8
- data/.hoerc +1 -1
- data/.rubocop.yml +3 -0
- data/History.md +31 -0
- data/Manifest.txt +4 -2
- data/README.rdoc +26 -25
- data/Rakefile +11 -6
- data/config/project-list.xml +8 -7
- data/config/projectlist_1_2_0.xsd +39 -0
- data/lib/pmdtester/builders/liquid_renderer.rb +60 -3
- data/lib/pmdtester/builders/pmd_report_builder.rb +9 -3
- data/lib/pmdtester/builders/project_builder.rb +14 -9
- data/lib/pmdtester/builders/project_hasher.rb +41 -39
- data/lib/pmdtester/builders/rule_set_builder.rb +116 -75
- data/lib/pmdtester/builders/summary_report_builder.rb +1 -0
- data/lib/pmdtester/parsers/options.rb +5 -0
- data/lib/pmdtester/parsers/pmd_report_document.rb +1 -3
- data/lib/pmdtester/parsers/projects_parser.rb +1 -1
- data/lib/pmdtester/pmd_branch_detail.rb +6 -0
- data/lib/pmdtester/pmd_tester_utils.rb +1 -0
- data/lib/pmdtester/pmd_violation.rb +11 -1
- data/lib/pmdtester/project.rb +24 -11
- data/lib/pmdtester/report_diff.rb +20 -4
- data/lib/pmdtester/runner.rb +8 -3
- data/lib/pmdtester/semver.rb +36 -0
- data/lib/pmdtester.rb +2 -1
- data/pmdtester.gemspec +18 -18
- data/resources/css/pmd-tester.css +17 -1
- data/resources/js/code-snippets.js +48 -15
- data/resources/js/project-report.js +5 -3
- data/resources/project_diff_report.html +9 -0
- data/resources/project_index.html +11 -0
- data/resources/project_pmd_report.html +186 -0
- metadata +26 -30
- data/.ci/files/env.gpg +0 -1
- data/.ci/inc/install-openjdk.inc +0 -26
data/lib/pmdtester/project.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'pathname'
|
4
|
+
|
3
5
|
module PmdTester
|
4
6
|
# This class represents all the information about the project
|
5
7
|
class Project
|
@@ -12,7 +14,8 @@ module PmdTester
|
|
12
14
|
attr_reader :connection
|
13
15
|
attr_reader :webview_url
|
14
16
|
attr_reader :tag
|
15
|
-
attr_reader :
|
17
|
+
attr_reader :exclude_patterns
|
18
|
+
attr_reader :src_subpath
|
16
19
|
attr_accessor :report_diff
|
17
20
|
# key: pmd branch name as String => value: local path of pmd report
|
18
21
|
attr_reader :build_command
|
@@ -20,7 +23,7 @@ module PmdTester
|
|
20
23
|
# stores the auxclasspath calculated after cloning/preparing the project
|
21
24
|
attr_accessor :auxclasspath
|
22
25
|
|
23
|
-
def initialize(project)
|
26
|
+
def initialize(project) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
24
27
|
@name = project.at_xpath('name').text
|
25
28
|
@type = project.at_xpath('type').text
|
26
29
|
@connection = project.at_xpath('connection').text
|
@@ -31,9 +34,10 @@ module PmdTester
|
|
31
34
|
@webview_url = default_webview_url
|
32
35
|
@webview_url = webview_url_element.text unless webview_url_element.nil?
|
33
36
|
|
34
|
-
@
|
37
|
+
@src_subpath = project.at_xpath('src-subpath')&.text || '.'
|
38
|
+
@exclude_patterns = []
|
35
39
|
project.xpath('exclude-pattern').each do |ep|
|
36
|
-
@
|
40
|
+
@exclude_patterns.push(ep.text)
|
37
41
|
end
|
38
42
|
|
39
43
|
@build_command = project.at_xpath('build-command')&.text
|
@@ -56,17 +60,17 @@ module PmdTester
|
|
56
60
|
# Change the file path from 'LOCAL_DIR/SOURCE_CODE_PATH' to
|
57
61
|
# 'WEB_VIEW_URL/SOURCE_CODE_PATH'
|
58
62
|
def get_webview_url(file_path)
|
59
|
-
file_path.gsub(%r{/#{
|
63
|
+
file_path.gsub(%r{/#{clone_root_path}}, @webview_url)
|
60
64
|
end
|
61
65
|
|
62
66
|
# Change the file path from 'LOCAL_DIR/SOURCE_CODE_PATH' to
|
63
67
|
# 'PROJECT_NAME/SOURCE_CODE_PATH'
|
64
68
|
def get_path_inside_project(file_path)
|
65
|
-
file_path.gsub(%r{/#{
|
69
|
+
file_path.gsub(%r{/#{clone_root_path}}, @name)
|
66
70
|
end
|
67
71
|
|
68
72
|
def get_local_path(file_path)
|
69
|
-
file_path.sub(%r{/#{
|
73
|
+
file_path.sub(%r{/#{clone_root_path}/}, '')
|
70
74
|
end
|
71
75
|
|
72
76
|
def get_pmd_report_path(branch_name)
|
@@ -93,6 +97,19 @@ module PmdTester
|
|
93
97
|
end
|
94
98
|
end
|
95
99
|
|
100
|
+
##
|
101
|
+
# Path to the sources to analyze (below or equal to clone_root_path)
|
102
|
+
def local_source_path
|
103
|
+
# normalize path
|
104
|
+
Pathname.new("#{clone_root_path}/#{src_subpath}").cleanpath
|
105
|
+
end
|
106
|
+
|
107
|
+
##
|
108
|
+
# Path to the clone directory
|
109
|
+
def clone_root_path
|
110
|
+
"#{REPOSITORIES_PATH}/#{@name}"
|
111
|
+
end
|
112
|
+
|
96
113
|
def get_project_target_dir(branch_name)
|
97
114
|
branch_filename = PmdBranchDetail.branch_filename(branch_name)
|
98
115
|
dir = "target/reports/#{branch_filename}/#{@name}"
|
@@ -100,10 +117,6 @@ module PmdTester
|
|
100
117
|
dir
|
101
118
|
end
|
102
119
|
|
103
|
-
def local_source_path
|
104
|
-
"#{REPOSITORIES_PATH}/#{@name}"
|
105
|
-
end
|
106
|
-
|
107
120
|
def compute_report_diff(base_branch, patch_branch, filter_set)
|
108
121
|
self.report_diff = build_report_diff(get_pmd_report_path(base_branch),
|
109
122
|
get_pmd_report_path(patch_branch),
|
@@ -57,28 +57,45 @@ module PmdTester
|
|
57
57
|
:configerrors_by_rule,
|
58
58
|
:exec_time,
|
59
59
|
:timestamp,
|
60
|
-
:
|
60
|
+
:file
|
61
61
|
|
62
62
|
def initialize(report_document: nil,
|
63
|
+
file: '',
|
63
64
|
exec_time: 0,
|
64
65
|
timestamp: '0')
|
65
66
|
initialize_empty
|
66
67
|
initialize_with_report_document report_document unless report_document.nil?
|
67
68
|
@exec_time = exec_time
|
68
69
|
@timestamp = timestamp
|
70
|
+
@file = file
|
69
71
|
end
|
70
72
|
|
71
73
|
def self.empty
|
72
74
|
new
|
73
75
|
end
|
74
76
|
|
77
|
+
def rule_summaries
|
78
|
+
summary = {}
|
79
|
+
@violations_by_file.each_value do |violation|
|
80
|
+
unless summary.key?(violation.rule_name)
|
81
|
+
summary[violation.rule_name] = {
|
82
|
+
'name' => violation.rule_name,
|
83
|
+
'info_url' => violation.info_url,
|
84
|
+
'count' => 0
|
85
|
+
}
|
86
|
+
end
|
87
|
+
summary[violation.rule_name]['count'] += 1
|
88
|
+
end
|
89
|
+
|
90
|
+
summary.values
|
91
|
+
end
|
92
|
+
|
75
93
|
private
|
76
94
|
|
77
95
|
def initialize_with_report_document(report_document)
|
78
96
|
@violations_by_file = report_document.violations
|
79
97
|
@errors_by_file = report_document.errors
|
80
98
|
@configerrors_by_rule = report_document.configerrors
|
81
|
-
@infos_by_rule = report_document.infos_by_rules
|
82
99
|
|
83
100
|
PmdTester.logger.debug("Loaded #{@violations_by_file.total_size} violations " \
|
84
101
|
"in #{@violations_by_file.num_files} files")
|
@@ -91,7 +108,6 @@ module PmdTester
|
|
91
108
|
@violations_by_file = CollectionByFile.new
|
92
109
|
@errors_by_file = CollectionByFile.new
|
93
110
|
@configerrors_by_rule = {}
|
94
|
-
@infos_by_rule = {}
|
95
111
|
end
|
96
112
|
end
|
97
113
|
|
@@ -122,7 +138,7 @@ module PmdTester
|
|
122
138
|
@error_diffs_by_file = {}
|
123
139
|
@configerror_diffs_by_rule = {}
|
124
140
|
|
125
|
-
@rule_infos_union =
|
141
|
+
@rule_infos_union = {}
|
126
142
|
@base_report = base_report
|
127
143
|
@patch_report = patch_report
|
128
144
|
|
data/lib/pmdtester/runner.rb
CHANGED
@@ -33,8 +33,11 @@ module PmdTester
|
|
33
33
|
def run_local_mode
|
34
34
|
logger.info "Mode: #{@options.mode}"
|
35
35
|
get_projects(@options.project_list) unless @options.nil?
|
36
|
-
|
37
|
-
|
36
|
+
if @options.auto_config_flag
|
37
|
+
run_required = RuleSetBuilder.new(@options).build?
|
38
|
+
logger.debug "Run required: #{run_required}"
|
39
|
+
return unless run_required
|
40
|
+
end
|
38
41
|
|
39
42
|
base_branch_details = create_pmd_report(config: @options.base_config, branch: @options.base_branch)
|
40
43
|
patch_branch_details = create_pmd_report(config: @options.patch_config, branch: @options.patch_branch)
|
@@ -51,7 +54,8 @@ module PmdTester
|
|
51
54
|
get_projects(project_list)
|
52
55
|
|
53
56
|
if @options.auto_config_flag
|
54
|
-
|
57
|
+
logger.info 'Autogenerating a dynamic ruleset based on source changes'
|
58
|
+
return unless RuleSetBuilder.new(@options).build?
|
55
59
|
elsif @options.patch_config == Options::DEFAULT_CONFIG_PATH
|
56
60
|
# patch branch build pmd reports with same configuration as base branch
|
57
61
|
# if not specified otherwise. This allows to use a different config (e.g. less rules)
|
@@ -59,6 +63,7 @@ module PmdTester
|
|
59
63
|
@options.patch_config = "#{baseline_path}/config.xml"
|
60
64
|
else
|
61
65
|
logger.info "Using config #{@options.patch_config} which might differ from baseline"
|
66
|
+
RuleSetBuilder.new(@options).calculate_filter_set if @options.filter_with_patch_config
|
62
67
|
end
|
63
68
|
|
64
69
|
patch_branch_details = create_pmd_report(config: @options.patch_config, branch: @options.patch_branch)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PmdTester
|
4
|
+
# Utility to deal with semantic versions
|
5
|
+
class Semver
|
6
|
+
def self.compare(version_a, version_b)
|
7
|
+
PmdTester.logger.debug "Comparing #{version_a} <=> #{version_b}"
|
8
|
+
m = /(\d+)\.(\d+)\.(\d+)(.*)/.match(version_a)
|
9
|
+
a_major = m[1].to_i
|
10
|
+
a_minor = m[2].to_i
|
11
|
+
a_patch = m[3].to_i
|
12
|
+
a_snapshot = m[4]
|
13
|
+
PmdTester.logger.debug " a_major: #{a_major} a_minor: #{a_minor} a_patch: #{a_patch} a_snapshot: #{a_snapshot}"
|
14
|
+
|
15
|
+
m = /(\d+)\.(\d+)\.(\d+)(.*)/.match(version_b)
|
16
|
+
b_major = m[1].to_i
|
17
|
+
b_minor = m[2].to_i
|
18
|
+
b_patch = m[3].to_i
|
19
|
+
b_snapshot = m[4]
|
20
|
+
PmdTester.logger.debug " b_major: #{b_major} b_minor: #{b_minor} b_patch: #{b_patch} b_snapshot: #{b_snapshot}"
|
21
|
+
|
22
|
+
return a_major <=> b_major if a_major != b_major
|
23
|
+
return a_minor <=> b_minor if a_minor != b_minor
|
24
|
+
return a_patch <=> b_patch if a_patch != b_patch
|
25
|
+
|
26
|
+
compare_snapshots(a_snapshot, b_snapshot)
|
27
|
+
end
|
28
|
+
|
29
|
+
private_class_method def self.compare_snapshots(a_snapshot, b_snapshot)
|
30
|
+
return -1 if a_snapshot == '-SNAPSHOT' && b_snapshot == ''
|
31
|
+
return 1 if a_snapshot == '' && b_snapshot == '-SNAPSHOT'
|
32
|
+
|
33
|
+
a_snapshot <=> b_snapshot
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/pmdtester.rb
CHANGED
@@ -15,6 +15,7 @@ require_relative 'pmdtester/project'
|
|
15
15
|
require_relative 'pmdtester/report_diff'
|
16
16
|
require_relative 'pmdtester/resource_locator'
|
17
17
|
require_relative 'pmdtester/runner'
|
18
|
+
require_relative 'pmdtester/semver'
|
18
19
|
|
19
20
|
require_relative 'pmdtester/builders/simple_progress_logger'
|
20
21
|
require_relative 'pmdtester/builders/project_builder'
|
@@ -32,7 +33,7 @@ require_relative 'pmdtester/parsers/projects_parser'
|
|
32
33
|
# and unexpected behaviors will not be introduced to PMD project
|
33
34
|
# after fixing an issue and new rules can work as expected.
|
34
35
|
module PmdTester
|
35
|
-
VERSION = '1.
|
36
|
+
VERSION = '1.4.0'
|
36
37
|
BASE = 'base'
|
37
38
|
PATCH = 'patch'
|
38
39
|
PR_NUM_ENV_VAR = 'PMD_CI_PULL_REQUEST_NUMBER' # see PmdBranchDetail
|
data/pmdtester.gemspec
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
# DO NOT EDIT THIS FILE. Instead, edit Rakefile, and run `rake hoe:spec`.
|
2
2
|
|
3
3
|
# -*- encoding: utf-8 -*-
|
4
|
-
# stub: pmdtester 1.
|
4
|
+
# stub: pmdtester 1.4.0 ruby lib
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "pmdtester".freeze
|
8
|
-
s.version = "1.
|
8
|
+
s.version = "1.4.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
11
11
|
s.metadata = { "bug_tracker_uri" => "https://github.com/pmd/pmd-regression-tester/issues", "homepage_uri" => "https://pmd.github.io", "source_code_uri" => "https://github.com/pmd/pmd-regression-tester" } if s.respond_to? :metadata=
|
12
12
|
s.require_paths = ["lib".freeze]
|
13
13
|
s.authors = ["Andreas Dangel".freeze, "Binguo Bao".freeze, "Cl\u00E9ment Fournier".freeze]
|
14
|
-
s.date = "
|
14
|
+
s.date = "2022-03-24"
|
15
15
|
s.description = "A regression testing tool ensure that new problems and unexpected behaviors will not be introduced to PMD project after fixing an issue , and new rules can work as expected.".freeze
|
16
16
|
s.email = ["andreas.dangel@pmd-code.org".freeze, "djydewang@gmail.com".freeze, "clement.fournier76@gmail.com".freeze]
|
17
17
|
s.executables = ["pmdtester".freeze]
|
18
18
|
s.extra_rdoc_files = ["History.md".freeze, "Manifest.txt".freeze, "README.rdoc".freeze]
|
19
|
-
s.files = [".ci/build.sh".freeze, ".ci/
|
19
|
+
s.files = [".ci/build.sh".freeze, ".ci/inc/fetch_ci_scripts.bash".freeze, ".ci/manual-integration-tests.sh".freeze, ".github/workflows/build.yml".freeze, ".github/workflows/manual-integration-tests.yml".freeze, ".gitignore".freeze, ".hoerc".freeze, ".rubocop.yml".freeze, ".rubocop_todo.yml".freeze, ".ruby-version".freeze, "Gemfile".freeze, "History.md".freeze, "LICENSE".freeze, "Manifest.txt".freeze, "README.rdoc".freeze, "Rakefile".freeze, "bin/pmdtester".freeze, "config/all-java.xml".freeze, "config/design.xml".freeze, "config/project-list.xml".freeze, "config/projectlist_1_0_0.xsd".freeze, "config/projectlist_1_1_0.xsd".freeze, "config/projectlist_1_2_0.xsd".freeze, "lib/pmdtester.rb".freeze, "lib/pmdtester/builders/liquid_renderer.rb".freeze, "lib/pmdtester/builders/pmd_report_builder.rb".freeze, "lib/pmdtester/builders/project_builder.rb".freeze, "lib/pmdtester/builders/project_hasher.rb".freeze, "lib/pmdtester/builders/rule_set_builder.rb".freeze, "lib/pmdtester/builders/simple_progress_logger.rb".freeze, "lib/pmdtester/builders/summary_report_builder.rb".freeze, "lib/pmdtester/cmd.rb".freeze, "lib/pmdtester/collection_by_file.rb".freeze, "lib/pmdtester/parsers/options.rb".freeze, "lib/pmdtester/parsers/pmd_report_document.rb".freeze, "lib/pmdtester/parsers/projects_parser.rb".freeze, "lib/pmdtester/pmd_branch_detail.rb".freeze, "lib/pmdtester/pmd_configerror.rb".freeze, "lib/pmdtester/pmd_error.rb".freeze, "lib/pmdtester/pmd_report_detail.rb".freeze, "lib/pmdtester/pmd_tester_utils.rb".freeze, "lib/pmdtester/pmd_violation.rb".freeze, "lib/pmdtester/project.rb".freeze, "lib/pmdtester/report_diff.rb".freeze, "lib/pmdtester/resource_locator.rb".freeze, "lib/pmdtester/runner.rb".freeze, "lib/pmdtester/semver.rb".freeze, "pmdtester.gemspec".freeze, "resources/_includes/diff_pill_row.html".freeze, "resources/css/bootstrap.min.css".freeze, "resources/css/datatables.min.css".freeze, "resources/css/pmd-tester.css".freeze, "resources/js/bootstrap.min.js".freeze, "resources/js/code-snippets.js".freeze, "resources/js/datatables.min.js".freeze, "resources/js/jquery-3.2.1.slim.min.js".freeze, "resources/js/jquery.min.js".freeze, "resources/js/popper.min.js".freeze, "resources/js/project-report.js".freeze, "resources/project_diff_report.html".freeze, "resources/project_index.html".freeze, "resources/project_pmd_report.html".freeze]
|
20
20
|
s.homepage = "https://pmd.github.io".freeze
|
21
21
|
s.licenses = ["BSD-2-Clause".freeze]
|
22
22
|
s.rdoc_options = ["--main".freeze, "README.rdoc".freeze]
|
@@ -29,35 +29,35 @@ Gem::Specification.new do |s|
|
|
29
29
|
end
|
30
30
|
|
31
31
|
if s.respond_to? :add_runtime_dependency then
|
32
|
-
s.add_runtime_dependency(%q<nokogiri>.freeze, ["
|
32
|
+
s.add_runtime_dependency(%q<nokogiri>.freeze, ["~> 1.13"])
|
33
33
|
s.add_runtime_dependency(%q<slop>.freeze, ["~> 4.6"])
|
34
34
|
s.add_runtime_dependency(%q<differ>.freeze, ["~> 0.1"])
|
35
|
-
s.add_runtime_dependency(%q<rufus-scheduler>.freeze, ["~> 3.
|
35
|
+
s.add_runtime_dependency(%q<rufus-scheduler>.freeze, ["~> 3.8"])
|
36
36
|
s.add_runtime_dependency(%q<logger-colors>.freeze, ["~> 1.0"])
|
37
|
-
s.add_runtime_dependency(%q<liquid>.freeze, ["
|
37
|
+
s.add_runtime_dependency(%q<liquid>.freeze, ["~> 5.2"])
|
38
38
|
s.add_development_dependency(%q<hoe-bundler>.freeze, ["~> 1.5"])
|
39
39
|
s.add_development_dependency(%q<hoe-git>.freeze, ["~> 1.6"])
|
40
40
|
s.add_development_dependency(%q<minitest>.freeze, ["~> 5.10"])
|
41
41
|
s.add_development_dependency(%q<mocha>.freeze, ["~> 1.5"])
|
42
|
-
s.add_development_dependency(%q<rubocop>.freeze, ["~> 0.
|
43
|
-
s.add_development_dependency(%q<test-unit>.freeze, ["~> 3.
|
44
|
-
s.add_development_dependency(%q<rdoc>.freeze, ["
|
45
|
-
s.add_development_dependency(%q<hoe>.freeze, ["~> 3.
|
42
|
+
s.add_development_dependency(%q<rubocop>.freeze, ["~> 0.93"])
|
43
|
+
s.add_development_dependency(%q<test-unit>.freeze, ["~> 3.5"])
|
44
|
+
s.add_development_dependency(%q<rdoc>.freeze, ["~> 6.4"])
|
45
|
+
s.add_development_dependency(%q<hoe>.freeze, ["~> 3.23"])
|
46
46
|
else
|
47
|
-
s.add_dependency(%q<nokogiri>.freeze, ["
|
47
|
+
s.add_dependency(%q<nokogiri>.freeze, ["~> 1.13"])
|
48
48
|
s.add_dependency(%q<slop>.freeze, ["~> 4.6"])
|
49
49
|
s.add_dependency(%q<differ>.freeze, ["~> 0.1"])
|
50
|
-
s.add_dependency(%q<rufus-scheduler>.freeze, ["~> 3.
|
50
|
+
s.add_dependency(%q<rufus-scheduler>.freeze, ["~> 3.8"])
|
51
51
|
s.add_dependency(%q<logger-colors>.freeze, ["~> 1.0"])
|
52
|
-
s.add_dependency(%q<liquid>.freeze, ["
|
52
|
+
s.add_dependency(%q<liquid>.freeze, ["~> 5.2"])
|
53
53
|
s.add_dependency(%q<hoe-bundler>.freeze, ["~> 1.5"])
|
54
54
|
s.add_dependency(%q<hoe-git>.freeze, ["~> 1.6"])
|
55
55
|
s.add_dependency(%q<minitest>.freeze, ["~> 5.10"])
|
56
56
|
s.add_dependency(%q<mocha>.freeze, ["~> 1.5"])
|
57
|
-
s.add_dependency(%q<rubocop>.freeze, ["~> 0.
|
58
|
-
s.add_dependency(%q<test-unit>.freeze, ["~> 3.
|
59
|
-
s.add_dependency(%q<rdoc>.freeze, ["
|
60
|
-
s.add_dependency(%q<hoe>.freeze, ["~> 3.
|
57
|
+
s.add_dependency(%q<rubocop>.freeze, ["~> 0.93"])
|
58
|
+
s.add_dependency(%q<test-unit>.freeze, ["~> 3.5"])
|
59
|
+
s.add_dependency(%q<rdoc>.freeze, ["~> 6.4"])
|
60
|
+
s.add_dependency(%q<hoe>.freeze, ["~> 3.23"])
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
@@ -10,9 +10,25 @@ code {
|
|
10
10
|
font-size: 13pt;
|
11
11
|
white-space: pre;
|
12
12
|
}
|
13
|
-
code.highlight {
|
13
|
+
code.highlight, tr.highlight {
|
14
14
|
background-color: yellow;
|
15
15
|
}
|
16
|
+
table.code-snippet > tbody > tr > td {
|
17
|
+
padding: 0px;
|
18
|
+
border: none;
|
19
|
+
}
|
20
|
+
table.code-snippet > tbody > tr > td.line-number > code:before {
|
21
|
+
content: attr(data-line-number);
|
22
|
+
}
|
23
|
+
.btn-clipboard {
|
24
|
+
margin-top: 1rem;
|
25
|
+
display: block;
|
26
|
+
padding: .25rem .5rem;
|
27
|
+
color: #0d6efd;
|
28
|
+
background-color: #fff;
|
29
|
+
border: 1px solid;
|
30
|
+
border-radius: .25rem;
|
31
|
+
}
|
16
32
|
a {
|
17
33
|
text-decoration: none;
|
18
34
|
}
|
@@ -15,18 +15,18 @@
|
|
15
15
|
|
16
16
|
// returns text, not html
|
17
17
|
function formatLineNumber(number) {
|
18
|
-
let prefix;
|
18
|
+
let prefix = '';
|
19
19
|
if (number < 10) {
|
20
|
-
prefix =
|
20
|
+
prefix = nbsp.repeat(3);
|
21
21
|
} else if (number < 100) {
|
22
|
-
prefix =
|
22
|
+
prefix = nbsp.repeat(2);
|
23
23
|
} else if (number < 1000) {
|
24
24
|
prefix = nbsp;
|
25
25
|
}
|
26
26
|
return prefix + number;
|
27
27
|
}
|
28
28
|
|
29
|
-
function fetchSnippet(document, container, url,
|
29
|
+
function fetchSnippet(document, container, url, violationLineNumber, weburl) {
|
30
30
|
var weburl, requestUrl, oReq;
|
31
31
|
|
32
32
|
requestUrl = url.replace(/github.com/, "raw.githubusercontent.com");
|
@@ -34,37 +34,70 @@
|
|
34
34
|
|
35
35
|
oReq = new XMLHttpRequest();
|
36
36
|
oReq.addEventListener("load", function() {
|
37
|
-
let lines, start, deleteCount;
|
37
|
+
let lines, start, deleteCount, lineSeparator;
|
38
38
|
|
39
39
|
// we'll append stuff in the loop below
|
40
40
|
container.innerHTML = '<p><a href="' + weburl + '" target="_blank" rel="noopener noreferrer">' + weburl + '</a></p>';
|
41
41
|
|
42
|
-
|
43
|
-
|
42
|
+
if (this.responseText.indexOf('\r\n') >= 0) {
|
43
|
+
lineSeparator = '\r\n';
|
44
|
+
} else {
|
45
|
+
lineSeparator = '\n';
|
46
|
+
}
|
47
|
+
lines = this.responseText.split(lineSeparator);
|
48
|
+
start = violationLineNumber - contextLines;
|
44
49
|
if (start > 0) {
|
45
50
|
lines.splice(0, start); // remove lines before
|
46
51
|
}
|
47
52
|
deleteCount = lines.length - (2 * contextLines) + 1;
|
48
53
|
lines.splice(2 * contextLines - 1, deleteCount); // delete lines after
|
49
54
|
|
55
|
+
let table = document.createElement('table');
|
56
|
+
table.classList.add('code-snippet');
|
57
|
+
let tableBody = document.createElement('tbody');
|
58
|
+
table.appendChild(tableBody);
|
50
59
|
// now we have just the lines which will be displayed
|
51
60
|
lines.forEach(line => {
|
52
61
|
start++;
|
53
|
-
let
|
54
|
-
if (start ===
|
55
|
-
|
62
|
+
let tableRow = document.createElement('tr');
|
63
|
+
if (start === violationLineNumber) {
|
64
|
+
tableRow.classList.add("highlight");
|
56
65
|
}
|
66
|
+
|
67
|
+
let lineNumberColumn = document.createElement('td');
|
68
|
+
lineNumberColumn.classList.add('line-number');
|
69
|
+
tableRow.appendChild(lineNumberColumn);
|
70
|
+
let lineNumberElement = document.createElement('code');
|
71
|
+
lineNumberColumn.appendChild(lineNumberElement);
|
72
|
+
lineNumberElement.setAttribute('data-line-number', formatLineNumber(start));
|
73
|
+
|
74
|
+
let codeColumn = document.createElement('td');
|
75
|
+
tableRow.appendChild(codeColumn);
|
76
|
+
let codeElement = document.createElement("code");
|
77
|
+
codeColumn.appendChild(codeElement);
|
57
78
|
// createTextNode escapes special chars
|
58
|
-
|
59
|
-
lineElt.appendChild(document.createElement("br"));
|
79
|
+
codeElement.appendChild(document.createTextNode(line));
|
60
80
|
|
61
|
-
|
81
|
+
tableBody.appendChild(tableRow); // append row to the table
|
62
82
|
});
|
83
|
+
container.appendChild(table);
|
84
|
+
|
85
|
+
if (navigator.clipboard) {
|
86
|
+
let copyButton = document.createElement('button');
|
87
|
+
copyButton.classList.add('btn-clipboard');
|
88
|
+
copyButton.setAttribute('title', 'Copy to clipboard');
|
89
|
+
copyButton.appendChild(document.createTextNode('copy'));
|
90
|
+
copyButton.onclick = function() {
|
91
|
+
navigator.clipboard.writeText(lines.join(lineSeparator));
|
92
|
+
}
|
93
|
+
container.appendChild(copyButton);
|
94
|
+
}
|
63
95
|
});
|
64
|
-
oReq.open("GET", requestUrl);
|
65
|
-
oReq.send();
|
66
96
|
|
67
97
|
container.innerHTML = "<samp>fetching...</samp>";
|
98
|
+
|
99
|
+
oReq.open("GET", requestUrl);
|
100
|
+
oReq.send();
|
68
101
|
}
|
69
102
|
|
70
103
|
window.pmd_code_snippets = {
|
@@ -52,12 +52,13 @@ $(document).ready(function () {
|
|
52
52
|
],
|
53
53
|
deferRender: true,
|
54
54
|
// scrollY: "6000px",
|
55
|
-
dom: '
|
55
|
+
dom: 'Pfrtipl', // Search Panes, filtering input, processing display element, table, table information summary, pagination control, length changing input control
|
56
56
|
searchPanes: {
|
57
57
|
viewTotal: true,
|
58
58
|
cascadePanes: true,
|
59
59
|
columns: [0, 1, 3],
|
60
|
-
order: ['Rule', 'Location (click row to expand)', 'Type']
|
60
|
+
order: ['Rule', 'Location (click row to expand)', 'Type'],
|
61
|
+
threshold: 1 // always show filters in search pane (default: 0.6)
|
61
62
|
},
|
62
63
|
// scrollCollapse: true,
|
63
64
|
// paging: false,
|
@@ -112,12 +113,13 @@ $(document).ready(function () {
|
|
112
113
|
},
|
113
114
|
],
|
114
115
|
displayLength: 25,
|
116
|
+
lengthMenu: [ [10, 20, 25, 50, 100, -1], [10, 20, 25, 50, 100, "All"] ],
|
115
117
|
rowCallback(row, data, index) {
|
116
118
|
$(row).addClass(cssClass[data.t]);
|
117
119
|
},
|
118
120
|
});
|
119
121
|
|
120
|
-
$('#violationsTable tbody').on('click', 'tr', function() {
|
122
|
+
$('#violationsTable tbody').on('click', 'tr[role=row]', function() {
|
121
123
|
var tr = $(this).closest('tr');
|
122
124
|
var row = table.row( tr );
|
123
125
|
|
@@ -18,6 +18,9 @@
|
|
18
18
|
|
19
19
|
</head>
|
20
20
|
<body>
|
21
|
+
<div class="section">
|
22
|
+
<h1>PMD Regression Tester Diff Report for {{project_name}}</h1>
|
23
|
+
</div>
|
21
24
|
<div class="section">
|
22
25
|
<h2>Summary</h2>
|
23
26
|
<div class="section-content">
|
@@ -68,6 +71,12 @@
|
|
68
71
|
<td class="patch">{{diff.patch_timestamp}}</td>
|
69
72
|
<td class="diff"></td>
|
70
73
|
</tr>
|
74
|
+
<tr>
|
75
|
+
<td class="item">Full Report</td>
|
76
|
+
<td class="base"><a href="base_pmd_report.html">Base PMD Report</a></td>
|
77
|
+
<td class="patch"><a href="patch_pmd_report.html">Patch PMD Report</a></td>
|
78
|
+
<td class="diff"></td>
|
79
|
+
</tr>
|
71
80
|
</tbody>
|
72
81
|
</table>
|
73
82
|
</div>
|
@@ -13,6 +13,12 @@
|
|
13
13
|
<link rel="stylesheet" href="css/pmd-tester.css">
|
14
14
|
</head>
|
15
15
|
<body>
|
16
|
+
<div class="section">
|
17
|
+
<h1>PMD Regression Tester Report</h1>
|
18
|
+
<p>
|
19
|
+
<a href="https://github.com/pmd/pmd-regression-tester">github.com/pmd/pmd-regression-tester</a>
|
20
|
+
</p>
|
21
|
+
</div>
|
16
22
|
<div class="section">
|
17
23
|
<h2>Branch details</h2>
|
18
24
|
<div class="section-content">
|
@@ -37,6 +43,11 @@
|
|
37
43
|
<span class="external-link-secondary"><a href="{{ comparison_url }}">[Compare]</a></span>
|
38
44
|
</td>
|
39
45
|
</tr>
|
46
|
+
<tr>
|
47
|
+
<td class="item">Timestamp</td>
|
48
|
+
<td class="base">{{base.timestamp}}</td>
|
49
|
+
<td class="patch">{{patch.timestamp}}</td>
|
50
|
+
</tr>
|
40
51
|
<tr>
|
41
52
|
<td class="item">Total PMD runtime</td>
|
42
53
|
<td class="base">{{base.execution_time}}</td>
|