codescout-analyzer 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 62251be9162445198519b9683c482b680f905c47
4
+ data.tar.gz: 4c3d259900e1fa5bb7e2eb42f4422555e0c08d53
5
+ SHA512:
6
+ metadata.gz: 1ecb2fe301d2cbb23644a595e05718287f40718398fe4aeaf6663e374677b4d21f388d0f0f120dc7b971f4f60769f99e5741fe5193bd7a850471205f5ed481a1
7
+ data.tar.gz: 9ef8e29a834c4b5df1040de509a855c3d70a71ebeba8272c0a7dfbc2902f0e4061cc302e49fc36626b587fe71af006ac28e1d7d27968fa11d90736f3bd17690c
data/.gitignore ADDED
@@ -0,0 +1,24 @@
1
+ #*
2
+ *.gem
3
+ *.rbc
4
+ *.swp
5
+ *.tmproj
6
+ *~
7
+ .#*
8
+ .DS_Store
9
+ .bundle
10
+ .config
11
+ .yardoc
12
+ Gemfile.lock
13
+ InstalledFiles
14
+ _yardoc
15
+ coverage
16
+ doc/
17
+ lib/bundler/man
18
+ pkg
19
+ rdoc
20
+ spec/reports
21
+ test/tmp
22
+ test/version_tmp
23
+ tmp
24
+ tmtags
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "https://rubygems.org"
2
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/codescout ADDED
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path(File.dirname(__FILE__) + "/../lib")
4
+ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
5
+
6
+ require "rubygems"
7
+
8
+ path = ARGV.shift.to_s
9
+ if path.empty?
10
+ STDERR.puts "Please specify path to project"
11
+ exit 1
12
+ end
13
+
14
+ require "codescout/repo_analyzer"
15
+ require "codescout/source_file"
16
+ require "codescout/flog_stats"
17
+ require "codescout/flay_stats"
18
+ require "codescout/file_stats"
19
+ require "codescout/churn_stats"
20
+ require "codescout/brakeman_stats"
21
+ require "codescout/rubocop_stats"
22
+
23
+ analyzer = Codescout::RepoAnalyzer.new(path)
24
+ analyzer.analyze
25
+
26
+ puts JSON.dump(analyzer.result)
@@ -0,0 +1,25 @@
1
+ require File.expand_path("../lib/codescout/version", __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "codescout-analyzer"
5
+ s.version = Codescout::VERSION
6
+ s.summary = "No description for now"
7
+ s.description = "No description for now, maybe later"
8
+ s.homepage = "https://github.com"
9
+ s.authors = ["Dan Sosedoff"]
10
+ s.email = ["dan.sosedoff@gmail.com"]
11
+ s.license = "MIT"
12
+
13
+ s.add_dependency "flog", "4.3.0"
14
+ s.add_dependency "flay", "2.5.0"
15
+ s.add_dependency "churn", "1.0.1"
16
+ s.add_dependency "parser", "2.2.0.pre.4"
17
+ s.add_dependency "ruby2ruby", "2.1.1"
18
+ s.add_dependency "brakeman", "2.6.2"
19
+ s.add_dependency "rubocop", "0.25.0"
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
+ s.executables = `git ls-files -- bin/*`.split("\n").map{|f| File.basename(f)}
24
+ s.require_paths = ["lib"]
25
+ end
@@ -0,0 +1,283 @@
1
+ AllCops:
2
+ Exclude:
3
+ - db/schema.rb
4
+
5
+ AccessorMethodName:
6
+ Enabled: false
7
+
8
+ AccessModifierIndentation:
9
+ Enabled: false
10
+
11
+ ActionFilter:
12
+ Enabled: false
13
+
14
+ Alias:
15
+ Enabled: false
16
+
17
+ ArrayJoin:
18
+ Enabled: false
19
+
20
+ AsciiComments:
21
+ Enabled: false
22
+
23
+ AsciiIdentifiers:
24
+ Enabled: false
25
+
26
+ Attr:
27
+ Enabled: false
28
+
29
+ BlockNesting:
30
+ Enabled: false
31
+
32
+ CaseEquality:
33
+ Enabled: false
34
+
35
+ CharacterLiteral:
36
+ Enabled: false
37
+
38
+ ClassAndModuleChildren:
39
+ Enabled: false
40
+
41
+ ClassLength:
42
+ Enabled: false
43
+
44
+ ClassVars:
45
+ Enabled: false
46
+
47
+ CollectionMethods:
48
+ PreferredMethods:
49
+ find: detect
50
+ reduce: inject
51
+ collect: map
52
+ find_all: select
53
+
54
+ ColonMethodCall:
55
+ Enabled: false
56
+
57
+ CommentAnnotation:
58
+ Enabled: false
59
+
60
+ CyclomaticComplexity:
61
+ Enabled: false
62
+
63
+ Delegate:
64
+ Enabled: false
65
+
66
+ DeprecatedHashMethods:
67
+ Enabled: false
68
+
69
+ Documentation:
70
+ Enabled: false
71
+
72
+ DotPosition:
73
+ EnforcedStyle: trailing
74
+
75
+ DoubleNegation:
76
+ Enabled: false
77
+
78
+ EachWithObject:
79
+ Enabled: false
80
+
81
+ EmptyLiteral:
82
+ Enabled: false
83
+
84
+ EmptyLines:
85
+ Enabled: false
86
+
87
+ Encoding:
88
+ Enabled: false
89
+
90
+ EvenOdd:
91
+ Enabled: false
92
+
93
+ HashSyntax:
94
+ Enabled: false
95
+
96
+ FileName:
97
+ Enabled: false
98
+
99
+ FlipFlop:
100
+ Enabled: false
101
+
102
+ FormatString:
103
+ Enabled: false
104
+
105
+ GlobalVars:
106
+ Enabled: false
107
+
108
+ GuardClause:
109
+ Enabled: false
110
+
111
+ IfUnlessModifier:
112
+ Enabled: false
113
+
114
+ IfWithSemicolon:
115
+ Enabled: false
116
+
117
+ InlineComment:
118
+ Enabled: false
119
+
120
+ Lambda:
121
+ Enabled: false
122
+
123
+ LambdaCall:
124
+ Enabled: false
125
+
126
+ LineEndConcatenation:
127
+ Enabled: false
128
+
129
+ LineLength:
130
+ Max: 80
131
+
132
+ MethodLength:
133
+ Enabled: false
134
+
135
+ ModuleFunction:
136
+ Enabled: false
137
+
138
+ NegatedIf:
139
+ Enabled: false
140
+
141
+ NegatedWhile:
142
+ Enabled: false
143
+
144
+ Next:
145
+ Enabled: false
146
+
147
+ NilComparison:
148
+ Enabled: false
149
+
150
+ Not:
151
+ Enabled: false
152
+
153
+ NumericLiterals:
154
+ Enabled: false
155
+
156
+ OneLineConditional:
157
+ Enabled: false
158
+
159
+ OpMethod:
160
+ Enabled: false
161
+
162
+ ParameterLists:
163
+ Enabled: false
164
+
165
+ PercentLiteralDelimiters:
166
+ Enabled: false
167
+
168
+ PerlBackrefs:
169
+ Enabled: false
170
+
171
+ PredicateName:
172
+ NamePrefixBlacklist:
173
+ - is_
174
+
175
+ Proc:
176
+ Enabled: false
177
+
178
+ RaiseArgs:
179
+ Enabled: false
180
+
181
+ RegexpLiteral:
182
+ Enabled: false
183
+
184
+ SelfAssignment:
185
+ Enabled: false
186
+
187
+ SingleLineBlockParams:
188
+ Enabled: false
189
+
190
+ SingleLineMethods:
191
+ Enabled: false
192
+
193
+ SignalException:
194
+ Enabled: false
195
+
196
+ SingleSpaceBeforeFirstArg:
197
+ Enabled: false
198
+
199
+ SpecialGlobalVars:
200
+ Enabled: false
201
+
202
+ SpaceAfterSemicolon:
203
+ Enabled: false
204
+
205
+ StringLiterals:
206
+ Enabled: false
207
+
208
+ TrailingBlankLines:
209
+ Enabled: false
210
+
211
+ VariableInterpolation:
212
+ Enabled: false
213
+
214
+ TrailingComma:
215
+ Enabled: false
216
+
217
+ TrailingWhitespace:
218
+ Enabled: false
219
+
220
+ TrivialAccessors:
221
+ Enabled: false
222
+
223
+ VariableInterpolation:
224
+ Enabled: false
225
+
226
+ WhenThen:
227
+ Enabled: false
228
+
229
+ WhileUntilModifier:
230
+ Enabled: false
231
+
232
+ WordArray:
233
+ Enabled: false
234
+
235
+ PerceivedComplexity:
236
+ Enabled: false
237
+
238
+ # Lint
239
+
240
+ AmbiguousOperator:
241
+ Enabled: false
242
+
243
+ AmbiguousRegexpLiteral:
244
+ Enabled: false
245
+
246
+ AssignmentInCondition:
247
+ Enabled: false
248
+
249
+ ConditionPosition:
250
+ Enabled: false
251
+
252
+ DeprecatedClassMethods:
253
+ Enabled: false
254
+
255
+ ElseLayout:
256
+ Enabled: false
257
+
258
+ HandleExceptions:
259
+ Enabled: false
260
+
261
+ InvalidCharacterLiteral:
262
+ Enabled: false
263
+
264
+ LiteralInCondition:
265
+ Enabled: false
266
+
267
+ LiteralInInterpolation:
268
+ Enabled: false
269
+
270
+ Loop:
271
+ Enabled: false
272
+
273
+ ParenthesesAsGroupedExpression:
274
+ Enabled: false
275
+
276
+ RequireParentheses:
277
+ Enabled: false
278
+
279
+ UnderscorePrefixedVariableName:
280
+ Enabled: false
281
+
282
+ Void:
283
+ Enabled: false
@@ -0,0 +1,26 @@
1
+ module Codescout
2
+ class BrakemanStats
3
+ attr_reader :results
4
+
5
+ def initialize(analyzer)
6
+ @results = []
7
+
8
+ collect_results if generate_report
9
+ end
10
+
11
+ private
12
+
13
+ def generate_report
14
+ `brakeman -f json -o brakeman.json`
15
+ $?.success?
16
+ end
17
+
18
+ def report
19
+ JSON.load(File.read("brakeman.json"))
20
+ end
21
+
22
+ def collect_results
23
+ @results = report["warnings"]
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,34 @@
1
+ require "churn/calculator"
2
+
3
+ module Codescout
4
+ class ChurnStats
5
+ OPTIONS = {
6
+ minimum_churn_count: 1,
7
+ start_date: nil
8
+ }
9
+
10
+ attr_reader :files
11
+
12
+ def initialize(analyzer)
13
+ @analyzer = analyzer
14
+ @files = {}
15
+
16
+ generate_report
17
+ collect_results
18
+ end
19
+
20
+ private
21
+
22
+ def generate_report
23
+ @churn = Churn::ChurnCalculator.new(OPTIONS)
24
+ @churn.report
25
+ end
26
+
27
+ def collect_results
28
+ @churn.instance_variable_get("@changes").each do |c|
29
+ next unless @analyzer.valid_file?(c[:file_path])
30
+ @files[c[:file_path]] = c[:times_changed]
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,84 @@
1
+ module Codescout
2
+ class FileStats
3
+ PATTERNS = {
4
+ line_comment: /^\s*#/,
5
+ begin_block_comment: /^=begin/,
6
+ end_block_comment: /^=end/,
7
+ class: /^\s*class\s+[_A-Z]/,
8
+ method: /^\s*def\s+[_a-z]/,
9
+ }
10
+
11
+ attr_reader :file_size, # File size in bytes
12
+ :lines, # Total number of lines
13
+ :loc, # Number of code lines
14
+ :method_loc, # Average lines of code per method
15
+ :classes_count, # Number of class definitions
16
+ :methods_count # Number of methods definitions
17
+
18
+ def initialize(base_path, path)
19
+ @path = path
20
+ @full_path = File.join(base_path, path)
21
+
22
+ init_metrics
23
+ calculate_file_metrics
24
+ calculate_code_metrics
25
+ end
26
+
27
+ def to_hash
28
+ {
29
+ file_size: file_size,
30
+ lines: lines,
31
+ loc: loc,
32
+ method_loc: method_loc,
33
+ classes_count: classes_count,
34
+ methods_count: methods_count
35
+ }
36
+ end
37
+
38
+ private
39
+
40
+ def init_metrics
41
+ @file_size = 0
42
+ @lines = 0
43
+ @loc = 0
44
+ @method_loc = 0
45
+ @classes_count = 0
46
+ @methods_count = 0
47
+ end
48
+
49
+ def calculate_file_metrics
50
+ @file_size = File.size(@full_path)
51
+ end
52
+
53
+ def calculate_code_metrics
54
+ io = File.open(@full_path)
55
+ patterns = PATTERNS
56
+ comment_started = false
57
+
58
+ while line = io.gets
59
+ @lines += 1
60
+
61
+ if comment_started
62
+ if patterns[:end_block_comment] && line =~ patterns[:end_block_comment]
63
+ comment_started = false
64
+ end
65
+ next
66
+ else
67
+ if patterns[:begin_block_comment] && line =~ patterns[:begin_block_comment]
68
+ comment_started = true
69
+ next
70
+ end
71
+ end
72
+
73
+ @classes_count += 1 if patterns[:class] && line =~ patterns[:class]
74
+ @methods_count += 1 if patterns[:method] && line =~ patterns[:method]
75
+
76
+ if line !~ /^\s*$/ && (patterns[:line_comment].nil? || line !~ patterns[:line_comment])
77
+ @loc += 1
78
+ end
79
+ end
80
+
81
+ @method_loc = @methods_count > 0 ? @loc / @methods_count : 0
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,85 @@
1
+ require "flay"
2
+
3
+ module Codescout
4
+ class FlayStats
5
+ OPTIONS = {
6
+ :diff => true,
7
+ :mass => 16,
8
+ :summary => false,
9
+ :verbose => false,
10
+ :number => true,
11
+ :timeout => 10,
12
+ :liberal => false,
13
+ :fuzzy => false,
14
+ :only => nil
15
+ }
16
+
17
+ attr_reader :matches
18
+
19
+ def initialize(analyzer)
20
+ @matches = []
21
+ @base_path = analyzer.base_path
22
+
23
+ @flay = Flay.new(OPTIONS)
24
+ @flay.process(*analyzer.files)
25
+
26
+ process_matches(@flay.analyze)
27
+ @flay = nil
28
+ end
29
+
30
+ private
31
+
32
+ def process_matches(items)
33
+ items.each_with_index do |item, count|
34
+ match_item = {
35
+ match: item.identical? ? "identical" : "similar",
36
+ node: item.name.to_s,
37
+ bonus: item.bonus ? item.bonus.sub("*", "").to_i : nil,
38
+ mass: item.mass,
39
+ locations: locations(item)
40
+ }
41
+
42
+ nodes = @flay.hashes[item.structural_hash]
43
+
44
+ sources = nodes.map do |s|
45
+ msg = "sexp_to_#{File.extname(s.file).sub(/./, '')}"
46
+ @flay.respond_to?(msg) ? @flay.send(msg, s) : @flay.sexp_to_rb(s)
47
+ end
48
+
49
+ diff = @flay.n_way_diff(*sources)
50
+
51
+ parse_diff(diff, item.locations.size).each_with_index do |code,i|
52
+ match_item[:locations][i][:code] = code
53
+ end
54
+
55
+ @matches << match_item
56
+ end
57
+ end
58
+
59
+ def locations(item)
60
+ item.locations.map do |l|
61
+ {
62
+ file: l.file.sub("#{@base_path}/", ""),
63
+ line: l.line
64
+ }
65
+ end
66
+ end
67
+
68
+ def parse_diff(diff, size)
69
+ chunks = Array.new(size) { [] }
70
+
71
+ diff.split("\n").each do |line|
72
+ if line =~ /^([^:]):\s?(.+)/
73
+ key = ($1.ord - ?A.ord).to_i
74
+ chunks[key] << $2
75
+ else
76
+ chunks.each_with_index do |_,i|
77
+ chunks[i] << line.gsub(/^\s{3}/, "")
78
+ end
79
+ end
80
+ end
81
+
82
+ chunks.map { |c| c.join("\n") }
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,87 @@
1
+ require "flog"
2
+
3
+ module Codescout
4
+ class FlogStats
5
+ attr_reader :score, :average_score
6
+ attr_reader :scores
7
+
8
+ def initialize(analyzer)
9
+ options = {
10
+ all: true,
11
+ methods: true,
12
+ continue: true,
13
+ parser: Ruby19Parser
14
+ }
15
+
16
+ @flog = Flog.new(options)
17
+ @flog.flog(*analyzer.files)
18
+ @flog.calculate
19
+
20
+ @score = @flog.total_score
21
+ @average_score = @flog.average
22
+ @scores = {}
23
+
24
+ @flog.mass.each_pair do |file, mass|
25
+ @scores[file] = { score: 0, scores: [] }
26
+ end
27
+
28
+ @flog.totals.each_pair do |k,v|
29
+ next if @flog.method_locations[k].nil?
30
+
31
+ score = v.round
32
+ class_name, method_name = parse_method_string(k)
33
+ path, line = @flog.method_locations[k].split(":")
34
+ code = nil
35
+
36
+ if score >= 25 && method_name
37
+ method_source = Codescout::SourceFile.new(File.read(path)).method_source(method_name)
38
+
39
+ if method_source
40
+ code = method_source.code
41
+ end
42
+ end
43
+
44
+ @scores[path][:score] += score
45
+
46
+ @scores[path][:scores] << {
47
+ class_name: class_name,
48
+ method_name: method_name,
49
+ score: score,
50
+ line: line,
51
+ code: code
52
+ }
53
+ end
54
+
55
+ @flog = nil
56
+ end
57
+
58
+ private
59
+
60
+ def parse_method_string(str)
61
+ chunks = str.split("#")
62
+ klass = extract_class(chunks[0])
63
+ method = chunks[1]
64
+
65
+ # Parse class method, they're prefixed with "::"
66
+ if method.nil?
67
+ method = chunks[0].split("::").last
68
+ end
69
+
70
+ # Allow only properly formatter method names in ruby.
71
+ # Anything that looks like DSL or sugar does not have a method name.
72
+ if invalid_def?(method)
73
+ method = nil
74
+ end
75
+
76
+ return klass, method
77
+ end
78
+
79
+ def extract_class(str)
80
+ str.split("::").reject { |c| c =~ /^[^A-Z]/ }.join("::")
81
+ end
82
+
83
+ def invalid_def?(str)
84
+ str =~ /[\/\(\)]/ ? true : false
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,87 @@
1
+ module Codescout
2
+ class RepoAnalyzer
3
+ ALLOWED_FILES = %w(.rb .rake .gemspec)
4
+
5
+ attr_reader :base_path, :files
6
+
7
+ def initialize(path)
8
+ @base_path = File.expand_path(path)
9
+ @files = []
10
+ end
11
+
12
+ def analyze
13
+ within_base do
14
+ scan_files
15
+ run_filestats
16
+ run_flog
17
+ run_flay
18
+ run_churn
19
+ run_brakeman
20
+ run_rubocop
21
+ end
22
+ end
23
+
24
+ def result
25
+ {
26
+ file_stats: @file_stats,
27
+ flog: @flog,
28
+ flay: @flay,
29
+ churn: @churn,
30
+ brakeman: @brakeman,
31
+ rubocop: @rubocop
32
+ }
33
+ end
34
+
35
+ def within_base(&blk)
36
+ Dir.chdir(@base_path) { blk.call }
37
+ end
38
+
39
+ def scan_files
40
+ Dir["**/*"].each { |file| @files << file if valid_file?(file) }
41
+ end
42
+
43
+ def run_flay
44
+ STDERR.puts "Running flay"
45
+ @flay = Codescout::FlayStats.new(self).matches
46
+ end
47
+
48
+ def run_flog
49
+ STDERR.puts "Running flog"
50
+ @flog = Codescout::FlogStats.new(self).scores
51
+ end
52
+
53
+ def run_filestats
54
+ STDERR.puts "Running filestats"
55
+ @file_stats = {}
56
+
57
+ @files.each do |f|
58
+ @file_stats[f] = Codescout::FileStats.new(@base_path, f).to_hash
59
+ end
60
+
61
+ if File.exists?("Gemfile")
62
+ @file_stats["Gemfile"] = Codescout::FileStats.new(@base_path, "Gemfile").to_hash
63
+ end
64
+ end
65
+
66
+ def run_churn
67
+ STDERR.puts "Running churn"
68
+ @churn = Codescout::ChurnStats.new(self).files
69
+ end
70
+
71
+ def run_brakeman
72
+ STDERR.puts "Running brakeman"
73
+ @brakeman = Codescout::BrakemanStats.new(self).results
74
+ end
75
+
76
+ def run_rubocop
77
+ STDERR.puts "Running rubocop"
78
+ @rubocop = Codescout::RubocopStats.new(self).results
79
+ end
80
+
81
+ def valid_file?(file)
82
+ return false unless ALLOWED_FILES.include?(File.extname(file))
83
+ return false if file =~ /^db|spec|features|test|examples|samples\//
84
+ true
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,39 @@
1
+ module Codescout
2
+ class RubocopStats
3
+ attr_reader :results
4
+
5
+ def initialize(analyzer)
6
+ @analyzer = analyzer
7
+ @results = {}
8
+
9
+ install_config
10
+
11
+ `rubocop -c rubocop.yml -f json -o rubocop.json`
12
+
13
+ json = JSON.load(File.read("rubocop.json"))
14
+
15
+ json["files"].each do |file|
16
+ next unless @analyzer.files.include?(file["path"])
17
+ next if file["offenses"].empty?
18
+
19
+ lines = File.read(file["path"]).split("\n")
20
+
21
+ @results[file["path"]] = select_offences(lines, file["offenses"])
22
+ end
23
+ end
24
+
25
+ def select_offences(lines, offenses)
26
+ offenses.map { |o| o["code"] = lines[o["location"]["line"] - 1] ; o }
27
+ end
28
+
29
+ private
30
+
31
+ def config_path
32
+ "#{File.dirname(__FILE__)}/../../config/rubocop.yml"
33
+ end
34
+
35
+ def install_config
36
+ FileUtils.cp(config_path, "rubocop.yml")
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,56 @@
1
+ require "parser/current"
2
+
3
+ module Codescout
4
+ class SourceFile
5
+ class ObjectMethod
6
+ attr_reader :line, :line_end
7
+ attr_reader :code
8
+
9
+ def initialize(exp)
10
+ @line = exp.begin.line
11
+ @line_end = exp.end.line
12
+ @code = exp.source
13
+ end
14
+ end
15
+
16
+ def initialize(code)
17
+ @parser = Parser::CurrentRuby.parse(code)
18
+ end
19
+
20
+ def method_source(method_name)
21
+ @method_source = nil
22
+
23
+ recursive_search_ast(@parser, method_name) do |exp|
24
+ @method_source = ObjectMethod.new(exp)
25
+ end
26
+
27
+ @method_source
28
+ end
29
+
30
+ def method_lines(method_name)
31
+ @method_lines = nil
32
+
33
+ recursive_search_ast(@parser, method_name) do |exp|
34
+ @method_lines = exp.begin.line, exp.end.line
35
+ end
36
+
37
+ @method_lines
38
+ end
39
+
40
+ private
41
+
42
+ def recursive_search_ast(ast, method_name, &blk)
43
+ ast.children.each do |child|
44
+ if child.kind_of?(Parser::AST::Node)
45
+ if (child.type.to_s == "def" || child.type.to_s == "defs")
46
+ if child.children[0].to_s == method_name || child.children[1].to_s == method_name
47
+ blk.call(child.loc.expression)
48
+ end
49
+ else
50
+ recursive_search_ast(child, method_name, &blk)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,3 @@
1
+ module Codescout
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,158 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: codescout-analyzer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Dan Sosedoff
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-09-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: flog
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 4.3.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 4.3.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: flay
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 2.5.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 2.5.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: churn
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 1.0.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 1.0.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: parser
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 2.2.0.pre.4
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 2.2.0.pre.4
69
+ - !ruby/object:Gem::Dependency
70
+ name: ruby2ruby
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 2.1.1
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 2.1.1
83
+ - !ruby/object:Gem::Dependency
84
+ name: brakeman
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '='
88
+ - !ruby/object:Gem::Version
89
+ version: 2.6.2
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '='
95
+ - !ruby/object:Gem::Version
96
+ version: 2.6.2
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '='
102
+ - !ruby/object:Gem::Version
103
+ version: 0.25.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.25.0
111
+ description: No description for now, maybe later
112
+ email:
113
+ - dan.sosedoff@gmail.com
114
+ executables:
115
+ - codescout
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".gitignore"
120
+ - Gemfile
121
+ - Rakefile
122
+ - bin/codescout
123
+ - codescout-analyzer.gemspec
124
+ - config/rubocop.yml
125
+ - lib/codescout/brakeman_stats.rb
126
+ - lib/codescout/churn_stats.rb
127
+ - lib/codescout/file_stats.rb
128
+ - lib/codescout/flay_stats.rb
129
+ - lib/codescout/flog_stats.rb
130
+ - lib/codescout/repo_analyzer.rb
131
+ - lib/codescout/rubocop_stats.rb
132
+ - lib/codescout/source_file.rb
133
+ - lib/codescout/version.rb
134
+ homepage: https://github.com
135
+ licenses:
136
+ - MIT
137
+ metadata: {}
138
+ post_install_message:
139
+ rdoc_options: []
140
+ require_paths:
141
+ - lib
142
+ required_ruby_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ required_rubygems_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ requirements: []
153
+ rubyforge_project:
154
+ rubygems_version: 2.2.2
155
+ signing_key:
156
+ specification_version: 4
157
+ summary: No description for now
158
+ test_files: []