pmdtester 1.0.0.pre.beta3 → 1.1.2
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 +67 -0
- data/.ci/files/env.gpg +1 -0
- data/.ci/inc/install-openjdk.inc +26 -0
- data/.ci/manual-integration-tests.sh +20 -0
- data/.github/workflows/build.yml +39 -0
- data/.github/workflows/manual-integration-tests.yml +32 -0
- data/.gitignore +9 -0
- data/.hoerc +1 -1
- data/.rubocop.yml +13 -2
- data/.rubocop_todo.yml +7 -8
- data/.ruby-version +1 -0
- data/Gemfile +1 -12
- data/History.md +104 -0
- data/Manifest.txt +30 -6
- data/README.rdoc +110 -60
- data/Rakefile +27 -15
- data/config/all-java.xml +1 -1
- data/config/design.xml +1 -1
- data/config/projectlist_1_0_0.xsd +2 -1
- data/config/projectlist_1_1_0.xsd +31 -0
- data/lib/pmdtester.rb +12 -4
- data/lib/pmdtester/builders/liquid_renderer.rb +73 -0
- data/lib/pmdtester/builders/pmd_report_builder.rb +134 -60
- data/lib/pmdtester/builders/project_builder.rb +100 -0
- data/lib/pmdtester/builders/project_hasher.rb +126 -0
- data/lib/pmdtester/builders/rule_set_builder.rb +94 -48
- data/lib/pmdtester/builders/simple_progress_logger.rb +27 -0
- data/lib/pmdtester/builders/summary_report_builder.rb +62 -117
- data/lib/pmdtester/cmd.rb +15 -1
- data/lib/pmdtester/collection_by_file.rb +55 -0
- data/lib/pmdtester/parsers/options.rb +25 -2
- data/lib/pmdtester/parsers/pmd_report_document.rb +79 -27
- data/lib/pmdtester/parsers/projects_parser.rb +2 -4
- data/lib/pmdtester/pmd_branch_detail.rb +36 -12
- data/lib/pmdtester/pmd_configerror.rb +62 -0
- data/lib/pmdtester/pmd_error.rb +34 -34
- data/lib/pmdtester/pmd_report_detail.rb +10 -13
- data/lib/pmdtester/pmd_tester_utils.rb +57 -0
- data/lib/pmdtester/pmd_violation.rb +66 -26
- data/lib/pmdtester/project.rb +28 -23
- data/lib/pmdtester/report_diff.rb +194 -70
- data/lib/pmdtester/resource_locator.rb +4 -0
- data/lib/pmdtester/runner.rb +81 -54
- data/pmdtester.gemspec +64 -0
- 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 +136 -0
- data/resources/project_diff_report.html +205 -0
- data/resources/project_index.html +102 -0
- metadata +122 -38
- data/.travis.yml +0 -22
- data/lib/pmdtester/builders/diff_builder.rb +0 -30
- data/lib/pmdtester/builders/diff_report_builder.rb +0 -225
- data/lib/pmdtester/builders/html_report_builder.rb +0 -33
- data/resources/css/maven-base.css +0 -155
- data/resources/css/maven-theme.css +0 -171
@@ -1,78 +1,91 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'fileutils'
|
4
|
+
require 'rufus-scheduler'
|
4
5
|
|
5
6
|
module PmdTester
|
6
7
|
# Building pmd xml reports according to a list of standard
|
7
8
|
# projects and branch of pmd source code
|
8
9
|
class PmdReportBuilder
|
9
10
|
include PmdTester
|
10
|
-
|
11
|
-
|
11
|
+
|
12
|
+
def initialize(projects, options, branch_config, branch_name)
|
12
13
|
@projects = projects
|
13
|
-
@local_git_repo = local_git_repo
|
14
|
-
@
|
14
|
+
@local_git_repo = options.local_git_repo
|
15
|
+
@threads = options.threads
|
16
|
+
@error_recovery = options.error_recovery
|
17
|
+
@branch_config = branch_config
|
18
|
+
@pmd_branch_name = branch_name
|
15
19
|
@pwd = Dir.getwd
|
16
20
|
|
17
|
-
@pmd_branch_details = PmdBranchDetail.new(pmd_branch_name)
|
21
|
+
@pmd_branch_details = PmdBranchDetail.new(@pmd_branch_name)
|
22
|
+
@project_builder = ProjectBuilder.new(@projects)
|
18
23
|
end
|
19
24
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
when 'hg'
|
25
|
-
reset_cmd = "hg up #{tag}"
|
26
|
-
end
|
25
|
+
def get_pmd_binary_file
|
26
|
+
logger.info "#{@pmd_branch_name}: Start packaging PMD"
|
27
|
+
Dir.chdir(@local_git_repo) do
|
28
|
+
build_branch_sha = Cmd.execute("git rev-parse #{@pmd_branch_name}^{commit}")
|
27
29
|
|
28
|
-
|
29
|
-
end
|
30
|
+
checkout_build_branch # needs a clean working tree, otherwise fails
|
30
31
|
|
31
|
-
|
32
|
-
logger.info 'Cloning projects started'
|
32
|
+
raise "Wrong branch #{get_last_commit_sha}" unless build_branch_sha == get_last_commit_sha
|
33
33
|
|
34
|
-
|
35
|
-
logger.
|
36
|
-
|
37
|
-
|
38
|
-
if File.
|
39
|
-
logger.
|
34
|
+
distro_path = saved_distro_path(build_branch_sha)
|
35
|
+
logger.debug "#{@pmd_branch_name}: PMD Version is #{@pmd_version} " \
|
36
|
+
"(sha=#{build_branch_sha})"
|
37
|
+
logger.debug "#{@pmd_branch_name}: distro_path=#{distro_path}"
|
38
|
+
if File.directory?(distro_path)
|
39
|
+
logger.info "#{@pmd_branch_name}: Skipping packaging - saved version exists " \
|
40
|
+
" in #{distro_path}"
|
40
41
|
else
|
41
|
-
|
42
|
+
build_pmd(into_dir: distro_path)
|
42
43
|
end
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
logger.info "Cloning #{project.name} completed"
|
45
|
+
# we're still on the build branch
|
46
|
+
@pmd_branch_details.branch_last_sha = build_branch_sha
|
47
|
+
@pmd_branch_details.branch_last_message = get_last_commit_message
|
48
48
|
end
|
49
|
+
logger.info "#{@pmd_branch_name}: Packaging PMD completed"
|
49
50
|
end
|
50
51
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
52
|
+
# builds pmd on currently checked out branch
|
53
|
+
def build_pmd(into_dir:)
|
54
|
+
# in CI there might have been a build performed already. In that case
|
55
|
+
# we reuse the build result, otherwise we build PMD freshly
|
56
|
+
pmd_dist_target = "pmd-dist/target/pmd-bin-#{@pmd_version}.zip"
|
57
|
+
binary_exists = File.exist?(pmd_dist_target)
|
58
|
+
logger.debug "#{@pmd_branch_name}: Does the file #{pmd_dist_target} exist? #{binary_exists} (cwd: #{Dir.getwd})"
|
59
|
+
if binary_exists
|
60
|
+
# that's a warning, because we don't know, whether this build really
|
61
|
+
# belongs to the current branch or whether it's from a previous branch.
|
62
|
+
# In CI, that's not a problem, because the workspace is always fresh.
|
63
|
+
logger.warn "#{@pmd_branch_name}: Reusing already existing #{pmd_dist_target}"
|
64
|
+
else
|
65
|
+
logger.info "#{@pmd_branch_name}: Building PMD #{@pmd_version}..."
|
66
|
+
package_cmd = './mvnw clean package' \
|
67
|
+
' -Dmaven.test.skip=true' \
|
68
|
+
' -Dmaven.javadoc.skip=true' \
|
69
|
+
' -Dmaven.source.skip=true' \
|
70
|
+
' -Dcheckstyle.skip=true' \
|
71
|
+
' -Dpmd.skip=true' \
|
72
|
+
' -T1C'
|
62
73
|
Cmd.execute(package_cmd)
|
74
|
+
end
|
63
75
|
|
64
|
-
|
65
|
-
|
66
|
-
|
76
|
+
logger.info "#{@pmd_branch_name}: Extracting the zip"
|
77
|
+
Cmd.execute("unzip -qo #{pmd_dist_target} -d pmd-dist/target/exploded")
|
78
|
+
Cmd.execute("mv pmd-dist/target/exploded/pmd-bin-#{@pmd_version} #{into_dir}")
|
79
|
+
end
|
67
80
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
81
|
+
def determine_pmd_version
|
82
|
+
version_cmd = "./mvnw -q -Dexec.executable=\"echo\" -Dexec.args='${project.version}' " \
|
83
|
+
'--non-recursive org.codehaus.mojo:exec-maven-plugin:1.5.0:exec'
|
84
|
+
Cmd.execute(version_cmd)
|
72
85
|
end
|
73
86
|
|
74
87
|
def get_last_commit_sha
|
75
|
-
get_last_commit_sha_cmd = 'git rev-parse HEAD'
|
88
|
+
get_last_commit_sha_cmd = 'git rev-parse HEAD^{commit}'
|
76
89
|
Cmd.execute(get_last_commit_sha_cmd)
|
77
90
|
end
|
78
91
|
|
@@ -81,31 +94,55 @@ module PmdTester
|
|
81
94
|
Cmd.execute(get_last_commit_message_cmd)
|
82
95
|
end
|
83
96
|
|
84
|
-
def generate_pmd_report(
|
85
|
-
|
86
|
-
|
87
|
-
|
97
|
+
def generate_pmd_report(project)
|
98
|
+
error_recovery_options = @error_recovery ? 'PMD_JAVA_OPTS="-Dpmd.error_recovery -ea" ' : ''
|
99
|
+
run_path = "#{saved_distro_path(@pmd_branch_details.branch_last_sha)}/bin/run.sh"
|
100
|
+
pmd_cmd = "#{error_recovery_options}" \
|
101
|
+
"#{run_path} pmd -d #{project.local_source_path} -f xml " \
|
102
|
+
"-R #{project.get_config_path(@pmd_branch_name)} " \
|
103
|
+
"-r #{project.get_pmd_report_path(@pmd_branch_name)} " \
|
104
|
+
"-failOnViolation false -t #{@threads} " \
|
105
|
+
"#{project.auxclasspath}"
|
88
106
|
start_time = Time.now
|
89
|
-
|
107
|
+
if File.exist?(project.get_pmd_report_path(@pmd_branch_name))
|
108
|
+
logger.warn "#{@pmd_branch_name}: Skipping PMD run - report " \
|
109
|
+
"#{project.get_pmd_report_path(@pmd_branch_name)} already exists"
|
110
|
+
else
|
111
|
+
Cmd.execute(pmd_cmd)
|
112
|
+
end
|
90
113
|
end_time = Time.now
|
91
114
|
[end_time - start_time, end_time]
|
92
115
|
end
|
93
116
|
|
117
|
+
def generate_config_for(project)
|
118
|
+
logger.debug "Generating ruleset with excludes from #{@branch_config}"
|
119
|
+
doc = Nokogiri::XML(File.read(@branch_config))
|
120
|
+
ruleset = doc.at_css('ruleset')
|
121
|
+
ruleset.add_child("\n")
|
122
|
+
project.exclude_pattern.each do |exclude_pattern|
|
123
|
+
ruleset.add_child(" <exclude-pattern>#{exclude_pattern}</exclude-pattern>\n")
|
124
|
+
end
|
125
|
+
|
126
|
+
File.open(project.get_config_path(@pmd_branch_name), 'w') do |x|
|
127
|
+
x << doc.to_s
|
128
|
+
end
|
129
|
+
|
130
|
+
logger.debug "Created file #{project.get_config_path(@pmd_branch_name)}"
|
131
|
+
end
|
132
|
+
|
94
133
|
def generate_pmd_reports
|
95
134
|
logger.info "Generating PMD report started -- branch #{@pmd_branch_name}"
|
96
|
-
get_pmd_binary_file
|
97
135
|
|
98
136
|
sum_time = 0
|
99
137
|
@projects.each do |project|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
138
|
+
progress_logger = SimpleProgressLogger.new("generating #{project.name}'s PMD report")
|
139
|
+
progress_logger.start
|
140
|
+
generate_config_for(project)
|
141
|
+
execution_time, end_time = generate_pmd_report(project)
|
142
|
+
progress_logger.stop
|
104
143
|
sum_time += execution_time
|
105
144
|
|
106
|
-
report_details = PmdReportDetail.new
|
107
|
-
report_details.execution_time = execution_time
|
108
|
-
report_details.timestamp = end_time
|
145
|
+
report_details = PmdReportDetail.new(execution_time: execution_time, timestamp: end_time)
|
109
146
|
report_details.save(project.get_report_info_path(@pmd_branch_name))
|
110
147
|
logger.info "#{project.name}'s PMD report was generated successfully"
|
111
148
|
end
|
@@ -116,9 +153,46 @@ module PmdTester
|
|
116
153
|
@pmd_branch_details
|
117
154
|
end
|
118
155
|
|
156
|
+
# returns the branch details
|
119
157
|
def build
|
120
|
-
|
158
|
+
@project_builder.clone_projects
|
159
|
+
@project_builder.build_projects
|
160
|
+
get_pmd_binary_file
|
121
161
|
generate_pmd_reports
|
122
162
|
end
|
163
|
+
|
164
|
+
private
|
165
|
+
|
166
|
+
def checkout_build_branch
|
167
|
+
logger.info "#{@pmd_branch_name}: Checking out the branch"
|
168
|
+
# note that this would fail if the tree is dirty
|
169
|
+
Cmd.execute("git checkout #{@pmd_branch_name}")
|
170
|
+
|
171
|
+
# determine the version
|
172
|
+
@pmd_version = determine_pmd_version
|
173
|
+
|
174
|
+
return unless wd_has_dirty_git_changes
|
175
|
+
|
176
|
+
# working dir is dirty....
|
177
|
+
# we don't allow this because we need the SHA to address the zip file
|
178
|
+
logger.error "#{@pmd_branch_name}: Won\'t build without a clean working tree, " \
|
179
|
+
'commit your changes'
|
180
|
+
end
|
181
|
+
|
182
|
+
def work_dir
|
183
|
+
"#{@pwd}/target"
|
184
|
+
end
|
185
|
+
|
186
|
+
# path to the unzipped distribution
|
187
|
+
# e.g. <cwd>/pmd-bin-<version>-<branch>-<sha>
|
188
|
+
def saved_distro_path(build_sha)
|
189
|
+
"#{work_dir}/pmd-bin-#{@pmd_version}" \
|
190
|
+
"-#{PmdBranchDetail.branch_filename(@pmd_branch_name)}" \
|
191
|
+
"-#{build_sha}"
|
192
|
+
end
|
193
|
+
|
194
|
+
def wd_has_dirty_git_changes
|
195
|
+
!Cmd.execute('git status --porcelain').empty?
|
196
|
+
end
|
123
197
|
end
|
124
198
|
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'tempfile'
|
5
|
+
|
6
|
+
module PmdTester
|
7
|
+
# Clones and builds the projects, that are configured in the project-list.xml
|
8
|
+
class ProjectBuilder
|
9
|
+
include PmdTester
|
10
|
+
|
11
|
+
def initialize(projects)
|
12
|
+
@projects = projects
|
13
|
+
end
|
14
|
+
|
15
|
+
def clone_projects
|
16
|
+
logger.info 'Cloning projects started'
|
17
|
+
|
18
|
+
@projects.each do |project|
|
19
|
+
logger.info "Start cloning #{project.name} repository"
|
20
|
+
path = project.local_source_path
|
21
|
+
clone_cmd = "#{project.type} clone #{project.connection} #{path}"
|
22
|
+
if File.exist?(path)
|
23
|
+
logger.warn "Skipping clone, project path #{path} already exists"
|
24
|
+
else
|
25
|
+
Cmd.execute(clone_cmd)
|
26
|
+
end
|
27
|
+
|
28
|
+
Dir.chdir(path) do
|
29
|
+
execute_reset_cmd(project.type, project.tag)
|
30
|
+
end
|
31
|
+
logger.info "Cloning #{project.name} completed"
|
32
|
+
end
|
33
|
+
|
34
|
+
logger.info 'Cloning projects completed'
|
35
|
+
end
|
36
|
+
|
37
|
+
def build_projects
|
38
|
+
logger.info 'Building projects started'
|
39
|
+
|
40
|
+
@projects.each do |project|
|
41
|
+
path = project.local_source_path
|
42
|
+
Dir.chdir(path) do
|
43
|
+
progress_logger = SimpleProgressLogger.new("building #{project.name} in #{path}")
|
44
|
+
progress_logger.start
|
45
|
+
prepare_project(project)
|
46
|
+
progress_logger.stop
|
47
|
+
end
|
48
|
+
logger.info "Building #{project.name} completed"
|
49
|
+
end
|
50
|
+
|
51
|
+
logger.info 'Building projects completed'
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def prepare_project(project)
|
57
|
+
# Note: current working directory is the project directory,
|
58
|
+
# where the source code has been cloned to
|
59
|
+
if project.build_command
|
60
|
+
logger.debug "Executing build-command: #{project.build_command}"
|
61
|
+
run_as_script(Dir.getwd, project.build_command)
|
62
|
+
end
|
63
|
+
if project.auxclasspath_command
|
64
|
+
logger.debug "Executing auxclasspath-command: #{project.auxclasspath_command}"
|
65
|
+
auxclasspath = run_as_script(Dir.getwd, project.auxclasspath_command)
|
66
|
+
project.auxclasspath = "-auxclasspath #{auxclasspath}"
|
67
|
+
else
|
68
|
+
project.auxclasspath = ''
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def run_as_script(path, command)
|
73
|
+
script = Tempfile.new(['pmd-regression-', '.sh'], path)
|
74
|
+
logger.debug "Creating script #{script.path}"
|
75
|
+
begin
|
76
|
+
script.write(command)
|
77
|
+
script.close
|
78
|
+
shell = 'sh -xe'
|
79
|
+
if command.start_with?('#!')
|
80
|
+
shell = command.lines[0].chomp[2..] # remove leading "#!"
|
81
|
+
end
|
82
|
+
stdout = Cmd.execute("#{shell} #{script.path}")
|
83
|
+
ensure
|
84
|
+
script.unlink
|
85
|
+
end
|
86
|
+
stdout
|
87
|
+
end
|
88
|
+
|
89
|
+
def execute_reset_cmd(type, tag)
|
90
|
+
case type
|
91
|
+
when 'git'
|
92
|
+
reset_cmd = "git checkout #{tag}; git reset --hard #{tag}"
|
93
|
+
when 'hg'
|
94
|
+
reset_cmd = "hg up #{tag}"
|
95
|
+
end
|
96
|
+
|
97
|
+
Cmd.execute(reset_cmd)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'differ'
|
4
|
+
|
5
|
+
module PmdTester
|
6
|
+
# Turn a project report into a hash that can be rendered somewhere else
|
7
|
+
module ProjectHasher
|
8
|
+
include PmdTester
|
9
|
+
|
10
|
+
def report_diff_to_h(rdiff)
|
11
|
+
{
|
12
|
+
'violation_counts' => rdiff.violation_counts.to_h.transform_keys(&:to_s),
|
13
|
+
'error_counts' => rdiff.error_counts.to_h.transform_keys(&:to_s),
|
14
|
+
'configerror_counts' => rdiff.configerror_counts.to_h.transform_keys(&:to_s),
|
15
|
+
|
16
|
+
'base_execution_time' => PmdReportDetail.convert_seconds(rdiff.base_report.exec_time),
|
17
|
+
'patch_execution_time' => PmdReportDetail.convert_seconds(rdiff.patch_report.exec_time),
|
18
|
+
'diff_execution_time' => PmdReportDetail.convert_seconds(rdiff.patch_report.exec_time -
|
19
|
+
rdiff.base_report.exec_time),
|
20
|
+
|
21
|
+
'base_timestamp' => rdiff.base_report.timestamp,
|
22
|
+
'patch_timestamp' => rdiff.patch_report.timestamp,
|
23
|
+
|
24
|
+
'rule_diffs' => rdiff.rule_summaries
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def errors_to_h(project)
|
29
|
+
errors = project.report_diff.error_diffs_by_file.values.flatten
|
30
|
+
errors.map { |e| error_to_hash(e, project) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def configerrors_to_h(project)
|
34
|
+
configerrors = project.report_diff.configerror_diffs_by_rule.values.flatten
|
35
|
+
configerrors.map { |e| configerror_to_hash(e) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def violations_to_hash(project)
|
39
|
+
filename_index = []
|
40
|
+
all_vs = []
|
41
|
+
project.report_diff.violation_diffs_by_file.each do |file, vs|
|
42
|
+
file_ref = filename_index.size
|
43
|
+
filename_index.push(project.get_local_path(file))
|
44
|
+
vs.each do |v|
|
45
|
+
all_vs.push(make_violation_hash(file_ref, v))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
{
|
50
|
+
'file_index' => filename_index,
|
51
|
+
'violations' => all_vs
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
def link_template(project)
|
56
|
+
l_str = project.type == 'git' ? 'L' : 'l'
|
57
|
+
"#{project.webview_url}/{file}##{l_str}{line}"
|
58
|
+
end
|
59
|
+
|
60
|
+
def violation_type(violation)
|
61
|
+
if violation.changed?
|
62
|
+
'~'
|
63
|
+
elsif violation.branch == 'patch'
|
64
|
+
'+'
|
65
|
+
else
|
66
|
+
'-'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def make_violation_hash(file_ref, violation)
|
71
|
+
h = {
|
72
|
+
't' => violation_type(violation),
|
73
|
+
'l' => violation.line,
|
74
|
+
'f' => file_ref,
|
75
|
+
'r' => violation.rule_name,
|
76
|
+
'm' => violation.changed? ? diff_fragments(violation) : violation.message
|
77
|
+
}
|
78
|
+
h['ol'] = violation.old_line if violation.changed? && violation.line != violation.old_line
|
79
|
+
h
|
80
|
+
end
|
81
|
+
|
82
|
+
def diff_fragments(violation)
|
83
|
+
diff = Differ.diff_by_word(violation.message, violation.old_message)
|
84
|
+
diff.format_as(:html)
|
85
|
+
end
|
86
|
+
|
87
|
+
def error_to_hash(error, project)
|
88
|
+
escaped_stacktrace = sanitize_stacktrace(error)
|
89
|
+
old_stacktrace = error.old_error.nil? ? nil : sanitize_stacktrace(error.old_error)
|
90
|
+
|
91
|
+
{
|
92
|
+
'file_url' => project.get_webview_url(error.filename),
|
93
|
+
'stack_trace_html' => escaped_stacktrace,
|
94
|
+
'old_stack_trace_html' => old_stacktrace,
|
95
|
+
'short_message' => error.short_message,
|
96
|
+
'short_filename' => error.short_filename,
|
97
|
+
'filename' => error.filename,
|
98
|
+
'change_type' => change_type(error)
|
99
|
+
}
|
100
|
+
end
|
101
|
+
|
102
|
+
def sanitize_stacktrace(error)
|
103
|
+
CGI.escapeHTML(error.stack_trace)
|
104
|
+
.gsub(error.filename, '<span class="meta-var">$FILE</span>')
|
105
|
+
.gsub(/\w++(?=\(\w++\.java:\d++\))/, '<span class="stack-trace-method">\\0</span>')
|
106
|
+
end
|
107
|
+
|
108
|
+
def configerror_to_hash(configerror)
|
109
|
+
{
|
110
|
+
'rule' => configerror.rulename,
|
111
|
+
'message' => configerror.msg,
|
112
|
+
'change_type' => change_type(configerror)
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
116
|
+
def change_type(item)
|
117
|
+
if item.branch == BASE
|
118
|
+
'removed'
|
119
|
+
elsif item.changed?
|
120
|
+
'changed'
|
121
|
+
else
|
122
|
+
'added'
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|