Skip to content

Commit ae5f594

Browse files
committed
Merge pull request #55 from codeclimate/will/rescue-less
rescue less
2 parents 90b5a4e + 724e48f commit ae5f594

File tree

10 files changed

+104
-89
lines changed

10 files changed

+104
-89
lines changed

lib/cc/engine/analyzers/analyzer_base.rb

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,26 @@
1+
require "cc/engine/analyzers/parser_error"
2+
13
module CC
24
module Engine
35
module Analyzers
46
class Base
7+
RESCUABLE_ERRORS = [
8+
::CC::Engine::Analyzers::ParserError,
9+
::Racc::ParseError,
10+
]
11+
512
def initialize(engine_config:)
613
@engine_config = engine_config
714
end
815

916
def run(file)
1017
process_file(file)
18+
rescue *RESCUABLE_ERRORS => ex
19+
$stderr.puts("Skipping file #{file} due to exception:")
20+
$stderr.puts("(#{ex.class}) #{ex.message} #{ex.backtrace.join("\n")}")
1121
rescue => ex
12-
$stderr.puts "Skipping file #{file} due to exception"
13-
$stderr.puts "(#{ex.class}) #{ex.message} #{ex.backtrace.join("\n")}"
22+
$stderr.puts("#{ex.class} error occurred processing file #{file}: aborting.")
23+
raise ex
1424
end
1525

1626
def files
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
require "open3"
2+
require "timeout"
3+
4+
module CC
5+
module Engine
6+
module Analyzers
7+
class CommandLineRunner
8+
DEFAULT_TIMEOUT = 300
9+
10+
def initialize(command, timeout = DEFAULT_TIMEOUT)
11+
@command = command
12+
@timeout = timeout
13+
end
14+
15+
def run(input)
16+
Timeout.timeout(timeout) do
17+
Open3.popen3 command, "r+" do |stdin, stdout, stderr, wait_thr|
18+
stdin.puts input
19+
stdin.close
20+
21+
exit_code = wait_thr.value
22+
23+
output = stdout.gets
24+
stdout.close
25+
26+
err_output = stderr.gets
27+
stderr.close
28+
29+
if 0 == exit_code
30+
yield output
31+
else
32+
raise ::CC::Engine::Analyzers::ParserError, "Python parser exited with code #{exit_code}:\n#{err_output}"
33+
end
34+
end
35+
end
36+
end
37+
38+
private
39+
40+
attr_reader :command, :timeout
41+
end
42+
end
43+
end
44+
end
45+

lib/cc/engine/analyzers/javascript/parser.rb

+2-32
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
require 'timeout'
1+
require "cc/engine/analyzers/command_line_runner"
22

33
module CC
44
module Engine
@@ -13,7 +13,7 @@ def initialize(code, filename)
1313
end
1414

1515
def parse
16-
runner = CommandLineRunner.new(js_command, self)
16+
runner = CommandLineRunner.new(js_command)
1717
runner.run(strip_shebang(code)) do |ast|
1818
json_ast = JSON.parse(ast)
1919
@syntax_tree = json_ast
@@ -37,36 +37,6 @@ def strip_shebang(code)
3737
end
3838
end
3939
end
40-
41-
class CommandLineRunner
42-
attr_reader :command, :delegate
43-
44-
DEFAULT_TIMEOUT = 20
45-
EXCEPTIONS = [
46-
StandardError,
47-
Timeout::Error,
48-
SystemStackError
49-
]
50-
51-
def initialize(command, delegate)
52-
@command = command
53-
@delegate = delegate
54-
end
55-
56-
def run(input, timeout = DEFAULT_TIMEOUT)
57-
Timeout.timeout(timeout) do
58-
IO.popen command, 'r+' do |io|
59-
io.puts input
60-
io.close_write
61-
62-
output = io.gets
63-
io.close
64-
65-
yield output if $?.to_i == 0
66-
end
67-
end
68-
end
69-
end
7040
end
7141
end
7242
end
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module CC
2+
module Engine
3+
module Analyzers
4+
ParserError = Class.new(StandardError)
5+
end
6+
end
7+
end

lib/cc/engine/analyzers/php/parser.rb

+3-26
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
require 'cc/engine/analyzers/php/ast'
2-
require 'cc/engine/analyzers/php/nodes'
1+
require "cc/engine/analyzers/command_line_runner"
2+
require "cc/engine/analyzers/php/ast"
3+
require "cc/engine/analyzers/php/nodes"
34

