tag_ripper 0.2.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 375a528cbf8942e0dd48c51ffe10c005a6b3672b414e82b5d768011f3355e350
4
- data.tar.gz: f3e74892414a1587e5dfabeba4cda6839f2dd500f800bda6303fa2ea97f18042
3
+ metadata.gz: e8223c939423f3fce3c103a0e16649b925cc2cf9d0130618e4172c8f8e206bde
4
+ data.tar.gz: dbd6a188942b85df76b27189df7cdcbfea4257e10c6fd7003467fdb552eb25b7
5
5
  SHA512:
6
- metadata.gz: 49ababa76c465f7fa6a691f968290a6668762d884e0be15ca3790e6b6b884853aa1ff1bbbe78c9afdeef293b85ab4f3470357d635c9dda531257f26e81d4700b
7
- data.tar.gz: 07311f3a4768f8643c0fafcab84f3b6318392a5c1726bcfccf2fcfd1291db35e4039d4493adeb4e0241765b086e56bd2fbb3feee4e9065452c4880df3a9d88f9
6
+ metadata.gz: 1a72eee3e5dbcafe2729452701418ea233ee6f0439bab493d7220687081a0fa9efc6ec20cb4d4fab5eaf6ea427e0fc5a5df7d6269f20bbfd53feadc5454abf50
7
+ data.tar.gz: 556c44f1683a4c46c896e11d4c0da33c1e1c14af6061a8ce28072feb8187bc56e6763e357e7d7a568c55da99f2edb95d78a13b56ff0b19124023df382d703be7
data/.rubocop.yml CHANGED
@@ -11,6 +11,7 @@ AllCops:
11
11
  Exclude:
12
12
  - bin/*
13
13
  - test/fixtures/**/* # These files have particular styles that should be preserved
14
+ - samples/**/* # These files have particular styles that should be preserved
14
15
  Metrics/AbcSize:
15
16
  Exclude:
16
17
  - test/**/*
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.4.2
1
+ 3.4.3
data/Guardfile ADDED
@@ -0,0 +1,5 @@
1
+ guard :minitest, cli: "--verbose" do
2
+ watch(%r{^test/(.+)_test\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
4
+ watch("test/test_helper.rb") { "test" }
5
+ end
data/README.md CHANGED
@@ -5,7 +5,24 @@
5
5
 
6
6
  Lets you annotate Ruby code with tags that can be parsed and collected in code.
7
7
 
8
- Example:
8
+
9
+ ## Installation
10
+
11
+
12
+ Install the gem and add to the application's Gemfile by executing:
13
+
14
+ ```bash
15
+ bundle add tag_ripper
16
+ ```
17
+
18
+ If bundler is not being used to manage dependencies, install the gem by executing:
19
+
20
+ ```bash
21
+ gem install tag_ripper
22
+ ```
23
+
24
+ ## Usage
25
+
9
26
 
10
27
  ```ruby
11
28
  # @domain: Auth
@@ -35,25 +52,6 @@ TagRipper.new(File.read('user.rb')).taggables
35
52
  # parent: nil
36
53
  ```
37
54
 
38
- ## Installation
39
-
40
-
41
- Install the gem and add to the application's Gemfile by executing:
42
-
43
- ```bash
44
- bundle add tag_ripper
45
- ```
46
-
47
- If bundler is not being used to manage dependencies, install the gem by executing:
48
-
49
- ```bash
50
- gem install tag_ripper
51
- ```
52
-
53
- ## Usage
54
-
55
- TODO: Write usage instructions here
56
-
57
55
  ## Development
58
56
 
59
57
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -62,7 +60,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
62
60
 
63
61
  ## Contributing
64
62
 
65
- Bug reports and pull requests are welcome on GitHub at https://github.com/bodacious/tag-ripper. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/bodacious/tag-ripper/blob/master/CODE_OF_CONDUCT.md).
63
+ Bug reports and pull requests are welcome on GitHub at https://github.com/bodacious/tag_ripper. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/bodacious/tag_ripper/blob/master/CODE_OF_CONDUCT.md).
66
64
 
67
65
  ## License
68
66
 
@@ -70,4 +68,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
70
68
 
71
69
  ## Code of Conduct
72
70
 
73
- Everyone interacting in the Tag::Ripper project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/bodacious/tag-ripper/blob/master/CODE_OF_CONDUCT.md).
71
+ Everyone interacting in the Tag::Ripper project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/bodacious/tag_ripper/blob/master/CODE_OF_CONDUCT.md).
@@ -3,8 +3,22 @@ module TagRipper
3
3
  require "forwardable"
4
4
  extend Forwardable
5
5
 
