analyst 0.16.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 25e03d345e3eee79249da960a221c1635de9ded7
4
- data.tar.gz: 939e2a44f33bc42afed68a253be53e4110c0ea21
3
+ metadata.gz: cacc928955bbd8e72446dcf6b20a5cbebc5ec4fc
4
+ data.tar.gz: b4c9cad57b52ba7f6c48f04f9295935cbe918463
5
5
  SHA512:
6
- metadata.gz: 385373476be049c30d9ebccb8ab096496587eae69a85678e420631cf7c1bfb9ce04336b3a316b78e36f0f293186c8967714e3d7fe6d77857e776dfcd60daaa07
7
- data.tar.gz: 8423b501882aab60fac8dfea3b59272d539718731ac6a40e42152c0a512f339a68e8985c31717ecd6d3354d934fb3bd2eb9f4cd710ad53c794a99c91da7cff92
6
+ metadata.gz: 00085874da8ad41948eca83217e3d36e519518a65d197c8fb6b38bb2fbca0ae3fd6a25bb7f3f00337d5400f1d240987a630955a6eefde5419001db7655637360
7
+ data.tar.gz: 238d01df95d83893c687a2bf1e1e9b578dc12218f446137439a997127ec92f16fec87c38b1e1317c4f26a88a563907e5ad92755bdae8e79d96fc41dbb138b0ea
data/analyst.gemspec CHANGED
@@ -32,6 +32,7 @@ Gem::Specification.new do |spec|
32
32
  spec.add_development_dependency "pry"
33
33
  spec.add_development_dependency "byebug"
34
34
  spec.add_development_dependency "awesome_print"
35
+ spec.add_development_dependency "flog"
35
36
 
36
37
  end
37
38
 
@@ -10,11 +10,7 @@ module Analyst
10
10
  end
11
11
 
12
12
  def full_name
13
- scope.nil? ? name : scope.full_name + '::' + name
14
- end
15
-
16
- def scope
17
- @scope ||= process_node(ast.children.first)
13
+ parent.nil? ? name : parent.full_name + '::' + name
18
14
  end
19
15
 
20
16
  private
@@ -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
@@ -25,6 +25,12 @@ module Analyst
25
25
  hash
26
26
  end
27
27
  end
28
+
29
+ private
30
+
31
+ def contents
32
+ pairs
33
+ end
28
34
  end
29
35
  end
30
36
  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
@@ -7,7 +7,7 @@ module Analyst
7
7
  extend Forwardable
8
8
 
9
9
  def_delegators :root, :classes, :top_level_classes, :constants,
10
- :methods
10
+ :methods, :method_calls, :hashes
11
11
 
12
12
  def self.for_files(*path_to_files)
13
13
  file_paths = path_to_files.map do |path|
@@ -1,3 +1,3 @@
1
1
  module Analyst
2
- VERSION = "0.16.1"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -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
@@ -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
@@ -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.16.1
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-10 00:00:00.000000000 Z
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/class_spec.rb
239
- - spec/constant_spec.rb
240
- - spec/entity_spec.rb
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/class_spec.rb
271
- - spec/constant_spec.rb
272
- - spec/entity_spec.rb
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:
data/spec/method_spec.rb DELETED
@@ -1,9 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Analyst::Entities::InstanceMethod do
4
-
5
- it "has specs" do
6
- expect(false).to be_truthy
7
- end
8
-
9
- end