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 ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :rubygems
2
+ gemspec
3
+ gem 'rspec'
4
+ gem 'debugger'
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
+ ![Screenshot](http://dl.dropbox.com/u/48928587/Screenshots/h.png)
data/bin/wegolint ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'wegolint'
4
+
5
+ linter = WegoLint::WegoLinter.new(ARGV[0])
6
+ linter.lint!
7
+ puts linter.output
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
@@ -0,0 +1,4 @@
1
+ RSpec.configure do |config|
2
+ config.treat_symbols_as_metadata_keys_with_true_values = true
3
+ config.run_all_when_everything_filtered = true
4
+ end
@@ -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: []