6
- TAG_REGEX = /#\s@(?<tag_name>[\w_-]+):\s(?<tag_value>.+)/
7
- END_TOKEN = "end".freeze
6
+ TAG_REGEX = /#\s@(?<tag_name>[\w-]+):\s(?<tag_value>.+)/
7
+
8
+ ##
9
+ # = Operators =
10
+
11
+ DOUBLE_COLON = "::".freeze
12
+ SINGLETON_CLASS = "<<".freeze
13
+
14
+ ##
15
+ # = Keywords =
16
+
17
+ KEYWORD_CONST = "const".freeze
18
+ KEYWORD_CLASS = "class".freeze
19
+ KEYWORD_DEF = "def".freeze
20
+ KEYWORD_END = "end".freeze
21
+ KEYWORD_MODULE = "module".freeze
8
22
 
9
23
  class Location
10
24
  attr_reader :col
@@ -50,7 +64,11 @@ module TagRipper
50
64
  end
51
65
 
52
66
  def double_colon?
53
- token == "::"
67
+ token == DOUBLE_COLON
68
+ end
69
+
70
+ def singleton_class?
71
+ token == SINGLETON_CLASS
54
72
  end
55
73
 
56
74
  def keyword?
@@ -58,7 +76,7 @@ module TagRipper
58
76
  end
59
77
 
60
78
  def end?
61
- keyword? && token == END_TOKEN
79
+ keyword? && token == KEYWORD_END
62
80
  end
63
81
 
64
82
  def tag_name
@@ -76,13 +94,10 @@ module TagRipper
76
94
  def on_kw_type
77
95
  return nil unless keyword?
78
96
 
79
- case token
80
- when "const" then :class
81
- when "module" then :module
82
- when "def" then :instance_method
83
- else
84
- :unknown
85
- end
97
+ const_lookup = "KEYWORD_#{token.upcase}"
98
+ return :unknown unless self.class.const_defined?(const_lookup)
99
+
100
+ self.class.const_get(const_lookup).to_sym
86
101
  end
87
102
  end
88
103
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: false
2
+
1
3
  module TagRipper
2
4
  # Follows the state changes of a taggable entity (class, model, or method)
3
5
  # as it responds to various Lexical tokens.
@@ -26,6 +28,7 @@ module TagRipper
26
28
  pending
27
29
  tagged
28
30
  awaiting_name
31
+ naming
29
32
  named
30
33
  closed
31
34
  ].freeze
@@ -34,22 +37,32 @@ module TagRipper
34
37
  # @return [Array<Symbol>]
35
38
  OPENED_STATUSES = %i[tagged awaiting_name named].freeze
36
39
 
37
- def initialize(name: nil, parent: nil)
40
+ def initialize(name: nil, parent: nil, type: nil, status: :pending)
38
41
  @name = name
39
42
  @tags = Hash.new { |hash, key| hash[key] = Set.new }
40
43
  @parent = parent
41
- @type = nil
42
- self.status = :pending
44
+ @type = type
45
+ self.status = status
43
46
  end
44
47
 
45
48
  alias id object_id
46
49
 
47
50
  def send_event(event_name, lex)
48
- if respond_to?(event_name, true)
49
- send(event_name, lex)
50
- else
51
- self
52
- end
51
+ debug(<<~DEBUG)
52
+ Sending #{event_name} to #{self} with #{lex.token.inspect}
53
+ #{inspect}
54
+
55
+ DEBUG
56
+
57
+ return self unless respond_to?(event_name, true)
58
+
59
+ send(event_name, lex)
60
+ end
61
+
62
+ def debug(*strings)
63
+ return if ENV.fetch("TAG_RIPPER_DEBUG", "false") == "false"
64
+
65
+ puts strings.join(" - ")
53
66
  end
54
67
 
55
68
  def module?
@@ -63,7 +76,7 @@ module TagRipper
63
76
  # The fully-qualified name of this entity (e.g. +"Foo::Bar::MyClass"+)
64
77
  # @return [String]
65
78
  def fqn
66
- return nil unless named?
79
+ return nil unless name?
67
80
  return name if fqn_names.size == 1
68
81
 
69
82
  if type == :instance_method
@@ -100,12 +113,16 @@ module TagRipper
100
113
  self.status = :awaiting_name
101
114
  end
102
115
 
103
- def name=(name)
104
- unless may_name?
116
+ def name?
117
+ !!@name
118
+ end
119
+
120
+ def name=(value)
121
+ unless may_append_name?
105
122
  raise IllegalStateTransitionError.new(from: @status, to: :named)
106
123
  end
107
124
 
108
- @name = name.to_s
125
+ @name = value
109
126
  self.status = :named
110
127
  end
111
128
 
@@ -133,14 +150,28 @@ module TagRipper
133
150
  awaiting_name?
134
151
  end
135
152
 
153
+ def may_append_name?
154
+ awaiting_name? | naming?
155
+ end
156
+
136
157
  def may_close?
137
158
  named?
138
159
  end
139
160
 
161
+ def parent_id
162
+ parent&.id
163
+ end
164
+
140
165
  def inspect
