codeqa 0.3.1 → 0.4.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +6 -1
- data/Guardfile +2 -3
- data/lib/codeqa.rb +0 -1
- data/lib/codeqa/checker.rb +1 -10
- data/lib/codeqa/checkers/check_erb.rb +3 -3
- data/lib/codeqa/checkers/check_erb_html.rb +3 -3
- data/lib/codeqa/checkers/html_validator.rb +52 -0
- data/lib/codeqa/checkers/pattern_checker.rb +1 -1
- data/lib/codeqa/checkers/rubocop_full.rb +29 -3
- data/lib/codeqa/runner_decorator.rb +20 -7
- data/lib/codeqa/{check_errors.rb → utils/check_errors.rb} +0 -0
- data/lib/codeqa/utils/erb_sanitizer.rb +85 -0
- data/lib/codeqa/version.rb +1 -1
- data/lib/templates/pre-commit +1 -3
- data/spec/fixtures/erb_example.html +31 -0
- data/spec/fixtures/erb_example.html.erb +31 -0
- data/spec/lib/codeqa/checkers/check_conflict_spec.rb +3 -3
- data/spec/lib/codeqa/checkers/check_erb_html_spec.rb +3 -3
- data/spec/lib/codeqa/checkers/check_linkto_spec.rb +3 -1
- data/spec/lib/codeqa/checkers/check_strange_chars_spec.rb +6 -2
- data/spec/lib/codeqa/checkers/html_validator_spec.rb +78 -0
- data/spec/lib/codeqa/checkers/rubocop_lint_spec.rb +1 -1
- data/spec/lib/codeqa/runner_decorator_spec.rb +71 -12
- data/spec/lib/codeqa/utils/erb_sanitizer_spec.rb +58 -0
- metadata +15 -6
- data/lib/codeqa/fake_erb.rb +0 -80
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3ae0299a503f1cb9639e037907ade194edfe3db0
|
4
|
+
data.tar.gz: 859128b8f52f560cc2dedb79157134237179b042
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 198df6738b57d3fbfb076bd3522b7b715b10245ce40769bbfb6b67e3e4af07df622504edc2d867d98cf8fc713582cbf95aa63de01c9a69e914e78c7d6d00c991
|
7
|
+
data.tar.gz: ec6c8833e4b66ba642b0ee30016f2c7d5d7e477f64cc59f69c5d6c49202c41667496e998631687e2ae863fa95f8f9c37a3cbbe0bfab81370ff2ceddecb5dc626
|
data/Gemfile
CHANGED
@@ -4,7 +4,6 @@ source 'https://rubygems.org'
|
|
4
4
|
gemspec
|
5
5
|
|
6
6
|
group :development do
|
7
|
-
gem 'rubocop'
|
8
7
|
gem 'guard-rspec'
|
9
8
|
gem 'guard-rubocop'
|
10
9
|
gem 'rb-inotify', :require => false
|
@@ -12,6 +11,12 @@ group :development do
|
|
12
11
|
# gem 'rb-fchange', :require => false #windows only
|
13
12
|
end
|
14
13
|
|
14
|
+
group :development, :test do
|
15
|
+
gem 'pry-byebug'
|
16
|
+
gem 'nokogiri'
|
17
|
+
gem 'rubocop'
|
18
|
+
end
|
19
|
+
|
15
20
|
group :test do
|
16
21
|
gem 'simplecov', :require => false
|
17
22
|
gem 'coveralls', :require => false
|
data/Guardfile
CHANGED
@@ -9,9 +9,8 @@ group :red_green_refactor, halt_on_fail: true do
|
|
9
9
|
watch(%r{^spec/.+_spec\.rb$})
|
10
10
|
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
11
11
|
watch('spec/spec_helper.rb') { 'spec' }
|
12
|
-
watch(
|
13
|
-
watch(
|
14
|
-
watch(%r{^spec/factories/(.+)\.rb}) { 'spec' }
|
12
|
+
watch(%r{^spec/support/(.+)\.rb}) { 'spec' }
|
13
|
+
watch(%r{^spec/fixtures/(.+)}) { 'spec' }
|
15
14
|
end
|
16
15
|
|
17
16
|
guard :rubocop, cli: %w(--display-cop-names --auto-correct) do
|
data/lib/codeqa.rb
CHANGED
data/lib/codeqa/checker.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'stringio'
|
2
2
|
require 'tempfile'
|
3
3
|
require 'forwardable'
|
4
|
+
require 'codeqa/utils/check_errors'
|
4
5
|
|
5
6
|
module Codeqa
|
6
7
|
class Checker
|
@@ -33,15 +34,5 @@ module Codeqa
|
|
33
34
|
end
|
34
35
|
end
|
35
36
|
end
|
36
|
-
|
37
|
-
def capture
|
38
|
-
$stdout, stdout = StringIO.new, $stdout
|
39
|
-
$stderr, stderr = StringIO.new, $stderr
|
40
|
-
result = yield
|
41
|
-
[result, $stdout.string + $stderr.string]
|
42
|
-
ensure
|
43
|
-
$stdout = stdout
|
44
|
-
$stderr = stderr
|
45
|
-
end
|
46
37
|
end
|
47
38
|
end
|
@@ -24,10 +24,10 @@ module Codeqa
|
|
24
24
|
else
|
25
25
|
ERB.new(sourcefile.content.gsub('<%=', '<%'), nil, '-').result
|
26
26
|
end
|
27
|
-
rescue SyntaxError
|
27
|
+
rescue SyntaxError => e
|
28
28
|
errors.add(nil, <<-EOF)
|
29
|
-
#{
|
30
|
-
#{
|
29
|
+
#{e.message}
|
30
|
+
#{e.backtrace.join("\n")}
|
31
31
|
EOF
|
32
32
|
rescue Exception
|
33
33
|
true # valid syntax - just the proper setup for the template/rendering is missing
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'codeqa/
|
1
|
+
require 'codeqa/utils/erb_sanitizer'
|
2
2
|
require 'open3'
|
3
3
|
module Codeqa
|
4
4
|
module Checkers
|
@@ -25,13 +25,13 @@ module Codeqa
|
|
25
25
|
end # Tempfile
|
26
26
|
|
27
27
|
return unless result
|
28
|
-
errors.add(
|
28
|
+
errors.add(:source, html)
|
29
29
|
errors.add(nil, result)
|
30
30
|
end
|
31
31
|
|
32
32
|
def html
|
33
33
|
@html ||= begin
|
34
|
-
html =
|
34
|
+
html = ErbSanitizer.new(sourcefile.content).result
|
35
35
|
html = html.force_encoding('UTF-8') if html.respond_to?(:force_encoding)
|
36
36
|
html.gsub(%r{<script[ >].*?</script>|<style[ >].*?</style>}m,
|
37
37
|
'<!--removed script/style tag-->')
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'codeqa/utils/erb_sanitizer'
|
2
|
+
|
3
|
+
module Codeqa
|
4
|
+
module Checkers
|
5
|
+
class HtmlValidator < Checker
|
6
|
+
def self.check?(sourcefile)
|
7
|
+
sourcefile.html?
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.available?
|
11
|
+
nokogiri?
|
12
|
+
end
|
13
|
+
|
14
|
+
def name
|
15
|
+
'html'
|
16
|
+
end
|
17
|
+
|
18
|
+
def hint
|
19
|
+
'Nokogiri found XHTML errors, please fix them.'
|
20
|
+
end
|
21
|
+
|
22
|
+
REMOVED_NOKOGIRI_ERRORS = Regexp.union(
|
23
|
+
/Opening and ending tag mismatch: (special line 1|\w+ line 1 and special)/,
|
24
|
+
/Premature end of data in tag special/,
|
25
|
+
/Extra content at the end of the document/,
|
26
|
+
/xmlParseEntityRef: no name/
|
27
|
+
)
|
28
|
+
def check
|
29
|
+
return unless self.class.nokogiri?
|
30
|
+
doc = Nokogiri::XML "<special>#{stripped_html}</special>"
|
31
|
+
|
32
|
+
doc.errors.delete_if{ |e| e.message =~ REMOVED_NOKOGIRI_ERRORS }
|
33
|
+
errors.add(:source, sourcefile.content) unless doc.errors.empty?
|
34
|
+
# errors.add(:source, stripped_html) unless doc.errors.empty?
|
35
|
+
doc.errors.each do |error|
|
36
|
+
errors.add(error.line, error.message) unless error.warning?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def stripped_html
|
41
|
+
@html ||= ErbSanitizer.new(sourcefile.content).result
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.nokogiri?
|
45
|
+
@loaded ||= begin
|
46
|
+
require 'nokogiri'
|
47
|
+
true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -4,7 +4,7 @@ module Codeqa
|
|
4
4
|
def check
|
5
5
|
sourcefile.content.lines.each.with_index do |line, line_number|
|
6
6
|
pos = (line =~ pattern)
|
7
|
-
errors.add(
|
7
|
+
errors.add([line_number + 1, pos + 1], error_msg(line, line_number + 1, pos)) if pos
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
1
3
|
module Codeqa
|
2
4
|
module Checkers
|
3
5
|
class Rubocop < Checker
|
@@ -21,14 +23,14 @@ module Codeqa
|
|
21
23
|
return unless self.class.rubocop?
|
22
24
|
with_existing_file do |filename|
|
23
25
|
args = config_args << filename
|
24
|
-
success,
|
26
|
+
success, raw_json = capture do
|
25
27
|
if defined?(RuboCop) # its RuboCop since 0.24
|
26
28
|
::RuboCop::CLI.new.run(default_args + args) == 0
|
27
29
|
else
|
28
30
|
::Rubocop::CLI.new.run(default_args + args) == 0
|
29
31
|
end
|
30
32
|
end
|
31
|
-
|
33
|
+
handle_rubocop_results(raw_json) unless success
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
@@ -39,15 +41,39 @@ module Codeqa
|
|
39
41
|
end
|
40
42
|
|
41
43
|
def default_args
|
42
|
-
%w(--
|
44
|
+
%w(--format json)
|
43
45
|
end
|
44
46
|
|
47
|
+
def handle_rubocop_results(raw)
|
48
|
+
data = JSON.parse raw, :object_class => OpenStruct
|
49
|
+
data.files.
|
50
|
+
reject{ |f| f.offenses.empty? }.
|
51
|
+
each do |file|
|
52
|
+
file.offenses.each do |offense|
|
53
|
+
position = [offense.location.line, offense.location.column]
|
54
|
+
errors.add(position, "#{offense.cop_name}: #{offense.message}")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
45
58
|
def self.rubocop?
|
46
59
|
@loaded ||= begin
|
47
60
|
require 'rubocop'
|
48
61
|
true
|
49
62
|
end
|
50
63
|
end
|
64
|
+
|
65
|
+
# Since using the json format we only care about stdout
|
66
|
+
# stderr will be silent
|
67
|
+
def capture
|
68
|
+
$stdout, stdout = StringIO.new, $stdout
|
69
|
+
$stderr, stderr = StringIO.new, $stderr
|
70
|
+
result = yield
|
71
|
+
# [result, $stdout.string + $stderr.string]
|
72
|
+
[result, $stdout.string]
|
73
|
+
ensure
|
74
|
+
$stdout = stdout
|
75
|
+
$stderr = stderr
|
76
|
+
end
|
51
77
|
end
|
52
78
|
end
|
53
79
|
end
|
@@ -32,13 +32,26 @@ module Codeqa
|
|
32
32
|
|
33
33
|
private
|
34
34
|
|
35
|
+
# TODO: move this error formating into check error class
|
35
36
|
def error_details
|
36
37
|
msg = ''
|
37
38
|
@runner.failures.each do |checker|
|
38
|
-
msg << error("------- #{checker.name}
|
39
|
-
msg << error("#{checker.hint}\n"
|
40
|
-
checker.errors.details.each do |
|
41
|
-
|
39
|
+
msg << error("------- #{checker.name} -------") << "\n"
|
40
|
+
msg << error("#{checker.hint}") << "\n"
|
41
|
+
checker.errors.details.each do |type, content|
|
42
|
+
case type
|
43
|
+
when :source
|
44
|
+
content.each_line.with_index do |l, i|
|
45
|
+
msg << yellow((i + 1).to_s.rjust(3)) << '|' << l
|
46
|
+
end
|
47
|
+
when Integer
|
48
|
+
msg << info('Line: ') << yellow(type) << '|' << info(content)
|
49
|
+
when Array
|
50
|
+
msg << info('Pos: ') << yellow(type.join(',')) << '|' << info(content)
|
51
|
+
when nil
|
52
|
+
msg << info(content)
|
53
|
+
end
|
54
|
+
msg << "\n"
|
42
55
|
end
|
43
56
|
end
|
44
57
|
msg
|
@@ -73,9 +86,9 @@ module Codeqa
|
|
73
86
|
colorize(32, txt)
|
74
87
|
end
|
75
88
|
|
76
|
-
|
77
|
-
|
78
|
-
|
89
|
+
def yellow(txt)
|
90
|
+
colorize(33, txt)
|
91
|
+
end
|
79
92
|
|
80
93
|
# def pink(txt)
|
81
94
|
# colorize(35, txt)
|
File without changes
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'erb'
|
2
|
+
# Based on ERB source from ruby 2.1.2
|
3
|
+
# https://github.com/ruby/ruby/blob/v2_1_2/lib/erb.rb#L597
|
4
|
+
module Codeqa
|
5
|
+
class ErbSanitizer < ERB
|
6
|
+
def make_compiler(trim_mode)
|
7
|
+
ErbSanitizer::Compiler.new(trim_mode)
|
8
|
+
end
|
9
|
+
|
10
|
+
class Compiler < ERB::Compiler
|
11
|
+
# Compiles an ERB template into Ruby code. Returns an array of the code
|
12
|
+
# and encoding like ["code", Encoding].
|
13
|
+
# rubocop:disable Style/CyclomaticComplexity
|
14
|
+
def compile(s)
|
15
|
+
enc = s.encoding
|
16
|
+
raise ArgumentError, "#{enc} is not ASCII compatible" if enc.dummy?
|
17
|
+
s = s.b # see String#b
|
18
|
+
enc = detect_magic_comment(s) || enc
|
19
|
+
out = Buffer.new(self, enc)
|
20
|
+
|
21
|
+
content = ''
|
22
|
+
scanner = make_scanner(s)
|
23
|
+
scanner.scan do |token|
|
24
|
+
next if token.nil?
|
25
|
+
next if token == ''
|
26
|
+
if scanner.stag.nil?
|
27
|
+
case token
|
28
|
+
when PercentLine
|
29
|
+
add_put_cmd(out, content) if content.size > 0
|
30
|
+
content = ''
|
31
|
+
out.push(token.to_s)
|
32
|
+
out.cr
|
33
|
+
when :cr
|
34
|
+
out.cr
|
35
|
+
when '<%', '<%=', '<%#'
|
36
|
+
scanner.stag = token
|
37
|
+
add_put_cmd(out, content) if content.size > 0
|
38
|
+
content = ''
|
39
|
+
when "\n"
|
40
|
+
content << "\n"
|
41
|
+
add_put_cmd(out, content)
|
42
|
+
content = ''
|
43
|
+
when '<%%'
|
44
|
+
content << '<%'
|
45
|
+
else
|
46
|
+
content << token
|
47
|
+
end
|
48
|
+
else
|
49
|
+
case token
|
50
|
+
when '%>'
|
51
|
+
# in here we deal with the content of a erb tag
|
52
|
+
(content.scan("\n").count).times do
|
53
|
+
add_put_cmd(out, "\n")
|
54
|
+
end
|
55
|
+
# case scanner.stag
|
56
|
+
# when '<%'
|
57
|
+
# if content[-1] == ?\n
|
58
|
+
# content.chop!
|
59
|
+
# out.push(content)
|
60
|
+
# out.cr
|
61
|
+
# else
|
62
|
+
# out.push(content)
|
63
|
+
# end
|
64
|
+
# when '<%='
|
65
|
+
# add_insert_cmd(out, content)
|
66
|
+
# when '<%#'
|
67
|
+
# # out.push("# #{content_dump(content)}")
|
68
|
+
# end
|
69
|
+
scanner.stag = nil
|
70
|
+
content = ''
|
71
|
+
when '%%>'
|
72
|
+
content << '%>'
|
73
|
+
else
|
74
|
+
content << token
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
add_put_cmd(out, content) if content.size > 0
|
79
|
+
out.close
|
80
|
+
[out.script, enc]
|
81
|
+
end
|
82
|
+
# rubocop:enable Style/CyclomaticComplexity
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/lib/codeqa/version.rb
CHANGED
data/lib/templates/pre-commit
CHANGED
@@ -38,13 +38,11 @@ print "Codeqa checking #{files_to_check.count} files"
|
|
38
38
|
# fail fast
|
39
39
|
success = files_to_check.all? do |file|
|
40
40
|
print '.'
|
41
|
-
Codeqa.check(file, :
|
41
|
+
Codeqa.check(file, :silent_success => true)
|
42
42
|
end
|
43
43
|
|
44
44
|
if success
|
45
|
-
puts 'success'
|
46
45
|
exit 0
|
47
46
|
else
|
48
|
-
puts 'error'
|
49
47
|
exit 1
|
50
48
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<body>
|
2
|
+
<div class="jobdetail">
|
3
|
+
<%= render :partial => 'header',
|
4
|
+
:locals => @header_options.reverse_merge(
|
5
|
+
:position_presenter => @position_presenter,
|
6
|
+
:bookmark => @bookmark,
|
7
|
+
:account_id => @account.id,
|
8
|
+
:social_share => @social_share) if @position_presenter.show_header? %>
|
9
|
+
<% if @position_presenter.internal_view? %>
|
10
|
+
<%= render :partial => 'intern',
|
11
|
+
:locals => @header_options.reverse_merge(
|
12
|
+
:position_presenter => @position_presenter,
|
13
|
+
:account_id => @account.id) %>
|
14
|
+
<% else %>
|
15
|
+
<iframe src="<%= raw @position_presenter.url %>" scrolling="no">
|
16
|
+
</iframe>
|
17
|
+
<% end %>
|
18
|
+
</div>
|
19
|
+
|
20
|
+
<%#
|
21
|
+
params:
|
22
|
+
@header_options
|
23
|
+
@account_id
|
24
|
+
@bookmark
|
25
|
+
@position
|
26
|
+
@position_presenter
|
27
|
+
%>
|
28
|
+
<script>
|
29
|
+
ujsOpenDialog('.ujsDialog');
|
30
|
+
</script>
|
31
|
+
</body>
|
@@ -15,9 +15,9 @@ describe Codeqa::Checkers::CheckConflict do
|
|
15
15
|
checker = check_with(described_class, source)
|
16
16
|
expect(checker).to be_error
|
17
17
|
expect(checker.errors.details).to eq([
|
18
|
-
[
|
19
|
-
[
|
20
|
-
[
|
18
|
+
[[2, 1], 'conflict leftovers in line 2, please merge properly'],
|
19
|
+
[[3, 1], 'conflict leftovers in line 3, please merge properly'],
|
20
|
+
[[5, 1], 'conflict leftovers in line 5, please merge properly']
|
21
21
|
])
|
22
22
|
end
|
23
23
|
|
@@ -21,7 +21,7 @@ unless ENV['TRAVIS']
|
|
21
21
|
checker = check_with(described_class, source)
|
22
22
|
expect(checker).to be_error
|
23
23
|
expect(checker.errors.details).to eq([
|
24
|
-
[
|
24
|
+
[:source, '<div><ul></div>'],
|
25
25
|
[nil, "line 1 column 10 - Error: unexpected </div> in <ul>\n"]])
|
26
26
|
end
|
27
27
|
|
@@ -30,7 +30,7 @@ unless ENV['TRAVIS']
|
|
30
30
|
checker = check_with(described_class, source)
|
31
31
|
expect(checker).to be_error
|
32
32
|
expect(checker.errors.details).to eq([
|
33
|
-
[
|
33
|
+
[:source, "<div class='halfopen></div>"],
|
34
34
|
[nil, "line 1 column 28 - Warning: <div> end of file while parsing attributes\n"]])
|
35
35
|
|
36
36
|
end
|
@@ -39,7 +39,7 @@ unless ENV['TRAVIS']
|
|
39
39
|
checker = check_with(described_class, source)
|
40
40
|
expect(checker).to be_error
|
41
41
|
expect(checker.errors.details).to eq([
|
42
|
-
[
|
42
|
+
[:source, "<div class=\"halfopen next=\"ok\"></div>"],
|
43
43
|
[nil, "line 1 column 1 - Warning: <div> attribute with missing trailing quote mark\n"]])
|
44
44
|
|
45
45
|
end
|
@@ -14,7 +14,9 @@ describe Codeqa::Checkers::CheckLinkto do
|
|
14
14
|
source = source_with("<% link_to '/page',do_some_paths do%>", 'file.html.erb')
|
15
15
|
checker = check_with(described_class, source)
|
16
16
|
expect(checker).to be_error
|
17
|
-
expect(checker.errors.details).to eq([
|
17
|
+
expect(checker.errors.details).to eq([
|
18
|
+
[[1, 1], 'old style block link_to in line 1']
|
19
|
+
])
|
18
20
|
end
|
19
21
|
|
20
22
|
it 'should find not find if not there ' do
|
@@ -14,14 +14,18 @@ describe Codeqa::Checkers::CheckStrangeChars do
|
|
14
14
|
source = source_with("one\x09two")
|
15
15
|
checker = check_with(described_class, source)
|
16
16
|
expect(checker).to be_error
|
17
|
-
expect(checker.errors.details).to eq([
|
17
|
+
expect(checker.errors.details).to eq([
|
18
|
+
[[1, 4], 'TAB x09 at line 1 column 4']
|
19
|
+
])
|
18
20
|
end
|
19
21
|
|
20
22
|
it 'should detect form feeds' do
|
21
23
|
source = source_with("one\n\x0ctwo")
|
22
24
|
checker = check_with(described_class, source)
|
23
25
|
expect(checker).to be_error
|
24
|
-
expect(checker.errors.details).to eq([
|
26
|
+
expect(checker.errors.details).to eq([
|
27
|
+
[[2, 1], 'FORM FEED x0C at line 2 column 1']
|
28
|
+
])
|
25
29
|
end
|
26
30
|
|
27
31
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe Codeqa::Checkers::HtmlValidator do
|
3
|
+
it_behaves_like 'a checker'
|
4
|
+
|
5
|
+
it 'should check erb files' do
|
6
|
+
source = source_with('', 'file.html.erb')
|
7
|
+
expect(described_class.check?(source)).to be_truthy
|
8
|
+
source = source_with('', 'test.rhtml')
|
9
|
+
expect(described_class.check?(source)).to be_truthy
|
10
|
+
source = source_with('', 'test.text.html')
|
11
|
+
expect(described_class.check?(source)).to be_truthy
|
12
|
+
|
13
|
+
source = source_with('', 'zipped.zip')
|
14
|
+
expect(described_class.check?(source)).to be_falsey
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should detect html tag errors' do
|
18
|
+
text = '<div><ul></div>'
|
19
|
+
source = source_with(text)
|
20
|
+
checker = check_with(described_class, source)
|
21
|
+
expect(checker).to be_error
|
22
|
+
expect(checker.errors.details).to eq([
|
23
|
+
[:source, text],
|
24
|
+
[1, 'Opening and ending tag mismatch: ul line 1 and div']
|
25
|
+
])
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should detect attribute till end of file errors' do
|
29
|
+
text = "<div class='halfopen></div>"
|
30
|
+
source = source_with(text)
|
31
|
+
checker = check_with(described_class, source)
|
32
|
+
expect(checker).to be_error
|
33
|
+
expect(checker.errors.details).to eq([
|
34
|
+
[:source, text],
|
35
|
+
[1, "Unescaped '<' not allowed in attributes values"],
|
36
|
+
[1, 'attributes construct error'],
|
37
|
+
[1, "Couldn't find end of Start Tag div line 1"]
|
38
|
+
])
|
39
|
+
end
|
40
|
+
it 'should detect attribute with missing trailing qute mark' do
|
41
|
+
text = '<div class="halfopen next="ok"></div>'
|
42
|
+
source = source_with(text)
|
43
|
+
checker = check_with(described_class, source)
|
44
|
+
expect(checker).to be_error
|
45
|
+
expect(checker.errors.details).to eq([
|
46
|
+
[:source, text],
|
47
|
+
[1, 'attributes construct error'],
|
48
|
+
[1, "Couldn't find end of Start Tag div line 1"]
|
49
|
+
])
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should find not find errors if html is ok ' do
|
53
|
+
source = source_with('<div><ul></ul></div>')
|
54
|
+
checker = check_with(described_class, source)
|
55
|
+
expect(checker).to be_success
|
56
|
+
end
|
57
|
+
|
58
|
+
# context 'javascript' do
|
59
|
+
# it 'should ignore javascript' do
|
60
|
+
# source = source_with('<div><script></ul></script></div>')
|
61
|
+
# checker = check_with(described_class, source)
|
62
|
+
# expect(checker).to be_success
|
63
|
+
# end
|
64
|
+
# it 'should ignore javascript' do
|
65
|
+
# source = source_with('<div><script type="text/javascript" charset="utf-8"></ul></script></div>')
|
66
|
+
# checker = check_with(described_class, source)
|
67
|
+
# expect(checker).to be_success
|
68
|
+
# source = source_with("<div><script>multiline\n</ul></script></div>")
|
69
|
+
# checker = check_with(described_class, source)
|
70
|
+
# expect(checker).to be_success
|
71
|
+
# end
|
72
|
+
# it 'should ignore javascript' do
|
73
|
+
# source = source_with('<div><style></ul></style></div>')
|
74
|
+
# checker = check_with(described_class, source)
|
75
|
+
# expect(checker).to be_success
|
76
|
+
# end
|
77
|
+
# end
|
78
|
+
end
|
@@ -14,7 +14,7 @@ describe Codeqa::Checkers::RubocopLint do
|
|
14
14
|
source = source_with('class MyClass')
|
15
15
|
checker = check_with(described_class, source)
|
16
16
|
expect(checker).to be_error
|
17
|
-
expect(checker.errors.details.first
|
17
|
+
expect(checker.errors.details.first).to eq([[1, 14], 'Syntax: unexpected token $end'])
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'should find not find if not there ' do
|
@@ -1,19 +1,78 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Codeqa::RunnerDecorator do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
let(:errors){ Codeqa::CheckErrors.new }
|
5
|
+
let(:decorator) do
|
6
|
+
checker = double(Codeqa::Checker, :errors => errors,
|
7
|
+
:name => 'test',
|
8
|
+
:hint => 'testtest')
|
9
|
+
runner = double(Codeqa::Runner, :failures => [checker],
|
10
|
+
:sourcefile => Codeqa::Sourcefile.new('foo.rb', 'foo'),
|
11
|
+
:success? => false)
|
12
|
+
Codeqa::RunnerDecorator.new(runner)
|
10
13
|
end
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
expect(
|
15
|
-
|
16
|
-
|
14
|
+
|
15
|
+
it 'should format error as line if number given' do
|
16
|
+
errors.add(77, 'test message')
|
17
|
+
expect(decorator.details_to_s).to eq(<<-EOF)
|
18
|
+
\e[31m------- test -------\e[0m
|
19
|
+
\e[31mtesttest\e[0m
|
20
|
+
Line: \e[33m77\e[0m|test message
|
21
|
+
EOF
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should format error as position if array given' do
|
25
|
+
errors.add([22, 77], 'test message')
|
26
|
+
expect(decorator.details_to_s).to eq(<<-EOF)
|
27
|
+
\e[31m------- test -------\e[0m
|
28
|
+
\e[31mtesttest\e[0m
|
29
|
+
Pos: \e[33m22,77\e[0m|test message
|
30
|
+
EOF
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should simply print error content if no context is given' do
|
34
|
+
errors.add(nil, 'test message')
|
35
|
+
expect(decorator.details_to_s).to eq(<<-EOF)
|
36
|
+
\e[31m------- test -------\e[0m
|
37
|
+
\e[31mtesttest\e[0m
|
38
|
+
test message
|
39
|
+
EOF
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should format error as source if :source token given' do
|
43
|
+
errors.add(:source, 'test message')
|
44
|
+
expect(decorator.details_to_s).to eq(<<-EOF)
|
45
|
+
\e[31m------- test -------\e[0m
|
46
|
+
\e[31mtesttest\e[0m
|
47
|
+
\e[33m 1\e[0m|test message
|
48
|
+
EOF
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should correctly format multiline source' do
|
52
|
+
errors.add(:source, "test message\nline two\nthird\n\nfifth")
|
53
|
+
expect(decorator.details_to_s).to eq(<<-EOF)
|
54
|
+
\e[31m------- test -------\e[0m
|
55
|
+
\e[31mtesttest\e[0m
|
56
|
+
\e[33m 1\e[0m|test message
|
57
|
+
\e[33m 2\e[0m|line two
|
58
|
+
\e[33m 3\e[0m|third
|
59
|
+
\e[33m 4\e[0m|
|
60
|
+
\e[33m 5\e[0m|fifth
|
61
|
+
EOF
|
17
62
|
end
|
63
|
+
# it 'should run provide the errors if the checker failed' do
|
64
|
+
# source = source_with('def syntax_error', 'ruby.rb')
|
65
|
+
# runner = Codeqa::Runner.run(source)
|
66
|
+
# expect(runner.success?).to be false
|
67
|
+
# decorator = Codeqa::RunnerDecorator.new(runner)
|
68
|
+
# expect(decorator.to_s).to match(/syntax/)
|
69
|
+
# end
|
70
|
+
# it 'should run list the ran checkers' do
|
71
|
+
# source = source_with('def foo; end', 'ruby.rb')
|
72
|
+
# runner = Codeqa::Runner.run(source)
|
73
|
+
# expect(runner.success?).to be true
|
74
|
+
# decorator = Codeqa::RunnerDecorator.new(runner)
|
75
|
+
# expect(decorator.to_s).to match(/Passed tests.+strange chars/)
|
76
|
+
# end
|
18
77
|
|
19
78
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Codeqa::ErbSanitizer do
|
4
|
+
context 'erb' do
|
5
|
+
# let(:source) do
|
6
|
+
# source_with(
|
7
|
+
# IO.read(
|
8
|
+
# Codeqa.root.join('spec', 'fixtures', 'erb_example.html.erb')
|
9
|
+
# )
|
10
|
+
# )
|
11
|
+
# end
|
12
|
+
def compile(content)
|
13
|
+
described_class.new(content).result
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should remove erb tags' do
|
17
|
+
source = '<div><% some ruby %></div>'
|
18
|
+
expected = '<div></div>'
|
19
|
+
doc = compile(source)
|
20
|
+
expect(doc).to eq(expected)
|
21
|
+
expect(Nokogiri::XML(doc).errors).to be_empty
|
22
|
+
end
|
23
|
+
it 'should remove erb tags within attributes' do
|
24
|
+
source = '<div <%dont touch this%> baz="bla <%=inside%> <%=inside2%> stuff" after="meh"></div>'
|
25
|
+
expected = '<div baz="bla stuff" after="meh"></div>'
|
26
|
+
doc = compile(source)
|
27
|
+
expect(doc).to eq(expected)
|
28
|
+
expect(Nokogiri::XML(doc).errors).to be_empty
|
29
|
+
end
|
30
|
+
it 'should properly remove multiline erb tags and keep the correct line numbers' do
|
31
|
+
source = <<-EOR
|
32
|
+
<div>
|
33
|
+
<% render :partial => :foo, :locals => { :foo => 'foo',
|
34
|
+
:bar => 'bar'
|
35
|
+
:baz => 'baz' }%>
|
36
|
+
</div>
|
37
|
+
EOR
|
38
|
+
expected = <<-EOR
|
39
|
+
<div>
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
</div>
|
44
|
+
EOR
|
45
|
+
doc = compile(source)
|
46
|
+
expect(doc).to eq(expected)
|
47
|
+
expect(Nokogiri::XML(doc).errors).to be_empty
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should work on a more difficult example' do
|
51
|
+
source = IO.read(Codeqa.root.join('spec', 'fixtures', 'erb_example.html.erb'))
|
52
|
+
expected = IO.read(Codeqa.root.join('spec', 'fixtures', 'erb_example.html'))
|
53
|
+
doc = compile(source)
|
54
|
+
expect(doc).to eq(expected)
|
55
|
+
expect(Nokogiri::XML(doc).errors).to be_empty
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: codeqa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Schrammel
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-08-
|
12
|
+
date: 2014-08-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -79,7 +79,6 @@ files:
|
|
79
79
|
- codeqa.gemspec
|
80
80
|
- config/default.rb
|
81
81
|
- lib/codeqa.rb
|
82
|
-
- lib/codeqa/check_errors.rb
|
83
82
|
- lib/codeqa/checker.rb
|
84
83
|
- lib/codeqa/checkers/check_conflict.rb
|
85
84
|
- lib/codeqa/checkers/check_erb.rb
|
@@ -91,17 +90,21 @@ files:
|
|
91
90
|
- lib/codeqa/checkers/check_strange_chars.rb
|
92
91
|
- lib/codeqa/checkers/check_utf8_encoding.rb
|
93
92
|
- lib/codeqa/checkers/check_yard.rb
|
93
|
+
- lib/codeqa/checkers/html_validator.rb
|
94
94
|
- lib/codeqa/checkers/pattern_checker.rb
|
95
95
|
- lib/codeqa/checkers/rubocop_formatter.rb
|
96
96
|
- lib/codeqa/checkers/rubocop_full.rb
|
97
97
|
- lib/codeqa/checkers/rubocop_lint.rb
|
98
98
|
- lib/codeqa/configuration.rb
|
99
|
-
- lib/codeqa/fake_erb.rb
|
100
99
|
- lib/codeqa/runner.rb
|
101
100
|
- lib/codeqa/runner_decorator.rb
|
102
101
|
- lib/codeqa/sourcefile.rb
|
102
|
+
- lib/codeqa/utils/check_errors.rb
|
103
|
+
- lib/codeqa/utils/erb_sanitizer.rb
|
103
104
|
- lib/codeqa/version.rb
|
104
105
|
- lib/templates/pre-commit
|
106
|
+
- spec/fixtures/erb_example.html
|
107
|
+
- spec/fixtures/erb_example.html.erb
|
105
108
|
- spec/fixtures/html_error.html.erb
|
106
109
|
- spec/fixtures/html_error.text.html
|
107
110
|
- spec/fixtures/isolation/home/project/dir/.gitkeep
|
@@ -119,6 +122,7 @@ files:
|
|
119
122
|
- spec/lib/codeqa/checkers/check_strange_chars_spec.rb
|
120
123
|
- spec/lib/codeqa/checkers/check_utf8_encoding_spec.rb
|
121
124
|
- spec/lib/codeqa/checkers/check_yard_spec.rb
|
125
|
+
- spec/lib/codeqa/checkers/html_validator_spec.rb
|
122
126
|
- spec/lib/codeqa/checkers/rubocop_formatter_spec.rb
|
123
127
|
- spec/lib/codeqa/checkers/rubocop_full_spec.rb
|
124
128
|
- spec/lib/codeqa/checkers/rubocop_lint_spec.rb
|
@@ -126,6 +130,7 @@ files:
|
|
126
130
|
- spec/lib/codeqa/runner_decorator_spec.rb
|
127
131
|
- spec/lib/codeqa/runner_spec.rb
|
128
132
|
- spec/lib/codeqa/sourcefile_spec.rb
|
133
|
+
- spec/lib/codeqa/utils/erb_sanitizer_spec.rb
|
129
134
|
- spec/lib/codeqa_spec.rb
|
130
135
|
- spec/spec_helper.rb
|
131
136
|
- spec/support/checker.rb
|
@@ -144,9 +149,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
144
149
|
version: '2.0'
|
145
150
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
151
|
requirements:
|
147
|
-
- - "
|
152
|
+
- - ">"
|
148
153
|
- !ruby/object:Gem::Version
|
149
|
-
version:
|
154
|
+
version: 1.3.1
|
150
155
|
requirements: []
|
151
156
|
rubyforge_project:
|
152
157
|
rubygems_version: 2.2.2
|
@@ -154,6 +159,8 @@ signing_key:
|
|
154
159
|
specification_version: 4
|
155
160
|
summary: Code checker
|
156
161
|
test_files:
|
162
|
+
- spec/fixtures/erb_example.html
|
163
|
+
- spec/fixtures/erb_example.html.erb
|
157
164
|
- spec/fixtures/html_error.html.erb
|
158
165
|
- spec/fixtures/html_error.text.html
|
159
166
|
- spec/fixtures/isolation/home/project/dir/.gitkeep
|
@@ -171,6 +178,7 @@ test_files:
|
|
171
178
|
- spec/lib/codeqa/checkers/check_strange_chars_spec.rb
|
172
179
|
- spec/lib/codeqa/checkers/check_utf8_encoding_spec.rb
|
173
180
|
- spec/lib/codeqa/checkers/check_yard_spec.rb
|
181
|
+
- spec/lib/codeqa/checkers/html_validator_spec.rb
|
174
182
|
- spec/lib/codeqa/checkers/rubocop_formatter_spec.rb
|
175
183
|
- spec/lib/codeqa/checkers/rubocop_full_spec.rb
|
176
184
|
- spec/lib/codeqa/checkers/rubocop_lint_spec.rb
|
@@ -178,6 +186,7 @@ test_files:
|
|
178
186
|
- spec/lib/codeqa/runner_decorator_spec.rb
|
179
187
|
- spec/lib/codeqa/runner_spec.rb
|
180
188
|
- spec/lib/codeqa/sourcefile_spec.rb
|
189
|
+
- spec/lib/codeqa/utils/erb_sanitizer_spec.rb
|
181
190
|
- spec/lib/codeqa_spec.rb
|
182
191
|
- spec/spec_helper.rb
|
183
192
|
- spec/support/checker.rb
|
data/lib/codeqa/fake_erb.rb
DELETED
@@ -1,80 +0,0 @@
|
|
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
|