docrb-parser 0.1.0 → 0.1.2

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: bfa4a19237733b6e0ace1d9af8584eeeb1dc671ec3a08c000d2b5f99adfcfa90
4
- data.tar.gz: 02e8182ff82e529c89c99655411a7980a56c89a511263923616468c1bbbc0f65
3
+ metadata.gz: ad89c50b2d48ce08a1c2c2584fd09f765b43555f8d8daf67b1eb727524f81855
4
+ data.tar.gz: 4b297fde78ae009658f319812c8f3d605d7bfbaf7f9e9f7621867a2e856323ff
5
5
  SHA512:
6
- metadata.gz: '048771cd5044806674962f019c76fa4fedbd5f2778ff461b3b7fd4eef77076bf93b4562283b5667318d0f68d99d7c816dd77b6a803c26fe8859f6f8358075ea7'
7
- data.tar.gz: ba979ca0cb853ec2a3ef2542957f887f0b5b9e92355e380e1006bfd6883e06506b65ed49c3ed867116f7f11bfc9e32470b595a140e2917d669f5b407667e579c
6
+ metadata.gz: 39c21d2bc0feb1796b612cdf59e0d1c5f8bc545ce9294765a02153c03f8883f9493bfabe0f570e30b60fc548d40a27f5a41d1fd3c49eff0dc8cc66dc2b4d8433
7
+ data.tar.gz: 646866daab9663552dd05e253f4cc90cf0081e19cd0c3899dabc83ed6b681f3abe66389820b2703468b2fc77dece7f59c7e14c49329101a0ce258e3e758f782f
data/docrb-parser.gemspec CHANGED
@@ -5,7 +5,7 @@ require_relative "lib/docrb/parser/version"
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "docrb-parser"
7
7
  spec.version = Docrb::Parser::VERSION
8
- spec.authors = ["Victor Gama"]
8
+ spec.authors = ["Vito Sartori"]
9
9
  spec.email = ["hey@vito.io"]
10
10
 
11
11
  spec.summary = "Docrb's Ruby Parser"
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.required_ruby_version = ">= 3.2"
19
19
 
20
20
  spec.metadata["homepage_uri"] = spec.homepage
21
- spec.metadata["source_code_uri"] = "#{spec.homepage}/tree/trunk/lib/docrb-parser"
21
+ spec.metadata["source_code_uri"] = "#{spec.homepage}/tree/master/lib/docrb-parser"
22
22
  spec.metadata["changelog_uri"] = spec.homepage
23
23
  spec.metadata["rubygems_mfa_required"] = "true"
24
24
 
@@ -34,5 +34,5 @@ Gem::Specification.new do |spec|
34
34
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
35
35
  spec.require_paths = ["lib"]
36
36
 
37
- spec.add_dependency "prism", "~> 0.13"
37
+ spec.add_dependency "prism", "~> 1"
38
38
  end
@@ -64,7 +64,10 @@ module Docrb
64
64
  return false if parent.nil? || !parent.fulfilled?
65
65
  return true if parent.resolved.id == obj.parent.id
66
66
 
67
- is_inherited?(obj, parent.dereference!.inherits)
67
+ deref = parent.dereference!
68
+ return is_inherited?(obj, deref.inherits) if deref.is_a? Class
69
+
70
+ false
68
71
  end
69
72
 
70
73
  def source_of(obj)
@@ -10,6 +10,11 @@ module Docrb
10
10
  SPACE = " "
11
11
  DASH = "-"
12
12
  COLON = ":"
13
+ IGNORED_ANNOTATIONS = [
14
+ ":nodoc:",
15
+ ":nocov:",
16
+ /^rubocop:\s?(enable|disable)/
17
+ ].freeze
13
18
 
14
19
  attr_accessor :objects, :current_object, :cursor, :visibility
15
20
 
@@ -17,8 +22,8 @@ module Docrb
17
22
  new(data)
18
23
  .tap(&:parse)
19
24
  .then do |parser|