141
- "<id=#{id},@name=#{@name},tags=#{@tags},parent=#{@parent}>"
166
+ exposed_properties = %i[object_id name fqn type parent_id status tags]
167
+ inner_string = exposed_properties.map do |property|
168
+ "#{property}=#{public_send(property)}"
169
+ end.join(", ")
170
+ "<#{inner_string}>"
142
171
  end
143
172
 
173
+ alias to_s inspect
174
+
144
175
  def tags
145
176
  @tags.dup
146
177
  end
@@ -153,11 +184,19 @@ module TagRipper
153
184
  @parent
154
185
  end
155
186
 
187
+ def status
188
+ @status
189
+ end
190
+
156
191
  protected
157
192
 
158
193
  def append_name!(string)
159
- raise StandardError, "Cannot append #{string} to nil" unless @name
194
+ unless may_append_name?
195
+ raise IllegalStateTransitionError.new(from: @status, to: :naming)
196
+ end
160
197
 
198
+ @status = :naming
199
+ @name ||= ""
161
200
  @name.concat(string.to_s)
162
201
  end
163
202
 
@@ -182,10 +221,6 @@ module TagRipper
182
221
  @tags[name].add(value)
183
222
  end
184
223
 
185
- def named?
186
- !!@name
187
- end
188
-
189
224
  def build_child
190
225
  self.class.new(parent: self)
191
226
  end
@@ -216,7 +251,7 @@ module TagRipper
216
251
  returnable_entity = named? ? build_child : self
217
252
 
218
253
  returnable_entity.await_name!
219
- self.type = lex.on_kw_type
254
+ returnable_entity.type = lex.on_kw_type
220
255
 
221
256
  returnable_entity
222
257
  end
@@ -229,22 +264,36 @@ module TagRipper
229
264
  define_method].freeze
230
265
  private_constant :IGNORED_IDENT_KEYWORDS
231
266
 
232
- def name_from_lex(lex) # rubocop:disable Metrics
267
+ def name_from_lex(lex)
233
268
  return self if IGNORED_IDENT_KEYWORDS.include?(lex.token)
234
- # TODO: Simplify this logic
235
- return self if named? && !@name.end_with?("::")
236
- return self unless may_name? || @name.end_with?("::")
237
269
 
238
- # self.status = :awaiting_name # TODO: Fix this with a proper state
239
- if named? && @name.end_with?("::")
240
- append_name!(lex.token)
241
- else
242
- self.name = "#{name}#{lex.token}"
243
- end
270
+ # If we are already done naming, then we don't want to name some more...
271
+ return self if named?
272
+
273
+ # Unless we are awaiting more name information, return self
274
+ return self unless may_append_name?
275
+
276
+ append_name!(lex.token)
244
277
 
245
278
  self
246
279
  end # rubocop:enable Metrics
247
280
 
281
+ # Token is not likely to be part of a TaggableEntity name
282
+ # (e.g. spaces, newlines, semicolons, keywords...)
283
+ def on_non_name_token(_lex)
284
+ if naming?
285
+ @status = :named
286
+ end
287
+ self
288
+ end
289
+
290
+ alias on_nl on_non_name_token
291
+ alias on_sp on_non_name_token
292
+ alias on_semicolon on_non_name_token
293
+ alias on_comma on_non_name_token
294
+ alias on_lparen on_non_name_token
295
+ alias on_rparen on_non_name_token
296
+
248
297
  ##
249
298
  # Matches names of constants: module names, const names, etc.
250
299
  alias on_const name_from_lex
@@ -254,9 +303,27 @@ module TagRipper
254
303
  alias on_ident name_from_lex
255
304
 
256
305
  def on_op(lex)
257
- if lex.double_colon?
306
+ if lex.double_colon? && may_append_name?
258
307
  append_name!(lex.token)
259
308
  end
309
+
310
+ # return name_from_op(lex) if lex.singleton_class?
311
+ self
312
+ end
313
+
314
+ def on_kw_self(lex)
315
+ if module? && awaiting_name?
316
+ self.name = lex.token
317
+ return self
318
+ end
319
+
320
+ self
321
+ end
322
+
323
+ ##
324
+ # Name the current entity 'self' based on an operator (e.g. +class << self+)
325
+ def name_from_kw(lex)
326
+ self.name = lex.token
260
327
  self
261
328
  end
262
329
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TagRipper
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tag_ripper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gavin Morrice
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-06-19 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: Add tags to your Ruby code comments and then Rip the as lexical tokens
13
13
  email:
@@ -21,6 +21,7 @@ files:
21
21
  - ".ruby-version"
22
22
  - CHANGELOG.md
23
23
  - CODE_OF_CONDUCT.md
24
+ - Guardfile
24
25
  - LICENSE.txt
25
26
  - README.md
26
27
  - Rakefile
@@ -52,7 +53,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
52
53
  - !ruby/object:Gem::Version
53
54
  version: '0'
54
55
  requirements: []
55
- rubygems_version: 3.6.2
56
+ rubygems_version: 3.6.7
56
57
  specification_version: 4
57
58
  summary: Rips tags from Ruby code
58
59
  test_files: []