45
module CC
56
module Engine
@@ -36,30 +37,6 @@ def parser_path
3637
)
3738
end
3839
end
39-
40-
class CommandLineRunner
41-
attr_reader :command, :delegate
42-
43-
DEFAULT_TIMEOUT = 20
44-
45-
def initialize(command)
46-
@command = command
47-
end
48-
49-
def run(input, timeout = DEFAULT_TIMEOUT)
50-
Timeout.timeout(timeout) do
51-
IO.popen command, 'r+' do |io|
52-
io.puts input
53-
io.close_write
54-
55-
output = io.gets
56-
io.close
57-
58-
yield output if $?.to_i == 0
59-
end
60-
end
61-
end
62-
end
6340
end
6441
end
6542
end

lib/cc/engine/analyzers/python/parser.rb

+4-28
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
require 'timeout'
2-
require 'json'
1+
require "cc/engine/analyzers/command_line_runner"
2+
require "timeout"
3+
require "json"
34

45
module CC
56
module Engine
@@ -14,7 +15,7 @@ def initialize(code, filename)
1415
end
1516

1617
def parse
17-
runner = CommandLineRunner.new(python_command, self)
18+
runner = CommandLineRunner.new(python_command)
1819
runner.run(code) do |ast|
1920
json_ast = JSON.parse(ast)
2021
@syntax_tree = json_ast
@@ -28,31 +29,6 @@ def python_command
2829
"python #{file}"
2930
end
3031
end
31-
32-
class CommandLineRunner
33-
DEFAULT_TIMEOUT = 20
34-
35-
attr_reader :command, :delegate
36-
37-
def initialize(command, delegate)
38-
@command = command
39-
@delegate = delegate
40-
end
41-
42-
def run(input, timeout = DEFAULT_TIMEOUT)
43-
Timeout.timeout(timeout) do
44-
IO.popen command, "r+" do |io|
45-
io.puts input
46-
io.close_write
47-
48-
output = io.gets
49-
io.close
50-
51-
yield output if $?.to_i == 0
52-
end
53-
end
54-
end
55-
end
5632
end
5733
end
5834
end

lib/cc/engine/analyzers/ruby/main.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class Main < CC::Engine::Analyzers::Base
1919
]
2020
DEFAULT_MASS_THRESHOLD = 18
2121
BASE_POINTS = 10_000
22-
TIMEOUT = 10
22+
TIMEOUT = 300
2323

2424
private
2525

spec/cc/engine/analyzers/javascript/main_spec.rb

+10
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@
3636
expect(json["content"]["body"]).to match /This issue has a mass of `99`/
3737
expect(json["fingerprint"]).to eq("55ae5d0990647ef496e9e0d315f9727d")
3838
end
39+
40+
it "skips unparsable files" do
41+
create_source_file("foo.js", <<-EOJS)
42+
function () { do(); // missing closing brace
43+
EOJS
44+
45+
expect {
46+
expect(run_engine(engine_conf)).to eq("")
47+
}.to output(/Skipping file/).to_stderr
48+
end
3949
end
4050

4151
it "does not flag duplicate comments" do

spec/cc/engine/analyzers/php/main_spec.rb

+10
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@
4848
expect(json["content"]["body"]).to match /This issue has a mass of `44`/
4949
expect(json["fingerprint"]).to eq("667da0e2bab866aa2fe9d014a65d57d9")
5050
end
51+
52+
it "skips unparsable files" do
53+
create_source_file("foo.php", <<-EOPHP)
54+
<?php blorb &; "fee
55+
EOPHP
56+
57+
expect {
58+
expect(run_engine(engine_conf)).to eq("")
59+
}.to output(/Skipping file/).to_stderr
60+
end
5161
end
5262

5363
def printed_issue

spec/cc/engine/analyzers/python/main_spec.rb

+10
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@
3636
expect(json["content"]["body"]).to match /This issue has a mass of `54`/
3737
expect(json["fingerprint"]).to eq("42b832387c997f54a2012efb2159aefc")
3838
end
39+
40+
it "skips unparsable files" do
41+
create_source_file("foo.py", <<-EOPY)
42+
---
43+
EOPY
44+
45+
expect {
46+
expect(run_engine(engine_conf)).to eq("")
47+
}.to output(/Skipping file/).to_stderr
48+
end
3949
end
4050

4151
def engine_conf

0 commit comments

Comments
 (0)