jslint-v8 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,14 @@
1
+
2
+ module JSLintV8
3
+ class LintError
4
+ attr_reader :line_number, :character, :reason, :evidence
5
+
6
+ def initialize(jsobject)
7
+ @line_number = jsobject["line"]
8
+ @character = jsobject["character"]
9
+ @reason = jsobject["reason"]
10
+ @evidence = jsobject["evidence"]
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,79 @@
1
+ require 'rake'
2
+ require 'rake/tasklib'
3
+
4
+ module JSLintV8
5
+ class RakeTask < ::Rake::TaskLib
6
+ # name of the rake task
7
+ attr_accessor :name
8
+
9
+ # description for the task
10
+ attr_accessor :description
11
+
12
+ # inclusion glob pattern for files
13
+ attr_accessor :include_pattern
14
+
15
+ # exclusion glob pattern for files
16
+ attr_accessor :exclude_pattern
17
+
18
+ # output stream for this task
19
+ attr_accessor :output_stream
20
+
21
+ def initialize
22
+ # a default name
23
+ @name = "lint"
24
+
25
+ # a default description
26
+ @description = "Runs the JSLint Test Suite"
27
+
28
+ # by default a glob pattern that will include javascript files found in rails
29
+ @include_pattern = "app/javascripts/**/*.js"
30
+
31
+ # by default a glob pattern which will match no files
32
+ @exclude_pattern = ""
33
+
34
+ # by default use standard output for writing information
35
+ @output_stream = STDOUT
36
+
37
+ # if a block was given allow the block to call elements on this object
38
+ yield self if block_given?
39
+
40
+ # create the rake task
41
+ new_task = task(name) do
42
+ formatter = JSLintV8::Formatter.new(output_stream)
43
+
44
+ lint_result = runner.run do |file, errors|
45
+ formatter.tick(errors)
46
+ end
47
+
48
+ # put a separator line in between the ticks and any summary
49
+ output_stream.print "\n"
50
+
51
+ # print a summary of failed files
52
+ formatter.summary(files_to_run, lint_result)
53
+
54
+ # raise an exception if there are errors
55
+ raise "jslint suite failed" unless lint_result.empty?
56
+ end
57
+
58
+ # assign the description to the rake task
59
+ new_task.comment = description
60
+ end
61
+
62
+ #
63
+ # Returns a list of all files to run, sorted
64
+ #
65
+ def files_to_run
66
+ included_files = Dir.glob(include_pattern)
67
+ excluded_files = Dir.glob(exclude_pattern)
68
+
69
+ (included_files - excluded_files).sort
70
+ end
71
+
72
+ private
73
+
74
+ def runner
75
+ JSLintV8::Runner.new(files_to_run)
76
+ end
77
+
78
+ end
79
+ end
@@ -0,0 +1,82 @@
1
+ require 'v8'
2
+
3
+ module JSLintV8
4
+ class Runner
5
+ JSLintLibraryFilename = File.expand_path("js/jslint.js", File.dirname(__FILE__))
6
+
7
+ attr_reader :file_list
8
+
9
+ def initialize(files)
10
+ if(files.is_a?(Array))
11
+ @file_list = files
12
+ else
13
+ @file_list = [files]
14
+ end
15
+ end
16
+
17
+ def run
18
+ # make sure all files exit
19
+ file_list.each do |file|
20
+ raise "file not found: #{file}" unless File.exist?(file)
21
+ end
22
+
23
+ result = {}
24
+
25
+ file_list.each do |file|
26
+ errors = jslint(File.read(file))
27
+
28
+ yield(file, errors) if block_given?
29
+
30
+ next if errors.empty?
31
+
32
+ result[file] = errors
33
+ end
34
+
35
+ result
36
+ end
37
+
38
+ def runtime
39
+ @runtime ||= lambda do
40
+ runtime = V8::Context.new
41
+
42
+ # load the jslint library into the runtime
43
+ runtime.eval(File.read JSLintLibraryFilename)
44
+
45
+ # return the runtime
46
+ runtime
47
+ end.call
48
+ end
49
+
50
+ def jslint(source_code)
51
+ jslint_function.call(source_code, jslint_options)
52
+ jslint_result
53
+ end
54
+
55
+ def jslint_function
56
+ runtime["JSLINT"];
57
+ end
58
+
59
+ def jslint_result
60
+ runtime["JSLINT"]["errors"].to_a.compact.map do |error_object|
61
+ JSLintV8::LintError.new(error_object)
62
+ end
63
+ end
64
+
65
+ def jslint_options
66
+ {
67
+ "bitwise" => true,
68
+ "eqeqeq" => true,
69
+ "immed" => true,
70
+ "newcap" => true,
71
+ "nomen" => true,
72
+ "onevar" => true,
73
+ "plusplus" => true,
74
+ "regexp" => true,
75
+ "rhino" => true,
76
+ "undef" => true,
77
+ "white" => true
78
+ }
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,11 @@
1
+
2
+ module JSLintV8
3
+ module Version
4
+ MAJOR = 1
5
+ MINOR = 0
6
+ PATCH = 0
7
+ BUILD = nil
8
+
9
+ STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
10
+ end
11
+ end
data/lib/jslint-v8.rb ADDED
@@ -0,0 +1,6 @@
1
+ module JSLintV8 end
2
+
3
+ require File.expand_path("jslint-v8/runner", File.dirname(__FILE__))
4
+ require File.expand_path("jslint-v8/rake_task", File.dirname(__FILE__))
5
+ require File.expand_path("jslint-v8/lint_error", File.dirname(__FILE__))
6
+ require File.expand_path("jslint-v8/formatter", File.dirname(__FILE__))
data/test/helper.rb ADDED
@@ -0,0 +1,18 @@
1
+ require "rubygems"
2
+ require 'test/unit'
3
+ require 'erb'
4
+
5
+ # require the library code
6
+ require File.expand_path("../lib/jslint-v8", File.dirname(__FILE__))
7
+
8
+ def erb_fixture(basename)
9
+ ::ERB.new(File.read(erb_filename(basename))).result
10
+ end
11
+
12
+ def erb_filename(basename)
13
+ File.expand_path("fixtures/#{basename}.txt.erb", File.dirname(__FILE__))
14
+ end
15
+
16
+ def js_filename(basename)
17
+ File.expand_path("fixtures/#{basename}.js", File.dirname(__FILE__))
18
+ end
data/test/suite.rb ADDED
@@ -0,0 +1,5 @@
1
+
2
+ # require all test cases
3
+ Dir.glob(File.join(File.dirname(__FILE__), "test_*.rb")).each do |test_file|
4
+ require test_file
5
+ end
data/test/test_cli.rb ADDED
@@ -0,0 +1,44 @@
1
+ require File.expand_path('helper', File.dirname(__FILE__))
2
+ require 'erb'
3
+
4
+ class TestCli < Test::Unit::TestCase
5
+ Executable = File.expand_path("../bin/jslint-v8", File.dirname(__FILE__))
6
+
7
+ def test_executable_exists
8
+ assert File.exist?(Executable)
9
+ end
10
+
11
+ def test_empty_args
12
+ result = `#{Executable}`
13
+
14
+ assert_equal "usage: jslint-v8 FILES\n", result
15
+ assert_equal false, $?.success?
16
+ end
17
+
18
+ def test_valid
19
+ result = %x{#{Executable} "#{js_filename "valid"}"}
20
+
21
+ assert $?.success?
22
+ assert_equal erb_fixture("cli-valid-expected-output"), result
23
+ end
24
+
25
+ def test_invalid
26
+ result = %x{#{Executable} "#{js_filename "invalid"}"}
27
+
28
+ assert_equal false, $?.success?
29
+ assert_equal erb_fixture("cli-invalid-expected-output"), result
30
+ end
31
+
32
+ def test_suite
33
+ defined_globals = js_filename("defined-globals")
34
+ defined_options = js_filename("defined-options")
35
+ invalid = js_filename("invalid")
36
+ valid = js_filename("valid")
37
+
38
+ result = %x{#{Executable} "#{defined_globals}" "#{defined_options}" "#{invalid}" "#{valid}"}
39
+
40
+ assert_equal false, $?.success?
41
+ assert_equal erb_fixture("cli-suite-expected-output"), result
42
+ end
43
+
44
+ end
@@ -0,0 +1,51 @@
1
+ require File.expand_path('helper', File.dirname(__FILE__))
2
+ require 'erb'
3
+ require 'stringio'
4
+
5
+ class TestFormatter < Test::Unit::TestCase
6
+
7
+ def setup
8
+ @output = String.new
9
+ @output_stream = StringIO.new(@output, "w+")
10
+
11
+ @formatter = JSLintV8::Formatter.new(@output_stream)
12
+ end
13
+
14
+ def test_create
15
+ assert_equal @output_stream.object_id, @formatter.output_stream.object_id
16
+ end
17
+
18
+ def test_tick
19
+ assert_equal "", @output
20
+
21
+ @formatter.tick([])
22
+
23
+ assert_equal ".", @output
24
+
25
+ @formatter.tick(["foo"])
26
+
27
+ assert_equal ".*", @output
28
+ end
29
+
30
+ def test_summary_with_no_errors
31
+ @formatter.summary(%w(foo bar), {})
32
+
33
+ assert_equal erb_fixture("formatter-summary-noerrors"), @output
34
+ end
35
+
36
+ def test_summary_with_errors
37
+ error_1 = JSLintV8::LintError.new("line" => 42, "character" => 10, "reason" => "because i can")
38
+ error_2 = JSLintV8::LintError.new("line" => 43, "character" => 3, "reason" => "a proof is not a proof")
39
+ error_3 = JSLintV8::LintError.new("line" => 139, "character" => 12, "reason" => "undefined global 'foo'")
40
+
41
+ result = {
42
+ "foo" => [error_1, error_2],
43
+ "bar" => [error_3]
44
+ }
45
+
46
+ @formatter.summary(%w(foo bar baz one two three), result)
47
+
48
+ assert_equal erb_fixture("formatter-summary-errors"), @output
49
+ end
50
+
51
+ end
@@ -0,0 +1,32 @@
1
+ require File.expand_path('helper', File.dirname(__FILE__))
2
+
3
+ class TestLintError < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @object = {
7
+ "line" => 42,
8
+ "character" => 10,
9
+ "reason" => "because i can",
10
+ "evidence" => "I don't know, a proof is a proof. What kind of a proof? It's a proof. A proof is a proof, and when you have a good proof, it's because it's proven."
11
+ }
12
+
13
+ @error = JSLintV8::LintError.new(@object)
14
+ end
15
+
16
+ def test_line_number
17
+ assert_equal @error.line_number, 42
18
+ end
19
+
20
+ def test_character
21
+ assert_equal @error.character, 10
22
+ end
23
+
24
+ def test_reason
25
+ assert_equal @error.reason, "because i can"
26
+ end
27
+
28
+ def test_evidence
29
+ assert_equal @error.evidence, "I don't know, a proof is a proof. What kind of a proof? It's a proof. A proof is a proof, and when you have a good proof, it's because it's proven."
30
+ end
31
+
32
+ end
@@ -0,0 +1,141 @@
1
+ require File.expand_path('helper', File.dirname(__FILE__))
2
+
3
+ class TestRunner < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @runner = JSLintV8::Runner.new(%w(foo bar))
7
+ end
8
+
9
+ def test_lint_library_filename
10
+ assert File.exist? JSLintV8::Runner::JSLintLibraryFilename
11
+ end
12
+
13
+ def test_file_list
14
+ assert_equal @runner.file_list, %w(foo bar)
15
+ end
16
+
17
+ def test_constructor_enumerable_wrapping
18
+ @runner = JSLintV8::Runner.new("foo")
19
+
20
+ assert_equal @runner.file_list, %w(foo)
21
+ end
22
+
23
+ def test_file_not_found
24
+ assert_raise RuntimeError do
25
+ @runner.run
26
+ end
27
+ end
28
+
29
+ def test_file_found
30
+ filename = js_filename "valid"
31
+
32
+ assert_nothing_raised do
33
+ JSLintV8::Runner.new(filename).run
34
+ end
35
+ end
36
+
37
+ def test_runtime
38
+ assert @runner.runtime.is_a?(V8::Context)
39
+ end
40
+
41
+ def test_runtime_caching
42
+ first = @runner.runtime
43
+ assert_equal @runner.runtime.object_id, first.object_id
44
+ end
45
+
46
+ def test_jslint_function_proxy
47
+ assert_not_nil @runner.jslint_function
48
+ end
49
+
50
+ def test_jslint_result
51
+ assert @runner.jslint_result.is_a?(Array)
52
+ end
53
+
54
+ def test_jslint_default_options
55
+ assert @runner.jslint_options.keys.any?
56
+ end
57
+
58
+ def test_jslint_returns_array_of_errors
59
+ result = @runner.jslint("if(true) alert('foo');")
60
+
61
+ assert result.is_a?(Array)
62
+ assert result.length > 0
63
+ assert result.all? {|error| error.is_a?(JSLintV8::LintError) }
64
+ end
65
+
66
+ def test_run
67
+ filename = js_filename("invalid")
68
+
69
+ result = JSLintV8::Runner.new(filename).run
70
+
71
+ assert result.is_a?(Hash)
72
+ assert result.keys.include?(filename)
73
+ assert result[filename].is_a?(Array)
74
+ end
75
+
76
+ def test_valid_run
77
+ filename = js_filename("valid")
78
+
79
+ result = JSLintV8::Runner.new(filename).run
80
+
81
+ errors = result[filename]
82
+
83
+ assert errors.nil?
84
+ end
85
+
86
+ def test_invalid_run
87
+ filename = js_filename("invalid")
88
+
89
+ result = JSLintV8::Runner.new(filename).run
90
+
91
+ errors = result[filename]
92
+
93
+ assert errors.any?
94
+ end
95
+
96
+ def test_defined_globals
97
+ filename = js_filename("defined-globals")
98
+
99
+ result = JSLintV8::Runner.new(filename).run
100
+
101
+ errors = result[filename]
102
+
103
+ assert errors.nil?
104
+ end
105
+
106
+ def test_defined_options
107
+ filename = js_filename("defined-options")
108
+
109
+ result = JSLintV8::Runner.new(filename).run
110
+
111
+ errors = result[filename]
112
+
113
+ assert errors.nil?
114
+ end
115
+
116
+ def test_block
117
+ filename = js_filename("valid")
118
+
119
+ count = 0
120
+
121
+ JSLintV8::Runner.new(filename).run do |file, errors|
122
+ count += 1
123
+
124
+ if count == 1
125
+ assert_equal file, filename
126
+ assert_equal errors, []
127
+ end
128
+ end
129
+
130
+ assert_equal count, 1
131
+ end
132
+
133
+ def test_rejects_successful
134
+ valid_file = js_filename("valid")
135
+ invalid_file = js_filename("invalid")
136
+
137
+ result = JSLintV8::Runner.new([valid_file, invalid_file]).run
138
+
139
+ assert_equal result.keys.length, 1
140
+ end
141
+ end
data/test/test_task.rb ADDED
@@ -0,0 +1,126 @@
1
+ require File.expand_path('helper', File.dirname(__FILE__))
2
+ require 'rake'
3
+ require 'tempfile'
4
+
5
+ class TestTask < Test::Unit::TestCase
6
+
7
+ def setup
8
+ # completely reset the rake application to ensure everything is clean
9
+ Rake.application = nil
10
+ end
11
+
12
+ def test_creation
13
+ initial_length = Rake.application.tasks.length
14
+
15
+ JSLintV8::RakeTask.new
16
+
17
+ # the number of tasks should have increased by 1
18
+ assert_equal initial_length + 1, Rake.application.tasks.length
19
+ end
20
+
21
+ def test_default_name
22
+ JSLintV8::RakeTask.new
23
+
24
+ task = Rake.application.lookup("lint")
25
+
26
+ assert_equal "lint", task.name
27
+ end
28
+
29
+ def test_default_description
30
+ JSLintV8::RakeTask.new
31
+
32
+ task = Rake.application.lookup("lint")
33
+
34
+ assert_equal "Runs the JSLint Test Suite", task.comment
35
+ end
36
+
37
+ def test_default_include_pattern
38
+ task = JSLintV8::RakeTask.new
39
+
40
+ assert_equal "app/javascripts/**/*.js", task.include_pattern
41
+ end
42
+
43
+ def test_default_exclude_pattern
44
+ task = JSLintV8::RakeTask.new
45
+
46
+ assert_equal "", task.exclude_pattern
47
+ end
48
+
49
+ def test_default_output_stream
50
+ task = JSLintV8::RakeTask.new
51
+
52
+ assert_equal STDOUT, task.output_stream
53
+ end
54
+
55
+ def test_creation_block
56
+ tempfile = Tempfile.new("foo")
57
+
58
+ task = JSLintV8::RakeTask.new do |task|
59
+ task.name = "foo"
60
+ task.description = "Points out the bad codezzzz"
61
+ task.include_pattern = "js/**/*.js"
62
+ task.exclude_pattern = "js/**/*.txt"
63
+ task.output_stream = tempfile
64
+ end
65
+
66
+ rake_task = Rake.application.lookup("foo")
67
+
68
+ assert_equal "foo", rake_task.name
69
+ assert_equal "Points out the bad codezzzz", rake_task.comment
70
+ assert_equal "js/**/*.js", task.include_pattern
71
+ assert_equal "js/**/*.txt", task.exclude_pattern
72
+ assert_equal tempfile.object_id, task.output_stream.object_id
73
+ end
74
+
75
+ def test_files_to_run
76
+ task = JSLintV8::RakeTask.new do |task|
77
+ task.include_pattern = File.expand_path("fixtures/*", File.dirname(__FILE__))
78
+ task.exclude_pattern = File.expand_path("fixtures/*.erb", File.dirname(__FILE__))
79
+ end
80
+
81
+ expected_files = Dir.glob(File.expand_path("fixtures/*.js", File.dirname(__FILE__))).sort
82
+
83
+ assert_equal expected_files, task.files_to_run
84
+ end
85
+
86
+ def test_valid_output
87
+ result = String.new
88
+
89
+ task = JSLintV8::RakeTask.new do |task|
90
+ task.include_pattern = File.expand_path("fixtures/valid.js", File.dirname(__FILE__))
91
+ task.output_stream = StringIO.new(result, "w+")
92
+ end
93
+
94
+ Rake.application.lookup("lint").invoke
95
+
96
+ assert_equal erb_fixture("cli-valid-expected-output"), result
97
+ end
98
+
99
+ def test_invalid_output
100
+ result = String.new
101
+
102
+ task = JSLintV8::RakeTask.new do |task|
103
+ task.include_pattern = File.expand_path("fixtures/invalid.js", File.dirname(__FILE__))
104
+ task.output_stream = StringIO.new(result, "w+")
105
+ end
106
+
107
+ assert_raise RuntimeError do
108
+ Rake.application.lookup("lint").invoke
109
+ end
110
+
111
+ assert_equal erb_fixture("cli-invalid-expected-output"), result
112
+ end
113
+
114
+ def test_suite_output
115
+ result = String.new
116
+
117
+ task = JSLintV8::RakeTask.new do |task|
118
+ task.include_pattern = File.expand_path("fixtures/*.js", File.dirname(__FILE__))
119
+ task.output_stream = StringIO.new(result, "w+")
120
+ end
121
+
122
+ Rake.application.lookup("lint").invoke rescue # exception raised because of failing suite
123
+
124
+ assert_equal erb_fixture("cli-suite-expected-output"), result
125
+ end
126
+ end