Skip to content

Commit 71eee3b

Browse files
lekemulaclaude
andcommitted
Add support for symbol and string literals in TypesExplainer
- Add LITERALMATCH regex constant to match symbol (:symbol) and string ('string', "string") literals - Update TypesExplainer parser to recognize symbol and string literal types - Format literal values as "a literal value :symbol" for better readability - Add comprehensive test coverage for LITERALMATCH constant and literal type parsing - Fixes parsing inconsistency between YARD TypesExplainer and online parser Resolves #1627 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 5b93b3a commit 71eee3b

File tree

4 files changed

+47
-2
lines changed

4 files changed

+47
-2
lines changed

lib/yard/code_objects/base.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ def push(value)
6363
# Regular expression to match a fully qualified method def (self.foo, Class.foo).
6464
METHODMATCH = /(?:(?:#{NAMESPACEMATCH}|[a-z]\w*)\s*(?:#{CSEPQ}|#{NSEPQ})\s*)?#{METHODNAMEMATCH}/
6565

66+
# Regular expression to match symbol and string literals
67+
LITERALMATCH = /:\w+|'[^']*'|"[^"]*"/
68+
6669
# All builtin Ruby exception classes for inheritance tree.
6770
BUILTIN_EXCEPTIONS = ["ArgumentError", "ClosedQueueError", "EncodingError",
6871
"EOFError", "Exception", "FiberError", "FloatDomainError", "IndexError",

lib/yard/tags/types_explainer.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ def initialize(name)
3333
def to_s(singular = true)
3434
if name[0, 1] == "#"
3535
singular ? "an object that responds to #{name}" : "objects that respond to #{name}"
36+
elsif name[0, 1] == ":" || (name[0, 1] =~ /['"]/ && name[-1, 1] =~ /['"]/)
37+
"a literal value #{name}"
3638
elsif name[0, 1] =~ /[A-Z]/
3739
singular ? "a#{name[0, 1] =~ /[aeiou]/i ? 'n' : ''} " + name : "#{name}#{name[-1, 1] =~ /[A-Z]/ ? "'" : ''}s"
3840
else
@@ -101,7 +103,7 @@ class Parser
101103
:collection_end => />/,
102104
:fixed_collection_start => /\(/,
103105
:fixed_collection_end => /\)/,
104-
:type_name => /#{ISEP}#{METHODNAMEMATCH}|#{NAMESPACEMATCH}|\w+/,
106+
:type_name => /#{ISEP}#{METHODNAMEMATCH}|#{NAMESPACEMATCH}|#{LITERALMATCH}|\w+/,
105107
:type_next => /[,;]/,
106108
:whitespace => /\s+/,
107109
:hash_collection_start => /\{/,

spec/code_objects/constants_spec.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,26 @@ def silence_warnings
5656
end
5757
end
5858

59+
describe :LITERALMATCH do
60+
it "matches symbol literals" do
61+
expect(":symbol"[CodeObjects::LITERALMATCH]).to eq ":symbol"
62+
expect(":some_symbol"[CodeObjects::LITERALMATCH]).to eq ":some_symbol"
63+
expect("not_a_symbol"[CodeObjects::LITERALMATCH]).to be nil
64+
end
65+
66+
it "matches single-quoted string literals" do
67+
expect("'string'"[CodeObjects::LITERALMATCH]).to eq "'string'"
68+
expect("'some string with spaces'"[CodeObjects::LITERALMATCH]).to eq "'some string with spaces'"
69+
expect("not_quoted"[CodeObjects::LITERALMATCH]).to be nil
70+
end
71+
72+
it "matches double-quoted string literals" do
73+
expect('"string"'[CodeObjects::LITERALMATCH]).to eq '"string"'
74+
expect('"some string with spaces"'[CodeObjects::LITERALMATCH]).to eq '"some string with spaces"'
75+
expect("not_quoted"[CodeObjects::LITERALMATCH]).to be nil
76+
end
77+
end
78+
5979
describe :BUILTIN_EXCEPTIONS do
6080
it "includes all base exceptions" do
6181
bad_names = []

spec/tags/types_explainer_spec.rb

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ def parse_fail(types)
4545
expect(@t.to_s(false)).to eq name
4646
end
4747
end
48+
49+
it "works for literal values" do
50+
[':symbol', "'5'"].each do |name|
51+
@t.name = name
52+
expect(@t.to_s).to eq "a literal value #{name}"
53+
expect(@t.to_s(false)).to eq "a literal value #{name}"
54+
end
55+
end
4856
end
4957

5058
describe CollectionType, '#to_s' do
@@ -131,6 +139,17 @@ def parse_fail(types)
131139
expect(type[3].name).to eq "E"
132140
end
133141

142+
it 'parses a list of literal values' do
143+
type = parse("true, false, nil, 4, :symbol, '5'")
144+
expect(type.size).to eq 6
145+
expect(type[0].name).to eq "true"
146+
expect(type[1].name).to eq "false"
147+
expect(type[2].name).to eq "nil"
148+
expect(type[3].name).to eq "4"
149+
expect(type[4].name).to eq ":symbol"
150+
expect(type[5].name).to eq "'5'"
151+
end
152+
134153
it "parses a collection type" do
135154
type = parse("MyList<String>")
136155
expect(type.first).to be_a(CollectionType)
@@ -192,7 +211,8 @@ def parse_fail(types)
192211
a Hash with keys made of (Foos or Bars) and values of (Symbols or Numbers)",
193212
"#weird_method?, #<=>, #!=" => "an object that responds to #weird_method?;
194213
an object that responds to #<=>;
195-
an object that responds to #!="
214+
an object that responds to #!=",
215+
":symbol, 'string'" => "a literal value :symbol; a literal value 'string'"
196216
}
197217
expect.each do |input, expected|
198218
explain = YARD::Tags::TypesExplainer.explain(input)

0 commit comments

Comments
 (0)