tag_ripper 0.1.0 → 0.2.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 +3 -2
- data/README.md +16 -5
- data/lib/tag_ripper/lexical_token.rb +4 -0
- data/lib/tag_ripper/taggable_entity.rb +83 -29
- data/lib/tag_ripper/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 375a528cbf8942e0dd48c51ffe10c005a6b3672b414e82b5d768011f3355e350
|
4
|
+
data.tar.gz: f3e74892414a1587e5dfabeba4cda6839f2dd500f800bda6303fa2ea97f18042
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49ababa76c465f7fa6a691f968290a6668762d884e0be15ca3790e6b6b884853aa1ff1bbbe78c9afdeef293b85ab4f3470357d635c9dda531257f26e81d4700b
|
7
|
+
data.tar.gz: 07311f3a4768f8643c0fafcab84f3b6318392a5c1726bcfccf2fcfd1291db35e4039d4493adeb4e0241765b086e56bd2fbb3feee4e9065452c4880df3a9d88f9
|
data/.rubocop.yml
CHANGED
@@ -8,7 +8,9 @@ AllCops:
|
|
8
8
|
TargetRubyVersion: 3.1
|
9
9
|
NewCops: enable
|
10
10
|
SuggestExtensions: true
|
11
|
-
|
11
|
+
Exclude:
|
12
|
+
- bin/*
|
13
|
+
- test/fixtures/**/* # These files have particular styles that should be preserved
|
12
14
|
Metrics/AbcSize:
|
13
15
|
Exclude:
|
14
16
|
- test/**/*
|
@@ -30,4 +32,3 @@ Style/TrivialAccessors:
|
|
30
32
|
|
31
33
|
Style/StringLiteralsInInterpolation:
|
32
34
|
EnforcedStyle: double_quotes
|
33
|
-
|
data/README.md
CHANGED
@@ -17,15 +17,26 @@ class User
|
|
17
17
|
end
|
18
18
|
|
19
19
|
TagRipper.new(File.read('user.rb')).taggables
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
20
|
+
# (Beautified output)
|
21
|
+
# ---
|
22
|
+
# -
|
23
|
+
# id: 2221
|
24
|
+
# name: some_method_that_isnt_tested
|
25
|
+
# tags:
|
26
|
+
# warning:
|
27
|
+
# - "untested
|
28
|
+
# parent: 22224,
|
29
|
+
# -
|
30
|
+
# id: 22224
|
31
|
+
# name: User
|
32
|
+
# tags:
|
33
|
+
# domain:
|
34
|
+
# - "Auth"
|
35
|
+
# parent: nil
|
24
36
|
```
|
25
37
|
|
26
38
|
## Installation
|
27
39
|
|
28
|
-
TODO: Replace `tag_ripper` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
|
29
40
|
|
30
41
|
Install the gem and add to the application's Gemfile by executing:
|
31
42
|
|
@@ -9,22 +9,42 @@ module TagRipper
|
|
9
9
|
# entity is spawned. This creates a sort of recursion that allows a taggable
|
10
10
|
# entity to be flexible to any amount of code nesting.
|
11
11
|
class TaggableEntity
|
12
|
+
# Unable to move transition from one state to another
|
12
13
|
class IllegalStateTransitionError < StandardError
|
13
14
|
def initialize(from:, to:)
|
14
15
|
super("Cannot transition from #{from} to #{to}")
|
15
16
|
end
|
16
17
|
end
|
17
18
|
|
19
|
+
# Attempting to set status to an unknown value
|
20
|
+
class InvalidStatusError < ArgumentError; end
|
21
|
+
|
22
|
+
# TODO: define naming state, to represent a partial name token
|
23
|
+
# The valid statuses that a TaggableEntity can move through.
|
24
|
+
# @return [Array<Symbol>]
|
25
|
+
VALID_STATUSES = %i[
|
26
|
+
pending
|
27
|
+
tagged
|
28
|
+
awaiting_name
|
29
|
+
named
|
30
|
+
closed
|
31
|
+
].freeze
|
32
|
+
|
33
|
+
# Statuses that represent an open lexical scope.
|
34
|
+
# @return [Array<Symbol>]
|
35
|
+
OPENED_STATUSES = %i[tagged awaiting_name named].freeze
|
36
|
+
|
18
37
|
def initialize(name: nil, parent: nil)
|
19
38
|
@name = name
|
20
39
|
@tags = Hash.new { |hash, key| hash[key] = Set.new }
|
21
40
|
@parent = parent
|
22
41
|
@type = nil
|
23
|
-
|
42
|
+
self.status = :pending
|
24
43
|
end
|
25
44
|
|
45
|
+
alias id object_id
|
46
|
+
|
26
47
|
def send_event(event_name, lex)
|
27
|
-
puts "send_event: #{event_name} - #{lex} #(#{@status})"
|
28
48
|
if respond_to?(event_name, true)
|
29
49
|
send(event_name, lex)
|
30
50
|
else
|
@@ -39,6 +59,9 @@ module TagRipper
|
|
39
59
|
def type
|
40
60
|
@type
|
41
61
|
end
|
62
|
+
|
63
|
+
# The fully-qualified name of this entity (e.g. +"Foo::Bar::MyClass"+)
|
64
|
+
# @return [String]
|
42
65
|
def fqn
|
43
66
|
return nil unless named?
|
44
67
|
return name if fqn_names.size == 1
|
@@ -51,14 +74,10 @@ module TagRipper
|
|
51
74
|
end
|
52
75
|
alias fully_qualified_name fqn
|
53
76
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
def awaiting_name? = @status == :awaiting_name
|
59
|
-
|
60
|
-
OPENED_STATUSES = %i[tagged awaiting_name named].freeze
|
61
|
-
|
77
|
+
# Have we opened a new lexical scope? (e.g. evaluating within the body
|
78
|
+
# of a class, rather than comments before the class)
|
79
|
+
#
|
80
|
+
# @return [Boolean]
|
62
81
|
def open?
|
63
82
|
OPENED_STATUSES.include?(@status)
|
64
83
|
end
|
@@ -68,7 +87,7 @@ module TagRipper
|
|
68
87
|
raise IllegalStateTransitionError.new(from: @status, to: :tagged)
|
69
88
|
end
|
70
89
|
|
71
|
-
|
90
|
+
self.status = :tagged
|
72
91
|
|
73
92
|
add_tag(tag_name, tag_value)
|
74
93
|
end
|
@@ -78,7 +97,7 @@ module TagRipper
|
|
78
97
|
raise IllegalStateTransitionError.new(from: @status, to: :awaiting_name)
|
79
98
|
end
|
80
99
|
|
81
|
-
|
100
|
+
self.status = :awaiting_name
|
82
101
|
end
|
83
102
|
|
84
103
|
def name=(name)
|
@@ -87,17 +106,19 @@ module TagRipper
|
|
87
106
|
end
|
88
107
|
|
89
108
|
@name = name.to_s
|
90
|
-
|
109
|
+
self.status = :named
|
91
110
|
end
|
92
111
|
|
93
112
|
def close!
|
94
113
|
@open = false
|
95
|
-
|
114
|
+
self.status = :closed
|
96
115
|
freeze
|
97
116
|
end
|
98
117
|
|
99
|
-
|
100
|
-
|
118
|
+
VALID_STATUSES.each do |status|
|
119
|
+
define_method(:"#{status}?") do
|
120
|
+
@status == status
|
121
|
+
end
|
101
122
|
end
|
102
123
|
|
103
124
|
def may_tag?
|
@@ -128,13 +149,28 @@ module TagRipper
|
|
128
149
|
@name.to_s.dup
|
129
150
|
end
|
130
151
|
|
131
|
-
def
|
132
|
-
@
|
152
|
+
def parent
|
153
|
+
@parent
|
133
154
|
end
|
134
155
|
|
135
156
|
protected
|
136
157
|
|
137
|
-
|
158
|
+
def append_name!(string)
|
159
|
+
raise StandardError, "Cannot append #{string} to nil" unless @name
|
160
|
+
|
161
|
+
@name.concat(string.to_s)
|
162
|
+
end
|
163
|
+
|
164
|
+
def status=(status)
|
165
|
+
status = status.to_sym
|
166
|
+
raise InvalidStatusError unless VALID_STATUSES.include?(status)
|
167
|
+
|
168
|
+
@status = status
|
169
|
+
end
|
170
|
+
|
171
|
+
def type=(type)
|
172
|
+
@type = type.to_sym
|
173
|
+
end
|
138
174
|
|
139
175
|
def fqn_names
|
140
176
|
return [name] if parent.nil?
|
@@ -142,10 +178,6 @@ module TagRipper
|
|
142
178
|
[*parent.fqn_names, name]
|
143
179
|
end
|
144
180
|
|
145
|
-
def parent
|
146
|
-
@parent
|
147
|
-
end
|
148
|
-
|
149
181
|
def add_tag(name, value)
|
150
182
|
@tags[name].add(value)
|
151
183
|
end
|
@@ -178,6 +210,8 @@ module TagRipper
|
|
178
210
|
send(event_token_method_name, lex)
|
179
211
|
end
|
180
212
|
|
213
|
+
##
|
214
|
+
# Lex is a keyword (e.g. def, class, module)
|
181
215
|
def on_new_taggable_context_kw(lex)
|
182
216
|
returnable_entity = named? ? build_child : self
|
183
217
|
|
@@ -191,21 +225,41 @@ module TagRipper
|
|
191
225
|
alias on_kw_module on_new_taggable_context_kw
|
192
226
|
alias on_kw_class on_new_taggable_context_kw
|
193
227
|
|
194
|
-
IGNORED_IDENT_KEYWORDS = %w[require private class_eval instance_eval
|
228
|
+
IGNORED_IDENT_KEYWORDS = %w[require private class_eval instance_eval
|
229
|
+
define_method].freeze
|
195
230
|
private_constant :IGNORED_IDENT_KEYWORDS
|
196
231
|
|
197
|
-
def name_from_lex(lex)
|
232
|
+
def name_from_lex(lex) # rubocop:disable Metrics
|
198
233
|
return self if IGNORED_IDENT_KEYWORDS.include?(lex.token)
|
199
|
-
|
200
|
-
return self
|
234
|
+
# TODO: Simplify this logic
|
235
|
+
return self if named? && !@name.end_with?("::")
|
236
|
+
return self unless may_name? || @name.end_with?("::")
|
237
|
+
|
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
|
201
244
|
|
202
|
-
self.name = lex.token
|
203
245
|
self
|
204
|
-
end
|
246
|
+
end # rubocop:enable Metrics
|
205
247
|
|
248
|
+
##
|
249
|
+
# Matches names of constants: module names, const names, etc.
|
206
250
|
alias on_const name_from_lex
|
251
|
+
|
252
|
+
##
|
253
|
+
# Matches tokens like: private, method names, argument names
|
207
254
|
alias on_ident name_from_lex
|
208
255
|
|
256
|
+
def on_op(lex)
|
257
|
+
if lex.double_colon?
|
258
|
+
append_name!(lex.token)
|
259
|
+
end
|
260
|
+
self
|
261
|
+
end
|
262
|
+
|
209
263
|
def on_kw_end(_lex)
|
210
264
|
close!
|
211
265
|
parent
|
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.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gavin Morrice
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-06-19 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:
|
@@ -30,13 +30,13 @@ files:
|
|
30
30
|
- lib/tag_ripper/ripper.rb
|
31
31
|
- lib/tag_ripper/taggable_entity.rb
|
32
32
|
- lib/tag_ripper/version.rb
|
33
|
-
homepage: https://github.com/Bodacious/
|
33
|
+
homepage: https://github.com/Bodacious/tag_ripper/
|
34
34
|
licenses:
|
35
35
|
- MIT
|
36
36
|
metadata:
|
37
|
-
homepage_uri: https://github.com/Bodacious/
|
38
|
-
source_code_uri: https://github.com/Bodacious/
|
39
|
-
changelog_uri: https://github.com/Bodacious/
|
37
|
+
homepage_uri: https://github.com/Bodacious/tag_ripper/
|
38
|
+
source_code_uri: https://github.com/Bodacious/tag_ripper/
|
39
|
+
changelog_uri: https://github.com/Bodacious/tag_ripper/
|
40
40
|
rubygems_mfa_required: 'true'
|
41
41
|
rdoc_options: []
|
42
42
|
require_paths:
|