codeqa 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeqa.rb +22 -0
- data/.gitignore +20 -0
- data/.rspec +3 -0
- data/.rubocop.yml +93 -0
- data/.ruby-version +1 -0
- data/.travis.yml +10 -0
- data/.vimrc +1 -0
- data/CHANGELOG +8 -0
- data/Gemfile +18 -0
- data/Guardfile +21 -0
- data/LICENSE +22 -0
- data/README.md +97 -0
- data/Rakefile +19 -0
- data/bin/codeqa +75 -0
- data/codeqa.gemspec +21 -0
- data/config/default.rb +42 -0
- data/lib/codeqa/check_errors.rb +21 -0
- data/lib/codeqa/checker.rb +47 -0
- data/lib/codeqa/checkers/check_conflict.rb +28 -0
- data/lib/codeqa/checkers/check_erb.rb +48 -0
- data/lib/codeqa/checkers/check_erb_html.rb +42 -0
- data/lib/codeqa/checkers/check_linkto.rb +28 -0
- data/lib/codeqa/checkers/check_pry.rb +28 -0
- data/lib/codeqa/checkers/check_rspec_focus.rb +28 -0
- data/lib/codeqa/checkers/check_ruby_syntax.rb +25 -0
- data/lib/codeqa/checkers/check_strange_chars.rb +29 -0
- data/lib/codeqa/checkers/check_utf8_encoding.rb +22 -0
- data/lib/codeqa/checkers/check_yard.rb +55 -0
- data/lib/codeqa/checkers/pattern_checker.rb +26 -0
- data/lib/codeqa/checkers/rubocop_formatter.rb +29 -0
- data/lib/codeqa/checkers/rubocop_full.rb +53 -0
- data/lib/codeqa/checkers/rubocop_lint.rb +21 -0
- data/lib/codeqa/configuration.rb +94 -0
- data/lib/codeqa/fake_erb.rb +80 -0
- data/lib/codeqa/runner.rb +61 -0
- data/lib/codeqa/runner_decorator.rb +84 -0
- data/lib/codeqa/sourcefile.rb +50 -0
- data/lib/codeqa/version.rb +3 -0
- data/lib/codeqa.rb +78 -0
- data/lib/templates/pre-commit +50 -0
- data/spec/fixtures/html_error.html.erb +10 -0
- data/spec/fixtures/html_error.text.html +3 -0
- data/spec/fixtures/isolation/home/project/dir/.gitkeep +0 -0
- data/spec/fixtures/isolation/home/project/file.rb +1 -0
- data/spec/fixtures/isolation/home/project/ignored/some_file.txt +1 -0
- data/spec/fixtures/ruby.rb +3 -0
- data/spec/fixtures/ruby_error.rb +3 -0
- data/spec/lib/codeqa/checkers/check_conflict_spec.rb +30 -0
- data/spec/lib/codeqa/checkers/check_erb_html_spec.rb +72 -0
- data/spec/lib/codeqa/checkers/check_erb_spec.rb +31 -0
- data/spec/lib/codeqa/checkers/check_linkto_spec.rb +26 -0
- data/spec/lib/codeqa/checkers/check_pry_spec.rb +25 -0
- data/spec/lib/codeqa/checkers/check_rspec_focus_spec.rb +25 -0
- data/spec/lib/codeqa/checkers/check_ruby_syntax_spec.rb +26 -0
- data/spec/lib/codeqa/checkers/check_strange_chars_spec.rb +27 -0
- data/spec/lib/codeqa/checkers/check_utf8_encoding_spec.rb +26 -0
- data/spec/lib/codeqa/checkers/check_yard_spec.rb +21 -0
- data/spec/lib/codeqa/checkers/rubocop_formatter_spec.rb +5 -0
- data/spec/lib/codeqa/checkers/rubocop_full_spec.rb +5 -0
- data/spec/lib/codeqa/checkers/rubocop_lint_spec.rb +26 -0
- data/spec/lib/codeqa/configuration_spec.rb +52 -0
- data/spec/lib/codeqa/runner_decorator_spec.rb +19 -0
- data/spec/lib/codeqa/runner_spec.rb +5 -0
- data/spec/lib/codeqa/sourcefile_spec.rb +33 -0
- data/spec/lib/codeqa_spec.rb +52 -0
- data/spec/spec_helper.rb +56 -0
- data/spec/support/checker.rb +20 -0
- metadata +183 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'codeqa/fake_erb'
|
2
|
+
require 'open3'
|
3
|
+
module Codeqa
|
4
|
+
module Checkers
|
5
|
+
class CheckErbHtml < Checker
|
6
|
+
def self.check?(sourcefile)
|
7
|
+
sourcefile.html?
|
8
|
+
end
|
9
|
+
|
10
|
+
def name
|
11
|
+
'erb html'
|
12
|
+
end
|
13
|
+
|
14
|
+
def hint
|
15
|
+
'The html I see after removing the erb stuff is not valid (find the unclosed tags and attributes).'
|
16
|
+
end
|
17
|
+
|
18
|
+
def check
|
19
|
+
result = nil
|
20
|
+
with_existing_file(html) do |filename|
|
21
|
+
Open3.popen3("tidy -q -e -xml '#{filename}'") do |_in_stream, _out_stream, err_stream|
|
22
|
+
message = err_stream.read
|
23
|
+
result = message if message =~ /(Error:|missing trailing quote|end of file while parsing attributes)/m
|
24
|
+
end # IO.popen
|
25
|
+
end # Tempfile
|
26
|
+
|
27
|
+
return unless result
|
28
|
+
errors.add(nil, html)
|
29
|
+
errors.add(nil, result)
|
30
|
+
end
|
31
|
+
|
32
|
+
def html
|
33
|
+
@html ||= begin
|
34
|
+
html = FakeERB.new(sourcefile.content.gsub('<%=', '<%')).result
|
35
|
+
html = html.force_encoding('UTF-8') if html.respond_to?(:force_encoding)
|
36
|
+
html.gsub(%r{<script[ >].*?</script>|<style[ >].*?</style>}m,
|
37
|
+
'<!--removed script/style tag-->')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'codeqa/checkers/pattern_checker'
|
2
|
+
|
3
|
+
module Codeqa
|
4
|
+
module Checkers
|
5
|
+
class CheckLinkto < PatternChecker
|
6
|
+
def name
|
7
|
+
'link_to'
|
8
|
+
end
|
9
|
+
|
10
|
+
def hint
|
11
|
+
"<% link_to ... do ... %> detected add an '=' after the <%"
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.check?(sourcefile)
|
15
|
+
sourcefile.erb?
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def self.pattern
|
21
|
+
@pattern ||= /<% link_to.* do.*%>/
|
22
|
+
end
|
23
|
+
def error_msg(_line, line_number, _pos)
|
24
|
+
"old style block link_to in line #{line_number}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'codeqa/checkers/pattern_checker'
|
2
|
+
|
3
|
+
module Codeqa
|
4
|
+
module Checkers
|
5
|
+
class CheckPry < PatternChecker
|
6
|
+
def name
|
7
|
+
'pry'
|
8
|
+
end
|
9
|
+
|
10
|
+
def hint
|
11
|
+
'Leftover binding.pry found, please remove it.'
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.check?(sourcefile)
|
15
|
+
sourcefile.ruby?
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def self.pattern
|
21
|
+
@pattern ||= /binding\.pry/
|
22
|
+
end
|
23
|
+
def error_msg(_line, line_number, _pos)
|
24
|
+
"binding.pry in line #{line_number}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'codeqa/checkers/pattern_checker'
|
2
|
+
|
3
|
+
module Codeqa
|
4
|
+
module Checkers
|
5
|
+
class CheckRspecFocus < PatternChecker
|
6
|
+
def name
|
7
|
+
'rspec-focus'
|
8
|
+
end
|
9
|
+
|
10
|
+
def hint
|
11
|
+
'Leftover :focus in spec found, please remove it.'
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.check?(sourcefile)
|
15
|
+
sourcefile.spec?
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def self.pattern
|
21
|
+
@pattern ||= /:focus/
|
22
|
+
end
|
23
|
+
def error_msg(_line, line_number, _pos)
|
24
|
+
":focus in line #{line_number}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'erb'
|
2
|
+
module Codeqa
|
3
|
+
module Checkers
|
4
|
+
class CheckRubySyntax < Checker
|
5
|
+
def self.check?(sourcefile)
|
6
|
+
sourcefile.ruby?
|
7
|
+
end
|
8
|
+
|
9
|
+
def name
|
10
|
+
'ruby syntax'
|
11
|
+
end
|
12
|
+
|
13
|
+
def hint
|
14
|
+
'Ruby can not parse the file, please check it for syntax errors.'
|
15
|
+
end
|
16
|
+
|
17
|
+
def check
|
18
|
+
with_existing_file do |filename|
|
19
|
+
command = "/usr/bin/env ruby -c '#{filename}' 1>/dev/null 2>/dev/null"
|
20
|
+
errors.add(nil, 'Ruby syntax error') unless system(command)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'codeqa/checkers/pattern_checker'
|
2
|
+
|
3
|
+
module Codeqa
|
4
|
+
module Checkers
|
5
|
+
class CheckStrangeChars < PatternChecker
|
6
|
+
def name
|
7
|
+
'strange chars'
|
8
|
+
end
|
9
|
+
|
10
|
+
def hint
|
11
|
+
'The file contains a tab or form feed. Remove them.'
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.check?(sourcefile)
|
15
|
+
sourcefile.text?
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def self.pattern
|
21
|
+
@pattern ||= /(\x09|\x0c)/
|
22
|
+
end
|
23
|
+
def error_msg(line, line_number, pos)
|
24
|
+
strangeness = (line.include?("\x09") ? 'TAB x09' : 'FORM FEED x0C')
|
25
|
+
"#{strangeness} at line #{line_number} column #{pos + 1}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Codeqa
|
2
|
+
module Checkers
|
3
|
+
class CheckUtf8Encoding < Checker
|
4
|
+
def self.check?(sourcefile)
|
5
|
+
sourcefile.text?
|
6
|
+
end
|
7
|
+
|
8
|
+
def name
|
9
|
+
'utf8 encoding'
|
10
|
+
end
|
11
|
+
|
12
|
+
def hint
|
13
|
+
'The file contains non utf8 characters. Find and remove them.'
|
14
|
+
end
|
15
|
+
|
16
|
+
def check
|
17
|
+
return if sourcefile.content.force_encoding('UTF-8').valid_encoding?
|
18
|
+
errors.add(nil, 'encoding error, not utf8')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
3
|
+
module Codeqa
|
4
|
+
module Checkers
|
5
|
+
class CheckYard < Checker
|
6
|
+
def self.check?(sourcefile)
|
7
|
+
sourcefile.ruby? && !(sourcefile.filename =~ /^(test|spec)/)
|
8
|
+
end
|
9
|
+
def self.available?
|
10
|
+
yard?
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.io
|
14
|
+
@@io ||= StringIO.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def name
|
18
|
+
'yard'
|
19
|
+
end
|
20
|
+
|
21
|
+
def hint
|
22
|
+
'Yard gives us some warnings on the file you can run <yardoc filename> to check yourself.'
|
23
|
+
end
|
24
|
+
|
25
|
+
def check
|
26
|
+
if self.class.yard?
|
27
|
+
::YARD.parse_string(sourcefile.content) # let yard parse the file content
|
28
|
+
io.rewind # rewind the io
|
29
|
+
message = io.read
|
30
|
+
warnings = message.match(/\A\[warn\]: /)
|
31
|
+
errors.add(nil, message.gsub(/\(stdin\)/, sourcefile.filename)) if warnings
|
32
|
+
end
|
33
|
+
ensure
|
34
|
+
io.reopen # clear the message for the next file
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def io
|
40
|
+
self.class.io
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.yard?
|
44
|
+
@loaded ||= begin
|
45
|
+
require 'yard'
|
46
|
+
::YARD::Logger.instance(io) # replace YARD logger with io
|
47
|
+
true
|
48
|
+
rescue LoadError
|
49
|
+
puts 'yard not installed'
|
50
|
+
false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Codeqa
|
2
|
+
module Checkers
|
3
|
+
class PatternChecker < Checker
|
4
|
+
def check
|
5
|
+
sourcefile.content.lines.each.with_index do |line, line_number|
|
6
|
+
pos = (line =~ pattern)
|
7
|
+
errors.add("#{line_number + 1},#{pos + 1}", error_msg(line, line_number + 1, pos)) if pos
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.available?
|
12
|
+
respond_to?(:pattern)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def pattern
|
18
|
+
self.class.pattern
|
19
|
+
end
|
20
|
+
|
21
|
+
def error_msg(*_args)
|
22
|
+
raise 'not implemented'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'codeqa/checkers/rubocop_full'
|
2
|
+
|
3
|
+
module Codeqa
|
4
|
+
module Checkers
|
5
|
+
class RubocopFormatter < Rubocop
|
6
|
+
def name
|
7
|
+
'rubocop formatter'
|
8
|
+
end
|
9
|
+
|
10
|
+
def hint
|
11
|
+
<<-EOF
|
12
|
+
Rubocop reformatted your code.
|
13
|
+
Check what it has done and add the changes to git's index
|
14
|
+
EOF
|
15
|
+
end
|
16
|
+
|
17
|
+
def after_check
|
18
|
+
# add changes to the git index
|
19
|
+
# `git add #{sourcefile.filename}`
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def config_args
|
25
|
+
%w(--auto-correct --only ) << Codeqa.configuration.rubocop_formatter_cops.to_a.join(',')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Codeqa
|
2
|
+
module Checkers
|
3
|
+
class Rubocop < Checker
|
4
|
+
def self.check?(sourcefile)
|
5
|
+
sourcefile.ruby?
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.available?
|
9
|
+
rubocop?
|
10
|
+
end
|
11
|
+
|
12
|
+
def name
|
13
|
+
'rubocop'
|
14
|
+
end
|
15
|
+
|
16
|
+
def hint
|
17
|
+
'Rubocop does not like your syntax, please fix your code.'
|
18
|
+
end
|
19
|
+
|
20
|
+
def check
|
21
|
+
return unless self.class.rubocop?
|
22
|
+
with_existing_file do |filename|
|
23
|
+
args = config_args << filename
|
24
|
+
success, captured = capture do
|
25
|
+
if defined?(RuboCop) # its RuboCop since 0.24
|
26
|
+
::RuboCop::CLI.new.run(default_args + args) == 0
|
27
|
+
else
|
28
|
+
::Rubocop::CLI.new.run(default_args + args) == 0
|
29
|
+
end
|
30
|
+
end
|
31
|
+
errors.add(nil, captured) unless success
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def config_args
|
38
|
+
%w(--auto-correct --fail-level warning)
|
39
|
+
end
|
40
|
+
|
41
|
+
def default_args
|
42
|
+
%w(--display-cop-names --format emacs)
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.rubocop?
|
46
|
+
@loaded ||= begin
|
47
|
+
require 'rubocop'
|
48
|
+
true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'codeqa/checkers/rubocop_full'
|
2
|
+
|
3
|
+
module Codeqa
|
4
|
+
module Checkers
|
5
|
+
class RubocopLint < Rubocop
|
6
|
+
def name
|
7
|
+
'rubocop lint'
|
8
|
+
end
|
9
|
+
|
10
|
+
def hint
|
11
|
+
'Rubocop found syntax errors, please fix your code.'
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def config_args
|
17
|
+
%w(--lint --fail-level error)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'set'
|
2
|
+
module Codeqa
|
3
|
+
class Configuration
|
4
|
+
# the default config file will setup all variables to some sane defaults
|
5
|
+
attr_accessor :erb_engine
|
6
|
+
attr_reader :excludes,
|
7
|
+
:enabled_checker,
|
8
|
+
:rubocop_formatter_cops
|
9
|
+
|
10
|
+
def excludes=(val)
|
11
|
+
@excludes = Set[*val]
|
12
|
+
end
|
13
|
+
|
14
|
+
def enabled_checker=(val)
|
15
|
+
@enabled_checker = Set[*val]
|
16
|
+
end
|
17
|
+
|
18
|
+
def rubocop_formatter_cops=(val)
|
19
|
+
@rubocop_formatter_cops = Set[*val]
|
20
|
+
end
|
21
|
+
|
22
|
+
def default_config_path
|
23
|
+
Codeqa.root.join('config', 'default')
|
24
|
+
end
|
25
|
+
|
26
|
+
def home_config_path
|
27
|
+
home_dir_config = File.join(home_dir, DOTFILE)
|
28
|
+
return home_dir_config if File.exist? home_dir_config
|
29
|
+
false
|
30
|
+
end
|
31
|
+
|
32
|
+
def project_config_path
|
33
|
+
project_root_config = File.join(project_root, DOTFILE)
|
34
|
+
return project_root_config if File.exist? project_root_config
|
35
|
+
false
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# tests a given filepath if it should be excluded
|
40
|
+
# @param file File.join compatable filepath
|
41
|
+
#
|
42
|
+
# @return [Boolean]
|
43
|
+
def excluded?(file)
|
44
|
+
file = File.join(Dir.pwd, file) unless file.start_with?('/')
|
45
|
+
Codeqa.configuration.excludes.any?{ |pattern| match_path?(pattern, file) }
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
DOTFILE = '.codeqa.rb'
|
51
|
+
|
52
|
+
def home_dir
|
53
|
+
@home_dir ||= Dir.home
|
54
|
+
end
|
55
|
+
|
56
|
+
def project_root
|
57
|
+
@project_root ||= git_root_till_home
|
58
|
+
end
|
59
|
+
|
60
|
+
# ascend from the current dir till I find a .git folder or reach home_dir
|
61
|
+
def git_root_till_home
|
62
|
+
Pathname.new(Dir.pwd).ascend do |dir_pathname|
|
63
|
+
return dir_pathname if File.directory?("#{dir_pathname}/.git")
|
64
|
+
return nil if dir_pathname.to_s == home_dir
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def match_path?(pattern, path)
|
69
|
+
case pattern
|
70
|
+
when String
|
71
|
+
basename = File.basename(path)
|
72
|
+
pattern = File.join(project_root, pattern) unless pattern.start_with?('/')
|
73
|
+
path == pattern || basename == pattern || File.fnmatch(pattern, path)
|
74
|
+
when Regexp
|
75
|
+
path =~ pattern
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class << self
|
81
|
+
def configuration
|
82
|
+
@configuration ||= Configuration.new
|
83
|
+
end
|
84
|
+
|
85
|
+
def configure
|
86
|
+
yield(configuration) if block_given?
|
87
|
+
Codeqa.register_checkers
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
require Codeqa.configuration.default_config_path
|
93
|
+
require Codeqa.configuration.home_config_path if Codeqa.configuration.home_config_path
|
94
|
+
require Codeqa.configuration.project_config_path if Codeqa.configuration.project_config_path
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'erb'
|
2
|
+
module Codeqa
|
3
|
+
# copied from ERB
|
4
|
+
# throws away all the erb stuff so only html remains
|
5
|
+
# rubocop:disable MethodLength, LineLength, CyclomaticComplexity, BlockNesting
|
6
|
+
class FakeERB < ERB
|
7
|
+
def initialize(str, safe_level=nil, trim_mode=nil, eoutvar='_erbout', compiler_class=FakeERB::Compiler)
|
8
|
+
@safe_level = safe_level
|
9
|
+
compiler = compiler_class.new(trim_mode)
|
10
|
+
set_eoutvar(compiler, eoutvar)
|
11
|
+
@src = compiler.compile(str)
|
12
|
+
@filename = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
class Compiler < ERB::Compiler # :nodoc:
|
16
|
+
def compile(s)
|
17
|
+
out = Buffer.new(self)
|
18
|
+
|
19
|
+
content = ''
|
20
|
+
scanner = make_scanner(s)
|
21
|
+
scanner.scan do |token|
|
22
|
+
next if token.nil?
|
23
|
+
next if token == ''
|
24
|
+
if scanner.stag.nil?
|
25
|
+
case token
|
26
|
+
when PercentLine
|
27
|
+
out.push("#{@put_cmd} #{content_dump(content)}") if content.size > 0
|
28
|
+
content = ''
|
29
|
+
out.push(token.to_s)
|
30
|
+
out.cr
|
31
|
+
when :cr
|
32
|
+
out.cr
|
33
|
+
when '<%', '<%=', '<%#'
|
34
|
+
scanner.stag = token
|
35
|
+
out.push("#{@put_cmd} #{content_dump(content)}") if content.size > 0
|
36
|
+
content = ''
|
37
|
+
when "\n"
|
38
|
+
content << "\n"
|
39
|
+
out.push("#{@put_cmd} #{content_dump(content)}")
|
40
|
+
content = ''
|
41
|
+
when '<%%'
|
42
|
+
content << '<%'
|
43
|
+
else
|
44
|
+
content << token
|
45
|
+
end
|
46
|
+
else
|
47
|
+
case token
|
48
|
+
when '%>'
|
49
|
+
case scanner.stag
|
50
|
+
when '<%'
|
51
|
+
if content[-1] == "\n"
|
52
|
+
content.chop!
|
53
|
+
# out.push(content)
|
54
|
+
out.cr
|
55
|
+
else
|
56
|
+
# out.push(content)
|
57
|
+
end
|
58
|
+
when '<%='
|
59
|
+
# out.push("#{@insert_cmd}((#{content}).to_s)")
|
60
|
+
when '<%#'
|
61
|
+
# out.push("# #{content_dump(content)}")
|
62
|
+
end
|
63
|
+
scanner.stag = nil
|
64
|
+
content = ''
|
65
|
+
when '%%>'
|
66
|
+
content << '%>'
|
67
|
+
else
|
68
|
+
content << token
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
# puts "pushed2 #{content}"
|
73
|
+
out.push("#{@put_cmd} #{content_dump(content)}") if content.size > 0
|
74
|
+
out.close
|
75
|
+
out.script
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
# rubocop:enable MethodLength, LineLength, CyclomaticComplexity, BlockNesting
|
80
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Codeqa
|
4
|
+
class Runner
|
5
|
+
class << self
|
6
|
+
def registered_checkers
|
7
|
+
@@registered_checkers
|
8
|
+
end
|
9
|
+
|
10
|
+
def reset_checkers
|
11
|
+
@@registered_checkers = Set.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def register_checker(checker_class)
|
15
|
+
@@registered_checkers << checker_class
|
16
|
+
end
|
17
|
+
end
|
18
|
+
@@registered_checkers = reset_checkers
|
19
|
+
|
20
|
+
# run the checks on source
|
21
|
+
def self.run(sourcefile)
|
22
|
+
runner = new(sourcefile)
|
23
|
+
runner.run
|
24
|
+
runner
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize(sourcefile)
|
28
|
+
@sourcefile = sourcefile
|
29
|
+
@results = []
|
30
|
+
end
|
31
|
+
attr_reader :sourcefile
|
32
|
+
|
33
|
+
def run
|
34
|
+
return @results unless @results.empty?
|
35
|
+
@results = @@registered_checkers.map do |checker_klass|
|
36
|
+
next unless checker_klass.check?(sourcefile)
|
37
|
+
checker = checker_klass.new(sourcefile)
|
38
|
+
|
39
|
+
checker.before_check if checker.respond_to?(:before_check)
|
40
|
+
checker.check
|
41
|
+
checker.after_check if checker.respond_to?(:after_check)
|
42
|
+
checker
|
43
|
+
end.compact
|
44
|
+
end
|
45
|
+
|
46
|
+
# the results (checker instances of the run)
|
47
|
+
attr_reader :results
|
48
|
+
|
49
|
+
def failures
|
50
|
+
@failures ||= @results.reject{ |checker| checker.success? }
|
51
|
+
end
|
52
|
+
|
53
|
+
def success?
|
54
|
+
failures.empty?
|
55
|
+
end
|
56
|
+
|
57
|
+
def display_result(options={})
|
58
|
+
RunnerDecorator.new(self, options)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|