analyst 0.16.1 → 1.0.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.
- checksums.yaml +4 -4
- data/analyst.gemspec +1 -0
- data/lib/analyst/entities/constant_assignment.rb +1 -5
- data/lib/analyst/entities/entity.rb +8 -0
- data/lib/analyst/entities/hash.rb +6 -0
- data/lib/analyst/entities/method_call.rb +2 -10
- data/lib/analyst/entities/pair.rb +8 -2
- data/lib/analyst/parser.rb +1 -1
- data/lib/analyst/version.rb +1 -1
- data/spec/entities/class_method_spec.rb +29 -0
- data/spec/{class_spec.rb → entities/class_spec.rb} +8 -0
- data/spec/entities/constant_assignment_spec.rb +31 -0
- data/spec/{constant_spec.rb → entities/constant_spec.rb} +0 -0
- data/spec/{entity_spec.rb → entities/entity_spec.rb} +22 -0
- data/spec/entities/hash_spec.rb +45 -0
- data/spec/entities/instance_method_spec.rb +29 -0
- data/spec/entities/method_call_spec.rb +26 -0
- data/spec/entities/singleton_class_spec.rb +37 -0
- data/spec/entities/string_spec.rb +23 -0
- data/spec/fixtures/music.rb +12 -4
- data/spec/parser_spec.rb +3 -1
- metadata +36 -10
- data/spec/method_spec.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cacc928955bbd8e72446dcf6b20a5cbebc5ec4fc
|
4
|
+
data.tar.gz: b4c9cad57b52ba7f6c48f04f9295935cbe918463
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 00085874da8ad41948eca83217e3d36e519518a65d197c8fb6b38bb2fbca0ae3fd6a25bb7f3f00337d5400f1d240987a630955a6eefde5419001db7655637360
|
7
|
+
data.tar.gz: 238d01df95d83893c687a2bf1e1e9b578dc12218f446137439a997127ec92f16fec87c38b1e1317c4f26a88a563907e5ad92755bdae8e79d96fc41dbb138b0ea
|
data/analyst.gemspec
CHANGED
@@ -24,6 +24,10 @@ module Analyst
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
def strings
|
28
|
+
@strings ||= contents_of_type(Entities::String)
|
29
|
+
end
|
30
|
+
|
27
31
|
def modules
|
28
32
|
@modules ||= begin
|
29
33
|
nested_modules = top_level_modules.map(&:modules).flatten
|
@@ -70,6 +74,10 @@ module Analyst
|
|
70
74
|
@conditionals ||= contents_of_type(Entities::Conditional)
|
71
75
|
end
|
72
76
|
|
77
|
+
def hashes
|
78
|
+
@hashes ||= contents_of_type(Entities::Hash)
|
79
|
+
end
|
80
|
+
|
73
81
|
def location
|
74
82
|
"#{file_path}:#{line_number}"
|
75
83
|
end
|
@@ -19,18 +19,10 @@ module Analyst
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
def constants
|
23
|
-
if target.is_a? Analyst::Entities::Constant
|
24
|
-
super << target
|
25
|
-
else
|
26
|
-
super
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
22
|
private
|
31
23
|
|
32
24
|
def contents
|
33
|
-
arguments
|
25
|
+
(arguments + [target]).compact
|
34
26
|
end
|
35
27
|
|
36
28
|
def target_node
|
@@ -38,7 +30,7 @@ module Analyst
|
|
38
30
|
end
|
39
31
|
|
40
32
|
def target
|
41
|
-
process_node(target_node)
|
33
|
+
@target ||= process_node(target_node)
|
42
34
|
end
|
43
35
|
|
44
36
|
def name_node
|
@@ -6,11 +6,17 @@ module Analyst
|
|
6
6
|
handles_node :pair
|
7
7
|
|
8
8
|
def key
|
9
|
-
process_node(ast.children[0])
|
9
|
+
@key ||= process_node(ast.children[0])
|
10
10
|
end
|
11
11
|
|
12
12
|
def value
|
13
|
-
process_node(ast.children[1])
|
13
|
+
@value ||= process_node(ast.children[1])
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def contents
|
19
|
+
[key, value]
|
14
20
|
end
|
15
21
|
end
|
16
22
|
end
|
data/lib/analyst/parser.rb
CHANGED
data/lib/analyst/version.rb
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Analyst::Entities::ClassMethod do
|
4
|
+
|
5
|
+
let(:code) {<<-CODE
|
6
|
+
class DefaultCarrier
|
7
|
+
def self.register(carrier)
|
8
|
+
CarrierRegistry.add(carrier)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
CODE
|
12
|
+
}
|
13
|
+
let(:parser) { Analyst.for_source(code) }
|
14
|
+
let(:klass) { parser.classes.first }
|
15
|
+
let(:method) { klass.cmethods.first }
|
16
|
+
|
17
|
+
describe "#name" do
|
18
|
+
it "returns its short name" do
|
19
|
+
expect(method.name).to eq("register")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#fulL_name" do
|
24
|
+
it "returns its fully qualified name" do
|
25
|
+
expect(method.full_name).to eq("DefaultCarrier::register")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -5,6 +5,7 @@ describe Analyst::Entities::Class do
|
|
5
5
|
let(:parser) { Analyst.for_file("./spec/fixtures/music.rb") }
|
6
6
|
let(:artist) { parser.classes.detect { |klass| klass.full_name == "Artist" } }
|
7
7
|
let(:singer) { parser.classes.detect { |klass| klass.full_name == "Singer" } }
|
8
|
+
let(:amp) { parser.classes.detect { |klass| klass.full_name == "Performances::Equipment::Amp" }}
|
8
9
|
|
9
10
|
describe "#method_calls" do
|
10
11
|
it "lists all method invocations within a class definition" do
|
@@ -27,4 +28,11 @@ describe Analyst::Entities::Class do
|
|
27
28
|
end
|
28
29
|
end
|
29
30
|
|
31
|
+
describe "#constants" do
|
32
|
+
it "returns a list of constants" do
|
33
|
+
constants = amp.constants.map(&:name)
|
34
|
+
expect(constants).to match_array ["Interfaces::Basic", "Performances::Equipment::Microphone", "Performances::Equipment::MicStand"]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
30
38
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Analyst::Entities::ConstantAssignment do
|
4
|
+
|
5
|
+
let(:code) {<<-CODE
|
6
|
+
class Carrier
|
7
|
+
OBSTACLES = [:rain, :sleet, :snow]
|
8
|
+
def deliver(mail)
|
9
|
+
delivery = Delivery.new(mail)
|
10
|
+
delivery.deliver!
|
11
|
+
end
|
12
|
+
end
|
13
|
+
CODE
|
14
|
+
}
|
15
|
+
let(:parser) { Analyst.for_source(code) }
|
16
|
+
let(:klass) { parser.classes.first }
|
17
|
+
let(:constant_assignment) { klass.constant_assignments.first }
|
18
|
+
|
19
|
+
describe "#name" do
|
20
|
+
it "returns the short name of a constant" do
|
21
|
+
expect(constant_assignment.name).to eq("OBSTACLES")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#full_name" do
|
26
|
+
it "returns the full name of a constant" do
|
27
|
+
expect(constant_assignment.full_name).to eq("Carrier::OBSTACLES")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
File without changes
|
@@ -46,6 +46,12 @@ describe Analyst::Entities::Entity do
|
|
46
46
|
found = Analyst.for_source(code).constants.map(&:full_name)
|
47
47
|
expect(found).to match_array %w[A B C]
|
48
48
|
end
|
49
|
+
|
50
|
+
it "finds constants inside of interpolated strings" do
|
51
|
+
code = 'str = "Today, scientists classify Pluto as a #{Pluto.wtfru?}"'
|
52
|
+
found = Analyst.for_source(code).constants.map(&:name)
|
53
|
+
expect(found).to match_array %w[Pluto]
|
54
|
+
end
|
49
55
|
end
|
50
56
|
|
51
57
|
describe "#conditionals" do
|
@@ -115,4 +121,20 @@ end
|
|
115
121
|
end
|
116
122
|
end
|
117
123
|
|
124
|
+
describe "#method_calls" do
|
125
|
+
it "detects method calls" do
|
126
|
+
code = 'do_that_thang'
|
127
|
+
found = Analyst.for_source(code).method_calls.map(&:name)
|
128
|
+
expect(found).to match_array %w[do_that_thang]
|
129
|
+
end
|
130
|
+
|
131
|
+
it "detects calls inside calls" do
|
132
|
+
code = 'do_that_thang(with_this_stuff)'
|
133
|
+
do_that_thang = Analyst.for_source(code).method_calls.first
|
134
|
+
found = do_that_thang.method_calls.map(&:name)
|
135
|
+
expect(found).to match_array %w[with_this_stuff]
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
118
140
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Analyst::Entities::Hash do
|
4
|
+
|
5
|
+
let(:code) {<<-CODE
|
6
|
+
class Postmark
|
7
|
+
attr_accessor :date, :origin_city
|
8
|
+
def to_hash
|
9
|
+
{
|
10
|
+
date: self.date,
|
11
|
+
sent_from: self.origin_city
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
CODE
|
16
|
+
}
|
17
|
+
let(:parser) { Analyst.for_source(code) }
|
18
|
+
let(:klass) { parser.classes.first }
|
19
|
+
let(:methods) { klass.imethods }
|
20
|
+
|
21
|
+
describe "#pairs" do
|
22
|
+
let(:pairs) { methods.map(&:hashes).flatten.first.pairs }
|
23
|
+
|
24
|
+
it "extracts key/value pairs" do
|
25
|
+
expect(pairs.map(&:class)).to eq(
|
26
|
+
[Analyst::Entities::Pair, Analyst::Entities::Pair]
|
27
|
+
)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#to_hash" do
|
32
|
+
let(:hash_entity) { methods.map(&:hashes).flatten.first }
|
33
|
+
it "returns a hash with appropriate keys" do
|
34
|
+
expect(hash_entity.to_hash.keys).to eq(
|
35
|
+
[:date, :sent_from]
|
36
|
+
)
|
37
|
+
end
|
38
|
+
it "returns a hash with appropriate values" do
|
39
|
+
expect(hash_entity.to_hash.values.map(&:class)).to eq(
|
40
|
+
[Analyst::Entities::MethodCall, Analyst::Entities::MethodCall]
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Analyst::Entities::InstanceMethod do
|
4
|
+
|
5
|
+
let(:code) {<<-CODE
|
6
|
+
class DefaultCarrier
|
7
|
+
def initialize
|
8
|
+
@foo = "bar"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
CODE
|
12
|
+
}
|
13
|
+
let(:parser) { Analyst.for_source(code) }
|
14
|
+
let(:klass) { parser.classes.first }
|
15
|
+
let(:method) { klass.imethods.first }
|
16
|
+
|
17
|
+
describe "#name" do
|
18
|
+
it "returns its short name" do
|
19
|
+
expect(method.name).to eq("initialize")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#fulL_name" do
|
24
|
+
it "returns its fully qualified name" do
|
25
|
+
expect(method.full_name).to eq("DefaultCarrier#initialize")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Analyst::Entities::MethodCall do
|
4
|
+
|
5
|
+
describe "#constants" do
|
6
|
+
let(:code) { "Universe.spawn(Star, into: Galaxy.named('Milky Way'))" }
|
7
|
+
let(:method_call) { Analyst.for_source(code).method_calls.first }
|
8
|
+
|
9
|
+
it "lists constant targets and arguments" do
|
10
|
+
found = method_call.constants.map(&:name)
|
11
|
+
expect(found).to match_array %w[Universe Star Galaxy]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#arguments" do
|
16
|
+
it "lists arguments" do
|
17
|
+
code = "fn(:one, 'two', three)"
|
18
|
+
args = Analyst.for_source(code).method_calls.first.arguments
|
19
|
+
|
20
|
+
expect(args[0].value).to be :one
|
21
|
+
expect(args[1].value).to eq 'two'
|
22
|
+
expect(args[2].class).to eq Analyst::Entities::MethodCall
|
23
|
+
expect(args[2].name).to eq 'three'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Analyst::Entities::SingletonClass do
|
4
|
+
|
5
|
+
let(:code) {<<-CODE
|
6
|
+
class FriendlyStaff
|
7
|
+
class << self
|
8
|
+
def greet_customers
|
9
|
+
"Hello customers!"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
CODE
|
14
|
+
}
|
15
|
+
let(:parser) { Analyst.for_source(code) }
|
16
|
+
let(:klass) { parser.classes.first }
|
17
|
+
let(:singleton) { klass.singleton_class_blocks.first }
|
18
|
+
|
19
|
+
describe "#name" do
|
20
|
+
it "returns its short name" do
|
21
|
+
expect(singleton.name).to eq("FriendlyStaff!SINGLETON")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#fulL_name" do
|
26
|
+
it "returns its fully qualified name" do
|
27
|
+
expect(singleton.full_name).to eq("FriendlyStaff!SINGLETON")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#smethods" do
|
32
|
+
it "returns its singleton methods" do
|
33
|
+
expect(singleton.smethods.first.name).to eq("greet_customers")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Analyst::Entities::String do
|
4
|
+
|
5
|
+
let(:code) {<<-CODE
|
6
|
+
class DefaultCarrier
|
7
|
+
def initialize
|
8
|
+
"USPS"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
CODE
|
12
|
+
}
|
13
|
+
let(:parser) { Analyst.for_source(code) }
|
14
|
+
let(:klass) { parser.classes.first }
|
15
|
+
let(:string) { klass.imethods.first.strings.first }
|
16
|
+
|
17
|
+
describe "#value" do
|
18
|
+
it "returns the value of the string" do
|
19
|
+
expect(string.value).to eq("USPS")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/spec/fixtures/music.rb
CHANGED
@@ -49,7 +49,6 @@ class Singer < Artist
|
|
49
49
|
end
|
50
50
|
|
51
51
|
class Song
|
52
|
-
|
53
52
|
def initialize(popularity)
|
54
53
|
@popularity = popularity
|
55
54
|
end
|
@@ -58,14 +57,12 @@ end
|
|
58
57
|
module Instruments
|
59
58
|
|
60
59
|
class Stringed
|
61
|
-
|
62
60
|
def initialize(num_strings)
|
63
61
|
@num_strings = num_strings
|
64
62
|
end
|
65
63
|
end
|
66
64
|
|
67
65
|
class Guitar < Stringed
|
68
|
-
|
69
66
|
def initialize(sound)
|
70
67
|
super(6)
|
71
68
|
@sound = sound
|
@@ -76,11 +73,22 @@ end
|
|
76
73
|
|
77
74
|
module Performances
|
78
75
|
module Equipment
|
76
|
+
|
79
77
|
class Amp
|
78
|
+
include Interfaces::Basic
|
79
|
+
def self.companion_gear(type)
|
80
|
+
[
|
81
|
+
Performances::Equipment::Microphone.new("mic_1").on,
|
82
|
+
Performances::Equipment::MicStand.new("mic_1_stand")
|
83
|
+
]
|
84
|
+
end
|
80
85
|
end
|
81
86
|
|
82
87
|
class Microphone
|
83
88
|
end
|
89
|
+
|
90
|
+
class MicStand
|
91
|
+
end
|
92
|
+
|
84
93
|
end
|
85
94
|
end
|
86
|
-
|
data/spec/parser_spec.rb
CHANGED
@@ -18,7 +18,9 @@ describe "Parser" do
|
|
18
18
|
all_classes = %w[Artist Singer Song
|
19
19
|
Instruments::Stringed Instruments::Guitar
|
20
20
|
Performances::Equipment::Amp
|
21
|
-
Performances::Equipment::Microphone
|
21
|
+
Performances::Equipment::Microphone
|
22
|
+
Performances::Equipment::MicStand
|
23
|
+
]
|
22
24
|
|
23
25
|
class_names = parser.classes.map(&:full_name)
|
24
26
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: analyst
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Coraline Ada Ehmke
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-11-
|
12
|
+
date: 2014-11-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: haml
|
@@ -193,6 +193,20 @@ dependencies:
|
|
193
193
|
- - ">="
|
194
194
|
- !ruby/object:Gem::Version
|
195
195
|
version: '0'
|
196
|
+
- !ruby/object:Gem::Dependency
|
197
|
+
name: flog
|
198
|
+
requirement: !ruby/object:Gem::Requirement
|
199
|
+
requirements:
|
200
|
+
- - ">="
|
201
|
+
- !ruby/object:Gem::Version
|
202
|
+
version: '0'
|
203
|
+
type: :development
|
204
|
+
prerelease: false
|
205
|
+
version_requirements: !ruby/object:Gem::Requirement
|
206
|
+
requirements:
|
207
|
+
- - ">="
|
208
|
+
- !ruby/object:Gem::Version
|
209
|
+
version: '0'
|
196
210
|
description: A nice API for interacting with parsed Ruby source code.
|
197
211
|
email:
|
198
212
|
- coraline@idolhands.com
|
@@ -235,11 +249,17 @@ files:
|
|
235
249
|
- lib/analyst/parser.rb
|
236
250
|
- lib/analyst/processor.rb
|
237
251
|
- lib/analyst/version.rb
|
238
|
-
- spec/
|
239
|
-
- spec/
|
240
|
-
- spec/
|
252
|
+
- spec/entities/class_method_spec.rb
|
253
|
+
- spec/entities/class_spec.rb
|
254
|
+
- spec/entities/constant_assignment_spec.rb
|
255
|
+
- spec/entities/constant_spec.rb
|
256
|
+
- spec/entities/entity_spec.rb
|
257
|
+
- spec/entities/hash_spec.rb
|
258
|
+
- spec/entities/instance_method_spec.rb
|
259
|
+
- spec/entities/method_call_spec.rb
|
260
|
+
- spec/entities/singleton_class_spec.rb
|
261
|
+
- spec/entities/string_spec.rb
|
241
262
|
- spec/fixtures/music.rb
|
242
|
-
- spec/method_spec.rb
|
243
263
|
- spec/parser_spec.rb
|
244
264
|
- spec/spec_helper.rb
|
245
265
|
homepage: ''
|
@@ -267,11 +287,17 @@ signing_key:
|
|
267
287
|
specification_version: 4
|
268
288
|
summary: A nice API for interacting with parsed Ruby source code.
|
269
289
|
test_files:
|
270
|
-
- spec/
|
271
|
-
- spec/
|
272
|
-
- spec/
|
290
|
+
- spec/entities/class_method_spec.rb
|
291
|
+
- spec/entities/class_spec.rb
|
292
|
+
- spec/entities/constant_assignment_spec.rb
|
293
|
+
- spec/entities/constant_spec.rb
|
294
|
+
- spec/entities/entity_spec.rb
|
295
|
+
- spec/entities/hash_spec.rb
|
296
|
+
- spec/entities/instance_method_spec.rb
|
297
|
+
- spec/entities/method_call_spec.rb
|
298
|
+
- spec/entities/singleton_class_spec.rb
|
299
|
+
- spec/entities/string_spec.rb
|
273
300
|
- spec/fixtures/music.rb
|
274
|
-
- spec/method_spec.rb
|
275
301
|
- spec/parser_spec.rb
|
276
302
|
- spec/spec_helper.rb
|
277
303
|
has_rdoc:
|