wegolint 0.0.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.
- data/.gitignore +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +33 -0
- data/README.md +23 -0
- data/bin/wegolint +7 -0
- data/lib/init.rb +1 -0
- data/lib/wegolint.rb +102 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/wegolint_spec.rb +199 -0
- data/wegolint.gemspec +16 -0
- metadata +60 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.gem
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
wegolint (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
columnize (0.3.6)
|
10
|
+
debugger (1.2.0)
|
11
|
+
columnize (>= 0.3.1)
|
12
|
+
debugger-linecache (~> 1.1.1)
|
13
|
+
debugger-ruby_core_source (~> 1.1.3)
|
14
|
+
debugger-linecache (1.1.2)
|
15
|
+
debugger-ruby_core_source (>= 1.1.1)
|
16
|
+
debugger-ruby_core_source (1.1.3)
|
17
|
+
diff-lcs (1.1.3)
|
18
|
+
rspec (2.11.0)
|
19
|
+
rspec-core (~> 2.11.0)
|
20
|
+
rspec-expectations (~> 2.11.0)
|
21
|
+
rspec-mocks (~> 2.11.0)
|
22
|
+
rspec-core (2.11.1)
|
23
|
+
rspec-expectations (2.11.3)
|
24
|
+
diff-lcs (~> 1.1.3)
|
25
|
+
rspec-mocks (2.11.2)
|
26
|
+
|
27
|
+
PLATFORMS
|
28
|
+
ruby
|
29
|
+
|
30
|
+
DEPENDENCIES
|
31
|
+
debugger
|
32
|
+
rspec
|
33
|
+
wegolint!
|
data/README.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
## What is it?
|
2
|
+
This is a tool that validates a code file for a set of style guide rules. These
|
3
|
+
rules are run along with the standard parser for the given language. The main
|
4
|
+
use for this tool is to pass errors and line numbers to the [Syntastic Vim
|
5
|
+
plugin](https://github.com/scrooloose/syntastic).
|
6
|
+
|
7
|
+
## Installation Steps
|
8
|
+
1. Install syntastic fork into `~/.vim/bundle/`:
|
9
|
+
`git clone git://github.com/tristil/syntastic.git` (you should be using
|
10
|
+
[pathogen](https://github.com/tpope/vim-pathogen) if you aren't already)
|
11
|
+
2. Install the `wegolint` gem: `gem install wegolint`
|
12
|
+
3. Put these lines in your `.vimrc`:
|
13
|
+
|
14
|
+
```vim
|
15
|
+
let syntastic_auto_loc_list=1
|
16
|
+
let g:syntastic_quiet_warnings=1
|
17
|
+
let g:syntastic_ruby_checker='wegolint'
|
18
|
+
let g:syntastic_javascript_checker='wegolint'
|
19
|
+
```
|
20
|
+
(first two are optional but recommended for using Syntastic)
|
21
|
+
|
22
|
+
## Screenshot with Syntastic
|
23
|
+

|
data/bin/wegolint
ADDED
data/lib/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'wegolint'
|
data/lib/wegolint.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
module WegoLint; end
|
2
|
+
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
class WegoLint::WegoLinter
|
6
|
+
def initialize(filename)
|
7
|
+
@filename = filename
|
8
|
+
@filetype = File.extname(@filename)
|
9
|
+
@ruleset = @filetype == '.js' ? :javascript : :ruby
|
10
|
+
@output = ''
|
11
|
+
end
|
12
|
+
|
13
|
+
def lint!
|
14
|
+
@output = run_language_parser
|
15
|
+
parse_file
|
16
|
+
end
|
17
|
+
|
18
|
+
def rules
|
19
|
+
@rules ||= {
|
20
|
+
general: [
|
21
|
+
{ name: 'More than eighty characters', pattern: /^.{80}.+$/ },
|
22
|
+
{ name: 'Curly brace on its own line', pattern: /^\s*(\{|\})\s*$/ },
|
23
|
+
{ name: "Hard tabs (use soft tabs)", pattern: /\t/ },
|
24
|
+
{ name: 'Whitespace at end of line', pattern: /^.*\w+.*\s+\n$/ }],
|
25
|
+
|
26
|
+
ruby: [
|
27
|
+
{ name: 'Space should be around block { |param| foo }',
|
28
|
+
pattern: /[\.\s]#{block_not_padded}/, collapse_quotes: true },
|
29
|
+
{ name: 'No spaces after (, [ or before ], )',
|
30
|
+
pattern: no_spaces_padding_parens, collapse_quotes: true },
|
31
|
+
{ name: 'No parentheses around function parameters',
|
32
|
+
pattern: /def \w+ \w/}]}
|
33
|
+
end
|
34
|
+
|
35
|
+
def output
|
36
|
+
@output
|
37
|
+
end
|
38
|
+
|
39
|
+
##############################################################################
|
40
|
+
private
|
41
|
+
|
42
|
+
def parse_file
|
43
|
+
File.open(@filename, 'r') do |file|
|
44
|
+
line_number = 0
|
45
|
+
file.each_line do |line|
|
46
|
+
line_number += 1
|
47
|
+
apply_rules(line, line_number)
|
48
|
+
apply_rules(line, line_number, @ruleset)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def run_language_parser
|
54
|
+
if @filetype == ".js"
|
55
|
+
`jsl -nologo -nofilelisting -nosummary -nocontext -process #{@filename} 2>&1`
|
56
|
+
else
|
57
|
+
`ruby -w -T1 -c #{@filename} 2>&1`
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def block_not_padded
|
62
|
+
# This won't work with chained blocks on one line
|
63
|
+
no_space_beginning_block = /\{[\w\|'"].*\}[\.\s]$/
|
64
|
+
no_space_end_block = /\{.*[\w'"]\}[\.\s]$/
|
65
|
+
/(#{no_space_beginning_block}|#{no_space_end_block})/
|
66
|
+
end
|
67
|
+
|
68
|
+
def no_spaces_padding_parens
|
69
|
+
space = /[ ]/
|
70
|
+
left_parens = /[\[\(]/
|
71
|
+
right_parens = /[\]\)]/
|
72
|
+
space_after_left_parens = /#{left_parens}#{space}/
|
73
|
+
space_before_right_parens = /^(?!\s+#{right_parens}).*#{space}#{right_parens}/
|
74
|
+
/(?:#{space_after_left_parens}|#{space_before_right_parens})/
|
75
|
+
end
|
76
|
+
|
77
|
+
# The real algorithm for this has to find the first instance of any pair,
|
78
|
+
# strip it, start over, find the second instance, strip it, start over, etc.
|
79
|
+
def collapse_quotes(line)
|
80
|
+
newline = line
|
81
|
+
['"', "'"].each do |char|
|
82
|
+
newline.gsub!(/#{char}.+?#{char}/, "#{char}TEST#{char}")
|
83
|
+
end
|
84
|
+
newline
|
85
|
+
end
|
86
|
+
|
87
|
+
def apply_rules(line, line_number, ruleset = :general)
|
88
|
+
return unless rules[ruleset]
|
89
|
+
|
90
|
+
rules[ruleset].each do |rule|
|
91
|
+
line = collapse_quotes(line) if rule[:collapse_quotes]
|
92
|
+
if line =~ rule[:pattern]
|
93
|
+
if @filetype == ".js"
|
94
|
+
full_path = File.realpath(@filename)
|
95
|
+
@output += "#{full_path}(#{line_number}): SyntaxError: #{rule[:name]}\n"
|
96
|
+
else
|
97
|
+
@output += "#{@filename}:#{line_number}: syntax error, #{rule[:name]}\n"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,199 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require_relative '../lib/wegolint'
|
3
|
+
|
4
|
+
include WegoLint
|
5
|
+
|
6
|
+
describe WegoLinter do
|
7
|
+
let(:test_data_dir) { '/tmp/wegolint_spec'}
|
8
|
+
let(:wegolinter) { WegoLinter.new(file) }
|
9
|
+
|
10
|
+
subject { wegolinter.output }
|
11
|
+
|
12
|
+
before do
|
13
|
+
FileUtils.mkdir_p test_data_dir
|
14
|
+
File.open(file, 'w+') do |f|
|
15
|
+
f.write(code)
|
16
|
+
end
|
17
|
+
wegolinter.lint!
|
18
|
+
end
|
19
|
+
|
20
|
+
after do
|
21
|
+
File.unlink(file)
|
22
|
+
FileUtils.rmdir test_data_dir
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "General errors" do
|
26
|
+
let(:file) { test_data_dir + '/foo.rb' }
|
27
|
+
|
28
|
+
context "hard tab" do
|
29
|
+
let(:code) { "\t" }
|
30
|
+
|
31
|
+
it { should_have_error "Hard tabs (use soft tabs)", 1, :ruby }
|
32
|
+
end
|
33
|
+
|
34
|
+
context "whitespace at end of line" do
|
35
|
+
let(:code) { "'foo' \n" }
|
36
|
+
|
37
|
+
it { should_have_error "Whitespace at end of line", 1, :ruby }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "Ruby errors" do
|
42
|
+
let(:file) { test_data_dir + '/foo.rb' }
|
43
|
+
|
44
|
+
context "ruby parser syntax errors" do
|
45
|
+
let(:code) do
|
46
|
+
<<-EOF
|
47
|
+
Foo
|
48
|
+
end
|
49
|
+
EOF
|
50
|
+
end
|
51
|
+
|
52
|
+
it { should_have_error "unexpected keyword_end, expecting $end",2, :ruby }
|
53
|
+
end
|
54
|
+
|
55
|
+
context "80 character limit" do
|
56
|
+
let(:code) do
|
57
|
+
<<-EOF
|
58
|
+
a = 1
|
59
|
+
"kjkjkjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk"
|
60
|
+
b = 3
|
61
|
+
EOF
|
62
|
+
end
|
63
|
+
|
64
|
+
it { should_have_error "More than eighty characters", 2, :ruby }
|
65
|
+
end
|
66
|
+
|
67
|
+
context "curly brace on its own line" do
|
68
|
+
let(:code) do
|
69
|
+
<<-EOF
|
70
|
+
q = 1
|
71
|
+
{
|
72
|
+
b = 1 }
|
73
|
+
c = a+b
|
74
|
+
EOF
|
75
|
+
end
|
76
|
+
|
77
|
+
it { should_have_error "Curly brace on its own line", 2, :ruby }
|
78
|
+
end
|
79
|
+
|
80
|
+
context "no space on inside of block" do
|
81
|
+
let(:code) do
|
82
|
+
<<-EOF
|
83
|
+
a = 1
|
84
|
+
['a','b','c'].each {|item| puts item }
|
85
|
+
['a','b','c'].each { |item| puts item}
|
86
|
+
b = 2
|
87
|
+
EOF
|
88
|
+
end
|
89
|
+
|
90
|
+
it { should_have_error "Space should be around block", 2, :ruby }
|
91
|
+
it { should_have_error "Space should be around block", 3, :ruby }
|
92
|
+
end
|
93
|
+
|
94
|
+
context "no spaces after (, [ or before ], )" do
|
95
|
+
let(:code) do
|
96
|
+
<<-EOF
|
97
|
+
b = [ 'a' ]
|
98
|
+
def something( foo )
|
99
|
+
c = " [ a ] "
|
100
|
+
c = ' [ ] '
|
101
|
+
[ 'a', 'b' ].each { |line| puts " [ ] " }
|
102
|
+
end
|
103
|
+
doSomething(bar: 'baz', baz: 'bar', foo: 'bar', fa: 'lalalalalalaalalalalalala'
|
104
|
+
)
|
105
|
+
EOF
|
106
|
+
end
|
107
|
+
|
108
|
+
it { should_have_error "No spaces after (", 1, :ruby }
|
109
|
+
it { should_have_error "No spaces after (", 2, :ruby }
|
110
|
+
|
111
|
+
context "when embedded in strings" do
|
112
|
+
it { should_not_have_error "No spaces after (", 3, :ruby }
|
113
|
+
it { should_not_have_error "No spaces after (", 4, :ruby }
|
114
|
+
it { should_have_error "No spaces after (", 5, :ruby }
|
115
|
+
it { should_not_have_error "No spaces after (", 8, :ruby }
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context "No parentheses around function parameters" do
|
120
|
+
let(:code) do
|
121
|
+
<<-EOF
|
122
|
+
def something(foo)
|
123
|
+
end
|
124
|
+
def something foo, bar
|
125
|
+
end
|
126
|
+
def something
|
127
|
+
end
|
128
|
+
EOF
|
129
|
+
end
|
130
|
+
|
131
|
+
it { should_not_have_error "No parentheses around", 1, :ruby }
|
132
|
+
it { should_have_error "No parentheses around", 3, :ruby }
|
133
|
+
it { should_not_have_error "No parentheses around", 5, :ruby }
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
describe "Javascript errors" do
|
139
|
+
let(:file) { test_data_dir + '/foo.js' }
|
140
|
+
|
141
|
+
context "ruby parser syntax errors" do
|
142
|
+
let(:code) do
|
143
|
+
<<-EOF
|
144
|
+
fah {
|
145
|
+
}
|
146
|
+
EOF
|
147
|
+
end
|
148
|
+
|
149
|
+
it { should_have_error 'missing ; before statement', 1, :javascript }
|
150
|
+
end
|
151
|
+
|
152
|
+
context "80 character limit" do
|
153
|
+
let(:code) do
|
154
|
+
<<-EOF
|
155
|
+
var a = 1;
|
156
|
+
"kjkjkjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk";
|
157
|
+
var b = 2;
|
158
|
+
EOF
|
159
|
+
end
|
160
|
+
|
161
|
+
it { should_have_error "More than eighty characters", 2, :javascript }
|
162
|
+
end
|
163
|
+
|
164
|
+
context "curly brace on its own line" do
|
165
|
+
let(:code) do
|
166
|
+
<<-EOF
|
167
|
+
var func = function()
|
168
|
+
{
|
169
|
+
var b = 1; }
|
170
|
+
EOF
|
171
|
+
end
|
172
|
+
|
173
|
+
it { should_have_error "Curly brace on its own line", 2, :javascript }
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def should_have_error message, line_number, language
|
178
|
+
message = build_error_message message, line_number, language
|
179
|
+
subject.should include message
|
180
|
+
end
|
181
|
+
|
182
|
+
def should_not_have_error message, line_number, language
|
183
|
+
message = build_error_message message, line_number, language
|
184
|
+
subject.should_not include message
|
185
|
+
end
|
186
|
+
|
187
|
+
def build_error_message message, line_number, language
|
188
|
+
if language == :ruby
|
189
|
+
name = "foo.rb"
|
190
|
+
line_number = ":#{line_number}:"
|
191
|
+
prefix = " syntax error,"
|
192
|
+
else
|
193
|
+
name = "foo.js"
|
194
|
+
line_number = "(#{line_number}):"
|
195
|
+
prefix = " SyntaxError:"
|
196
|
+
end
|
197
|
+
"#{name}#{line_number}#{prefix} #{message}"
|
198
|
+
end
|
199
|
+
end
|
data/wegolint.gemspec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'wegolint'
|
3
|
+
s.version = '0.0.1'
|
4
|
+
s.date = '2012-09-16'
|
5
|
+
s.summary = 'Parses code for style guide violations'
|
6
|
+
s.description = <<-EOF
|
7
|
+
Validates code according to style guide rules for an organization and outputs
|
8
|
+
them as error statements that can be consumed by another program.
|
9
|
+
EOF
|
10
|
+
s.authors = ["Joseph Method"]
|
11
|
+
s.email = 'jmethod@wegowise.com'
|
12
|
+
s.files = `git ls-files`.split("\n")
|
13
|
+
s.homepage = ''
|
14
|
+
s.require_paths = ['lib']
|
15
|
+
s.executables = ['wegolint']
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wegolint
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Joseph Method
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-16 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: ! 'Validates code according to style guide rules for an organization
|
15
|
+
and outputs
|
16
|
+
|
17
|
+
them as error statements that can be consumed by another program.
|
18
|
+
|
19
|
+
'
|
20
|
+
email: jmethod@wegowise.com
|
21
|
+
executables:
|
22
|
+
- wegolint
|
23
|
+
extensions: []
|
24
|
+
extra_rdoc_files: []
|
25
|
+
files:
|
26
|
+
- .gitignore
|
27
|
+
- Gemfile
|
28
|
+
- Gemfile.lock
|
29
|
+
- README.md
|
30
|
+
- bin/wegolint
|
31
|
+
- lib/init.rb
|
32
|
+
- lib/wegolint.rb
|
33
|
+
- spec/spec_helper.rb
|
34
|
+
- spec/wegolint_spec.rb
|
35
|
+
- wegolint.gemspec
|
36
|
+
homepage: ''
|
37
|
+
licenses: []
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options: []
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
requirements: []
|
55
|
+
rubyforge_project:
|
56
|
+
rubygems_version: 1.8.24
|
57
|
+
signing_key:
|
58
|
+
specification_version: 3
|
59
|
+
summary: Parses code for style guide violations
|
60
|
+
test_files: []
|