Skip to content

Commit

Permalink
Merge pull request #92 from adangel:include-full-pmd-report
Browse files Browse the repository at this point in the history
Include full pmd report #92
  • Loading branch information
adangel committed Jun 20, 2021
2 parents d10e25c + 6616934 commit 0e8f328
Show file tree
Hide file tree
Showing 26 changed files with 894 additions and 51 deletions.
3 changes: 3 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,6 @@ Metrics/ClassLength:
Metrics/BlockLength:
Exclude:
- 'lib/pmdtester/parsers/options.rb'

Metrics/ModuleLength:
CountAsOne: ['array', 'hash']
1 change: 1 addition & 0 deletions History.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

## Fixed Issues

* [#71](https://github.com/pmd/pmd-regression-tester/issues/71): Include full PMD report
* [#89](https://github.com/pmd/pmd-regression-tester/pull/89): Make it possible to select a subpath of cloned directory
* [#91](https://github.com/pmd/pmd-regression-tester/pull/91): Filter baseline based on patch config

Expand Down
1 change: 1 addition & 0 deletions Manifest.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,4 @@ resources/js/popper.min.js
resources/js/project-report.js
resources/project_diff_report.html
resources/project_index.html
resources/project_pmd_report.html
63 changes: 60 additions & 3 deletions lib/pmdtester/builders/liquid_renderer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,74 @@ def write_project_index(project, root)
write_file("#{root}/index.html", render_liquid('project_diff_report.html', liquid_env))
# generate array of violations in json
write_file("#{root}/project_data.js", dump_violations_json(project))
# copy original pmd reports
copy_file("#{root}/base_pmd_report.xml", project.report_diff.base_report.file)
copy_file("#{root}/patch_pmd_report.xml", project.report_diff.patch_report.file)
# render full pmd reports
write_file("#{root}/base_pmd_report.html",
render_liquid('project_pmd_report.html', pmd_report_liquid_env(project, BASE)))
write_file("#{root}/base_data.js", dump_violations_json(project, BASE))
write_file("#{root}/patch_pmd_report.html",
render_liquid('project_pmd_report.html', pmd_report_liquid_env(project, PATCH)))
write_file("#{root}/patch_data.js", dump_violations_json(project, PATCH))
end

def dump_violations_json(project)
def dump_violations_json(project, branch = 'diff')
violations_by_file = if branch == BASE
project.report_diff.base_report.violations_by_file.to_h
elsif branch == PATCH
project.report_diff.patch_report.violations_by_file.to_h
else
project.report_diff.violation_diffs_by_file
end

h = {
'source_link_base' => project.webview_url,
'source_link_template' => link_template(project),
**violations_to_hash(project)
**violations_to_hash(project, violations_by_file, branch == 'diff')
}

project_data = JSON.fast_generate(h)
project_data = JSON.fast_generate(h, indent: ' ', object_nl: "\n", array_nl: "\n")
"let project = #{project_data}"
end

private

def copy_file(target_file, source_file)
if File.exist? source_file
FileUtils.cp(source_file, target_file)
logger&.info "Written #{target_file}"
else
logger&.warn "File #{source_file} not found"
end
end

def pmd_report_liquid_env(project, branch)
report = if branch == BASE
project.report_diff.base_report
else
project.report_diff.patch_report
end
{
'project_name' => project.name,
'branch' => branch,
'report' => report_to_h(project, report)
}
end

def report_to_h(project, report)
{
'violation_counts' => report.violations_by_file.total_size,
'error_counts' => report.errors_by_file.total_size,
'configerror_counts' => report.configerrors_by_rule.values.flatten.length,

'execution_time' => PmdReportDetail.convert_seconds(report.exec_time),
'timestamp' => report.timestamp,

'rules' => report.rule_summaries,
'errors' => report.errors_by_file.all_values.map { |e| error_to_hash(e, project) },
'configerrors' => report.configerrors_by_rule.values.flatten.map { |e| configerror_to_hash(e) }
}
end
end
end
80 changes: 41 additions & 39 deletions lib/pmdtester/builders/project_hasher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,14 @@ def report_diff_to_h(rdiff)
}
end

def errors_to_h(project)
errors = project.report_diff.error_diffs_by_file.values.flatten
errors.map { |e| error_to_hash(e, project) }
end

def configerrors_to_h(project)
configerrors = project.report_diff.configerror_diffs_by_rule.values.flatten
configerrors.map { |e| configerror_to_hash(e) }
end

def violations_to_hash(project)
def violations_to_hash(project, violations_by_file, is_diff)
filename_index = []
all_vs = []
project.report_diff.violation_diffs_by_file.each do |file, vs|
violations_by_file.each do |file, vs|
file_ref = filename_index.size
filename_index.push(project.get_local_path(file))
vs.each do |v|
all_vs.push(make_violation_hash(file_ref, v))
all_vs.push(make_violation_hash(file_ref, v, is_diff))
end
end

Expand All @@ -52,36 +42,19 @@ def violations_to_hash(project)
}
end

def link_template(project)
l_str = project.type == 'git' ? 'L' : 'l'
"#{project.webview_url}/{file}##{l_str}{line}"
end

def violation_type(violation)
if violation.changed?
'~'
elsif violation.branch == 'patch'
'+'
else
'-'
end
def errors_to_h(project)
errors = project.report_diff.error_diffs_by_file.values.flatten
errors.map { |e| error_to_hash(e, project) }
end

def make_violation_hash(file_ref, violation)
h = {
't' => violation_type(violation),
'l' => violation.line,
'f' => file_ref,
'r' => violation.rule_name,
'm' => violation.changed? ? diff_fragments(violation) : violation.message
}
h['ol'] = violation.old_line if violation.changed? && violation.line != violation.old_line
h
def configerrors_to_h(project)
configerrors = project.report_diff.configerror_diffs_by_rule.values.flatten
configerrors.map { |e| configerror_to_hash(e) }
end

def diff_fragments(violation)
diff = Differ.diff_by_word(violation.message, violation.old_message)
diff.format_as(:html)
def link_template(project)
l_str = project.type == 'git' ? 'L' : 'l'
"#{project.webview_url}/{file}##{l_str}{line}"
end

def error_to_hash(error, project)
Expand Down Expand Up @@ -122,5 +95,34 @@ def change_type(item)
'added'
end
end

private

def violation_type(violation)
if violation.changed?
'~'
elsif violation.branch == PATCH
'+'
else
'-'
end
end

def make_violation_hash(file_ref, violation, is_diff = TRUE)
h = {
't' => is_diff ? violation_type(violation) : '+',
'l' => violation.line,
'f' => file_ref,
'r' => violation.rule_name,
'm' => is_diff && violation.changed? ? diff_fragments(violation) : violation.message
}
h['ol'] = violation.old_line if is_diff && violation.changed? && violation.line != violation.old_line
h
end

def diff_fragments(violation)
diff = Differ.diff_by_word(violation.message, violation.old_message)
diff.format_as(:html)
end
end
end
1 change: 1 addition & 0 deletions lib/pmdtester/builders/summary_report_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ def to_liquid(details, config_name)
'sha' => details.branch_last_sha,
'message' => details.branch_last_message
},
'timestamp' => details.timestamp,
'execution_time' => PmdReportDetail.convert_seconds(details.execution_time),
'jdk_info' => details.jdk_version,
'locale' => details.language,
Expand Down
2 changes: 0 additions & 2 deletions lib/pmdtester/parsers/pmd_report_document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,12 @@ class PmdReportDocument < Nokogiri::XML::SAX::Document
attr_reader :violations
attr_reader :errors
attr_reader :configerrors
attr_reader :infos_by_rules

