fastlane-plugin-code_static_analyzer 0.1.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +143 -0
- data/lib/assets/code_analys.sh +27 -0
- data/lib/assets/formatter.rb +31 -0
- data/lib/assets/junit_parser.rb +225 -0
- data/lib/assets/run_script.sh +13 -0
- data/lib/fastlane/plugin/code_static_analyzer.rb +17 -0
- data/lib/fastlane/plugin/code_static_analyzer/actions/code_static_analyzer_action.rb +310 -0
- data/lib/fastlane/plugin/code_static_analyzer/actions/cpd_analyzer.rb +134 -0
- data/lib/fastlane/plugin/code_static_analyzer/actions/ruby_analyzer.rb +112 -0
- data/lib/fastlane/plugin/code_static_analyzer/actions/warning_analyzer.rb +156 -0
- data/lib/fastlane/plugin/code_static_analyzer/helper/code_static_analyzer_helper.rb +12 -0
- data/lib/fastlane/plugin/code_static_analyzer/version.rb +5 -0
- metadata +168 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 31ca64424721af47394fb63b3f00532811b84bdf
|
4
|
+
data.tar.gz: e12379d050bad5565564d5402ab6b7517b8594a9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b7925823d710984f81d6b483aa41a010325475e68ecf9792fe6ce79a19e70de027170c7950d18565483b6ac16d6f29ef44b4a39b566cc2c687cd4d108c483b3b
|
7
|
+
data.tar.gz: 5c3fde6b0c8e7179ca53ea4952ff8f1c7fdddc242d79e6d6a598e85f5c22f46fa7cf879d1f812e73ce096caf7ca1545f7c91ae11d916bdc288d1764fe4edac24
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Olga Kniazska <olgak.kiev@ukr.net>
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
# code_static_analyzer plugin
|
2
|
+
|
3
|
+
[](https://rubygems.org/gems/fastlane-plugin-code_static_analyzer)
|
4
|
+
|
5
|
+
## Getting Started
|
6
|
+
|
7
|
+
This project is a [fastlane](https://github.com/fastlane/fastlane) plugin. To get started with `fastlane-plugin-code_static_analyzer`, add it to your project by running:
|
8
|
+
|
9
|
+
```bash
|
10
|
+
fastlane add_plugin code_static_analyzer
|
11
|
+
```
|
12
|
+
|
13
|
+
## About code_static_analyzer
|
14
|
+
|
15
|
+
This plugins runs different Static Analyzers for checking your code on warnings, copypaste, syntax, etc and generate reports.
|
16
|
+
Each analyzer in this plugin generate separate report `codeAnalysResult_<name of analyzer>.xml` and
|
17
|
+
save result status in shared values `<NAME>_ANALYZER_STATUS`: 0 - code is clear, any other value - code include warnings/errors.
|
18
|
+
Finally you can check plugin return value (true='code is clear'/false) to decide what to do next. <br />
|
19
|
+
All reports are generated in JUnit format for easier start-up at the CI servers.
|
20
|
+
|
21
|
+
## Important
|
22
|
+
- You can configure rubocop analyzer by creating configuration file `.rubocop.yml` in your project (more about rubocop configuration http://rubocop.readthedocs.io/en/latest/cops/)
|
23
|
+
- All paths should be relative to work directory.
|
24
|
+
|
25
|
+
### Specific for copy paste analyzer (CPD)
|
26
|
+
- PMD have to be installed on your machine (http://pmd.sourceforge.net/snapshot/usage/installing.html)
|
27
|
+
- [!]Pay attention on language parameter: if your code language is available in supported list you have to set this parameter.
|
28
|
+
|
29
|
+
## Actions
|
30
|
+
|
31
|
+
`code_static_analyzer` - runs all configured analyzers together (Copy paste analyzer always runs).<br />
|
32
|
+
You may run each analyzer separate:<br />
|
33
|
+
`cpd_analyzer` - finds copy paste in code (based on CPD from PMD package) <br />
|
34
|
+
`ruby_analyzer` - checks your ruby files. Some offenses can be auto-corrected (if you want to save the changes do it manually) <br />
|
35
|
+
`warning_analyzer` - this analyzer uses Xcode built-in analyzer mainly to detect warnings<br />
|
36
|
+
|
37
|
+
## Reference and Example
|
38
|
+
|
39
|
+
### `code_static_analyzer` (Run all analyzers)
|
40
|
+
|
41
|
+
````ruby
|
42
|
+
# minimum configuration
|
43
|
+
code_static_analyzer(
|
44
|
+
analyzers: 'all',
|
45
|
+
cpd_language: 'objectivec',
|
46
|
+
xcode_project_name: 'path/to/TestProject',
|
47
|
+
)
|
48
|
+
# full configuration
|
49
|
+
code_static_analyzer(
|
50
|
+
analyzers: 'all',
|
51
|
+
result_dir: 'result directory',
|
52
|
+
cpd_tokens: '150',
|
53
|
+
cpd_language: 'objectivec',
|
54
|
+
cpd_files_to_inspect: 'path/to/myFiles/', # or list %w('path/to/myFiles/' 'path/to/testFiles/')
|
55
|
+
cpd_files_to_exclude: 'Pods', # or list %w('Pods' 'path/to/filesNotToInspect/file1.m' 'path/to/filesNotToInspect/in/dir')
|
56
|
+
xcode_project_name: 'path/to/TestProject',
|
57
|
+
xcode_workspace_name: 'path/to/testWorkspace',
|
58
|
+
xcode_targets: ['TPClientTarget','TPServerTarget'],
|
59
|
+
ruby_files: 'fastlane/Fastfile'
|
60
|
+
)
|
61
|
+
````
|
62
|
+
Parameter | Description
|
63
|
+
--------- | -----------
|
64
|
+
`analyzers` | List of analysers you want to run. Supported analyzers: "xcodeWar", "rubocop", "CPD", "all"
|
65
|
+
`result_dir` | *(optional)* Directory's name for storing analysis results.
|
66
|
+
`cpd_tokens` | *(optional)* The min number of words in code that is detected as copy paste.<br />Default value: 100
|
67
|
+
`cpd_language` | *(optional)* Language used in files that will be inspected on copy paste.<br />Supported analyzers: ['python', 'objectivec', 'jsp', 'ecmascript', 'fortran', 'cpp', 'ruby', 'php', 'java', 'matlab', 'scala', 'plsql', 'go', 'cs']. If you need any other language just don't set this parameter.
|
68
|
+
`cpd_files_to_inspect` | *(optional)* List of paths (relative to work directory) to files/directories to be inspected on copy paste.
|
69
|
+
`cpd_files_to_exclude` | *(optional)* List of paths (relative to work directory) to files/directories not to be inspected on copy paste
|
70
|
+
`xcode_project_name` | *(required if use warning analyzer)* Xcode project name in work directory
|
71
|
+
`xcode_workspace_name`| *(optional)* Xcode workspace name in work directory. Set it if you use different project & workspace names
|
72
|
+
`xcode_targets` | *(optional)* List of Xcode targets to inspect. By default used all targets which are available in project
|
73
|
+
`ruby_files` | *(optional)* List of paths to ruby files to be inspected
|
74
|
+
|
75
|
+
### `code_static_analyzer` other examples (full configuration):
|
76
|
+
CPD:
|
77
|
+
````ruby
|
78
|
+
code_static_analyzer(
|
79
|
+
analyzers: 'cpd',
|
80
|
+
result_dir: 'result directory',
|
81
|
+
cpd_tokens: '150',
|
82
|
+
cpd_language: 'objectivec',
|
83
|
+
cpd_files_to_inspect: %w('path/to/myFiles/' 'path/to/testFiles/'),
|
84
|
+
cpd_files_to_exclude: %w('Pods' 'ThirdParty')
|
85
|
+
)
|
86
|
+
````
|
87
|
+
CPD + ruby:
|
88
|
+
````ruby
|
89
|
+
code_static_analyzer(
|
90
|
+
analyzers: 'rubocop',
|
91
|
+
result_dir: 'result directory',
|
92
|
+
cpd_tokens: '150',
|
93
|
+
cpd_language: 'objectivec',
|
94
|
+
cpd_files_to_inspect: %w('path/to/myFiles/' 'path/to/testFiles/'),
|
95
|
+
cpd_files_to_exclude: %w('Pods' 'ThirdParty'),
|
96
|
+
ruby_files: 'fastlane/Fastfile'
|
97
|
+
)
|
98
|
+
````
|
99
|
+
CPD + Xcode project warnings:
|
100
|
+
````ruby
|
101
|
+
code_static_analyzer(
|
102
|
+
analyzers: 'xcodewar',
|
103
|
+
result_dir: 'result directory',
|
104
|
+
cpd_tokens: '150',
|
105
|
+
cpd_language: 'objectivec',
|
106
|
+
cpd_files_to_inspect: %w('path/to/myFiles/' 'path/to/testFiles/'),
|
107
|
+
cpd_files_to_exclude: %w('Pods' 'ThirdParty'),
|
108
|
+
xcode_project_name: 'path/to/TestProject',
|
109
|
+
xcode_workspace_name: 'path/to/testWorkspace',
|
110
|
+
xcode_targets: ['TPClientTarget','TPServerTarget'],
|
111
|
+
)
|
112
|
+
````
|
113
|
+
|
114
|
+
## Run tests for this plugin
|
115
|
+
|
116
|
+
To run both the tests, and code style validation, run
|
117
|
+
|
118
|
+
```
|
119
|
+
rake
|
120
|
+
```
|
121
|
+
|
122
|
+
To automatically fix many of the styling issues, use
|
123
|
+
```
|
124
|
+
rubocop -a
|
125
|
+
```
|
126
|
+
|
127
|
+
## Issues and Feedback
|
128
|
+
|
129
|
+
- In some cases CPD can't recognize patterns in file/dir paths like `path/to/files/*.m`
|
130
|
+
(about path you may read in CPD documentation: http://pmd.sourceforge.net/snapshot/usage/cpd-usage.html)<br />
|
131
|
+
For any other issues and feedback about this plugin, please submit it to this repository.
|
132
|
+
|
133
|
+
## Troubleshooting
|
134
|
+
|
135
|
+
If you have trouble using plugins, check out the [Plugins Troubleshooting](https://docs.fastlane.tools/plugins/plugins-troubleshooting/) guide.
|
136
|
+
|
137
|
+
## Using `fastlane` Plugins
|
138
|
+
|
139
|
+
For more information about how the `fastlane` plugin system works, check out the [Plugins documentation](https://docs.fastlane.tools/plugins/create-plugin/).
|
140
|
+
|
141
|
+
## About `fastlane`
|
142
|
+
|
143
|
+
`fastlane` is the easiest way to automate beta deployments and releases for your iOS and Android apps. To learn more, check out [fastlane.tools](https://fastlane.tools).
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/bin/bash -o pipefail
|
2
|
+
#!/bin/sh -e
|
3
|
+
# code_analys.sh
|
4
|
+
# @desc Detect code warnings/errors by using static analyzer build in Xcode.
|
5
|
+
# @usage
|
6
|
+
# 1. Income parameters
|
7
|
+
# WORKSPACE_PROJECT - name of xcode project or workspace (.xcodeproj / .xcworkspace)
|
8
|
+
# BUILD_LANE - name of project target
|
9
|
+
# LOG - path-name of .log file for temporary usage to store full output of Xcode command
|
10
|
+
# IN_WORKSPACE - true if WORKSPACE_PROJECT=.xcworkspace
|
11
|
+
|
12
|
+
WORKSPACE_PROJECT=$1
|
13
|
+
BUILD_LANE=$2
|
14
|
+
LOG=$3
|
15
|
+
IN_WORKSPACE=$4
|
16
|
+
|
17
|
+
#detect warnings
|
18
|
+
#analyze code (build in xcode tools)
|
19
|
+
if $IN_WORKSPACE; then
|
20
|
+
xcodebuild -scheme $BUILD_LANE -workspace $WORKSPACE_PROJECT clean analyze |
|
21
|
+
tee "$LOG" |
|
22
|
+
xcpretty
|
23
|
+
else
|
24
|
+
xcodebuild -scheme $BUILD_LANE -project $WORKSPACE_PROJECT clean analyze |
|
25
|
+
tee "$LOG" |
|
26
|
+
xcpretty
|
27
|
+
fi
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
# output_looking.rb
|
3
|
+
# @desc Tools for preparing better looking running output
|
4
|
+
# @usage
|
5
|
+
# in needed file paste string: require './path-to-file/output_looking.rb
|
6
|
+
|
7
|
+
# Use to prepare formatted output
|
8
|
+
module Formatter
|
9
|
+
def self.return_status(mystatus)
|
10
|
+
puts light_blue(">>> Exit command status: #{mystatus}")
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.xcode_format(scheme)
|
14
|
+
puts ">>> Running Xcode analyze command... on #{scheme}..."
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.cpd_format(tokens, language, exclude, result_file, inspect)
|
18
|
+
puts "files : #{inspect}"
|
19
|
+
puts "min_tokens : #{tokens}"
|
20
|
+
puts "language : #{language}"
|
21
|
+
puts "exclude_files : #{exclude}"
|
22
|
+
puts 'format : xml'
|
23
|
+
puts "output_file : #{result_file}"
|
24
|
+
end
|
25
|
+
|
26
|
+
# String colorization
|
27
|
+
# call UI.message Actions::FormatterAction.light_blue(text)
|
28
|
+
def self.light_blue(mytext)
|
29
|
+
"\e[36m#{mytext}\e[0m"
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,225 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
# parser.sh
|
3
|
+
# @desc Parser
|
4
|
+
# @usage
|
5
|
+
# 1. Parser 1. Xcode analyze result (.log)
|
6
|
+
# 2. Parser 2. Rubocop result (.json)
|
7
|
+
# 3. Parser 3. CPD result (.xml)
|
8
|
+
|
9
|
+
require 'crack'
|
10
|
+
|
11
|
+
module JunitParser
|
12
|
+
#####################################################
|
13
|
+
# ================= For all parsers =================
|
14
|
+
#####################################################
|
15
|
+
|
16
|
+
def self.create_xml(xml_data_custom, result_file_name)
|
17
|
+
xml_data = '<?xml version="1.0" encoding="UTF-8"?>'
|
18
|
+
xml_data += xml_data_custom
|
19
|
+
File.open(result_file_name, 'w') do |f|
|
20
|
+
f.write(xml_data)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.create_testsuites(testsuites)
|
25
|
+
"#{xml_level(0)}<testsuites>#{testsuites}#{xml_level(0)}</testsuites>"
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.add_testsuite(name, testcases)
|
29
|
+
"#{xml_level(1)}<testsuite name='#{name}'>" \
|
30
|
+
"#{testcases}" \
|
31
|
+
"#{xml_level(1)}</testsuite>"
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.add_failed_testcase(name, failures)
|
35
|
+
"#{xml_level(2)}<testcase name='#{name}'>" \
|
36
|
+
"#{failures}#{xml_level(2)}</testcase>"
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.add_success_testcase(name)
|
40
|
+
"#{xml_level(2)}<testcase name='#{name}' status='success'/>"
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.add_failure(message, type, text)
|
44
|
+
"#{xml_level(3)}<failure #{insert_attribute('type', type)} status='failed' " \
|
45
|
+
"#{insert_attribute('message', message)}>" \
|
46
|
+
"#{text}" \
|
47
|
+
"#{xml_level(3)}</failure>"
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.add_properties(property_array, value_array)
|
51
|
+
properties = "#{xml_level(2)}<properties>"
|
52
|
+
property_array.each_with_index do |property, index|
|
53
|
+
value = value_array[index]
|
54
|
+
unless value.nil?
|
55
|
+
properties += "#{xml_level(3)}<property name='#{property}' value='#{value}' />"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
properties += "#{xml_level(2)}</properties>"
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.construct_failure_mes(attributes, values)
|
62
|
+
properties = xml_level(0).to_s
|
63
|
+
attributes.each_with_index do |property, index|
|
64
|
+
value = values[index]
|
65
|
+
properties += format("#{xml_level(4)}%-18s: %s", property, value) unless value.nil?
|
66
|
+
end
|
67
|
+
properties
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.insert_attribute(attribute, value)
|
71
|
+
value == '' ? '' : "#{attribute}='#{value}'"
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.add_code(codefragment)
|
75
|
+
"<![CDATA[#{codefragment}]]>"
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.get_failure_type(str)
|
79
|
+
failure_type = str[/\[(.*?)\]/, 1]
|
80
|
+
failure_type = '-W' if failure_type.nil?
|
81
|
+
failure_type
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.xml_level(level)
|
85
|
+
levelstr = "\n"
|
86
|
+
i = 1
|
87
|
+
while i < level
|
88
|
+
levelstr += "\s\s"
|
89
|
+
i += 1
|
90
|
+
end
|
91
|
+
levelstr
|
92
|
+
end
|
93
|
+
|
94
|
+
# create root xml content
|
95
|
+
def self.create_junit_xml(testsuite, result_file_name)
|
96
|
+
full_data = create_testsuites(testsuite)
|
97
|
+
create_xml(full_data, result_file_name)
|
98
|
+
end
|
99
|
+
|
100
|
+
#####################################################
|
101
|
+
# ============== Xcode-log Parser ================
|
102
|
+
#####################################################
|
103
|
+
|
104
|
+
def self.parse_xcode_log(file, project, is_warn)
|
105
|
+
if is_warn
|
106
|
+
error_text = ''
|
107
|
+
File.open(file).each do |line|
|
108
|
+
if line =~ /warning:|error:/
|
109
|
+
warning_params = line.split(':')
|
110
|
+
if warning_params.count == 5
|
111
|
+
error_text += construct_failure_mes(
|
112
|
+
['Error ClassType', 'Error in File', 'Error Line', 'Error Message'],
|
113
|
+
[get_failure_type(warning_params[4]), warning_params[0].tr('<', '').tr('>', ''),
|
114
|
+
"#{warning_params[1]}:#{warning_params[2]}", warning_params[4].tr("\n", '')]
|
115
|
+
)
|
116
|
+
else
|
117
|
+
error_text += construct_failure_mes(
|
118
|
+
['Error ClassType', 'Error Message'],
|
119
|
+
['-W', line.tr("\n", '')]
|
120
|
+
)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
next unless line =~ /BCEROR/
|
124
|
+
error_text += construct_failure_mes(['Error ClassType', 'Error in File', 'Error Message'],
|
125
|
+
[get_failure_type(line), 'project configuration',
|
126
|
+
line.tr("\n", '')])
|
127
|
+
end
|
128
|
+
failures = add_failure('', '', error_text)
|
129
|
+
add_failed_testcase(project, failures)
|
130
|
+
else
|
131
|
+
add_success_testcase(project)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
#####################################################
|
136
|
+
# ============== Rubocop-json Parser ================
|
137
|
+
#####################################################
|
138
|
+
|
139
|
+
def self.parse_json(file)
|
140
|
+
data_read = File.read(file)
|
141
|
+
data_hash = Crack::JSON.parse(data_read)
|
142
|
+
|
143
|
+
keys = data_hash['metadata'].keys.zip(data_hash['summary'].keys).flatten.compact
|
144
|
+
values = data_hash['metadata'].values.zip(data_hash['summary'].values).flatten.compact
|
145
|
+
properties = add_properties(keys, values)
|
146
|
+
|
147
|
+
testcase = parse_main_json(data_hash)
|
148
|
+
|
149
|
+
properties + testcase
|
150
|
+
end
|
151
|
+
|
152
|
+
# create main xml content
|
153
|
+
def self.parse_main_json(data_hash)
|
154
|
+
xml = ''
|
155
|
+
data_hash['files'].each do |inspected_file|
|
156
|
+
error_text = ''
|
157
|
+
errors = inspected_file['offenses']
|
158
|
+
if errors.empty?
|
159
|
+
xml += add_success_testcase((inspected_file['path']).to_s)
|
160
|
+
else
|
161
|
+
errors.each do |error|
|
162
|
+
error_text += construct_failure_mes(
|
163
|
+
['Error isCorrected', 'Error ClassType', 'Error Line', 'Error Message'],
|
164
|
+
[error['corrected'], "#{error['cop_name']} (#{error['severity']})",
|
165
|
+
parse_location(error['location']), error['message'].tr("\n", '')]
|
166
|
+
)
|
167
|
+
end
|
168
|
+
# TODO: corrected:6 failded:0 (if needed this info)
|
169
|
+
failures = add_failure('lineformat=line:column:length', '', error_text)
|
170
|
+
xml += add_failed_testcase((inspected_file['path']).to_s, failures)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
xml
|
174
|
+
end
|
175
|
+
|
176
|
+
def self.parse_location(location)
|
177
|
+
"#{location['line']}:#{location['column']}:#{location['length']}"
|
178
|
+
end
|
179
|
+
|
180
|
+
#####################################################
|
181
|
+
# ================= CPD-xml Parser ==================
|
182
|
+
#####################################################
|
183
|
+
|
184
|
+
def self.parse_xml(file)
|
185
|
+
data_read = File.read(file)
|
186
|
+
data_hash = Crack::XML.parse(data_read)
|
187
|
+
|
188
|
+
if data_hash.empty? or data_hash['pmd_cpd']==nil
|
189
|
+
puts 'empty data_hash'
|
190
|
+
add_success_testcase('casino duplications')
|
191
|
+
else
|
192
|
+
parse_code_duplications(data_hash)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def self.parse_code_duplications(data_hash)
|
197
|
+
xml = ''
|
198
|
+
duplications = data_hash['pmd_cpd']['duplication']
|
199
|
+
if duplications.kind_of?(Array)
|
200
|
+
index = 1
|
201
|
+
duplications.each do |error|
|
202
|
+
parsed_files = parse_inspected_files(error['file'])
|
203
|
+
failure = add_failure("lines:#{error['lines']} tokens:#{error['tokens']} #{xml_level(3)}files:#{parsed_files}", '', "\n#{add_code(error['codefragment'])}")
|
204
|
+
xml += add_failed_testcase("duplication #{index}", failure)
|
205
|
+
index += 1
|
206
|
+
end
|
207
|
+
else
|
208
|
+
parsed_files = parse_inspected_files(duplications['file'])
|
209
|
+
failure = add_failure("lines:#{duplications['lines']} tokens:#{duplications['tokens']} #{xml_level(3)}files:#{parsed_files}", '',
|
210
|
+
"\n #{add_code(duplications['codefragment'])}")
|
211
|
+
xml += add_failed_testcase('single duplication', failure)
|
212
|
+
end
|
213
|
+
xml
|
214
|
+
end
|
215
|
+
|
216
|
+
def self.parse_inspected_files(file_list)
|
217
|
+
index = 1
|
218
|
+
file_list_info = []
|
219
|
+
file_list.each do |file|
|
220
|
+
file_list_info.push("File #{index}: #{file['path']}::#{file['line']}")
|
221
|
+
index += 1
|
222
|
+
end
|
223
|
+
file_list_info
|
224
|
+
end
|
225
|
+
end
|