jruby-lint 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +12 -0
- data/Guardfile +12 -0
- data/History.txt +4 -0
- data/README.md +62 -0
- data/Rakefile +24 -0
- data/bin/jrlint +5 -0
- data/jruby-lint.gemspec +38 -0
- data/lib/jruby/lint.rb +19 -0
- data/lib/jruby/lint/ast.rb +56 -0
- data/lib/jruby/lint/checkers.rb +24 -0
- data/lib/jruby/lint/checkers/fork_exec.rb +47 -0
- data/lib/jruby/lint/checkers/gem.rb +45 -0
- data/lib/jruby/lint/checkers/gemspec.rb +41 -0
- data/lib/jruby/lint/checkers/object_space.rb +25 -0
- data/lib/jruby/lint/checkers/thread_critical.rb +26 -0
- data/lib/jruby/lint/cli.rb +61 -0
- data/lib/jruby/lint/collectors.rb +75 -0
- data/lib/jruby/lint/collectors/bundler.rb +9 -0
- data/lib/jruby/lint/collectors/gemspec.rb +9 -0
- data/lib/jruby/lint/collectors/rake.rb +9 -0
- data/lib/jruby/lint/collectors/ruby.rb +14 -0
- data/lib/jruby/lint/finding.rb +15 -0
- data/lib/jruby/lint/github.crt +76 -0
- data/lib/jruby/lint/libraries.rb +107 -0
- data/lib/jruby/lint/project.rb +56 -0
- data/lib/jruby/lint/reporters.rb +35 -0
- data/lib/jruby/lint/version.rb +5 -0
- data/spec/fixtures/C-Extension-Alternatives.html +557 -0
- data/spec/jruby/lint/ast_spec.rb +23 -0
- data/spec/jruby/lint/checkers_spec.rb +135 -0
- data/spec/jruby/lint/cli_spec.rb +66 -0
- data/spec/jruby/lint/collectors_spec.rb +34 -0
- data/spec/jruby/lint/finding_spec.rb +31 -0
- data/spec/jruby/lint/libraries_spec.rb +56 -0
- data/spec/jruby/lint/project_spec.rb +77 -0
- data/spec/jruby/lint/reporters_spec.rb +42 -0
- data/spec/jruby/lint/version_spec.rb +6 -0
- data/spec/spec_helper.rb +30 -0
- metadata +194 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
module JRuby::Lint
|
2
|
+
module Checkers
|
3
|
+
class ThreadCritical
|
4
|
+
include Checker
|
5
|
+
|
6
|
+
METHODS = %w(critical critical=)
|
7
|
+
|
8
|
+
def visitCallNode(node)
|
9
|
+
if METHODS.include?(node.name)
|
10
|
+
begin
|
11
|
+
if node.receiver_node.node_type.to_s == "CONSTNODE" && node.receiver_node.name == "Thread"
|
12
|
+
add_finding(collector, node)
|
13
|
+
end
|
14
|
+
rescue
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
alias visitAttrAssignNode visitCallNode
|
19
|
+
|
20
|
+
def add_finding(collector, node)
|
21
|
+
collector.findings << Finding.new("Use of Thread.critical is discouraged. Use a Mutex instead.",
|
22
|
+
[:threads, :warning], node.position)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module JRuby
|
2
|
+
module Lint
|
3
|
+
class CLI
|
4
|
+
def initialize(args)
|
5
|
+
process_options(args)
|
6
|
+
end
|
7
|
+
|
8
|
+
def process_options(args)
|
9
|
+
require 'optparse'
|
10
|
+
require 'ostruct'
|
11
|
+
@options = OpenStruct.new
|
12
|
+
OptionParser.new do |opts|
|
13
|
+
opts.banner = "Usage: jrlint [options] [files]"
|
14
|
+
opts.separator ""
|
15
|
+
opts.separator "Options:"
|
16
|
+
|
17
|
+
opts.on('-C', '--chdir DIRECTORY', "Change working directory") do |v|
|
18
|
+
Dir.chdir(v)
|
19
|
+
end
|
20
|
+
|
21
|
+
opts.on("-e", '--eval SCRIPT', "Lint an inline script") do |v|
|
22
|
+
@options.eval ||= []
|
23
|
+
@options.eval << v
|
24
|
+
end
|
25
|
+
|
26
|
+
opts.on_tail("-v", "--version", "Print version and exit") do
|
27
|
+
require 'jruby/lint/version'
|
28
|
+
puts "JRuby-Lint version #{VERSION}"
|
29
|
+
exit
|
30
|
+
end
|
31
|
+
|
32
|
+
opts.on_tail("-h", "--help", "This message") do
|
33
|
+
puts opts
|
34
|
+
exit
|
35
|
+
end
|
36
|
+
end.parse!(args)
|
37
|
+
|
38
|
+
@options.files = args.empty? ? nil : args
|
39
|
+
end
|
40
|
+
|
41
|
+
def run
|
42
|
+
require 'jruby/lint'
|
43
|
+
require 'benchmark'
|
44
|
+
project = JRuby::Lint::Project.new(@options)
|
45
|
+
|
46
|
+
puts "JRuby-Lint version #{JRuby::Lint::VERSION}"
|
47
|
+
time = Benchmark.realtime { project.run }
|
48
|
+
term = @options.eval ? 'expression' : 'file'
|
49
|
+
puts "Processed #{project.files.size} #{term}#{project.files.size == 1 ? '' : 's'} in #{'%0.02f' % time} seconds"
|
50
|
+
|
51
|
+
if project.findings.empty?
|
52
|
+
puts "OK"
|
53
|
+
exit
|
54
|
+
else
|
55
|
+
puts "Found #{project.findings.size} items"
|
56
|
+
exit 1
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module JRuby::Lint
|
2
|
+
class Collector
|
3
|
+
attr_accessor :checkers, :findings, :project, :contents, :file
|
4
|
+
|
5
|
+
def initialize(project = nil, file = nil)
|
6
|
+
@checkers = Checker.loaded_checkers.map(&:new)
|
7
|
+
@checkers.each {|c| c.collector = self }
|
8
|
+
@findings = []
|
9
|
+
@project, @file = project, file || '<inline-script>'
|
10
|
+
end
|
11
|
+
|
12
|
+
class CheckersVisitor < AST::Visitor
|
13
|
+
attr_reader :checkers
|
14
|
+
|
15
|
+
def initialize(ast, checkers)
|
16
|
+
super(ast)
|
17
|
+
@checkers = checkers
|
18
|
+
end
|
19
|
+
|
20
|
+
def visit(method, node)
|
21
|
+
after_hooks = []
|
22
|
+
checkers.each do |ch|
|
23
|
+
begin
|
24
|
+
if ch.respond_to?(method)
|
25
|
+
res = ch.send(method, node)
|
26
|
+
after_hooks << res if res.respond_to?(:call)
|
27
|
+
end
|
28
|
+
rescue => e
|
29
|
+
ch.collector.findings << Finding.new("Exception while traversing: #{e.message}",
|
30
|
+
[:internal, :debug], node.position)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
super
|
34
|
+
ensure
|
35
|
+
begin
|
36
|
+
after_hooks.each {|h| h.call }
|
37
|
+
rescue
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def run
|
43
|
+
begin
|
44
|
+
CheckersVisitor.new(ast, checkers).traverse
|
45
|
+
rescue SyntaxError => e
|
46
|
+
file, line, message = e.message.split(/:\s*/, 3)
|
47
|
+
findings << Finding.new(message, [:syntax, :error], file, line)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def ast
|
52
|
+
@ast ||= JRuby.parse(contents, file, true)
|
53
|
+
end
|
54
|
+
|
55
|
+
def contents
|
56
|
+
@contents || File.read(@file)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.inherited(base)
|
60
|
+
self.all << base
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.all
|
64
|
+
@collectors ||= []
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
module Collectors
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
require 'jruby/lint/collectors/ruby'
|
73
|
+
require 'jruby/lint/collectors/bundler'
|
74
|
+
require 'jruby/lint/collectors/rake'
|
75
|
+
require 'jruby/lint/collectors/gemspec'
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module JRuby::Lint
|
2
|
+
class Finding < Struct.new(:message, :tags, :file, :line)
|
3
|
+
def initialize(*args)
|
4
|
+
args[1].map! {|x| x.to_s } if args.size > 1
|
5
|
+
if args.size > 2 && args[2].respond_to?(:file) && args[2].respond_to?(:line)
|
6
|
+
args = [args[0], args[1], args[2].file, (args[2].line + 1)]
|
7
|
+
end
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
"#{file}:#{line}: [#{tags.join(', ')}] #{message}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMx
|
3
|
+
ITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
|
4
|
+
RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMTYw
|
5
|
+
MTU0MzdaFw0yNjExMTYwMTU0MzdaMIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMH
|
6
|
+
QXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5j
|
7
|
+
b20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j
|
8
|
+
b20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmlj
|
9
|
+
YXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4NzCCASIwDQYJKoZIhvcN
|
10
|
+
AQEBBQADggEPADCCAQoCggEBAMQt1RWMnCZM7DI161+4WQFapmGBWTtwY6vj3D3H
|
11
|
+
KrjJM9N55DrtPDAjhI6zMBS2sofDPZVUBJ7fmd0LJR4h3mUpfjWoqVTr9vcyOdQm
|
12
|
+
VZWt7/v+WIbXnvQAjYwqDL1CBM6nPwT27oDyqu9SoWlm2r4arV3aLGbqGmu75RpR
|
13
|
+
SgAvSMeYddi5Kcju+GZtCpyz8/x4fKL4o/K1w/O5epHBp+YlLpyo7RJlbmr2EkRT
|
14
|
+
cDCVw5wrWCs9CHRK8r5RsL+H0EwnWGu1NcWdrxcx+AuP7q2BNgWJCJjPOq8lh8BJ
|
15
|
+
6qf9Z/dFjpfMFDniNoW1fho3/Rb2cRGadDAW/hOUoz+EDU8CAwEAAaOCATIwggEu
|
16
|
+
MB0GA1UdDgQWBBT9rGEyk2xF1uLuhV+auud2mWjM5zAfBgNVHSMEGDAWgBTSxLDS
|
17
|
+
kdRMEXGzYcs9of7dqGrU4zASBgNVHRMBAf8ECDAGAQH/AgEAMDMGCCsGAQUFBwEB
|
18
|
+
BCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZ29kYWRkeS5jb20wRgYDVR0f
|
19
|
+
BD8wPTA7oDmgN4Y1aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBv
|
20
|
+
c2l0b3J5L2dkcm9vdC5jcmwwSwYDVR0gBEQwQjBABgRVHSAAMDgwNgYIKwYBBQUH
|
21
|
+
AgEWKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTAO
|
22
|
+
BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBANKGwOy9+aG2Z+5mC6IG
|
23
|
+
OgRQjhVyrEp0lVPLN8tESe8HkGsz2ZbwlFalEzAFPIUyIXvJxwqoJKSQ3kbTJSMU
|
24
|
+
A2fCENZvD117esyfxVgqwcSeIaha86ykRvOe5GPLL5CkKSkB2XIsKd83ASe8T+5o
|
25
|
+
0yGPwLPk9Qnt0hCqU7S+8MxZC9Y7lhyVJEnfzuz9p0iRFEUOOjZv2kWzRaJBydTX
|
26
|
+
RE4+uXR21aITVSzGh6O1mawGhId/dQb8vxRMDsxuxN89txJx9OjxUUAiKEngHUuH
|
27
|
+
qDTMBqLdElrRhjZkAzVvb3du6/KFUJheqwNTrZEjYx8WnM25sgVjOuH0aBsXBTWV
|
28
|
+
U+4=
|
29
|
+
-----END CERTIFICATE-----
|
30
|
+
-----BEGIN CERTIFICATE-----
|
31
|
+
MIIE+zCCBGSgAwIBAgICAQ0wDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1Zh
|
32
|
+
bGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIElu
|
33
|
+
Yy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24g
|
34
|
+
QXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAe
|
35
|
+
BgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTA0MDYyOTE3MDYyMFoX
|
36
|
+
DTI0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBE
|
37
|
+
YWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3MgMiBDZXJ0
|
38
|
+
aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgC
|
39
|
+
ggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
|
40
|
+
2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+q
|
41
|
+
N1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiO
|
42
|
+
r18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lN
|
43
|
+
f4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+YihfukEH
|
44
|
+
U1jPEX44dMX4/7VpkI+EdOqXG68CAQOjggHhMIIB3TAdBgNVHQ4EFgQU0sSw0pHU
|
45
|
+
TBFxs2HLPaH+3ahq1OMwgdIGA1UdIwSByjCBx6GBwaSBvjCBuzEkMCIGA1UEBxMb
|
46
|
+
VmFsaUNlcnQgVmFsaWRhdGlvbiBOZXR3b3JrMRcwFQYDVQQKEw5WYWxpQ2VydCwg
|
47
|
+
SW5jLjE1MDMGA1UECxMsVmFsaUNlcnQgQ2xhc3MgMiBQb2xpY3kgVmFsaWRhdGlv
|
48
|
+
biBBdXRob3JpdHkxITAfBgNVBAMTGGh0dHA6Ly93d3cudmFsaWNlcnQuY29tLzEg
|
49
|
+
MB4GCSqGSIb3DQEJARYRaW5mb0B2YWxpY2VydC5jb22CAQEwDwYDVR0TAQH/BAUw
|
50
|
+
AwEB/zAzBggrBgEFBQcBAQQnMCUwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmdv
|
51
|
+
ZGFkZHkuY29tMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jZXJ0aWZpY2F0ZXMu
|
52
|
+
Z29kYWRkeS5jb20vcmVwb3NpdG9yeS9yb290LmNybDBLBgNVHSAERDBCMEAGBFUd
|
53
|
+
IAAwODA2BggrBgEFBQcCARYqaHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNv
|
54
|
+
bS9yZXBvc2l0b3J5MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOBgQC1
|
55
|
+
QPmnHfbq/qQaQlpE9xXUhUaJwL6e4+PrxeNYiY+Sn1eocSxI0YGyeR+sBjUZsE4O
|
56
|
+
WBsUs5iB0QQeyAfJg594RAoYC5jcdnplDQ1tgMQLARzLrUc+cb53S8wGd9D0Vmsf
|
57
|
+
SxOaFIqII6hR8INMqzW/Rn453HWkrugp++85j09VZw==
|
58
|
+
-----END CERTIFICATE-----
|
59
|
+
-----BEGIN CERTIFICATE-----
|
60
|
+
MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
|
61
|
+
IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
|
62
|
+
BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
|
63
|
+
aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
|
64
|
+
9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy
|
65
|
+
NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
|
66
|
+
azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
|
67
|
+
YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
|
68
|
+
Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
|
69
|
+
cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY
|
70
|
+
dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9
|
71
|
+
WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS
|
72
|
+
v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v
|
73
|
+
UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu
|
74
|
+
IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC
|
75
|
+
W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd
|
76
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'net/https'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'tempfile'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
module JRuby::Lint
|
7
|
+
class Libraries
|
8
|
+
class Cache
|
9
|
+
def initialize(cache_dir = nil)
|
10
|
+
@cache_dir = cache_dir || ENV['JRUBY_LINT_CACHE'] ||
|
11
|
+
(defined?(Gem.user_dir) && File.join(Gem.user_dir, 'lint')) || Dir::tmpdir
|
12
|
+
FileUtils.mkdir_p(@cache_dir) unless File.directory?(@cache_dir)
|
13
|
+
end
|
14
|
+
|
15
|
+
def fetch(name)
|
16
|
+
filename = filename_for(name)
|
17
|
+
if File.file?(filename) && !stale?(filename)
|
18
|
+
File.read(filename)
|
19
|
+
else
|
20
|
+
read_from_wiki(name, filename)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def store(name, content)
|
25
|
+
File.open(filename_for(name), "w") {|f| f << content }
|
26
|
+
end
|
27
|
+
|
28
|
+
def filename_for(name)
|
29
|
+
name = File.basename(name)
|
30
|
+
File.join(@cache_dir, File.extname(name).empty? ? "#{name}.html" : name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def stale?(filename)
|
34
|
+
File.mtime(filename) < Time.now - 24 * 60 * 60
|
35
|
+
end
|
36
|
+
|
37
|
+
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
|
60
|
+
content
|
61
|
+
rescue => e
|
62
|
+
raise "Error while reading from wiki: #{e.message}\nPlease try again later."
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class CExtensions
|
67
|
+
attr_reader :gems
|
68
|
+
|
69
|
+
def initialize(cache)
|
70
|
+
@cache = cache
|
71
|
+
end
|
72
|
+
|
73
|
+
def load
|
74
|
+
@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
|
80
|
+
end
|
81
|
+
rescue => e
|
82
|
+
@error = "Unable to load C Extension alternatives list: #{e.message}"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
SOURCES = [CExtensions]
|
87
|
+
|
88
|
+
attr_reader :gems
|
89
|
+
|
90
|
+
def initialize(cache)
|
91
|
+
@sources = SOURCES.map {|s| s.new(cache) }
|
92
|
+
end
|
93
|
+
|
94
|
+
def load
|
95
|
+
@gems = {}.tap do |gems|
|
96
|
+
@sources.each do |s|
|
97
|
+
s.load
|
98
|
+
gems.update(s.gems)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def gems
|
104
|
+
@gems ||= load
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
module JRuby::Lint
|
5
|
+
class Project
|
6
|
+
DEFAULT_TAGS = %w(error warning info)
|
7
|
+
|
8
|
+
attr_reader :collectors, :reporters, :findings, :files, :tags, :libraries
|
9
|
+
|
10
|
+
def initialize(options = OpenStruct.new)
|
11
|
+
@tags = DEFAULT_TAGS
|
12
|
+
@collectors = []
|
13
|
+
@files = Set.new
|
14
|
+
|
15
|
+
if options.eval
|
16
|
+
options.eval.each {|e| @collectors << JRuby::Lint::Collectors::Ruby.new(self, '-e', e) }
|
17
|
+
@files += @collectors
|
18
|
+
end
|
19
|
+
|
20
|
+
@sources = options.files || (options.eval ? [] : Dir['./**/*'])
|
21
|
+
load_collectors
|
22
|
+
load_reporters
|
23
|
+
load_libraries
|
24
|
+
end
|
25
|
+
|
26
|
+
def run
|
27
|
+
@findings = []
|
28
|
+
collectors.each do |c|
|
29
|
+
c.run
|
30
|
+
reporters.each {|r| r.report(c.findings)}
|
31
|
+
@findings += c.findings
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def load_collectors
|
37
|
+
@sources.each do |f|
|
38
|
+
next unless File.file?(f)
|
39
|
+
Collector.all.each do |c|
|
40
|
+
if c.detect?(f)
|
41
|
+
@collectors << c.new(self, f)
|
42
|
+
@files << f
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def load_reporters
|
49
|
+
@reporters = [(STDOUT.tty? ? Reporters::ANSIColor : Reporters::Text).new(self, STDOUT)]
|
50
|
+
end
|
51
|
+
|
52
|
+
def load_libraries
|
53
|
+
@libraries = Libraries.new(Libraries::Cache.new)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|