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 +4 -4
- data/.rubocop.yml +1 -0
- data/.ruby-version +1 -1
- data/Guardfile +5 -0
- data/README.md +20 -22
- data/lib/tag_ripper/lexical_token.rb +26 -11
- data/lib/tag_ripper/taggable_entity.rb +97 -30
- data/lib/tag_ripper/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e8223c939423f3fce3c103a0e16649b925cc2cf9d0130618e4172c8f8e206bde
|
4
|
+
data.tar.gz: dbd6a188942b85df76b27189df7cdcbfea4257e10c6fd7003467fdb552eb25b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1a72eee3e5dbcafe2729452701418ea233ee6f0439bab493d7220687081a0fa9efc6ec20cb4d4fab5eaf6ea427e0fc5a5df7d6269f20bbfd53feadc5454abf50
|
7
|
+
data.tar.gz: 556c44f1683a4c46c896e11d4c0da33c1e1c14af6061a8ce28072feb8187bc56e6763e357e7d7a568c55da99f2edb95d78a13b56ff0b19124023df382d703be7
|
data/.rubocop.yml
CHANGED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.4.
|
1
|
+
3.4.3
|
data/Guardfile
ADDED
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
|
-
|
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/
|
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/
|
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>[\
|
7
|
-
|
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 ==
|
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
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
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 =
|
42
|
-
self.status =
|
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
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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
|
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
|
104
|
-
|
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 =
|
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
|
-
|
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
|
-
|
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
|
-
|
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)
|
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
|
-
#
|
239
|
-
if named?
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
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
|
|
data/lib/tag_ripper/version.rb
CHANGED
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.
|
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:
|
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.
|
56
|
+
rubygems_version: 3.6.7
|
56
57
|
specification_version: 4
|
57
58
|
summary: Rips tags from Ruby code
|
58
59
|
test_files: []
|