jruby-lint 0.4.1 → 0.9.0

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.
Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +2 -1
  3. data/README.md +2 -8
  4. data/jruby-lint.gemspec +2 -3
  5. data/lib/jruby/lint/ast.rb +1 -1
  6. data/lib/jruby/lint/checkers.rb +18 -1
  7. data/lib/jruby/lint/checkers/fork_exec.rb +22 -39
  8. data/lib/jruby/lint/checkers/gem.rb +44 -30
  9. data/lib/jruby/lint/checkers/gemspec.rb +4 -4
  10. data/lib/jruby/lint/checkers/nonatomic.rb +38 -8
  11. data/lib/jruby/lint/checkers/object_space.rb +8 -6
  12. data/lib/jruby/lint/checkers/system.rb +4 -4
  13. data/lib/jruby/lint/checkers/thread_critical.rb +4 -4
  14. data/lib/jruby/lint/cli.rb +8 -1
  15. data/lib/jruby/lint/collectors.rb +18 -7
  16. data/lib/jruby/lint/finding.rb +1 -1
  17. data/lib/jruby/lint/libraries.rb +21 -30
  18. data/lib/jruby/lint/project.rb +3 -3
  19. data/lib/jruby/lint/reporters/html.rb +4 -3
  20. data/lib/jruby/lint/reporters/jruby-lint.html.erb +10 -1
  21. data/lib/jruby/lint/reporters/text.rb +5 -4
  22. data/lib/jruby/lint/version.rb +1 -1
  23. data/spec/fixtures/C-Extension-Alternatives.md +81 -0
  24. data/spec/jruby/lint/ast_spec.rb +6 -6
  25. data/spec/jruby/lint/checkers_spec.rb +91 -62
  26. data/spec/jruby/lint/collectors_spec.rb +3 -9
  27. data/spec/jruby/lint/finding_spec.rb +10 -10
  28. data/spec/jruby/lint/libraries_spec.rb +13 -13
  29. data/spec/jruby/lint/project_spec.rb +34 -40
  30. data/spec/jruby/lint/reporters_spec.rb +22 -13
  31. data/spec/jruby/lint/version_spec.rb +1 -1
  32. data/spec/spec_helper.rb +1 -1
  33. metadata +30 -96
  34. data/lib/jruby/lint/checkers/timeout.rb +0 -21
  35. data/lib/jruby/lint/github.crt +0 -23
  36. data/spec/fixtures/C-Extension-Alternatives.html +0 -339
  37. data/spec/jruby/lint/cli_spec.rb +0 -73
@@ -38,6 +38,10 @@ module JRuby
38
38
  @options.ansi = true
39
39
  end
40
40
 
41
+ opts.on('--no-source-line', 'do not print out line of source') do
42
+ @options.no_src_line = true
43
+ end
44
+
41
45
  opts.on('--html [REPORT_FILE]', 'print report as html file') do |file|
42
46
  @options.html = file || 'jruby-lint.html'
43
47
  end
@@ -55,6 +59,9 @@ module JRuby
55
59
  end.parse!(args)
56
60
 
57
61
  @options.files = args.empty? ? nil : args
62
+ rescue OptionParser::InvalidOption
63
+ puts $!.message
64
+ exit -1
58
65
  end
59
66
 
60
67
  def run
@@ -71,7 +78,7 @@ module JRuby
71
78
  puts "OK"
72
79
  exit
73
80
  else
74
- puts "Found #{project.findings.size} items"
81
+ puts "Found #{project.findings.count { |e| !e.tags.include? "internal" } } items"
75
82
  exit 1
76
83
  end
77
84
  end
@@ -1,16 +1,25 @@
1
1
  module JRuby::Lint
2
2
  class Collector
3
- attr_accessor :checkers, :findings, :project, :contents, :file
3
+ attr_accessor :checkers, :findings, :project, :contents, :file, :stack
4
4
 
5
5
  def initialize(project = nil, file = nil)
6
6
  @checkers = Checker.loaded_checkers.map(&:new)
7
7
  @checkers.each {|c| c.collector = self }
8
8
  @findings = []
9
9
  @project, @file = project, file || '<inline-script>'
10
+
11
+ # top to bottom list of elements as they are visited
12
+ @stack = [] # FIXME: ast visiting is not something checkers can see so stored here for now
13
+ end
14
+
15
+ def add_finding(message, tags, line=nil)
16
+ src_line = line ? contents.split(/\n/)[line-1] : nil
17
+ @findings << Finding.new(message, tags, file, line, src_line)
10
18
  end
11
19
 
12
20
  class CheckersVisitor < AST::Visitor
13
- attr_reader :collector, :checkers
21
+ attr_reader :collector, :checkers, :stack
22
+
14
23
 
