Skip to content

Commit 197e8d5

Browse files
committed
GemSpec: new parser
Signed-off-by: Masatake YAMATO <[email protected]>
1 parent 05e6ab4 commit 197e8d5

File tree

11 files changed

+304
-0
lines changed

11 files changed

+304
-0
lines changed

Tmain/list-roles.d/stdout-expected.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ DTD p/parameterEntity partOfAttDef on part of attribute de
4242
Elm m/module imported on imported module
4343
Flex I/import import on imports
4444
GDScript c/class extended on used as a base class for extending
45+
GemSpec g/gem develDep on specifying development dependency
46+
GemSpec g/gem runtimeDep on specifying runtime dependency
4547
Go p/package imported on imported package
4648
Go u/unknown receiverType on receiver type
4749
HTML C/stylesheet extFile on referenced as external files
@@ -143,6 +145,8 @@ DTD p/parameterEntity partOfAttDef on part of attribute de
143145
Elm m/module imported on imported module
144146
Flex I/import import on imports
145147
GDScript c/class extended on used as a base class for extending
148+
GemSpec g/gem develDep on specifying development dependency
149+
GemSpec g/gem runtimeDep on specifying runtime dependency
146150
Go p/package imported on imported package
147151
Go u/unknown receiverType on receiver type
148152
HTML C/stylesheet extFile on referenced as external files

Tmain/list-subparsers-all.d/stdout-expected.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Autoconf M4 base <> sub {bidirectional}
44
Automake Make base <= sub {dedicated}
55
DBusIntrospect XML base <> sub {bidirectional}
66
FunctionParameters Perl base <> sub {bidirectional}
7+
GemSpec Ruby base <= sub {dedicated}
78
Glade XML base <> sub {bidirectional}
89
IPythonCell Python base => sub {shared}
910
ITcl Tcl base <> sub {bidirectional}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
--sort=no
2+
--extras=+r
3+
--fields=+r
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
rspec/core/version input.gemspec /^require "rspec\/core\/version"$/;" L roles:required
2+
rspec-core input.gemspec /^ s.name = "rspec-core"$/;" g roles:def
3+
rspec-support input.gemspec /^ s.add_runtime_dependency "rspec-support", "= #{RSpec::Core::Version::STRING}"$/;" g roles:runtimeDep
4+
rspec-support input.gemspec /^ s.add_runtime_dependency "rspec-support", "~> #{RSpec::Core::Version::STRING.split('.')[0..1/;" g roles:runtimeDep
5+
cucumber input.gemspec /^ s.add_development_dependency "cucumber", "~> 1.3"$/;" g roles:develDep
6+
minitest input.gemspec /^ s.add_development_dependency "minitest", "~> 5.3"$/;" g roles:develDep
7+
aruba input.gemspec /^ s.add_development_dependency "aruba", "~> 0.14.9"$/;" g roles:develDep
8+
coderay input.gemspec /^ s.add_development_dependency "coderay", "~> 1.1.1"$/;" g roles:develDep
9+
mocha input.gemspec /^ s.add_development_dependency "mocha", "~> 0.13.0"$/;" g roles:develDep
10+
rr input.gemspec /^ s.add_development_dependency "rr", "~> 1.0.4"$/;" g roles:develDep
11+
flexmock input.gemspec /^ s.add_development_dependency "flexmock", "~> 0.9.0"$/;" g roles:develDep
12+
thread_order input.gemspec /^ s.add_development_dependency "thread_order", "~> 1.1.0"$/;" g roles:develDep
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Taken from rspec-core/rspec-core.gemspec
2+
3+
# -*- encoding: utf-8 -*-
4+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
5+
require "rspec/core/version"
6+
7+
Gem::Specification.new do |s|
8+
s.name = "rspec-core"
9+
s.version = RSpec::Core::Version::STRING
10+
s.platform = Gem::Platform::RUBY
11+
s.license = "MIT"
12+
s.authors = ["Steven Baker", "David Chelimsky", "Chad Humphries", "Myron Marston"]
13+
s.email = "[email protected]"
14+
s.homepage = "https://github.com/rspec/rspec-core"
15+
s.summary = "rspec-core-#{RSpec::Core::Version::STRING}"
16+
s.description = "BDD for Ruby. RSpec runner and example groups."
17+
18+
s.metadata = {
19+
'bug_tracker_uri' => 'https://github.com/rspec/rspec-core/issues',
20+
'changelog_uri' => "https://github.com/rspec/rspec-core/blob/v#{s.version}/Changelog.md",
21+
'documentation_uri' => 'https://rspec.info/documentation/',
22+
'mailing_list_uri' => 'https://groups.google.com/forum/#!forum/rspec',
23+
'source_code_uri' => 'https://github.com/rspec/rspec-core',
24+
}
25+
26+
s.files = `git ls-files -- lib/*`.split("\n")
27+
s.files += %w[README.md LICENSE.md Changelog.md .yardopts .document]
28+
s.test_files = []
29+
s.bindir = 'exe'
30+
s.executables = `git ls-files -- exe/*`.split("\n").map{ |f| File.basename(f) }
31+
s.rdoc_options = ["--charset=UTF-8"]
32+
s.require_path = "lib"
33+
34+
s.required_ruby_version = '>= 1.8.7'
35+
36+
private_key = File.expand_path('~/.gem/rspec-gem-private_key.pem')
37+
if File.exist?(private_key)
38+
s.signing_key = private_key
39+
s.cert_chain = [File.expand_path('~/.gem/rspec-gem-public_cert.pem')]
40+
end
41+
42+
if RSpec::Core::Version::STRING =~ /[a-zA-Z]+/
43+
# rspec-support is locked to our version when running pre,rc etc
44+
s.add_runtime_dependency "rspec-support", "= #{RSpec::Core::Version::STRING}"
45+
else
46+
# rspec-support must otherwise match our major/minor version
47+
s.add_runtime_dependency "rspec-support", "~> #{RSpec::Core::Version::STRING.split('.')[0..1].concat(['0']).join('.')}"
48+
end
49+
50+
s.add_development_dependency "cucumber", "~> 1.3"
51+
s.add_development_dependency "minitest", "~> 5.3"
52+
s.add_development_dependency "aruba", "~> 0.14.9"
53+
54+
s.add_development_dependency "coderay", "~> 1.1.1"
55+
56+
s.add_development_dependency "mocha", "~> 0.13.0"
57+
s.add_development_dependency "rr", "~> 1.0.4"
58+
s.add_development_dependency "flexmock", "~> 0.9.0"
59+
s.add_development_dependency "thread_order", "~> 1.1.0"
60+
end

