-
Notifications
You must be signed in to change notification settings - Fork 1
/
collector.rb
87 lines (73 loc) · 1.96 KB
/
collector.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
require "parser/runner"
require "unparser"
require "set"
require "rubocop"
require_relative "config/environment"
class Collector < Parser::AST::Processor
include AST::Sexp
def initialize
@store = Set.new
@root_path = File.expand_path(__dir__)
end
def suspicious_consts
@store.to_a
end
def on_const(node)
return if node.parent.module_definition?
return if node.parent.class_definition?
namespace = node.namespace
while namespace
return if namespace.lvar_type?
return if namespace.send_type?
return if namespace.self_type?
break if namespace.cbase_type?
namespace = namespace.namespace
end
const_string = Unparser.unparse(node)
if node.namespace&.cbase_type?
store(const_string, node.location) unless validate_const(const_string)
else
namespace_const_names =
node
.each_ancestor
.select { |n| n.class_type? || n.module_type? }
.reverse
.map { |mod| mod.children.first.const_name }
(namespace_const_names.size + 1).times do |i|
concated = (namespace_const_names[0...namespace_const_names.size - i] + [node.const_name]).join("::")
return if validate_const(concated)
end
store(const_string, node.location)
end
end
def store(const_string, location)
@store << [
File.join(@root_path, location.name.to_s),
const_string
]
end
end
def validate_const(namespaced_const_string)
eval(namespaced_const_string)
true
rescue NameError, LoadError
false
end
runner =
Class.new(Parser::Runner) do
def runner_name
"dudu"
end
def process(buffer)
parser = @parser_class.new(RuboCop::AST::Builder.new)
collector = Collector.new
collector.process(parser.parse(buffer))
show(collector.suspicious_consts)
end
def show(collection)
return if collection.empty?
puts
collection.each { |pair| puts pair.join("\t") }
end
end
runner.go(ARGV)