15
24
  def initialize(ast, collector, checkers)
16
25
  super(ast)
@@ -18,6 +27,7 @@ module JRuby::Lint
18
27
  end
19
28
 
20
29
  def visit(method, node)
30
+ @collector.stack.push node
21
31
  after_hooks = []
22
32
  checkers.each do |ch|
23
33
  begin
@@ -26,19 +36,20 @@ module JRuby::Lint
26
36
  after_hooks << res if res.respond_to?(:call)
27
37
  end
28
38
  rescue Exception => e
29
- collector.findings << Finding.new("Exception while traversing: #{e.message}\n at #{e.backtrace.first}",
30
- [:internal, :debug], node.position)
39
+ collector.add_finding("Exception while traversing: #{e.message}\n at #{e.backtrace.first}",
40
+ [:internal, :debug], node.line+1)
31
41
  end
32
42
  end
33
43
  super
34
44
  rescue Exception => e
35
- collector.findings << Finding.new("Exception while traversing: #{e.message}\n at #{e.backtrace.first}",
36
- [:internal, :debug], node.position)
45
+ collector.add_finding("Exception while traversing: #{e.message}\n at #{e.backtrace.first}",
46
+ [:internal, :debug], node.line+1)
37
47
  ensure
38
48
  begin
39
49
  after_hooks.each {|h| h.call }
40
50
  rescue
41
51
  end
52
+ @collector.stack.pop
42
53
  end
43
54
  end
44
55
 
@@ -47,7 +58,7 @@ module JRuby::Lint
47
58
  CheckersVisitor.new(ast, self, checkers).traverse
48
59
  rescue SyntaxError => e
49
60
  file, line, message = e.message.split(/:\s*/, 3)
50
- findings << Finding.new(message, [:syntax, :error], file, line)
61
+ add_finding(message, [:syntax, :error], line.to_i)
51
62
  end
52
63
  end
53
64
 
@@ -1,5 +1,5 @@
1
1
  module JRuby::Lint
2
- class Finding < Struct.new(:message, :tags, :file, :line)
2
+ class Finding < Struct.new(:message, :tags, :file, :line, :src_line)
3
3
  def initialize(*args)
4
4
  args[1].map! {|x| x.to_s } if args.size > 1
5
5
  if args.size > 2 && args[2].respond_to?(:file) && args[2].respond_to?(:line)
@@ -1,5 +1,4 @@
1
1
  require 'net/https'
2
- require 'nokogiri'
3
2
  require 'tempfile'
4
3
  require 'fileutils'
5
4
 
@@ -27,7 +26,7 @@ module JRuby::Lint
27
26
 
28
27
  def filename_for(name)
29
28
  name = File.basename(name)
30
- File.join(@cache_dir, File.extname(name).empty? ? "#{name}.html" : name)
29
+ File.join(@cache_dir, File.extname(name).empty? ? "#{name}.md" : name)
31
30
  end
32
31
 
33
32
  def stale?(filename)
@@ -35,28 +34,10 @@ module JRuby::Lint
35
34
  end
36
35
 
37
36
  def read_from_wiki(name, filename)
38
- content = nil
39
- uri = Net::HTTP.start('wiki.jruby.org', 80) do |http|
40
- URI.parse http.head(name =~ %r{^/} ? name : "/#{name}")['Location']
41
- end
42
- if uri.host == "github.com"
43
- Net::HTTP.new(uri.host, uri.port).tap do |http|
44
- if uri.scheme == "https"
45
- http.use_ssl = true
46
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
47
- # gd_bundle.crt from https://certs.godaddy.com/anonymous/repository.seam
48
- http.ca_file = File.expand_path('../github.crt', __FILE__)
49
- end
50
- http.start do
51
- response = http.get(uri.path)
52
- content = response.body
53
- File.open(filename, "w") do |f|
54
- f << content
55
- end
56
- end
57
- end
58
- end
59
- raise "Unknown location '#{uri}' for page '#{name}'" unless content
37
+ require 'open-uri'
38
+ download = open('https://github.com/jruby/jruby/wiki/C-Extension-Alternatives.md')
39
+ content = download.read(nil)
40
+ File.open(filename, "w") { |f| f << content }
60
41
  content
61
42
  rescue => e
62
43
  raise "Error while reading from wiki: #{e.message}\nPlease try again later."
@@ -72,11 +53,21 @@ module JRuby::Lint
72
53
 
73
54
  def load
74
55
  @gems = {}
