codeclimate 0.14.0 → 0.14.1
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/bin/codeclimate +1 -0
- data/config/coffeelint/coffeelint.json +129 -0
- data/lib/cc/analyzer/engine.rb +1 -0
- data/lib/cc/cli.rb +1 -0
- data/lib/cc/cli/test.rb +270 -0
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f7d10a3e340b114a674a576928f4fcfecf003804
|
4
|
+
data.tar.gz: f457eb3fc54b3e7e63aeb3d64010b57736c4165d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7abfdf98943e97e6a5c43cb5a63f767e15b98a5b2b67ad2353ed417e3ce2835f8478dbe7b38f7de025128c5f79245db70c67e2faacbff2538e7a237cb0e00265
|
7
|
+
data.tar.gz: f97c25a43e0e1b44b1f05c6e5bbff19fbbbe5a018bd4008dcadadf28ff233c9951c981c6c7a556cae2ef23a540792854afc22ef74a3f0c8c147b045e724c09e0
|
data/bin/codeclimate
CHANGED
@@ -0,0 +1,129 @@
|
|
1
|
+
{
|
2
|
+
"arrow_spacing": {
|
3
|
+
"level": "ignore"
|
4
|
+
},
|
5
|
+
"braces_spacing": {
|
6
|
+
"level": "ignore",
|
7
|
+
"spaces": 0,
|
8
|
+
"empty_object_spaces": 0
|
9
|
+
},
|
10
|
+
"camel_case_classes": {
|
11
|
+
"level": "error"
|
12
|
+
},
|
13
|
+
"coffeescript_error": {
|
14
|
+
"level": "error"
|
15
|
+
},
|
16
|
+
"colon_assignment_spacing": {
|
17
|
+
"level": "ignore",
|
18
|
+
"spacing": {
|
19
|
+
"left": 0,
|
20
|
+
"right": 0
|
21
|
+
}
|
22
|
+
},
|
23
|
+
"cyclomatic_complexity": {
|
24
|
+
"value": 10,
|
25
|
+
"level": "ignore"
|
26
|
+
},
|
27
|
+
"duplicate_key": {
|
28
|
+
"level": "error"
|
29
|
+
},
|
30
|
+
"empty_constructor_needs_parens": {
|
31
|
+
"level": "ignore"
|
32
|
+
},
|
33
|
+
"ensure_comprehensions": {
|
34
|
+
"level": "warn"
|
35
|
+
},
|
36
|
+
"eol_last": {
|
37
|
+
"level": "ignore"
|
38
|
+
},
|
39
|
+
"indentation": {
|
40
|
+
"value": 2,
|
41
|
+
"level": "error"
|
42
|
+
},
|
43
|
+
"line_endings": {
|
44
|
+
"level": "ignore",
|
45
|
+
"value": "unix"
|
46
|
+
},
|
47
|
+
"max_line_length": {
|
48
|
+
"value": 80,
|
49
|
+
"level": "error",
|
50
|
+
"limitComments": true
|
51
|
+
},
|
52
|
+
"missing_fat_arrows": {
|
53
|
+
"level": "ignore",
|
54
|
+
"is_strict": false
|
55
|
+
},
|
56
|
+
"newlines_after_classes": {
|
57
|
+
"value": 3,
|
58
|
+
"level": "ignore"
|
59
|
+
},
|
60
|
+
"no_backticks": {
|
61
|
+
"level": "error"
|
62
|
+
},
|
63
|
+
"no_debugger": {
|
64
|
+
"level": "warn",
|
65
|
+
"console": false
|
66
|
+
},
|
67
|
+
"no_empty_functions": {
|
68
|
+
"level": "ignore"
|
69
|
+
},
|
70
|
+
"no_empty_param_list": {
|
71
|
+
"level": "ignore"
|
72
|
+
},
|
73
|
+
"no_implicit_braces": {
|
74
|
+
"level": "ignore",
|
75
|
+
"strict": true
|
76
|
+
},
|
77
|
+
"no_implicit_parens": {
|
78
|
+
"strict": true,
|
79
|
+
"level": "ignore"
|
80
|
+
},
|
81
|
+
"no_interpolation_in_single_quotes": {
|
82
|
+
"level": "ignore"
|
83
|
+
},
|
84
|
+
"no_plusplus": {
|
85
|
+
"level": "ignore"
|
86
|
+
},
|
87
|
+
"no_stand_alone_at": {
|
88
|
+
"level": "ignore"
|
89
|
+
},
|
90
|
+
"no_tabs": {
|
91
|
+
"level": "error"
|
92
|
+
},
|
93
|
+
"no_this": {
|
94
|
+
"level": "ignore"
|
95
|
+
},
|
96
|
+
"no_throwing_strings": {
|
97
|
+
"level": "error"
|
98
|
+
},
|
99
|
+
"no_trailing_semicolons": {
|
100
|
+
"level": "error"
|
101
|
+
},
|
102
|
+
"no_trailing_whitespace": {
|
103
|
+
"level": "error",
|
104
|
+
"allowed_in_comments": false,
|
105
|
+
"allowed_in_empty_lines": true
|
106
|
+
},
|
107
|
+
"no_unnecessary_double_quotes": {
|
108
|
+
"level": "ignore"
|
109
|
+
},
|
110
|
+
"no_unnecessary_fat_arrows": {
|
111
|
+
"level": "warn"
|
112
|
+
},
|
113
|
+
"non_empty_constructor_needs_parens": {
|
114
|
+
"level": "ignore"
|
115
|
+
},
|
116
|
+
"prefer_english_operator": {
|
117
|
+
"level": "ignore",
|
118
|
+
"doubleNotLevel": "ignore"
|
119
|
+
},
|
120
|
+
"space_operators": {
|
121
|
+
"level": "ignore"
|
122
|
+
},
|
123
|
+
"spacing_after_comma": {
|
124
|
+
"level": "ignore"
|
125
|
+
},
|
126
|
+
"transform_messes_up_line_numbers": {
|
127
|
+
"level": "warn"
|
128
|
+
}
|
129
|
+
}
|
data/lib/cc/analyzer/engine.rb
CHANGED
data/lib/cc/cli.rb
CHANGED
data/lib/cc/cli/test.rb
ADDED
@@ -0,0 +1,270 @@
|
|
1
|
+
require "shellwords"
|
2
|
+
require "cc/yaml"
|
3
|
+
|
4
|
+
module CC
|
5
|
+
module CLI
|
6
|
+
class Marker
|
7
|
+
def self.from_text(engine_name, test_file, line_number, text)
|
8
|
+
marker = Marker.new(line_number, text)
|
9
|
+
attrs = attrs_from_marker(text.sub(/^.*\[issue\] ?/, ""))
|
10
|
+
|
11
|
+
marker.issue = attrs.merge(
|
12
|
+
"engine_name" => engine_name,
|
13
|
+
"location" => {
|
14
|
+
"path" => test_file,
|
15
|
+
"lines" => {
|
16
|
+
"begin" => line_number + 1,
|
17
|
+
"end" => line_number + 1,
|
18
|
+
},
|
19
|
+
},
|
20
|
+
)
|
21
|
+
|
22
|
+
if marker.issue["category"]
|
23
|
+
marker.issue["categories"] = Array.wrap(marker.issue["category"])
|
24
|
+
marker.issue.delete("category")
|
25
|
+
end
|
26
|
+
|
27
|
+
marker
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.attrs_from_marker(text)
|
31
|
+
if text.blank?
|
32
|
+
{}
|
33
|
+
else
|
34
|
+
matches = text.scan(/([a-z\._-]+)=(?:(")((?:\\.|[^"])*)"|([^\s]*))/).map(&:compact)
|
35
|
+
|
36
|
+
key_values = matches.map do |match|
|
37
|
+
munge_match(match)
|
38
|
+
end
|
39
|
+
|
40
|
+
Hash[key_values]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.munge_match(match)
|
45
|
+
if match.size == 3 # Quoted
|
46
|
+
key, _, value = match
|
47
|
+
value = '"' + value + '"'
|
48
|
+
else
|
49
|
+
key, value = match
|
50
|
+
end
|
51
|
+
|
52
|
+
[key, munge_value(value)]
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.munge_value(value)
|
56
|
+
JSON.load(value)
|
57
|
+
rescue JSON::ParserError
|
58
|
+
value
|
59
|
+
end
|
60
|
+
|
61
|
+
attr_reader :line, :line_text
|
62
|
+
attr_accessor :issue
|
63
|
+
|
64
|
+
def initialize(line, line_text)
|
65
|
+
@line = line
|
66
|
+
@line_text = line_text
|
67
|
+
@issue = issue
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class Test < Command
|
72
|
+
def run
|
73
|
+
@engine_name = @args.first
|
74
|
+
|
75
|
+
if @engine_name.blank?
|
76
|
+
fatal "Usage: codeclimate test #{rainbow.wrap('engine_name').underline}"
|
77
|
+
end
|
78
|
+
|
79
|
+
test_engine
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_engine
|
83
|
+
within_tempdir do
|
84
|
+
prepare_working_dir
|
85
|
+
unpack_tests
|
86
|
+
run_tests
|
87
|
+
end
|
88
|
+
ensure
|
89
|
+
remove_null_container
|
90
|
+
end
|
91
|
+
|
92
|
+
def within_tempdir
|
93
|
+
tmpdir = create_tmpdir
|
94
|
+
|
95
|
+
Dir.chdir(tmpdir) do
|
96
|
+
yield
|
97
|
+
end
|
98
|
+
ensure
|
99
|
+
FileUtils.rm_rf(tmpdir)
|
100
|
+
end
|
101
|
+
|
102
|
+
def unpack_tests
|
103
|
+
test_paths.each do |test_path|
|
104
|
+
unpack(test_path)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def run_tests
|
109
|
+
Dir["**/*"].each do |test_file|
|
110
|
+
next unless File.file?(test_file)
|
111
|
+
process_file(test_file)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def process_file(test_file)
|
116
|
+
markers = markers_in(test_file)
|
117
|
+
|
118
|
+
actual_issues = issues_in(test_file)
|
119
|
+
compare_issues(actual_issues, markers)
|
120
|
+
end
|
121
|
+
|
122
|
+
def compare_issues(actual_issues, markers)
|
123
|
+
markers.each do |marker|
|
124
|
+
validate_issue(marker, actual_issues)
|
125
|
+
end
|
126
|
+
|
127
|
+
validate_unexpected_issues(actual_issues)
|
128
|
+
end
|
129
|
+
|
130
|
+
def validate_issue(marker, actual_issues)
|
131
|
+
if (index = locate_match(actual_issues, marker))
|
132
|
+
announce_pass(marker)
|
133
|
+
actual_issues.delete_at(index)
|
134
|
+
else
|
135
|
+
announce_fail(marker, actual_issues)
|
136
|
+
fatal "Expected issue not found."
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def locate_match(actual_issues, marker)
|
141
|
+
actual_issues.each_with_index do |actual, index|
|
142
|
+
if fuzzy_match(marker.issue, actual)
|
143
|
+
return index
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
nil
|
148
|
+
end
|
149
|
+
|
150
|
+
def announce_pass(marker)
|
151
|
+
say format("PASS %3d: %s", marker.line, marker.line_text)
|
152
|
+
end
|
153
|
+
|
154
|
+
def announce_fail(marker, actual_issues)
|
155
|
+
say colorize(format("FAIL %3d: %s", marker.line, marker.line_text), :red)
|
156
|
+
say colorize("Expected:", :yellow)
|
157
|
+
say colorize(JSON.pretty_generate(marker.issue), :yellow)
|
158
|
+
say "\n"
|
159
|
+
say colorize("Actual:", :yellow)
|
160
|
+
say colorize(JSON.pretty_generate(actual_issues), :yellow)
|
161
|
+
end
|
162
|
+
|
163
|
+
def validate_unexpected_issues(actual_issues)
|
164
|
+
if actual_issues.any?
|
165
|
+
say colorize("Actuals not empty after matching.", :red)
|
166
|
+
say
|
167
|
+
say colorize("#{actual_issues.size} remaining:", :yellow)
|
168
|
+
say colorize(JSON.pretty_generate(actual_issues), :yellow)
|
169
|
+
fatal "Unexpected issue found."
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def fuzzy_match(expected, actual)
|
174
|
+
expected.all? do |key, value|
|
175
|
+
actual[key] == value
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def issues_in(test_file)
|
180
|
+
issue_docs = capture_stdout do
|
181
|
+
codeclimate_analyze(test_file)
|
182
|
+
end
|
183
|
+
|
184
|
+
JSON.parse(issue_docs)
|
185
|
+
end
|
186
|
+
|
187
|
+
def codeclimate_analyze(relative_path)
|
188
|
+
codeclimate_path = File.expand_path(File.join(File.dirname(__FILE__), "../../../bin/codeclimate"))
|
189
|
+
|
190
|
+
system([
|
191
|
+
"unset CODE_PATH &&",
|
192
|
+
"unset FILESYSTEM_DIR &&",
|
193
|
+
Shellwords.escape(codeclimate_path),
|
194
|
+
"analyze",
|
195
|
+
"--engine", Shellwords.escape(@engine_name),
|
196
|
+
"-f", "json",
|
197
|
+
Shellwords.escape(relative_path)
|
198
|
+
].join(" "))
|
199
|
+
end
|
200
|
+
|
201
|
+
def prepare_working_dir
|
202
|
+
`git init`
|
203
|
+
|
204
|
+
File.open(".codeclimate.yml", "w") do |config|
|
205
|
+
config.write("engines:\n #{@engine_name}:\n enabled: true")
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def markers_in(test_file)
|
210
|
+
lines = File.readlines(test_file)
|
211
|
+
|
212
|
+
[].tap do |markers|
|
213
|
+
lines.each_with_index do |line, index|
|
214
|
+
if line =~ /\[issue\].*/
|
215
|
+
markers << Marker.from_text(@engine_name, test_file, index + 1, line)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def create_tmpdir
|
222
|
+
tmpdir = File.join("/tmp/cc", SecureRandom.uuid)
|
223
|
+
FileUtils.mkdir_p(tmpdir)
|
224
|
+
tmpdir
|
225
|
+
end
|
226
|
+
|
227
|
+
def unpack(path)
|
228
|
+
system("docker cp #{null_container_id}:#{path} .")
|
229
|
+
end
|
230
|
+
|
231
|
+
def null_container_id
|
232
|
+
# docker cp only works with containers, not images so
|
233
|
+
# workaround it by creating a throwaway container
|
234
|
+
@null_container_id = `docker run -d #{engine_image} false`.chomp
|
235
|
+
end
|
236
|
+
|
237
|
+
def remove_null_container
|
238
|
+
`docker rm -f #{null_container_id}` if null_container_id
|
239
|
+
end
|
240
|
+
|
241
|
+
def test_paths
|
242
|
+
Array.wrap(engine_spec["test_paths"])
|
243
|
+
end
|
244
|
+
|
245
|
+
def engine_spec
|
246
|
+
@engine_spec ||= JSON.parse(`docker run --rm #{engine_image} cat /engine.json`)
|
247
|
+
end
|
248
|
+
|
249
|
+
def engine_image
|
250
|
+
engine_registry[@engine_name]["image"]
|
251
|
+
end
|
252
|
+
|
253
|
+
# Stolen from ActiveSupport (where it was deprecated)
|
254
|
+
def capture_stdout
|
255
|
+
captured_stream = Tempfile.new("stdout")
|
256
|
+
origin_stream = $stdout.dup
|
257
|
+
$stdout.reopen(captured_stream)
|
258
|
+
|
259
|
+
yield
|
260
|
+
|
261
|
+
$stdout.rewind
|
262
|
+
return captured_stream.read
|
263
|
+
ensure
|
264
|
+
captured_stream.close
|
265
|
+
captured_stream.unlink
|
266
|
+
$stdout.reopen(origin_stream)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: codeclimate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.14.
|
4
|
+
version: 0.14.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Code Climate
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-11-
|
11
|
+
date: 2015-11-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -50,14 +50,14 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - "~>"
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: 0.
|
53
|
+
version: 0.5.0
|
54
54
|
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
57
|
requirements:
|
58
58
|
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version: 0.
|
60
|
+
version: 0.5.0
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: faraday
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -193,6 +193,7 @@ files:
|
|
193
193
|
- bin/codeclimate-init
|
194
194
|
- bin/prep-release
|
195
195
|
- bin/release
|
196
|
+
- config/coffeelint/coffeelint.json
|
196
197
|
- config/csslint/.csslintrc
|
197
198
|
- config/engines.yml
|
198
199
|
- config/eslint/.eslintrc
|
@@ -237,6 +238,7 @@ files:
|
|
237
238
|
- lib/cc/cli/help.rb
|
238
239
|
- lib/cc/cli/init.rb
|
239
240
|
- lib/cc/cli/runner.rb
|
241
|
+
- lib/cc/cli/test.rb
|
240
242
|
- lib/cc/cli/upgrade_config_generator.rb
|
241
243
|
- lib/cc/cli/validate_config.rb
|
242
244
|
- lib/cc/cli/version.rb
|
@@ -261,7 +263,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
261
263
|
version: '0'
|
262
264
|
requirements: []
|
263
265
|
rubyforge_project:
|
264
|
-
rubygems_version: 2.4.
|
266
|
+
rubygems_version: 2.4.5
|
265
267
|
signing_key:
|
266
268
|
specification_version: 4
|
267
269
|
summary: Code Climate CLI
|