syntaxer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "http://rubygems.org"
2
+ gem "git"
3
+ gem "rainbow"
4
+
5
+ # Add dependencies to develop your gem here.
6
+ # Include everything needed to run rake, tests, features, etc.
7
+ group :development do
8
+ gem "rspec", "~> 2.3.0"
9
+ gem "yard", "~> 0.6.0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.5.2"
12
+ gem "rcov", ">= 0"
13
+ gem "cucumber"
14
+ gem "aruba"
15
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,54 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ aruba (0.3.2)
5
+ childprocess (~> 0.1.6)
6
+ cucumber (~> 0.10.0)
7
+ rspec (~> 2.3.0)
8
+ builder (3.0.0)
9
+ childprocess (0.1.8)
10
+ ffi (~> 1.0.6)
11
+ cucumber (0.10.2)
12
+ builder (>= 2.1.2)
13
+ diff-lcs (>= 1.1.2)
14
+ gherkin (>= 2.3.5)
15
+ json (>= 1.4.6)
16
+ term-ansicolor (>= 1.0.5)
17
+ diff-lcs (1.1.2)
18
+ ffi (1.0.7)
19
+ rake (>= 0.8.7)
20
+ gherkin (2.3.5)
21
+ json (>= 1.4.6)
22
+ git (1.2.5)
23
+ jeweler (1.5.2)
24
+ bundler (~> 1.0.0)
25
+ git (>= 1.2.5)
26
+ rake
27
+ json (1.5.1)
28
+ rainbow (1.1.1)
29
+ rake (0.8.7)
30
+ rcov (0.9.9)
31
+ rspec (2.3.0)
32
+ rspec-core (~> 2.3.0)
33
+ rspec-expectations (~> 2.3.0)
34
+ rspec-mocks (~> 2.3.0)
35
+ rspec-core (2.3.1)
36
+ rspec-expectations (2.3.0)
37
+ diff-lcs (~> 1.1.2)
38
+ rspec-mocks (2.3.0)
39
+ term-ansicolor (1.0.5)
40
+ yard (0.6.4)
41
+
42
+ PLATFORMS
43
+ ruby
44
+
45
+ DEPENDENCIES
46
+ aruba
47
+ bundler (~> 1.0.0)
48
+ cucumber
49
+ git
50
+ jeweler (~> 1.5.2)
51
+ rainbow
52
+ rcov
53
+ rspec (~> 2.3.0)
54
+ yard (~> 0.6.0)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 artemk
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,104 @@
1
+ = syntaxer
2
+
3
+ == Overview
4
+
5
+ Syntaxer make possible check syntax of scripts. It may be used in standalone mode and with git repository.
6
+ When syntaxer is used with git it checks syntax in added and changed files before every commit and stop it if there are an error in some of the files.
7
+
8
+ == Installation
9
+
10
+ To install syntaxer run
11
+
12
+ sudo gem install syntaxer
13
+
14
+ == Usage
15
+
16
+ == Syntaxer with rails
17
+
18
+ Example of usage:
19
+
20
+ Run syntax checking in current directory recursively
21
+
22
+ syntaxer
23
+
24
+ Run syntax checking in another directory recursively
25
+
26
+ syntaxer -p ./developement
27
+
28
+ Install hook to git repository in current directory
29
+
30
+ syntaxer -i -r git
31
+
32
+ Indicate custom config file
33
+
34
+ syntaxer -c config.rb
35
+
36
+
37
+ Describe your rules in syntaxer.rb file and put in "initializers" folder for rails
38
+
39
+ Example of syntaxer.rb file:
40
+
41
+ syntaxer do
42
+ languages :ruby, :haml, :sass do # type of files to be watched
43
+ folders 'app/**/*', 'lib/**/*' # folders to be checked
44
+ end
45
+ end
46
+
47
+ You can specify multiple rules, for example you want to check only ruby files in app/controllers/* and only haml in app/views/*, you can write the next in your "initializers/syntaxer.rb" file:
48
+
49
+ syntaxer do
50
+ languages :ruby do
51
+ folders 'app/controllers/*'
52
+ end
53
+
54
+ lang :haml do # lang is an alias for languages
55
+ f 'app/views/*' #f is an alias for folders
56
+ end
57
+
58
+ #all supported types at app/**
59
+ languages :all do
60
+ folders 'app/**'
61
+ end
62
+
63
+ ignore_folders 'app/models/**' # this folders will be deleted from all languages
64
+ end
65
+
66
+
67
+ Languages available for now are: ruby, erb, haml, sass. But you can extend this by your own, how to do that i will describe below.
68
+
69
+
70
+ Options for usage
71
+ -c, --config specify config file
72
+ -p, --path path for syntax check. If this option is not specify it checks files from current directory
73
+ -l, --languages specify language for check. Available sass, haml and ruby. By default check all of them.
74
+ -r, --repo indicate type of repository. Available git and svn at this time.
75
+ -i, --install generates pre-commit hook and put it in .git/hooks folder. It checks syntax of languages what are indicated in options file before every commit
76
+ -q, --quite disable information messages.
77
+ -h, --help show help and options describe above.
78
+
79
+ == Contributing to syntaxer
80
+
81
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
82
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
83
+ * Fork the project
84
+ * Start a feature/bugfix branch
85
+ * Commit and push until you are happy with your contribution
86
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
87
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
88
+
89
+ == TODO
90
+
91
+ * Have to fix the problem with only created repository and initial commit with GIT reposytory
92
+ * Add SVN support
93
+
94
+ == Author
95
+
96
+ Artyom Kramarenko (artemk) Svitla Systems Inc (svitla.com)
97
+
98
+ == Contributors
99
+
100
+ Artem Melnikov (ignar) Svitla Systems Inc (svitla.com)
101
+
102
+ == Copyright
103
+
104
+ See LICENSE.txt for further details.
data/Rakefile ADDED
@@ -0,0 +1,42 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "syntaxer"
16
+ gem.homepage = "http://github.com/artemk/syntaxer"
17
+ gem.license = "MIT"
18
+ gem.summary = "Syntax checker for ruby and other languages"
19
+ gem.description = %Q{Syntax checker for ruby and other languages}
20
+ gem.email = "kramarenko.artyom@gmail.com"
21
+ gem.authors = ["artemk"]
22
+ gem.executables = ["syntaxer"]
23
+ gem.add_runtime_dependency 'git', '>=1.2.5'
24
+ gem.add_runtime_dependency 'rainbow', '>=1.1.1'
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = Rake::FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = true
37
+ end
38
+
39
+ task :default => :spec
40
+
41
+ require 'yard'
42
+ YARD::Rake::YardocTask.new
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/bin/syntaxer ADDED
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) #TODO: remove this
4
+
5
+ require 'optparse'
6
+ require 'ostruct'
7
+ require 'pp'
8
+
9
+ require 'syntaxer'
10
+
11
+ class SyntaxerCLI
12
+
13
+ def self.parse(args)
14
+ options = OpenStruct.new
15
+ options.config_file = Syntaxer::SYNTAXER_RULES_FILE
16
+ options.root_path = Dir.getwd
17
+ options.languages = :all
18
+
19
+ opts = OptionParser.new do |opts|
20
+ opts.banner = "Usage: syntaxer [options]"
21
+
22
+ opts.separator ""
23
+ opts.separator "Specific options:"
24
+
25
+ opts.on("-c", "--config [CONFIG_FILE]", String,
26
+ "Syntax rules file to be used for syntaxer") do |config_file|
27
+ options.config_file = config_file
28
+ end
29
+
30
+ opts.on("-p", "--path [DIR]", String, "If you want to check files not from current place") do |r|
31
+ options.root_path = r
32
+ end
33
+
34
+ opts.on("-l", "--languages [ruby, haml, sass]", Array, "List of languages to be used in syntax checking") do |l|
35
+ options.languages = l
36
+ end
37
+
38
+ opts.on("-r", "--repo [TYPE]", ['git', 'svn'],
39
+ "Select repository type (git, svn)") do |r|
40
+ options.repository = r
41
+ end
42
+
43
+ opts.on("-q", "--quite", "Run in verbose mode") do |r|
44
+ options.quite = true
45
+ end
46
+
47
+ opts.on("-i", "--install", "Write hooks to git") do |r|
48
+ options.generate = true
49
+ end
50
+
51
+ opts.separator ""
52
+ opts.separator "Common options:"
53
+
54
+ opts.on_tail("-h", "--help", "Show this message") do
55
+ puts opts
56
+ exit
57
+ end
58
+
59
+ opts.on_tail("--version", "Show version") do
60
+ puts Syntaxer::VERSION
61
+ exit
62
+ end
63
+ end
64
+
65
+ opts.parse!(args)
66
+ options
67
+ end
68
+
69
+ end
70
+
71
+ options = SyntaxerCLI.parse(ARGV)
72
+ if options.generate.nil?
73
+ Syntaxer.check_syntax(options.instance_variable_get("@table"))
74
+ else
75
+ Syntaxer.make_hook(options.instance_variable_get("@table"))
76
+ end
77
+
@@ -0,0 +1,14 @@
1
+ @announce
2
+ Feature: Check syntax in plain mode
3
+
4
+ In order to check syntax
5
+ A user who used gem
6
+ Should be abble run command
7
+
8
+ @plain
9
+ Scenario: Run checker in directory
10
+ Given directory containt two files
11
+ When I run `syntaxer` interactively
12
+ Then the exit status should not be 0
13
+ And the output should not contain "Syntax OK"
14
+
@@ -0,0 +1,13 @@
1
+ @announce
2
+ Feature: Check git repository before commit
3
+
4
+ In order to check syntax
5
+ A user print "git commit"
6
+ Commit have to be rejected in case of wrong syntax
7
+
8
+ @repo
9
+ Scenario: Run "git commit"
10
+ Given git repository
11
+ And some file with worng syntax
12
+ When run `git commit -m "some message"` interactively
13
+ Then the syntaxer should stop commit
@@ -0,0 +1,8 @@
1
+ Given /^directory containt two files$/ do
2
+ create_temp_plain_work_dir
3
+ end
4
+
5
+ When /^I cd to working directory$/ do
6
+ cd(@tmp_dir)
7
+ end
8
+
@@ -0,0 +1,18 @@
1
+ Given /^git repository$/ do
2
+ create_temp_repo_work_dir
3
+ end
4
+
5
+ Given /^some file with worng syntax$/ do
6
+ in_current_dir do
7
+ add_fixtures_files
8
+ end
9
+ end
10
+
11
+ When /^run `git commit \-m \"some message\"` interactively$/ do
12
+ add_hook
13
+ end
14
+
15
+ Then /^the syntaxer should stop commit$/ do
16
+ lambda{make_git_commit}.should raise_exception
17
+ #@last_exit_status.should_not == 0
18
+ end
@@ -0,0 +1,3 @@
1
+ require 'aruba/cucumber'
2
+ require 'fileutils'
3
+ require "git"
@@ -0,0 +1,7 @@
1
+ Before do
2
+
3
+ end
4
+
5
+ After do
6
+
7
+ end
@@ -0,0 +1,73 @@
1
+ module PlainHelpers
2
+ @tmp_dir
3
+ def temp_dir
4
+ tmpdir = File.expand_path current_dir #"#{Time.now.to_i}"
5
+ @tmp_dir = tmpdir
6
+ tmpdir
7
+ end
8
+
9
+ def add_fixtures_files
10
+ Dir["#{fixtures_path}/*.example"].each do |f|
11
+ FileUtils.cp f, File.join(@tmp_dir,File.basename(f,'.example'))
12
+ end
13
+ end
14
+
15
+ def create_tmp_dir
16
+ tmpdir = temp_dir
17
+ create_dir(tmpdir)
18
+ tmpdir
19
+ end
20
+
21
+ def syntaxer_rules_example_file file = ''
22
+ File.join(File.expand_path('../../',File.dirname(__FILE__)), 'spec/fixtures', "#{file.empty? ? 'syntaxer_rules': file}.rb")
23
+ end
24
+
25
+ def create_tmp_repo_dir
26
+ end
27
+
28
+ def fixtures_path
29
+ File.join(File.expand_path('../../',File.dirname(__FILE__)),'spec/fixtures/ruby')
30
+ end
31
+
32
+ def create_temp_plain_work_dir
33
+ tmp = create_tmp_dir
34
+ in_current_dir do
35
+ add_fixtures_files
36
+ end
37
+ end
38
+
39
+ def create_temp_repo_work_dir
40
+ create_tmp_dir
41
+ g = Git.init(File.expand_path(File.join(@tmp_dir)))
42
+ FileUtils.touch(File.join(@tmp_dir,'README'))
43
+ g.add('.')
44
+ g.commit('first commit')
45
+ end
46
+
47
+ def add_hook
48
+ in_current_dir do
49
+ bin_file = File.join(File.expand_path('../../',File.dirname(__FILE__)), 'bin/syntaxer')
50
+ hook_file = File.expand_path(File.join('.git/hooks/pre-commit'))
51
+ File.open(hook_file, 'w') do |f|
52
+ f.puts "#{bin_file} -c #{syntaxer_rules_example_file('syntaxer_rules_git')} -r git -p #{File.expand_path(@tmp_dir)}"
53
+ end
54
+ File.chmod(0755, hook_file)
55
+ end
56
+ end
57
+
58
+ def make_git_commit
59
+ g = Git.open File.expand_path(@tmp_dir) #(File.expand_path(File.join(current_dir)))
60
+ g.add
61
+ #pp File.expand_path(current_dir)
62
+ #Dir.chdir(File.expand_path(current_dir)) do
63
+ #g = Git.open Dir.pwd
64
+ #g.add
65
+ Dir.chdir(current_dir)
66
+ g.commit('second commit')
67
+ #end
68
+
69
+ end
70
+
71
+ end
72
+
73
+ World(PlainHelpers)
data/init.rb ADDED
@@ -0,0 +1,5 @@
1
+ begin
2
+ require File.join(File.dirname(__FILE__), 'lib', 'syntaxer') # From here
3
+ rescue LoadError
4
+ require 'syntaxer' # From gem
5
+ end
@@ -0,0 +1,115 @@
1
+ # Rake::FileList
2
+ require 'set'
3
+ module Syntaxer
4
+ class Checker
5
+ include Open3
6
+ extend Forwardable
7
+
8
+ # Does not working
9
+ def_delegators Syntaxer::FileStatus, :error_files, :fine_files
10
+
11
+ attr_accessor :syntaxer, :reader
12
+
13
+ # List of files with correct syntax
14
+ #
15
+ # @return [Array<FileStatus>, #each] array with files
16
+ #
17
+ # @see FileStatus#fine_files
18
+
19
+ def self.fine_files
20
+ FileStatus.fine_files
21
+ end
22
+
23
+ # List of files with wrong syntax
24
+ #
25
+ # @return [Array<FileStatus>, #each] array with files
26
+ #
27
+ # @see FileStatus#fine_files
28
+
29
+ def self.error_files
30
+ FileStatus.error_files
31
+ end
32
+
33
+ def initialize(syntaxer)
34
+ @syntaxer = syntaxer
35
+ @reader = @syntaxer.reader
36
+ @results = []
37
+ end
38
+
39
+ # Factory for checker
40
+ #
41
+ # @return [RepoChecker, #process]
42
+
43
+ def self.process(syntaxer)
44
+ if syntaxer.repository
45
+ RepoChecker.new(syntaxer).process
46
+ else
47
+ PlainChecker.new(syntaxer).process
48
+ end
49
+ end
50
+
51
+ end
52
+
53
+ # Check status of files in repository
54
+
55
+ class RepoChecker < Checker
56
+
57
+ # Check syntax in repository directory
58
+ #
59
+ # @see Checker#process
60
+
61
+ def process
62
+ checked_files = Set.new
63
+ @reader.rules.each do |rule|
64
+ files_collection = []
65
+ rule.extensions.each do |ext|
66
+ files.each do |file|
67
+ if file.include?(ext) && !checked_files.include?(file)
68
+ files_collection << file
69
+ checked_files.add(file)
70
+ end
71
+ end
72
+ end
73
+
74
+ files_collection.each do |file|
75
+ errors = nil
76
+ full_path = File.join(@syntaxer.root_path,file)
77
+ stdout, stderr, status = capture3(rule.exec_rule.gsub('%filename%', full_path))
78
+ errors = stderr.split("\n")
79
+
80
+ Printer.print_progress errors.empty?
81
+ FileStatus.build(file, errors)
82
+ end
83
+ end
84
+ FileStatus
85
+ end
86
+
87
+ private
88
+ def files
89
+ @syntaxer.repository.changed_and_added_files
90
+ end
91
+ end
92
+
93
+ class PlainChecker < Checker
94
+
95
+ # Check syntax in indicated directory
96
+ #
97
+ # @see Checker#process
98
+
99
+ def process
100
+ @reader.rules.each do |rule|
101
+ rule.files_list(@syntaxer.root_path).each do |file|
102
+ errors = nil
103
+ stdout, stderr, status = capture3(rule.exec_rule.gsub('%filename%', file))
104
+ errors = stderr.split("\n")
105
+
106
+ Printer.print_progress errors.empty?
107
+ FileStatus.build(file, errors)
108
+ end
109
+ end
110
+ FileStatus
111
+ end
112
+
113
+ end
114
+
115
+ end
@@ -0,0 +1,34 @@
1
+ module Syntaxer
2
+
3
+ # Contain filename, status of the syntax and list of errors
4
+
5
+ class FileStatus
6
+ @@error_files = []
7
+ @@fine_files = []
8
+
9
+ attr_reader :file_name, :status, :errors
10
+
11
+ def initialize(file_name, errors = [])
12
+ @errors = errors
13
+ @file_name = file_name
14
+ @status = @errors.empty? ? :ok : :failed
15
+ end
16
+
17
+ class << self
18
+ def build(file_name, errors = [])
19
+ file_status = new(file_name, errors)
20
+ errors.empty? ? @@fine_files << file_status : @@error_files << file_status
21
+ end
22
+
23
+ def error_files
24
+ @@error_files
25
+ end
26
+
27
+ def fine_files
28
+ @@fine_files
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,43 @@
1
+ module Syntaxer
2
+ class LanguageDefinitionException < Exception; end
3
+
4
+ LanguageDefinition = Struct.new(:name, :extensions, :specific_files, :folders, :ignore_folders, :exec_rule) do
5
+ def initialize(*args)
6
+ super(*args)
7
+ raise LanguageDefinitionException.new "name can't be blank" unless self.name
8
+ end
9
+
10
+
11
+ def files_list(root_path)
12
+ main_rule = folders.map{|f| root_path + f + ".\{#{extensions.join(',')}\}"}
13
+ list = Rake::FileList.new(main_rule) do |fl|
14
+ #fl.add(specific_files) if specific_files TODO:fix this
15
+ fl.exclude(ignore_folders) if ignore_folders
16
+ end
17
+ list
18
+ end
19
+ end
20
+
21
+
22
+ class LanguageRules < Array
23
+
24
+ def << (smth)
25
+ raise LanguageDefinitionException.new "can't be other then LanguageDefinition class object" unless smth.is_a?(LanguageDefinition)
26
+ super
27
+ end
28
+
29
+ def find_or_create(name)
30
+ found = find(name)
31
+ unless found
32
+ found = LanguageDefinition.new(name)
33
+ self << found
34
+ end
35
+ found
36
+ end
37
+
38
+ def find(name)
39
+ self.detect{|ld| ld.name == name}
40
+ end
41
+ end
42
+
43
+ end