75
- content = @cache.fetch('C-Extension-Alternatives')
76
- doc = Nokogiri::HTML(content)
77
- doc.css('#wiki-body ul li').each do |li|
78
- key, message = li.text.split(/[ -]+/, 2)
79
- @gems[key.downcase] = message
56
+ content = @cache.fetch('C-Extension-Alternatives.md')
57
+
58
+ in_suggestions = false
59
+ content.split("\n").each do |line|
60
+ if line =~ /<!-- suggestions start/
61
+ in_suggestions = true
62
+ elsif !in_suggestions
63
+ next
64
+ elsif line =~ /<!-- suggestions end/
65
+ in_suggestions = false
66
+ break
67
+ else
68
+ _, key, value = line.gsub(/[\[\]]/, '').split("|", 3)
69
+ @gems[key.downcase] = value
70
+ end
80
71
  end
81
72
  rescue => e
82
73
  @error = "Unable to load C Extension alternatives list: #{e.message}"
@@ -85,7 +76,7 @@ module JRuby::Lint
85
76
 
86
77
  SOURCES = [CExtensions]
87
78
 
88
- attr_reader :gems
79
+ attr_accessor :gems
89
80
 
90
81
  def initialize(cache)
91
82
  @sources = SOURCES.map {|s| s.new(cache) }
@@ -52,9 +52,9 @@ module JRuby::Lint
52
52
 
53
53
  def load_reporters(options)
54
54
  @reporters = []
55
- @reporters << Reporters::Html.new(self, options.html) if options.html
56
- @reporters << Reporters::ANSIColor.new(self, STDOUT) if options.ansi || STDOUT.tty?
57
- @reporters << Reporters::Text.new(self, STDOUT) if options.text || @reporters.empty?
55
+ @reporters << Reporters::Html.new(self, options.html, options) if options.html
56
+ @reporters << Reporters::ANSIColor.new(self, STDOUT, options) if options.ansi || STDOUT.tty?
57
+ @reporters << Reporters::Text.new(self, STDOUT, options) if options.text || @reporters.empty?
58
58
  end
59
59
 
60
60
  def load_libraries
@@ -1,11 +1,12 @@
1
+ require 'ostruct'
2
+
1
3
  module JRuby::Lint
2
4
  module Reporters
3
5
  class Html
4
6
  require 'erb'
5
7
 
6
- def initialize(project, output)
7
- @tags = project.tags
8
- @output = output
8
+ def initialize(project, output, options=OpenStruct.new)
9
+ @tags, @output, @options = project.tags, output, options
9
10
  @template = ERB.new(File.read(File.expand_path('../jruby-lint.html.erb', __FILE__)))
10
11
  end
11
12
 
@@ -29,10 +29,19 @@ nav { position: relative; }
29
29
  <% @findings.each do |finding| %>
30
30
  <% if finding.error? %>
31
31
  <li class="error"><%= finding %></li>
32
- <% elsif finding.warning? %>
32
+ <% if finding.src_line && !@options.no_src_line%>
33
+ <pre><%= finding.src_line %></pre>
34
+ <% end %>
35
+ <% elsif finding.warning? %>
33
36
  <li class="warning"><%= finding %></li>
37
+ <% if finding.src_line && !@options.no_src_line%>
38
+ <pre><%= finding.src_line %></pre>
39
+ <% end %>
34
40
  <% else %>
35
41
  <li class="message"><%= finding %></li>
42
+ <% if finding.src_line && !@options.no_src_line%>
43
+ <pre><%= finding.src_line %></pre>
44
+ <% end %>
36
45
  <% end %>
37
46
  <% end %>
38
47
  </ul>
@@ -1,8 +1,8 @@
1
1
  module JRuby::Lint
2
2
  module Reporters
3
3
  class Text
4
- def initialize(project, output)
5
- @tags, @output = project.tags, output
4
+ def initialize(project, output, options=OpenStruct.new)
5
+ @tags, @output, @options = project.tags, output, options
6
6
  end
7
7
 
8
8
  def report(findings)
@@ -23,11 +23,12 @@ module JRuby::Lint
23
23
  msg = if finding.error?
24
24
  red(finding.to_s)
25
25
  elsif finding.warning?
26
- yellow(finding.to_s)
26
+ cyan(finding.to_s)
27
27
  else
28
- finding.to_s
28
+ blue(finding.to_s)
29
29
  end
30
30
  @output.puts msg
31
+ @output.puts finding.src_line if finding.src_line && !@options.no_src_line
31
32
  end
32
33
  end
33
34
  end
@@ -1,5 +1,5 @@
1
1
  module JRuby
2
2
  module Lint
3
- VERSION = "0.4.1"
3
+ VERSION = "0.9.0"
4
4
  end
5
5
  end