def initialize(branch_name, working_dir, filter_set = nil)
@violations = CollectionByFile.new
@errors = CollectionByFile.new
@configerrors = Hash.new { |hash, key| hash[key] = [] }

@infos_by_rules = {}
@current_violations = []
@current_violation = nil
@current_error = nil
Expand Down
6 changes: 6 additions & 0 deletions lib/pmdtester/pmd_branch_detail.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ class PmdBranchDetail
attr_accessor :branch_last_sha
attr_accessor :branch_last_message
attr_accessor :branch_name
# Start of the regression report
attr_accessor :timestamp
# The branch's execution time on all standard projects
attr_accessor :execution_time
attr_accessor :jdk_version
Expand All @@ -26,6 +28,7 @@ def initialize(branch_name)
@branch_name = branch_name
branch_filename = PmdBranchDetail.branch_filename(branch_name)
@base_branch_dir = "target/reports/#{branch_filename}" unless @branch_name.nil?
@timestamp = Time.now
@execution_time = 0
# the result of command 'java -version' is going to stderr
@jdk_version = Cmd.stderr_of('java -version')
Expand All @@ -42,11 +45,13 @@ def self.load(branch_name, logger)
details.branch_last_sha = hash['branch_last_sha']
details.branch_last_message = hash['branch_last_message']
details.branch_name = hash['branch_name']
details.timestamp = hash['timestamp']
details.execution_time = hash['execution_time']
details.jdk_version = hash['jdk_version']
details.language = hash['language']
details.pull_request = hash['pull_request']
else
details.timestamp = Time.now
details.jdk_version = ''
details.language = ''
logger&.warn "#{details.path_to_save_file} doesn't exist!"
Expand All @@ -58,6 +63,7 @@ def save
hash = { branch_last_sha: @branch_last_sha,
branch_last_message: @branch_last_message,
branch_name: @branch_name,
timestamp: @timestamp,
execution_time: @execution_time,
jdk_version: @jdk_version,
language: @language,
Expand Down
1 change: 1 addition & 0 deletions lib/pmdtester/pmd_tester_utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def parse_pmd_report(report_file, branch, report_details, filter_set = nil)
parser.parse_file(report_file) if File.exist?(report_file)
Report.new(
report_document: doc,
file: report_file,

timestamp: report_details.timestamp,
exec_time: report_details.execution_time
Expand Down
24 changes: 20 additions & 4 deletions lib/pmdtester/report_diff.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,28 +57,45 @@ class Report
:configerrors_by_rule,
:exec_time,
:timestamp,
:infos_by_rule
:file

def initialize(report_document: nil,
file: '',
exec_time: 0,
timestamp: '0')
initialize_empty
initialize_with_report_document report_document unless report_document.nil?
@exec_time = exec_time
@timestamp = timestamp
@file = file
end

def self.empty
new
end

def rule_summaries
summary = {}
@violations_by_file.each_value do |violation|
unless summary.key?(violation.rule_name)
summary[violation.rule_name] = {
'name' => violation.rule_name,
'info_url' => violation.info_url,
'count' => 0
}
end
summary[violation.rule_name]['count'] += 1
end

summary.values
end

private

def initialize_with_report_document(report_document)
@violations_by_file = report_document.violations
@errors_by_file = report_document.errors
@configerrors_by_rule = report_document.configerrors
@infos_by_rule = report_document.infos_by_rules

PmdTester.logger.debug("Loaded #{@violations_by_file.total_size} violations " \
"in #{@violations_by_file.num_files} files")
Expand All @@ -91,7 +108,6 @@ def initialize_empty
@violations_by_file = CollectionByFile.new
@errors_by_file = CollectionByFile.new
@configerrors_by_rule = {}
@infos_by_rule = {}
end
end

Expand Down Expand Up @@ -122,7 +138,7 @@ def initialize(base_report:, patch_report:)
@error_diffs_by_file = {}
@configerror_diffs_by_rule = {}

@rule_infos_union = base_report.infos_by_rule.dup
@rule_infos_union = {}
@base_report = base_report
@patch_report = patch_report

Expand Down
4 changes: 2 additions & 2 deletions pmdtester.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ Gem::Specification.new do |s|
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=
s.require_paths = ["lib".freeze]
s.authors = ["Andreas Dangel".freeze, "Binguo Bao".freeze, "Cl\u00E9ment Fournier".freeze]
s.date = "2021-06-17"
s.date = "2021-06-20"
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
s.email = ["[email protected]".freeze, "[email protected]".freeze, "[email protected]".freeze]
s.executables = ["pmdtester".freeze]
s.extra_rdoc_files = ["History.md".freeze, "Manifest.txt".freeze, "README.rdoc".freeze]
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, "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]
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, "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]
s.homepage = "https://pmd.github.io".freeze
s.licenses = ["BSD-2-Clause".freeze]
s.rdoc_options = ["--main".freeze, "README.rdoc".freeze]
Expand Down
3 changes: 2 additions & 1 deletion resources/js/project-report.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ $(document).ready(function () {
viewTotal: true,
cascadePanes: true,
columns: [0, 1, 3],
order: ['Rule', 'Location (click row to expand)', 'Type']
order: ['Rule', 'Location (click row to expand)', 'Type'],
threshold: 1 // always show filters in search pane (default: 0.6)
},
// scrollCollapse: true,
// paging: false,
Expand Down
9 changes: 9 additions & 0 deletions resources/project_diff_report.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

</head>
<body>
<div class="section">
<h1>PMD Regression Tester Diff Report for {{project_name}}</h1>
</div>
<div class="section">
<h2>Summary</h2>
<div class="section-content">
Expand Down Expand Up @@ -68,6 +71,12 @@ <h2>Summary</h2>
<td class="patch">{{diff.patch_timestamp}}</td>
<td class="diff"></td>
</tr>
<tr>
<td class="item">Full Report</td>
<td class="base"><a href="base_pmd_report.html">Base PMD Report</a></td>
<td class="patch"><a href="patch_pmd_report.html">Patch PMD Report</a></td>
<td class="diff"></td>
</tr>
</tbody>
</table>
</div>
Expand Down
Loading

0 comments on commit 0e8f328

Please sign in to comment.