20
- { meta: { visibility: parser.visibility }.compact, value: parser.objects }
21
- end
25
+ { meta: { visibility: parser.visibility }.compact, value: parser.objects }
26
+ end
22
27
  end
23
28
 
24
29
  def initialize(data)
@@ -28,6 +33,7 @@ module Docrb
28
33
  .split(NEWLINE)
29
34
  .map(&:rstrip)
30
35
  .map { _1.gsub(/^\s*#\s?/, "") }
36
+ .reject { reject_annotation? _1 }
31
37
  .join(NEWLINE)
32
38
  .each_grapheme_cluster
33
39
  .to_a
@@ -37,6 +43,16 @@ module Docrb
37
43
  @cursor = 0
38
44
  end
39
45
 
46
+ def reject_annotation?(value)
47
+ IGNORED_ANNOTATIONS.any? do |match|
48
+ case match
49
+ when Regexp then match.match? value
50
+ when String then value == match
51
+ else false
52
+ end
53
+ end
54
+ end
55
+
40
56
  def at_end? = (cursor >= @data_len)
41
57
 
42
58
  def will_end? = (cursor + 1 >= @data_len)
@@ -173,13 +189,13 @@ module Docrb
173
189
  end
174
190
 
175
191
  # rubocop:disable Layout/LineLength
176
- COMMENT_METHOD_REF_REGEXP = /(?:([A-Z][a-zA-Z0-9_]*::)*([A-Z][a-zA-Z0-9_]*))?(::|\.|#)([A-Za-z_][a-zA-Z0-9_@]*[!?]?)(?:\([a-zA-Z0-9=_,\s*]+\))?/
192
+ COMMENT_METHOD_REF_REGEXP = /(?:((?:::)?(?:[a-z][a-z0-9_]*::)*)([a-z][a-z0-9_]*))?(::|\.|#)([a-z_][a-z0-9_@]*[!?]?)(?:\([a-z0-9:=_,\s*]+\))?/i
177
193
  # rubocop:enable Layout/LineLength
178
194
 
179
195
  def extract_method_reference(text)
180
196
  match = COMMENT_METHOD_REF_REGEXP.match(text) or return nil
181
197
  value, class_path, target, invocation, name = match.to_a
182
- class_path&.gsub!(/::$/, "")
198
+ class_path&.gsub!(/(^::|::$)/, "")
183
199
 
184
200
  {
185
201
  start_idx: match.begin(0),
@@ -39,11 +39,16 @@ module Docrb
39
39
  last_found_node = resolve[:last_found_node] || parser
40
40
  if resolve[:missing_segments].empty?
41
41
  remove_from_parent!(node, parent: node.parent)
42
- node.parent = resolve[:last_found_node]
43
- if node.is_a? Class
44
- last_found_node.classes << node
45
- elsif node.is_a? Module
46
- last_found_node.modules << node
42
+ if last_found_node.is_a? Parser
43
+ node.parent = nil
44
+ last_found_node.nodes.append(node)
45
+ else
46
+ node.parent = resolve[:last_found_node]
47
+ if node.is_a? Class
48
+ last_found_node.classes << node
49
+ elsif node.is_a? Module
50
+ last_found_node.modules << node
51
+ end
47
52
  end
48
53
 
49
54
  return
@@ -93,59 +98,74 @@ module Docrb
93
98
  obj[:value].transform_values! { resolve_documentation_reference(node, _1) }
94
99
  obj
95
100
  when :method_ref
96
- resolve_documentation_pure_reference(node, obj)
101
+ resolve_method_reference(node, obj)
97
102
  when :span, :symbol
98
103
  obj
104
+ when :identifier
105
+ if obj[:value].to_sym == node.try(:name)&.to_sym
106
+ obj[:type] = :neutral_identifier
107
+ else
108
+ container = if node.is_a? Container
109
+ node
110
+ else
111
+ find_next_container(node)
112
+ end
113
+ resolved = resolve_path(container, [obj[:value].to_sym])
114
+ if resolved.respond_to?(:id)
115
+ obj[:type] = :reference
116
+ obj[:id] = resolved.id
117
+ obj[:path] = path_of(resolved)
118
+ else
119
+ obj[:type] = :unresolved_identifier
120
+ end
121
+ end
122
+ obj
123
+ when :class_path_ref
124
+ resolve_class_path_reference(node, obj)
99
125
  else
100
126
  puts "Unhandled documentation node #{obj[:type]}"
101
127
  obj
102
128
  end
129
+ end
130
+
131
+ def resolve_class_path_reference(node, ref)
132
+ path = (ref[:class_path].gsub(/(^::|::$)/, "").split("::") + [ref[:target]]).flatten.compact.map(&:to_sym)
133
+ node = find_next_container(node) unless node.is_a? Container
134
+ resolved = resolve_path_partial(path, node)
135
+
136
+ unless resolved[:missing_segments].empty?
137
+ ref[:type] = :unresolved_identifier
138
+ return ref
139
+ end
140
+
141
+ prefix = /^(::)/.match(ref[:value])&.to_a&.last
142
+ segments = resolved[:segment_list]
143
+ target = resolved[:last_found_node].all_objects.named(ref[:name].to_sym).first
144
+
145
+ if target.nil?
146
+ ref[:type] = :unresolved_identifier
147
+ return ref
148
+ end
103
149
 
104
- # obj[:value].each do |v|
105
- # case v[:type]
106
- # when :identifier
107
- # if v[:value].to_sym == node.try(:name)&.to_sym
108
- # v[:type] = :neutral_identifier
109
- # else
110
- # resolved = resolve_path(node, [v[:value].to_sym])
111
- # if resolved.respond_to?(:id)
112
- # v[:type] = :reference
113
- # v[:id] = resolved.id
114
- # v[:path] = path_of(resolved)
115
- # else
116
- # v[:type] = :unresolved_identifier
117
- # end
118
- # end
119
- # when :reference
120
- # resolve_documentation_pure_reference(v, node)
121
- # when :block
122
- # v[:value]
123
- # .reject { [:span, :symbol].include? _1[:type] }
124
- # .each { resolve_documentation_reference(node, _1) }
125
- # when :fields
126
- # val = v[:value].values.flatten
127
- # resolve_documentation_reference(node, { value: val })
128
- # else
129
- # puts "Unhandled documentation node #{v[:type]}"
130
- # end
131
- # end
150
+ {
151
+ type: :class_path_reference,
152
+ prefix:,
153
+ segments:,
154
+ target:
155
+ }
132
156
  end
133
157
 
134
- def resolve_documentation_pure_reference(node, ref)
158
+ def resolve_method_reference(node, ref)
135
159
  return ref if ref.key? :object
136
160
 
137
161
  node = find_next_container(node) unless node.is_a? Container
138
162
  name = ref[:name].to_sym
139
163
  obj = if ref[:class_path]
140
- resolve_path(ref[:class_path].split("::").map(&:to_sym), node)
164
+ resolve_path(node, ref[:class_path].split("::").map(&:to_sym))
141
165
  else
142
166
  node
143
167
  end
144
- result = if ref[:type] == :method
145
- obj.all_instance_methods.named(name).first || obj.all_class_methods.named(name).first
146
- else
147
- obj.all_objects.named(name).first
148
- end
168
+ result = resolve_path(obj, [ref[:target], name].compact.map(&:to_sym))
149
169
 
150
170
  if result.nil?
151
171
  ref[:type] = :unresolved_identifier
@@ -347,6 +367,7 @@ module Docrb
347
367
  c_filter = -> { container_only ? _1.is_a?(Container) : true }
348
368
 
349
369
  found_segments = []
370
+ segment_list = []
350
371
  until path.empty?
351
372
  last_parent = parent
352
373
  if parent.is_a? Parser
@@ -357,6 +378,7 @@ module Docrb
357
378
  end
358
379
 
359
380
  found_segments << path.shift
381
+ segment_list << parent
360
382
  next
361
383
  end
362
384
 
@@ -365,14 +387,15 @@ module Docrb
365
387
  parent = last_parent
366
388
  break
367
389
  end
368
-
369
390
  found_segments << path.shift
391
+ segment_list << parent
370
392
  end
371
393
 
372
394
  {
373
395
  last_found_node: parent,
374
396
  found_segments:,
375
- missing_segments: path
397
+ missing_segments: path,
398
+ segment_list:
376
399
  }
377
400
  end
378
401
 
@@ -455,8 +478,7 @@ module Docrb
455
478
  container&.all_class_methods&.named(name)&.first ||
456
479
  container&.all_class_attributes&.named(name)&.first ||
457
480
  (find_object(container.parent, name, container_only:) if container&.parent) ||
458
- parser.nodes.lazy.filter { _1.is_a?(Container) && _1.name == name }.first ||
459
- parser.nodes.lazy.filter { _1.is_a? Container }.first { find_object(_1, name) }
481
+ parser.nodes.lazy.filter { _1.is_a?(Container) && _1.name == name }.first
460
482
  end
461
483
 
462
484
  def find_next_container(obj)
@@ -108,9 +108,9 @@ module Docrb
108
108
  case
109
109
  when parent == id
110
110
  :self
111
- when @includes.filter(&:fulfilled?).any? { _1.resolved.id == id }
111
+ when @includes.filter(&:fulfilled?).any? { _1.resolved.id == parent }
112
112
  :included
113
- when @extends.filter(&:fulfilled?).any? { _1.resolved.id == id }
113
+ when @extends.filter(&:fulfilled?).any? { _1.resolved.id == parent }
114
114
  :extended
115
115
  else
116
116
  :unknown
@@ -13,7 +13,8 @@ module Docrb
13
13
  when Prism::RequiredParameterNode then :arg
14
14
  when Prism::OptionalParameterNode then :optarg
15
15
  when Prism::RestParameterNode then :rest
16
- when Prism::KeywordParameterNode then n.value ? :optkw : :kw
16
+ when Prism::OptionalKeywordParameterNode then n.value ? :optkw : :kw
17
+ when Prism::RequiredKeywordParameterNode then :kw
17
18
  when Prism::KeywordRestParameterNode then :kwrest
18
19
  when Prism::BlockParameterNode then :block
19
20
  else raise NotImplementedError, "Unsupported parameter kind #{n.class}"
@@ -75,6 +76,7 @@ module Docrb
75
76
  when Prism::StringNode then :string
76
77
  when Prism::IntegerNode, Prism::FloatNode then :number
77
78
  when Prism::ConstantReadNode, Prism::ConstantPathNode then :const
79
+ when Prism::HashNode then :hash
78
80
  else
79
81
  puts "Unhandled parameter value type #{value.class.name}"
80
82
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Docrb
4
4
  class Parser
5
- VERSION = "0.1.0"
5
+ VERSION = "0.1.2"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: docrb-parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
- - Victor Gama
7
+ - Vito Sartori
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-28 00:00:00.000000000 Z
11
+ date: 2024-09-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: prism
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.13'
19
+ version: '1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.13'
26
+ version: '1'
27
27
  description: "docrb-parser is responsible for parsing Ruby sources into a structured
28
28
  \nformat for usage by docrb and docrb-html.\n"
29
29
  email:
@@ -84,7 +84,7 @@ licenses:
84
84
  - MIT
85
85
  metadata:
86
86
  homepage_uri: https://github.com/heyvito/docrb
87
- source_code_uri: https://github.com/heyvito/docrb/tree/trunk/lib/docrb-parser
87
+ source_code_uri: https://github.com/heyvito/docrb/tree/master/lib/docrb-parser
88
88
  changelog_uri: https://github.com/heyvito/docrb
89
89
  rubygems_mfa_required: 'true'
90
90
  post_install_message:
@@ -102,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
102
102
  - !ruby/object:Gem::Version
103
103
  version: '0'
104
104
  requirements: []
105
- rubygems_version: 3.4.10
105
+ rubygems_version: 3.5.18
106
106
  signing_key:
107
107
  specification_version: 4
108
108
  summary: Docrb's Ruby Parser