deadlyzer 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +47 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/deadlyzer +7 -0
- data/lib/deadlyzer/analyzer/configurator.rb +10 -0
- data/lib/deadlyzer/analyzer/utils.rb +35 -0
- data/lib/deadlyzer/analyzer.rb +140 -0
- data/lib/deadlyzer/ast_matcher.rb +36 -0
- data/lib/deadlyzer/ast_parser.rb +47 -0
- data/lib/deadlyzer/constant_loader.rb +186 -0
- data/lib/deadlyzer/version.rb +5 -0
- data/lib/deadlyzer.rb +5 -0
- metadata +153 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 44f9e798e87a8ce44f9cc08c7ebe56e3e9d9078f49cb0bcc25955f804c6961d8
|
4
|
+
data.tar.gz: d99a693be1a3d66c2cd4d0b459508ad07faafec82b8ff53fba0e8f6ebafc22e4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 07743314cfc763ba0ab1f2125fecfc93200747863453490e6671e5882b471ab2cd111bab3fa631ce9cf5525879438513681ae3a3cb5f16398cec102636bcf1c2
|
7
|
+
data.tar.gz: 1423f22fe859022afbf0a9fc9319e75ca49da0452a82d7b768f3411cffb47779f4c81782fe3d6c450b41dc187965391f11de2243183d8b513e3052d553d5e6f4
|
data/README.md
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# Deadlyzer
|
2
|
+
Deadlyzer lets you to compare directories and reveal unreferenced, uncalled constats to remove
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
|
6
|
+
Add this line to your application's Gemfile:
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
gem 'deadlyzer'
|
10
|
+
```
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle install
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
$ gem install deadlyzer
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
To use deadlyzer you should create deadlyzer.yml file with following content
|
23
|
+
|
24
|
+
```yaml
|
25
|
+
target:
|
26
|
+
path: './app/workers'
|
27
|
+
exclude_consts:
|
28
|
+
- 'Sidekiq::Worker'
|
29
|
+
against:
|
30
|
+
path: './app/controllers'
|
31
|
+
```
|
32
|
+
|
33
|
+
Available options
|
34
|
+
|
35
|
+
* exclude_const (Array)
|
36
|
+
* exclude_dirs (Array)
|
37
|
+
|
38
|
+
```sh
|
39
|
+
user@desktop: ~$ deadlyzer # to run
|
40
|
+
```
|
41
|
+
|
42
|
+
## Development
|
43
|
+
|
44
|
+
Working principle is simple enough. Gem uses Rubocup and Parser gems to creat Abstract Syntax Tree. Using '(const ...)' pattern to match with nodes on the tree
|
45
|
+
|
46
|
+
## Contributing
|
47
|
+
Deadlyzer is still under development and created to use personal purpose where problems can solve with finding uncalled constants. If you also need it or would like to contribute it would be great :)
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "deadlyzer"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/exe/deadlyzer
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Deadlyzer
|
4
|
+
class Analyzer
|
5
|
+
module Utils
|
6
|
+
def self.included(base)
|
7
|
+
base.include InstanceMethods
|
8
|
+
end
|
9
|
+
|
10
|
+
module InstanceMethods
|
11
|
+
# @api private
|
12
|
+
# @since 0.1.0
|
13
|
+
def parse_yaml(path)
|
14
|
+
ctx = read_file(path)
|
15
|
+
|
16
|
+
YAML.load(ctx)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Default name of config file
|
20
|
+
# @api private
|
21
|
+
# @since 0.1.0
|
22
|
+
def default_config_file
|
23
|
+
'./deadlyzer.yml'
|
24
|
+
end
|
25
|
+
|
26
|
+
# @api private
|
27
|
+
# @since 0.1.0
|
28
|
+
def read_file(path)
|
29
|
+
File.read(File.expand_path(path))
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'deadlyzer/analyzer/utils'
|
2
|
+
require 'deadlyzer/analyzer/configurator'
|
3
|
+
require 'deadlyzer/constant_loader'
|
4
|
+
require 'deadlyzer/ast_parser'
|
5
|
+
|
6
|
+
require 'spinning_cursor'
|
7
|
+
require 'corol'
|
8
|
+
|
9
|
+
module Deadlyzer
|
10
|
+
class Analyzer
|
11
|
+
include Deadlyzer::Analyzer::Utils
|
12
|
+
|
13
|
+
# @api private
|
14
|
+
# @since 0.1.0
|
15
|
+
attr_reader :config_file
|
16
|
+
|
17
|
+
# @api private
|
18
|
+
# @since 0.1.0
|
19
|
+
attr_reader :config
|
20
|
+
|
21
|
+
# @api private
|
22
|
+
# @since 0.1.0
|
23
|
+
attr_reader :config_file_ctx
|
24
|
+
|
25
|
+
# @api private
|
26
|
+
# @since 0.1.0
|
27
|
+
attr_reader :target_constants
|
28
|
+
|
29
|
+
# @api private
|
30
|
+
# @since 0.1.0
|
31
|
+
attr_reader :against_constants
|
32
|
+
|
33
|
+
# @api private
|
34
|
+
# @since 0.1.0
|
35
|
+
attr_reader :constants_may_not_used
|
36
|
+
|
37
|
+
attr_reader :empty_files
|
38
|
+
|
39
|
+
def initialize(argv = [])
|
40
|
+
@config_file = argv.pop || default_config_file
|
41
|
+
@empty_files = []
|
42
|
+
@constants_may_not_used = []
|
43
|
+
end
|
44
|
+
|
45
|
+
# Main wrapper analize method
|
46
|
+
# @since 0.1.0
|
47
|
+
def analize!
|
48
|
+
SpinningCursor.run do
|
49
|
+
banner "Analyzing".yellow
|
50
|
+
type :dots
|
51
|
+
|
52
|
+
action do
|
53
|
+
read_configs!
|
54
|
+
load_config!
|
55
|
+
load_target_constants!
|
56
|
+
load_against_constants!
|
57
|
+
match!
|
58
|
+
send_out!
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
# @api private
|
65
|
+
# @since 0.1.0
|
66
|
+
def read_configs!
|
67
|
+
@config_file_ctx = parse_yaml(config_file)
|
68
|
+
rescue
|
69
|
+
puts 'No config file found'
|
70
|
+
exit 1
|
71
|
+
end
|
72
|
+
|
73
|
+
# @api private
|
74
|
+
# @since 0.1.0
|
75
|
+
def load_config!
|
76
|
+
@config = Configurator.new(config_file_ctx)
|
77
|
+
end
|
78
|
+
|
79
|
+
# @api private
|
80
|
+
# @since 0.1.0
|
81
|
+
def load_target_constants!
|
82
|
+
cl = ConstantLoader.new(
|
83
|
+
directory: config.target.fetch('path', nil),
|
84
|
+
excluded_dirs: config.target.fetch('exclude_dirs', nil),
|
85
|
+
excluded_consts: config.target.fetch('exclude_consts', nil),
|
86
|
+
)
|
87
|
+
|
88
|
+
empty_files.push cl.empty_files.uniq
|
89
|
+
@target_constants = cl.constants.uniq
|
90
|
+
end
|
91
|
+
|
92
|
+
# @api private
|
93
|
+
# @since 0.1.0
|
94
|
+
def load_against_constants!
|
95
|
+
cl = ConstantLoader.new(
|
96
|
+
directory: config.against.fetch('path', nil),
|
97
|
+
excluded_dirs: config.against.fetch('exclude_dirs', nil),
|
98
|
+
excluded_consts: config.against.fetch('exclude_consts', nil),
|
99
|
+
)
|
100
|
+
|
101
|
+
empty_files.push cl.empty_files.uniq
|
102
|
+
@against_constants = cl.constants.uniq
|
103
|
+
end
|
104
|
+
|
105
|
+
# @api private
|
106
|
+
# @since 0.1.0
|
107
|
+
def match!
|
108
|
+
match_constants(target: target_constants, against: against_constants)
|
109
|
+
constants_may_not_used
|
110
|
+
end
|
111
|
+
|
112
|
+
# @api private
|
113
|
+
# @since 0.1.0
|
114
|
+
def send_out!
|
115
|
+
puts "Files might be empty"
|
116
|
+
empty_files.each do |file|
|
117
|
+
puts file
|
118
|
+
end
|
119
|
+
|
120
|
+
puts "\nContants may not refered\n"
|
121
|
+
constants_may_not_used.each do |constant|
|
122
|
+
puts constant
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# @api private
|
127
|
+
# @since 0.1.0
|
128
|
+
def match_constants(target:, against:)
|
129
|
+
used_constants = target.select do |tc|
|
130
|
+
tc.name if against.any? {|ac| ac.name == tc.name}
|
131
|
+
end
|
132
|
+
|
133
|
+
constants = (used_constants + target).group_by(&:itself).transform_values(&:count)
|
134
|
+
constants.each do |constant, count|
|
135
|
+
constants_may_not_used.push constant if count < 2
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Deadlyzer
|
2
|
+
module AST
|
3
|
+
class Matcher
|
4
|
+
# @api private
|
5
|
+
# @since 0.1.0
|
6
|
+
DEFAULT_PATTERN = '(const ... )'
|
7
|
+
|
8
|
+
# @api private
|
9
|
+
# @since 0.1.0
|
10
|
+
attr_reader :matcher
|
11
|
+
|
12
|
+
# @api private
|
13
|
+
# @since 0.1.0
|
14
|
+
attr_reader :pattern
|
15
|
+
|
16
|
+
def initialize(matcher: nil, pattern: nil)
|
17
|
+
@matcher = matcher || default_matcher
|
18
|
+
@pattern = pattern || DEFAULT_PATTERN
|
19
|
+
end
|
20
|
+
|
21
|
+
# @api private
|
22
|
+
# @since 0.1.0
|
23
|
+
def match(node:)
|
24
|
+
matcher.new(pattern).match(node)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
# @api private
|
29
|
+
# @since 0.1.0
|
30
|
+
def default_matcher
|
31
|
+
require 'rubocop'
|
32
|
+
RuboCop::NodePattern
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Deadlyzer
|
2
|
+
module AST
|
3
|
+
class Parser
|
4
|
+
# AST Parser
|
5
|
+
# @api private
|
6
|
+
# @since 0.1.0
|
7
|
+
|
8
|
+
# @api private
|
9
|
+
# @since 0.1.0
|
10
|
+
attr_reader :parser
|
11
|
+
|
12
|
+
# @since 0.1.0
|
13
|
+
attr_reader :ast
|
14
|
+
|
15
|
+
# @since 0.1.0
|
16
|
+
attr_reader :file
|
17
|
+
|
18
|
+
def initialize(parser: nil)
|
19
|
+
@parser = parser || default_parser
|
20
|
+
end
|
21
|
+
|
22
|
+
# @api private
|
23
|
+
# @since 0.1.0
|
24
|
+
def parse(code, file = nil)
|
25
|
+
processed_source = parse_code(code, file)
|
26
|
+
@ast = processed_source.ast
|
27
|
+
@file = processed_source.path
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
# @api private
|
33
|
+
# @since 0.1.0
|
34
|
+
def default_parser
|
35
|
+
require 'rubocop'
|
36
|
+
RuboCop::ProcessedSource
|
37
|
+
end
|
38
|
+
|
39
|
+
# @api private
|
40
|
+
# @since 0.1.0
|
41
|
+
def parse_code(code, file)
|
42
|
+
parser.new(code, RUBY_VERSION.to_f, file)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'deadlyzer/ast_parser'
|
2
|
+
require 'deadlyzer/ast_matcher'
|
3
|
+
|
4
|
+
module Deadlyzer
|
5
|
+
class ConstantLoader
|
6
|
+
CURRENT_DIRECTORY = File.expand_path('.', __dir__)
|
7
|
+
DEFAULT_PATTERN = '/**/*.rb'
|
8
|
+
|
9
|
+
# @api private
|
10
|
+
# @since 0.1.0
|
11
|
+
attr_reader :directory
|
12
|
+
|
13
|
+
# @api private
|
14
|
+
# @since 0.1.0
|
15
|
+
attr_reader :excluded_dirs
|
16
|
+
|
17
|
+
# @api private
|
18
|
+
# @since 0.1.0
|
19
|
+
attr_reader :empty_files
|
20
|
+
|
21
|
+
# @api private
|
22
|
+
# @since 0.1.0
|
23
|
+
attr_reader :excluded_consts
|
24
|
+
|
25
|
+
# @api private
|
26
|
+
# @since 0.1.0
|
27
|
+
attr_reader :exclude
|
28
|
+
|
29
|
+
# @api private
|
30
|
+
# @since 0.1.0
|
31
|
+
attr_reader :pattern
|
32
|
+
|
33
|
+
# @api private
|
34
|
+
# @since 0.1.0
|
35
|
+
attr_accessor :ast
|
36
|
+
|
37
|
+
def initialize(directory: nil, excluded_dirs: nil, excluded_consts: nil, pattern: nil)
|
38
|
+
@directory = directory
|
39
|
+
@excluded_dirs = excluded_dirs || []
|
40
|
+
@excluded_consts = excluded_consts || []
|
41
|
+
@pattern = pattern || DEFAULT_PATTERN
|
42
|
+
@ast = []
|
43
|
+
@constants = []
|
44
|
+
@empty_files = []
|
45
|
+
end
|
46
|
+
|
47
|
+
# @api private
|
48
|
+
# @since 0.1.0
|
49
|
+
def constants
|
50
|
+
load_ast!
|
51
|
+
load_matcher!
|
52
|
+
load_constants!
|
53
|
+
@constants
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
# @api private
|
58
|
+
# @since 0.1.0
|
59
|
+
def load_ast!
|
60
|
+
files.each do |file|
|
61
|
+
# TODO: check momory issue
|
62
|
+
parser = Deadlyzer::AST::Parser.new
|
63
|
+
ast.push parser.parse(read(file), file)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# @api private
|
68
|
+
# @since 0.1.0
|
69
|
+
def load_matcher!
|
70
|
+
@matcher = Deadlyzer::AST::Matcher.new
|
71
|
+
end
|
72
|
+
|
73
|
+
# @api private
|
74
|
+
# @since 0.1.0
|
75
|
+
def load_constants!
|
76
|
+
ast.each do |node|
|
77
|
+
@empty_files.push node.file && next if node.ast.nil?
|
78
|
+
|
79
|
+
file = node.file
|
80
|
+
results = determine_consts(@matcher, node.ast)
|
81
|
+
|
82
|
+
results.each do |result|
|
83
|
+
line, name = humanize_const(result)
|
84
|
+
@constants.push(Constant.new(file, line, name)) unless excluded_consts.include?(name)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# @api private
|
90
|
+
# @since 0.1.0
|
91
|
+
def determine_consts(matcher, node)
|
92
|
+
match = matcher.match(node: node)
|
93
|
+
if match
|
94
|
+
match == true ? node : [match, node]
|
95
|
+
else
|
96
|
+
if node.respond_to?(:children) && !node.children.empty?
|
97
|
+
node.children.grep(RuboCop::AST::Node).flat_map{|e| determine_consts(matcher, e)}.compact
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# @api private
|
103
|
+
# @since 0.1.0
|
104
|
+
def humanize_const(result)
|
105
|
+
if result.is_a?(RuboCop::AST::Node)
|
106
|
+
range = result.source_range
|
107
|
+
result = result.source
|
108
|
+
else
|
109
|
+
result, node = result
|
110
|
+
range = node.source_range
|
111
|
+
end
|
112
|
+
[range.line, result, :ruby]
|
113
|
+
end
|
114
|
+
|
115
|
+
# @api private
|
116
|
+
# @since 0.1.0
|
117
|
+
def files
|
118
|
+
target_directory = list_dir(path(directory + pattern))
|
119
|
+
remove(files: excluded_files, from: target_directory)
|
120
|
+
end
|
121
|
+
|
122
|
+
# @api private
|
123
|
+
# @since 0.1.0
|
124
|
+
def excluded_files
|
125
|
+
excluded_dirs.flat_map {|dir| list_dir(path(dir+ pattern))}.flatten
|
126
|
+
end
|
127
|
+
|
128
|
+
# @api private
|
129
|
+
# @since 0.1.0
|
130
|
+
# def excluded_constants
|
131
|
+
|
132
|
+
# end
|
133
|
+
|
134
|
+
# @api private
|
135
|
+
# @since 0.1.0
|
136
|
+
def path(dir)
|
137
|
+
File.expand_path(dir)
|
138
|
+
end
|
139
|
+
|
140
|
+
# @api private
|
141
|
+
# @since 0.1.0
|
142
|
+
def list_dir(dir)
|
143
|
+
Dir[dir]
|
144
|
+
end
|
145
|
+
|
146
|
+
# @api private
|
147
|
+
# @since 0.1.0
|
148
|
+
def remove(files:, from:)
|
149
|
+
files.each do |file|
|
150
|
+
from.delete file
|
151
|
+
end
|
152
|
+
from
|
153
|
+
end
|
154
|
+
|
155
|
+
# @api private
|
156
|
+
# @since 0.1.0
|
157
|
+
def read(file)
|
158
|
+
File.read file
|
159
|
+
end
|
160
|
+
|
161
|
+
# @api private
|
162
|
+
# @since 0.1.0
|
163
|
+
class Constant
|
164
|
+
require 'coderay'
|
165
|
+
|
166
|
+
attr_reader :file
|
167
|
+
attr_reader :line
|
168
|
+
attr_reader :name
|
169
|
+
def initialize(file, line, name)
|
170
|
+
@file = file
|
171
|
+
@line = line
|
172
|
+
@name = name
|
173
|
+
end
|
174
|
+
|
175
|
+
def to_s
|
176
|
+
[file, line, rubyize(name)].join(':')
|
177
|
+
end
|
178
|
+
|
179
|
+
private
|
180
|
+
def rubyize(name)
|
181
|
+
" #{CodeRay.scan(name, :ruby).term}"
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
end
|
data/lib/deadlyzer.rb
ADDED
metadata
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: deadlyzer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Farhad
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-05-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '12.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '12.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry-nav
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rubocop
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: coderay
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: spinning_cursor
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: corol
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: Scan find unused constant on other directories, compare and remove
|
112
|
+
email:
|
113
|
+
- farhad9801@gmail.com
|
114
|
+
executables:
|
115
|
+
- deadlyzer
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- README.md
|
120
|
+
- bin/console
|
121
|
+
- bin/setup
|
122
|
+
- exe/deadlyzer
|
123
|
+
- lib/deadlyzer.rb
|
124
|
+
- lib/deadlyzer/analyzer.rb
|
125
|
+
- lib/deadlyzer/analyzer/configurator.rb
|
126
|
+
- lib/deadlyzer/analyzer/utils.rb
|
127
|
+
- lib/deadlyzer/ast_matcher.rb
|
128
|
+
- lib/deadlyzer/ast_parser.rb
|
129
|
+
- lib/deadlyzer/constant_loader.rb
|
130
|
+
- lib/deadlyzer/version.rb
|
131
|
+
homepage: https://github.com/0x2C6/deadlyzer
|
132
|
+
licenses: []
|
133
|
+
metadata: {}
|
134
|
+
post_install_message:
|
135
|
+
rdoc_options: []
|
136
|
+
require_paths:
|
137
|
+
- lib
|
138
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: 2.2.0
|
143
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0'
|
148
|
+
requirements: []
|
149
|
+
rubygems_version: 3.1.2
|
150
|
+
signing_key:
|
151
|
+
specification_version: 4
|
152
|
+
summary: Reveal uncalled constants
|
153
|
+
test_files: []
|