docs/news.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ The following parsers have been added:
414414
* Falcon
415415
* FunctionParameters *perl based subparser*
416416
* Gdbinit script *optlib*
417+
* GemSpec *Ruby based subparser*
417418
* GDScript
418419
* Glade *libxml*
419420
* Go

main/parsers_p.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
FyppParser, \
8989
GdbinitParser, \
9090
GDScriptParser, \
91+
GemSpecParser, \
9192
GoParser, \
9293
HaskellParser, \
9394
HaxeParser, \

parsers/gemspec.c

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
/*
2+
* A parser for RUBYGEM's specification
3+
*
4+
* Copyright (c) 2021, Red Hat, Inc.
5+
* Copyright (c) 2021, Masatake YAMATO
6+
*
7+
* Author: Masatake YAMATO <[email protected]>
8+
*
9+
* This program is free software; you can redistribute it and/or
10+
* modify it under the terms of the GNU General Public License
11+
* as published by the Free Software Foundation; either version 2
12+
* of the License, or (at your option) any later version.
13+
*
14+
* This program is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU General Public License
20+
* along with this program; if not, write to the Free Software
21+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22+
* USA.
23+
*
24+
* Reference:
25+
* - https://guides.rubygems.org/specification-reference/
26+
*
27+
* See also:
28+
* - https://yehudakatz.com/2010/12/16/clarifying-the-roles-of-the-gemspec-and-gemfile/
29+
*/
30+
31+
/*
32+
* INCLUDE FILES
33+
*/
34+
#include "general.h" /* must always come first */
35+
36+
#include "entry.h"
37+
#include "parse.h"
38+
#include "subparser.h"
39+
40+
#include "ruby.h"
41+
42+
#include <string.h>
43+
44+
/*
45+
* DATA STRUCTURES
46+
*/
47+
struct sGemSpecSubparser {
48+
rubySubparser ruby;
49+
vString *var_name;
50+
};
51+
52+
typedef enum {
53+
K_GEM,
54+
} gemspecKind;
55+
56+
typedef enum {
57+
R_GEM_RUNTIME_DEP,
58+
R_GEM_DEVEL_DEP,
59+
} gemspecGemRole;
60+
61+
static roleDefinition GemSpecGemRoles [] = {
62+
{ true, "runtimeDep", "specifying runtime dependency" },
63+
{ true, "develDep", "specifying development dependency" },
64+
};
65+
66+
static kindDefinition GemSpecKinds [] = {
67+
{ true, 'g', "gem", "gems",
68+
.referenceOnly = false, ATTACH_ROLES(GemSpecGemRoles)},
69+
};
70+
71+
/*
72+
* FUNCTIONS
73+
*/
74+
static void findGemSpecTags (void)
75+
{
76+
scheduleRunningBaseparser (0);
77+
}
78+
79+
static int lineNotify (rubySubparser *s, const unsigned char **cp)
80+
{
81+
struct sGemSpecSubparser *gemspec = (struct sGemSpecSubparser *)s;
82+
const unsigned char *p = *cp;
83+
84+
if (vStringLength (gemspec->var_name) > 0
85+
&& (strncmp ((char *)p, vStringValue (gemspec->var_name),
86+
vStringLength (gemspec->var_name)) == 0))
87+
{
88+
int kind = K_GEM;
89+
int role = ROLE_DEFINITION_INDEX;
90+
bool is_attr = true;
91+
92+
p += vStringLength (gemspec->var_name);
93+
94+
if (strncmp ((const char *)p, "name", 4) == 0)
95+
p += 4;
96+
else if (strncmp ((const char *)p, "add_runtime_dependency", 22) == 0)
97+
{
98+
p += 22;
99+
role = R_GEM_RUNTIME_DEP;
100+
is_attr = false;
101+
}
102+
else if (strncmp ((const char *)p, "add_development_dependency", 26) == 0)
103+
{
104+
p += 26;
105+
role = R_GEM_DEVEL_DEP;
106+
is_attr = false;
107+
}
108+
else
109+
p = NULL;
110+
111+
if (p)
112+
{
113+
rubySkipWhitespace (&p);
114+
if ((!is_attr) || *p == '=')
115+
{
116+
if (is_attr)
117+
{
118+
p++;
119+
rubySkipWhitespace (&p);
120+
}
121+
if (*p == '"' || *p == '\'')
122+
{
123+
unsigned char b = *p;
124+
vString *gem = vStringNew ();
125+
p++;
126+
if (rubyParseString (&p, b, gem))
127+
{
128+
if (role == ROLE_DEFINITION_INDEX)
129+
makeSimpleTag (gem, kind);
130+
else
131+
makeSimpleRefTag (gem, kind, role);
132+
}
133+
vStringDelete (gem);
134+
}
135+
}
136+
}
137+
}
138+
else if (rubyCanMatchKeywordWithAssign (&p, "Gem::Specification.new"))
139+
{
140+
vString *vstr = vStringNew ();
141+
bool curly_bracket = false;
142+
143+
rubySkipWhitespace (&p);
144+
145+
curly_bracket = (*p == '{');
146+
if (curly_bracket
147+
|| (rubyParseMethodName (&p, vstr)
148+
&& vStringLength (vstr) == 2
149+
&& strcmp (vStringValue(vstr), "do") == 0))
150+
{
151+
if (curly_bracket)
152+
p++;
153+
154+
rubySkipWhitespace (&p);
155+
if (*p == '|')
156+
{
157+
p++;
158+
rubySkipWhitespace (&p);
159+
vStringClear (vstr);
160+
if (rubyParseMethodName (&p, vstr))
161+
{
162+
vStringPut (vstr, '.');
163+
vStringCopy(gemspec->var_name, vstr);
164+
}
165+
}
166+
}
167+
vStringDelete (vstr);
168+
}
169+
return CORK_NIL;
170+
}
171+
172+
static void inputStart (subparser *s)
173+
{
174+
struct sGemSpecSubparser *gemspec = (struct sGemSpecSubparser *)s;
175+
176+
gemspec->var_name = vStringNew ();
177+
}
178+
179+
static void inputEnd (subparser *s)
180+
{
181+
struct sGemSpecSubparser *gemspec = (struct sGemSpecSubparser *)s;
182+
183+
vStringDelete (gemspec->var_name); /* NULL is acceptable. */
184+
gemspec->var_name = NULL;
185+
}
186+
187+
extern parserDefinition* GemSpecParser (void)
188+
{
189+
static const char *const extensions [] = { "gemspec", NULL };
190+
static struct sGemSpecSubparser gemspecSubparser = {
191+
.ruby = {
192+
.subparser = {
193+
.direction = SUBPARSER_SUB_RUNS_BASE,
194+
.inputStart = inputStart,
195+
.inputEnd = inputEnd,
196+
},
197+
.lineNotify = lineNotify,
198+
},
199+
.var_name = NULL,
200+
};
201+
202+
static parserDependency dependencies [] = {
203+
[0] = { DEPTYPE_SUBPARSER, "Ruby", &gemspecSubparser },
204+
};
205+
206+
parserDefinition* const def = parserNew ("GemSpec");
207+
208+
def->dependencies = dependencies;
209+
def->dependencyCount = ARRAY_SIZE(dependencies);
210+
def->kindTable = GemSpecKinds;
211+
def->kindCount = ARRAY_SIZE (GemSpecKinds);
212+
def->extensions = extensions;
213+
def->parser = findGemSpecTags;
214+
def->useCork = CORK_QUEUE;
215+
216+
return def;
217+
}

source.mak

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ PARSER_SRCS = \
294294
parsers/fortran.c \
295295
parsers/fypp.c \
296296
parsers/gdscript.c \
297+
parsers/gemspec.c \
297298
parsers/go.c \
298299
parsers/haskell.c \
299300
parsers/haxe.c \

win32/ctags_vs2013.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@
301301
<ClCompile Include="..\parsers\fortran.c" />
302302
<ClCompile Include="..\parsers\fypp.c" />
303303
<ClCompile Include="..\parsers\gdscript.c" />
304+
<ClCompile Include="..\parsers\gemspec.c" />
304305
<ClCompile Include="..\parsers\go.c" />
305306
<ClCompile Include="..\parsers\haskell.c" />
306307
<ClCompile Include="..\parsers\haxe.c" />

0 commit comments

Comments
 (0)