@@ -0,0 +1,81 @@
1
+ JRuby does not support native C extensions, but it does have it's own Java native extensions API. Several gems have implementations of both Java and C extensions rolled into the same gem and those will not be listed here since they will just work. In some cases there is a JRuby version with a slightly different name or possibly even a totally different name and we list these here so you can update your Gemfile:
2
+
3
+ ```ruby
4
+ gem 'therubyracer', platform: :mri
5
+ gem 'therubyrhino', platform: :jruby
6
+ ```
7
+
8
+ When there is not an exact match some gems come close enough where a little work on your part can make your application compatible with JRuby.
9
+
10
+ This page lists common C extensions and JRuby-friendly alternatives you can use to replace them.
11
+
12
+ If you are interested in helping us port an extension to JRuby, this article is helpful: [Your first Ruby native extension: Java](https://blog.jcoglan.com/2012/08/02/your-first-ruby-native-extension-java/) see also [JRuby examples](https://github.com/jruby/jruby-examples) for a maven build.
13
+
14
+ <!-- suggestions start -->
15
+ | Gem | Suggestions |
16
+ |-----|-------------|
17
+ |[RDiscount][]|Use [kramdown][], [Maruku][] (pure Ruby) or [markdown_j][] (wrapper around a Java library)|
18
+ |[RedCarpet][]|Same as with **RDiscount** use alternatives such as [kramdown][], [Maruku][] or [markdown_j][]|
19
+ |[RMagick][]|Try [RMagick4J][] (implements ImageMagick functionality in Java) or preferably use alternatives [mini_magick][] & [quick_magick][]. For simple resizing, cropping, greyscaling, etc look at [image_voodoo][]. You can also use Java's Graphics2D.|
20
+ |[Unicorn][]| Use [Puma][].|
21
+ |[Thin][]| Use [Puma][].|
22
+ |mysql|Use [activerecord-jdbcmysql-adapter][].|
23
+ |mysql2|Use [activerecord-jdbcmysql-adapter][].|
24
+ |sqlite3|Use [activerecord-jdbcsqlite3-adapter][].|
25
+ |pg|Use [activerecord-jdbcpostgresql-adapter][] instead or [pg_jruby][] (drop-in replacement).|
26
+ |[yajl-ruby][]|Try `json` or `json_pure` instead. Unfortunately there is no known equivalent JSON stream parser.|
27
+ |[oj][]|Try `gson`, `json` or `json_pure` instead.|
28
+ |[bson_ext][]|`bson_ext` isn't used with JRuby. Instead, some native Java extensions are bundled with the `bson` gem.|
29
+ |[win32ole][]|Use the `jruby-win32ole` gem (preinstalled in JRuby's Windows installer).|
30
+ |[curb][]|[Rurl][] is an example how to implement _some_ of curb's functionality using [Apache HttpClient][]|
31
+ |[therubyracer][]|Try using [therubyrhino][] instead (or [dienashorner][] on Java 8+).|
32
+ |[kyotocabinet][]|Try using [kyotocabinet-java][] instead. This isn't 100% complete yet, but it covers most of the API.|
33
+ |[memcached][]|Try using [jruby-memcached][] instead. Alternatively you can use [jruby-ehcache][], a JRuby interface to Java's (JSR-107 compliant) Ehcache.|
34
+ |[charlock_holmes][]|Use [charlock_holmes-jruby][] instead.|
35
+ <!-- suggestions end -->
36
+
37
+ Please add to this list with your findings.
38
+
39
+ *Note that the [JRuby-Lint][] gem parses the contents of the list above to use for its Ruby gem checker. In order for JRuby-Lint to use the information, please adhere to the table format above and the links to projects below (in the source for this page).
40
+
41
+ <!-- links start -->
42
+ [RDiscount]: http://dafoster.net/projects/rdiscount/
43
+ [RedCarpet]: https://github.com/vmg/redcarpet
44
+ [kramdown]: https://github.com/gettalong/kramdown
45
+ [Maruku]:https://github.com/bhollis/maruku
46
+ [markdown_j]: https://github.com/nate/markdown_j
47
+ [RMagick]: https://github.com/rmagick/rmagick
48
+ [RMagick4J]: https://github.com/Serabe/RMagick4J
49
+ [mini_magick]: https://github.com/minimagick/minimagick
50
+ [quick_magick]: https://github.com/aseldawy/quick_magick
51
+ [image_voodoo]: https://github.com/jruby/image_voodoo
52
+ [Unicorn]: http://unicorn.bogomips.org/
53
+ [Puma]: http://puma.io/
54
+ [Thin]: http://code.macournoyer.com/thin/
55
+ [Typhoeus]: https://github.com/dbalatero/typhoeus
56
+ [activerecord-jdbc-adapter]: https://github.com/jruby/activerecord-jdbc-adapter
57
+ [JRuby-Lint]: https://github.com/jruby/jruby-lint
58
+ [Nokogiri]: http://nokogiri.org/
59
+ [yajl-ruby]: https://github.com/brianmario/yajl-ruby
60
+ [bson_ext]: https://github.com/mongodb/mongo-ruby-driver
61
+ [Apache HttpClient]: http://hc.apache.org/httpcomponents-client-ga/
62
+ [HttpURLConnection]: http://download.oracle.com/javase/1,5.0/docs/api/java/net/HttpURLConnection.html
63
+ [win32ole]: http://www.ruby-doc.org/stdlib/libdoc/win32ole/rdoc/index.html
64
+ [Rurl]: https://github.com/rcyrus/Rurl
65
+ [curb]: https://github.com/taf2/curb
66
+ [therubyracer]: https://github.com/cowboyd/therubyracer
67
+ [therubyrhino]: https://github.com/cowboyd/therubyrhino
68
+ [dienashorner]: https://github.com/kares/dienashorner
69
+ [kyotocabinet]: http://fallabs.com/kyotocabinet/
70
+ [kyotocabinet-java]: https://github.com/csw/kyotocabinet-java
71
+ [memcached]: https://github.com/evan/memcached
72
+ [jruby-memcached]: https://github.com/aurorafeint/jruby-memcached
73
+ [jruby-ehcache]: https://github.com/dylanz/ehcache
74
+ [oj]: https://github.com/ohler55/oj
75
+ [activerecord-jdbcmysql-adapter]: https://rubygems.org/gems/activerecord-jdbcmysql-adapter
76
+ [activerecord-jdbcsqlite3-adapter]: https://rubygems.org/gems/activerecord-jdbcsqlite3-adapter
77
+ [activerecord-jdbcpostgresql-adapter]: https://rubygems.org/gems/activerecord-jdbcpostgresql-adapter
78
+ [pg_jruby]: https://rubygems.org/gems/pg_jruby
79
+ [charlock_holmes]: https://github.com/brianmario/charlock_holmes
80
+ [charlock_holmes-jruby]: https://github.com/siuying/charlock_holmes-jruby
81
+ <!-- links start -->
@@ -5,19 +5,19 @@ describe JRuby::Lint::AST::Visitor do
5
5
  Given(:visitor) { JRuby::Lint::AST::Visitor.new(ast) }
6
6
 
7
7
  # RootNode
8
- # NewlineNode
9
- # FCallOneArgNode |puts|
10
- # ArrayNode
11
- # StrNode =="hello"
8
+ # FCallOneArgNode |puts|
9
+ # ArrayNode
10
+ # StrNode =="hello"
12
11
  Given(:script) { %{puts "hello"} }
13
12
 
14
13
  context "visits all nodes" do
15
14
  When { visitor.each_node { @count ||= 0; @count += 1} }
16
- Then { @count.should == 5 }
15
+ Then { expect(@count).to eq(4) }
17
16
  end
18
17
 
19
18
  context "selects nodes" do
20
19
  When { @nodes = visitor.select {|n| n.node_type == org.jruby.ast.NodeType::STRNODE } }
21
- Then { @nodes.size.should == 1 && @nodes.first.value.to_s.should == "hello" }
20
+ Then { expect(@nodes.size).to(eq(1)) &&
21
+ expect(@nodes.first.value.to_s).to(eq("hello")) }
22
22
  end
23
23
  end
@@ -5,14 +5,14 @@ describe JRuby::Lint::Checker do
5
5
  subject { Class.new { include JRuby::Lint::Checker } }
6
6
 
7
7
  it "finds all loaded checkers" do
8
- JRuby::Lint::Checker.loaded_checkers.should include(subject)
8
+ expect(JRuby::Lint::Checker.loaded_checkers).to include(subject)
9
9
  end
10
10
  end
11
11
  end
12
12
 
13
13
  describe JRuby::Lint::Checkers do
14
14
  Given(:gems) { { "rdiscount" => "may not work", "bson_ext" => "not needed" } }
15
- Given(:project) { double("project").tap {|p| p.stub_chain("libraries.gems") { gems } } }
15
+ Given(:project) {JRuby::Lint::Project.new.tap {|p| p.libraries.gems = gems }}
16
16
  Given(:collector) do
17
17
  JRuby::Lint::Collector.new(project).tap do |c|
18
18
  c.contents = script
@@ -26,16 +26,16 @@ describe JRuby::Lint::Checkers do
26
26
 
27
27
  context "detects fcall-style" do
28
28
  # FCallNoArgBlockNode |fork|
29
- Given(:script) { "fork { }; exec('cmd')" }
29
+ Given(:script) { "fork { }" }
30
30
  When { collector.run }
31
- Then { collector.findings.size.should == 2 }
31
+ Then { expect(collector.findings.size).to eq(1) }
32
32
  end
33
33
 
34
34
  context "detects vcall-style" do
35
35
  # VCallNode |fork|
36
36
  Given(:script) { "fork" }
37
37
  When { collector.run }
38
- Then { collector.findings.size.should == 1 }
38
+ Then { expect(collector.findings.size).to eq(1) }
39
39
  end
40
40
 
41
41
  context "does not detect call-style" do
@@ -43,15 +43,15 @@ describe JRuby::Lint::Checkers do
43
43
  # VCallNode |fork|
44
44
  Given(:script) { "fork.fork" }
45
45
  When { collector.run }
46
- Then { collector.findings.size.should == 0 }
46
+ Then { expect(collector.findings.size).to eq(0) }
47
47
  end
48
48
 
49
49
  context "detects Kernel::fork style" do
50
50
  # CallNoArgNode |fork|
51
51
  # ConstNode |Kernel|
52
- Given(:script) { "Kernel::fork; Kernel::exec('cmd')" }
52
+ Given(:script) { "Kernel::fork" }
53
53
  When { collector.run }
54
- Then { collector.findings.size.should == 2 }
54
+ Then { expect(collector.findings.size).to eq(1) }
55
55
  end
56
56
  end
57
57
 
@@ -61,25 +61,43 @@ describe JRuby::Lint::Checkers do
61
61
  context "creates a finding for a gem mentioned in the libraries" do
62
62
  Given(:script) { "gem 'rdiscount'" }
63
63
  When { collector.run }
64
- Then { collector.findings.size.should == 2 }
64
+ Then { expect(collector.findings.size).to eq(2) }
65
65
  end
66
66
 
67
67
  context "creates one finding to mention the wiki for gem compatibility" do
68
68
  Given(:script) { "gem 'rdiscount'; gem 'bson_ext'" }
69
69
  When { collector.run }
70
- Then { collector.findings.size.should == 3 }
70
+ Then { expect(collector.findings.size).to eq(3) }
71
+ end
72
+
73
+ context "ignores platform for gem compatibility if not right platform" do
74
+ Given(:script) { "gem 'rdiscount', platform: :ruby" }
75
+ When { collector.run }
76
+ Then { expect(collector.findings.size).to eq(0) }
77
+ end
78
+
79
+ context "creates a finding if platform for gem compatibility is ours" do
80
+ Given(:script) { "gem 'rdiscount', platform: :jruby" }
81
+ When { collector.run }
82
+ Then { expect(collector.findings.size).to eq(2) }
83
+ end
84
+
85
+ context "creates no finding if in wrong platform block" do
86
+ Given(:script) { "platforms :ruby { gem 'rdiscount' }" }
87
+ When { collector.run }
88
+ Then { expect(collector.findings.size).to eq(1) }
71
89
  end
72
90
 
73
91
  context "does not create a finding for a gem not mentioned in the gems info" do
74
92
  Given(:script) { "gem 'json_pure'" }
75
93
  When { collector.run }
76
- Then { collector.findings.size.should == 0 }
94
+ Then { expect(collector.findings.size).to eq(0) }
77
95
  end
78
96
 
79
97
  context "only checks calls to #gem" do
80
98
  Given(:script) { "require 'rdiscount'" }
81
99
  When { collector.run }
82
- Then { collector.findings.size.should == 0 }
100
+ Then { expect(collector.findings.size).to eq(0) }
83
101
  end
84
102
  end
85
103
 
@@ -91,8 +109,8 @@ describe JRuby::Lint::Checkers do
91
109
  "s.add_development_dependency 'ruby-debug19'\nend\n" }
92
110
 
93
111
  When { collector.run }
94
- Then { collector.findings.size.should == 2 }
95
- Then { collector.findings.detect{|f| f.message =~ /rdiscount/ }.should be_true }
112
+ Then { expect(collector.findings.size).to eq(2) }
113
+ Then { expect(collector.findings.detect{|f| f.message =~ /rdiscount/ }).to be_truthy }
96
114
  end
97
115
 
98
116
  context "Thread.critical checker" do
@@ -101,13 +119,13 @@ describe JRuby::Lint::Checkers do
101
119
  context "read" do
102
120
  Given(:script) { "begin \n Thread.critical \n end"}
103
121
  When { collector.run }
104
- Then { collector.findings.size.should == 1 }
122
+ Then { expect(collector.findings.size).to eq(1) }
105
123
  end
106
124
 
107
125
  context "assign" do
108
126
  Given(:script) { "begin \n Thread.critical = true \n ensure Thread.critical = false \n end"}
109
127
  When { collector.run }
110
- Then { collector.findings.size.should == 2 }
128
+ Then { expect(collector.findings.size).to eq(2) }
111
129
  end
112
130
  end
113
131
 
@@ -117,70 +135,53 @@ describe JRuby::Lint::Checkers do
117
135
  context "_id2ref usage" do
118
136
  Given(:script) { "ObjectSpace._id2ref(obj)"}
119
137
  When { collector.run }
120
- Then { collector.findings.size.should == 1 }
138
+ Then { expect(collector.findings.size).to eq(1) }
121
139
  end
122
140
 
123
141
  context "each_object usage" do
124
142
  Given(:script) { "ObjectSpace.each_object { }"}
125
143
  When { collector.run }
126
- Then { collector.findings.size.should == 1 }
144
+ Then { expect(collector.findings.size).to eq(1) }
127
145
  end
128
146
 
129
147
  context "each_object(Class) usage is ok" do
130
148
  Given(:script) { "ObjectSpace.each_object(Class) { }"}
131
149
  When { collector.run }
132
- Then { collector.findings.size.should == 0 }
150
+ Then { collector.findings; expect(collector.findings.size).to eq(0) }
133
151
  end
134
152
  end
135
153
 
136
- context "Timeout::timeout" do
137
- Given(:checker) { JRuby::Lint::Checkers::Timeout.new }
138
-
139
- context "::timeout usage" do
140
- Given(:script) { "Timeout::timeout(5) { sleep 10 }"}
141
- When { collector.run }
142
- Then { collector.findings.size.should == 1}
143
- end
144
-
145
- context ".timeout usage" do
146
- Given(:script) { "Timeout.timeout(5) { sleep 10 }" }
147
- When { collector.run }
148
- Then { collector.findings.size.should == 1}
149
- end
150
- end
151
-
152
-
153
154
  context "System" do
154
155
  Given(:checker) { JRuby::Lint::Checkers::System.new }
155
156
 
156
157
  context "calling ruby -v in system" do
157
158
  Given(:script) { "system('echo'); system('/usr/bin/ruby -v')"}
158
159
  When { collector.run }
159
- Then { collector.findings.size.should == 1}
160
+ Then { expect(collector.findings.size).to eq(1) }
160
161
  end
161
162
 
162
163
  context "calling ruby in the first argument to system" do
163
164
  Given(:script) { "system('/usr/bin/ruby', '-v')"}
164
165
  When { collector.run }
165
- Then { collector.findings.size.should == 1}
166
+ Then { expect(collector.findings.size).to eq(1) }
166
167
  end
167
168
 
168
169
  context "calling irb or jirb from system" do
169
170
  Given(:script) { "system('jirb'); system('irb')"}
170
171
  When { collector.run }
171
- Then { collector.findings.size.should == 2 }
172
+ Then { expect(collector.findings.size).to eq(2) }
172
173
  end
173
174
 
174
175
  context "calling a .rb file from system" do
175
176
  Given(:script) { "system('asdf.rb')" }
176
177
  When { collector.run }
177
- Then { collector.findings.size.should == 1 }
178
+ Then { expect(collector.findings.size).to eq(1) }
178
179
  end
179
180
 
180
181
  context "calling ruby -v in Kernel.system should have a finding" do
181
182
  Given(:script) { "Kernel.system('ruby -v'); Kernel.system('echo \"zomg\"')"}
182
183
  When { collector.run }
183
- Then { collector.findings.size.should == 1}
184
+ Then { expect(collector.findings.size).to eq(1) }
184
185
  end
185
186
 
186
187
  end
@@ -191,75 +192,103 @@ describe JRuby::Lint::Checkers do
191
192
  context "class variable or-assignment" do
192
193
  Given(:script) { "@@foo ||= 1" }
193
194
  When { collector.run }
194
- Then { collector.findings.size.should == 1 }
195
+ Then { expect(collector.findings.size).to eq(1) }
195
196
  end
196
197
 
197
198
  context "instance variable or-assignment" do
198
199
  Given(:script) { "@foo ||= 1" }
199
200
  When { collector.run }
200
- Then { collector.findings.size.should == 1 }
201
+ Then { expect(collector.findings.size).to eq(1) }
202
+ Then { expect(collector.findings.first.message).to be =~ /\(@foo\)/ }
201
203
  end
202
204
 
203
205
  context "attribute or-assignment" do
204
206
  Given(:script) { "foo.bar ||= 1" }
205
207
  When { collector.run }
206
- Then { collector.findings.size.should == 1 }
208
+ Then { expect(collector.findings.size).to eq(1) }
209
+ Then { expect(collector.findings.first.message).to be =~ /\(bar\)/ }
207
210
  end
208
211
 
209
212
  context "element or-assignment" do
210
213
  Given(:script) { "foo[bar] ||= 1" }
211
214
  When { collector.run }
212
- Then { collector.findings.size.should == 1 }
215
+ Then { expect(collector.findings.size).to eq(1) }
216
+ Then { expect(collector.findings.first.message).to be =~ /\(foo\[bar\]\)/ }
213
217
  end
214
218
 
215
219
  context "class variable and-assignment" do
216
220
  Given(:script) { "@@foo &&= 1" }
217
221
  When { collector.run }
218
- Then { collector.findings.size.should == 1 }
222
+ Then { expect(collector.findings.size).to eq(1) }
223
+ Then { expect(collector.findings.first.message).to be =~ /\(@@foo\)/ }
219
224
  end
220
225
 
221
226
  context "instance variable and-assignment" do
222
227
  Given(:script) { "@foo &&= 1" }
223
228
  When { collector.run }
224
- Then { collector.findings.size.should == 1 }
229
+ Then { expect(collector.findings.size).to eq(1) }
230
+ Then { expect(collector.findings.first.message).to be =~ /\(@foo\)/ }
225
231
  end
226
232
 
227
233
  context "attribute and-assignment" do
228
234
  Given(:script) { "foo.bar &&= 1" }
229
235
  When { collector.run }
230
- Then { collector.findings.size.should == 1 }
236
+ Then { expect(collector.findings.size).to eq(1) }
237
+ Then { expect(collector.findings.first.message).to be =~ /\(bar\)/ }
231
238
  end
232
239
 
233
240
  context "element and-assignment" do
234
241
  Given(:script) { "foo[bar] &&= 1" }
235
242
  When { collector.run }
236
- Then { collector.findings.size.should == 1 }
243
+ Then { expect(collector.findings.size).to eq(1) }
244
+ Then { expect(collector.findings.first.message).to be =~ /\(foo\[bar\]\)/ }
237
245
  end
238
246
 
239
- pending "needs better representation in AST" do
240
- context "class variable op-assignment" do
241
- Given(:script) { "@@foo += 1" }
242
- When { collector.run }
243
- Then { collector.findings.size.should == 1 }
244
- end
247
+ context "element and-assignment (complicated name)" do
248
+ Given(:script) { "foo[bar(2, heh)] &&= 1" }
249
+ When { collector.run }
250
+ Then { expect(collector.findings.size).to eq(1) }
251
+ Then { expect(collector.findings.first.message).to be =~ /\(foo\[bar\(2, heh\)\]\)/ }
252
+ end
253
+
254
+ context "class variable op-assignment" do
255
+ Given(:script) { "@@foo += 1" }
256
+ When { collector.run }
257
+ Then { expect(collector.findings.size).to eq(1) }
258
+ Then { expect(collector.findings.first.message).to be =~ /\(@@foo\)/ }
259
+ end
245
260
 
246
- context "instance variable op-assignment" do
247
- Given(:script) { "@foo += 1" }
248
- When { collector.run }
249
- Then { collector.findings.size.should == 1 }
250
- end
261
+ context "instance variable op-assignment" do
262
+ Given(:script) { "@foo += 1" }
263
+ When { collector.run }
264
+ Then { expect(collector.findings.size).to eq(1) }
265
+ Then { expect(collector.findings.first.message).to be =~ /\(@foo\)/ }
251
266
  end
252
267
 
253
268
  context "attribute op-assignment" do
254
269
  Given(:script) { "foo.bar += 1" }
255
270
  When { collector.run }
256
- Then { collector.findings.size.should == 1 }
271
+ Then { expect(collector.findings.size).to eq(1) }
272
+ Then { expect(collector.findings.first.message).to be =~ /\(bar\)/ }
257
273
  end
258
274
 
259
275
  context "element op-assignment" do
260
276
  Given(:script) { "foo[bar] += 1" }
261
277
  When { collector.run }
262
- Then { collector.findings.size.should == 1 }
278
+ Then { expect(collector.findings.size).to eq(1) }
279
+ Then { expect(collector.findings.first.message).to be =~ /\(foo\[bar\]\)/ }
280
+ end
281
+
282
+ context "ignores simple inst assignment" do
283
+ Given(:script) { "@foo = 1" }
284
+ When { collector.run }
285
+ Then { expect(collector.findings.size).to eq(0) }
286
+ end
287
+
288
+ context "ignores simple cvar assignment" do
289
+ Given(:script) { "@@foo = 1" }
290
+ When { collector.run }
291
+ Then { expect(collector.findings.size).to eq(0) }
263
292
  end
264
293
  end
265
294
  end