defmastership-core 1.2.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f53b9cafb00c67beb3c5412e3668d5e72683db35a0d6d7a6449aafa5adf22494
4
- data.tar.gz: f7e347edb42e478b6103d09d74079c79571b9914fabceee5b7d27934a8dbaf7a
3
+ metadata.gz: b6b48fcdac016b1032cf07bb002e0c2672a8849af943e6394d5190bb2a3945e9
4
+ data.tar.gz: ac0c88a4f42312c140edd29f0395ea76774921799e2f4915a31c85dc51cd5fdb
5
5
  SHA512:
6
- metadata.gz: 5b95b3e3915b799e9025f741a201ad806e23b5048a2c7ef3438a48e73b21ac0e40012c9519a4d481fad38554f7b94869b59d6c8d54a8cfd7a09df14e2c3d44c1
7
- data.tar.gz: 06d4d2f26ec9a37a1756046c02b48c9e6921182d3861e27aa0b9518f9894fac39e57d1d2323eea7980a248180fdcc0e0d34f2b78b982ed4aa653707f80d88710
6
+ metadata.gz: 33adb210da4e371ba6b94ff7c5de5980b0d74cb8d31f0939f1adfe41f846970fa042ea08c449de038a21b1eb857f9a5852a278832e0af07c261ff3fd0f1dfcbd
7
+ data.tar.gz: 9e67eb21f21bb5d30faf71697f5865bbd5c98ba536e6af9a622f064ba44e274afcf5dfd0a354145e661e645b1ad5f6a86f2e77fae753553beca30a65887867aa
data/.gitlab-ci.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  default:
2
- image: ruby:3.3
2
+ image: ruby:3.4
3
3
  before_script:
4
4
  - apt-get update
5
5
  - ruby -v
@@ -54,6 +54,11 @@ unit tests ruby3.2:
54
54
  script:
55
55
  - bundle exec rake test:spec
56
56
 
57
+ unit tests ruby3.3:
58
+ image: ruby:3.3
59
+ script:
60
+ - bundle exec rake test:spec
61
+
57
62
  pages:
58
63
  stage: deploy
59
64
  script:
data/Gemfile CHANGED
@@ -10,27 +10,27 @@ ruby RUBY_VERSION
10
10
  # rubocop:disable Metrics/BlockLength
11
11
  group :development do
12
12
  # needed by yard to render documentation
13
- gem 'asciidoctor', '~> 2'
13
+ gem 'asciidoctor', '~> 2.0'
14
14
  # cucumber steps for command line tests
15
- gem 'aruba', '~> 2'
15
+ gem 'aruba', '~> 2.2'
16
16
  # bdd
17
- gem 'cucumber', '~> 9'
17
+ gem 'cucumber', '~> 9.2'
18
18
 
19
19
  # code duplication
20
- gem 'flay', '~> 2'
20
+ gem 'flay', '~> 2.13'
21
21
 
22
22
  # automatic test run
23
- gem 'guard', '~> 2'
23
+ gem 'guard', '~> 2.19'
24
24
  # automatic update invocation
25
- gem 'guard-bundler', '~> 3'
25
+ gem 'guard-bundler', '~> 3.0'
26
26
  if RUBY_VERSION >= '3.0'
27
27
  # automatic style check
28
28
  gem 'guard-reek', '~> 1.2'
29
29
  end
30
30
  # automatic tdd
31
- gem 'guard-rspec', '~> 4'
31
+ gem 'guard-rspec', '~> 4.7'
32
32
  # automatic style check
33
- gem 'guard-rubocop', '~> 1'
33
+ gem 'guard-rubocop', '~> 1.5'
34
34
 
35
35
  # if RUBY_VERSION >= '3.0'
36
36
  # # mutation testing
@@ -44,45 +44,45 @@ group :development do
44
44
  # gem 'mutant-rspec', '~> 0'
45
45
  # end
46
46
  # to parse and execute Rakefile
47
- gem 'rake', '~> 13'
47
+ gem 'rake', '~> 13.2'
48
48
 
49
49
  if RUBY_VERSION >= '3.0'
50
50
  # needed by yard to render documentation
51
- gem 'rdoc', '~> 6'
51
+ gem 'rdoc', '~> 6.1O'
52
52
  end
53
53
  # tdd
54
- gem 'rspec', '~> 3'
54
+ gem 'rspec', '~> 3.13'
55
55
  # # to test performances
56
56
  # gem 'rspec-benchmark', '~> 0'
57
57
  # code needs to be clean
58
- gem 'rubocop', '1.68'
58
+ gem 'rubocop', '1.69'
59
59
  # code needs to be clean
60
- gem 'rubocop-performance', '~> 1'
60
+ gem 'rubocop-performance', '~> 1.23'
61
61
  # test code needs to be clean
62
- gem 'rubocop-rspec', '~> 3'
62
+ gem 'rubocop-rspec', '~> 3.3'
63
63
  # Rakefiles need to be clean
64
- gem 'rubocop-rake', '~> 0'
64
+ gem 'rubocop-rake', '~> 0.6'
65
65
 
66
66
  if RUBY_VERSION >= '3.0'
67
67
  # detect selling code
68
- gem 'reek', '~> 6'
68
+ gem 'reek', '~> 6.3'
69
69
  # my code needs to be critiqued
70
- gem 'rubycritic', '~> 4'
70
+ gem 'rubycritic', '~> 4.9'
71
71
  # Doc need to be clean
72
- gem 'rubocop-yard', '~> 0'
72
+ gem 'rubocop-yard', '~> 0.10'
73
73
  end
74
74
 
75
75
  # What is tdd without code coverage ?
76
- gem 'simplecov', '~> 0'
76
+ gem 'simplecov', '~> 0.22'
77
77
 
78
78
  if RUBY_VERSION >= '3.0'
79
79
  # to document code
80
- gem 'yard', '~> 0'
80
+ gem 'yard', '~> 0.9'
81
81
  end
82
82
  end
83
83
  # rubocop:enable Metrics/BlockLength
84
84
 
85
85
  group :debugging do
86
86
  # Sometimes, we need to debug
87
- gem 'pry', '~> 0'
87
+ gem 'pry', '~> 0.15'
88
88
  end
@@ -7,60 +7,108 @@ module Defmastership
7
7
  # set of regexp of added asciidoctor constructions
8
8
  # This module smells of :reek:TooManyConstants
9
9
  module DMRegexp
10
+ # generic regexp pattern for ids
11
+ #
12
+ # @param backref_name [String] set the name of the id's backref
13
+ def self.an_id(backref_name)
14
+ "(?<#{backref_name}>[\\w-]+)"
15
+ end
16
+
10
17
  # [Regexp] to match a single line comment
11
18
  SINGLE_LINE_COMMENT = %r{^//[^/]}.freeze
12
19
  public_constant :SINGLE_LINE_COMMENT
13
20
 
21
+ # [Regexp] match the definition keyword
22
+ DEF_KEYWORD = '\s*define\s*'
23
+ public_constant :DEF_KEYWORD
24
+
25
+ # [Regexp] match a definition type
26
+ DEF_TYPE = ",\\s*#{an_id('type')}\\s*"
27
+ public_constant :DEF_TYPE
28
+
14
29
  # [Regexp] match all text before the definition's reference
15
- DEF_BEFORE_REF = <<~'BEF'
16
- ^\s*
17
- \[\s*define\s*,
18
- \s*(?<type>[\w:_-]+)\s*,
19
- \s*
30
+ DEF_BEFORE_REF = <<~"BEF"
31
+ ^
32
+ \\s*
33
+ \\[
34
+ #{DEF_KEYWORD}
35
+ #{DEF_TYPE}
36
+ ,
37
+ \\s*
20
38
  BEF
21
39
  public_constant :DEF_BEFORE_REF
22
40
 
23
- # [Regexp] match all text after the definition's reference
24
- DEF_AFTER_REF = <<~'AFT'
25
- \s*
26
- (,\s*\[\s*(?<labels>.*?)\s*\])?\s*\]
27
- AFT
28
- public_constant :DEF_AFTER_REF
29
-
30
41
  # [Regexp] match optional explicit version and explicit checksum
31
42
  DEF_VERSION_AND_CHECKSUM = '(?<version_and_checksum>' \
32
- '\((?<explicit_version>[^~]+)?(?<explicit_checksum>~[[:alnum:]]+)?\)' \
43
+ '\((?<explicit_version>[^~]+)?(?<explicit_checksum>~\h+)?\)' \
33
44
  ')?'
34
45
  public_constant :DEF_VERSION_AND_CHECKSUM
35
46
 
36
47
  # [Regexp] match reference
37
- REFERENCE = '(?<reference>[\\w:_-]+)'
48
+ REFERENCE = an_id('reference').freeze
38
49
  public_constant :REFERENCE
39
50
 
51
+ # [Regexp] match defintion summary
52
+ DEF_SUMMARY = <<~'SUM'
53
+ \s*
54
+ (,\s*
55
+ ((?<summary>[^\s,\[\]][^,\[\]]*?)|("(?<summary>[^""]*)"))
56
+ \s*)?
57
+ SUM
58
+ public_constant :DEF_SUMMARY
59
+
60
+ # [Regexp] match definition labels
61
+ DEF_LABELS = '(,\s*\[\s*(?<labels>.*\b)\s*\])?'
62
+ public_constant :DEF_LABELS
63
+
64
+ # [Regexp] match all text after the definition's reference
65
+ DEF_AFTER_REF = <<~"AFT"
66
+ \\s*
67
+ #{DEF_SUMMARY}
68
+ #{DEF_LABELS}
69
+ \\s*
70
+ \\]
71
+ AFT
72
+ public_constant :DEF_AFTER_REF
73
+
40
74
  # [Regexp] match a definition line
41
- DEFINITION = Regexp.new(
42
- "#{DEF_BEFORE_REF}#{REFERENCE}#{DEF_VERSION_AND_CHECKSUM}#{DEF_AFTER_REF}",
43
- Regexp::EXTENDED
44
- )
75
+ definition_re_string = <<~"DEF"
76
+ ^
77
+ \\s*
78
+ \\[
79
+ #{DEF_KEYWORD}
80
+ #{DEF_TYPE}
81
+ ,
82
+ \\s*
83
+ #{REFERENCE}
84
+ #{DEF_VERSION_AND_CHECKSUM}
85
+ \\s*
86
+ #{DEF_SUMMARY}
87
+ #{DEF_LABELS}
88
+ \\s*
89
+ \\]
90
+ DEF
91
+ # [Regexp] match a definition line
92
+ DEFINITION = Regexp.new(definition_re_string, Regexp::EXTENDED)
45
93
  public_constant :DEFINITION
46
94
 
47
95
  # [Regexp] match a asciidcotor attribute definition
48
- VARIABLE_DEF = /^\s*:(?<varname>[\w:_-]+):\s+
96
+ VARIABLE_DEF = /^\s*:#{an_id('varname')}:\s+
49
97
  (?<value>\S.*\S)\s*$/x.freeze
50
98
  public_constant :VARIABLE_DEF
51
99
 
52
100
  # [Regexp] match a asciidcotor attribute use
53
- VARIABLE_USE = /{(?<varname>[\w:_-]+)}/x.freeze
101
+ VARIABLE_USE = /{#{an_id('varname')}}/x.freeze
54
102
  public_constant :VARIABLE_USE
55
103
 
56
104
  # [Regexp] match an external cross reference type configuration
57
- EREF_CONFIG = /^\s*:eref-(?<reference>[\w:_-]+)-(?<symb>prefix|url):\s*
105
+ EREF_CONFIG = /^\s*:eref-#{an_id('reference')}-(?<symb>prefix|url):\s*
58
106
  \s*(?<value>\S.*\S)\s*/x.freeze
59
107
  public_constant :EREF_CONFIG
60
108
  # [Regexp] match an external cross reference use
61
109
  EREF_DEF = /^\s*
62
110
  defs:eref\[
63
- \s*(?<reference>[\w:_-]+)\s*,
111
+ \s*#{an_id('reference')}\s*,
64
112
  \s*\[\s*(?<extrefs>[^\]]+?)\s*\]\s*\]/x.freeze
65
113
  public_constant :EREF_DEF
66
114
 
@@ -76,19 +124,19 @@ module Defmastership
76
124
  public_constant :IREF_DEF_AFT
77
125
  # [Regexp] match an internal cross reference
78
126
  IREF_DEF = Regexp.new(
79
- "#{IREF_DEF_BEF}(?<intref>[\\w:_-]+)#{IREF_DEF_AFT}",
127
+ "#{IREF_DEF_BEF}#{an_id('intref')}#{IREF_DEF_AFT}",
80
128
  Regexp::EXTENDED
81
129
  )
82
130
  public_constant :IREF_DEF
83
131
 
84
132
  # [Regexp] match an attribute configuration
85
- ATTR_CONFIG = /\s*:attr-(?<attr>[\w:_-]+)-prefix:
133
+ ATTR_CONFIG = /\s*:attr-#{an_id('attr')}-prefix:
86
134
  \s+(?<prefix>.+?)\s*$/x.freeze
87
135
  public_constant :ATTR_CONFIG
88
136
  # [Regexp] match an attribute use
89
137
  ATTR_SET = /\s*
90
138
  defs:attribute\[
91
- \s*(?<attr>[\w:_-]+)\s*,
139
+ \s*#{an_id('attr')}\s*,
92
140
  \s*(?<value>.+?)\s*\]/x.freeze
93
141
  public_constant :ATTR_SET
94
142
 
@@ -101,13 +149,13 @@ module Defmastership
101
149
  public_constant :WHATEVER
102
150
 
103
151
  # [Regexp] match asciidoc include statement keyword
104
- INCLUDE_KEYWORD = '\binclude::'
152
+ INCLUDE_KEYWORD = '^\s*include::'
105
153
  public_constant :INCLUDE_KEYWORD
106
154
  # [Regexp] match asciidoc include statement path
107
155
  INCLUDE_PATH = '(?<path>.*/)?'
108
156
  public_constant :INCLUDE_PATH
109
157
  # [Regexp] match asciidoc include statement filename
110
- INCLUDE_FILENAME = '(?<filename>[^\\/]+)'
158
+ INCLUDE_FILENAME = '(?<filename>[^\\\/]+)'
111
159
  public_constant :INCLUDE_FILENAME
112
160
  # [Regexp] match asciidoc include statement options
113
161
  INCLUDE_OPTIONS = '\[(?<options>[^\]]*)\]'
@@ -5,7 +5,7 @@ module Defmastership
5
5
  # Common to defmastership and asciidoctor-defmastership
6
6
  module Core
7
7
  # [String] Gem version
8
- VERSION = '1.2.0'
8
+ VERSION = '1.4.0'
9
9
  public_constant :VERSION
10
10
  end
11
11
  end
@@ -0,0 +1,665 @@
1
+ # Copyright (c) 2020 Jerome Arbez-Gindre
2
+ # frozen_string_literal: true
3
+
4
+ require('defmastership/core/constants')
5
+
6
+ RSpec.describe(Defmastership::Core::DMRegexp) do
7
+ describe '#an id' do
8
+ subject(:regexp) { Regexp.new("^#{described_class.an_id('backref')}$", Regexp::EXTENDED) }
9
+
10
+ context 'when valid id' do
11
+ [
12
+ 'abc',
13
+ 'abc_efg',
14
+ '_abc_efg_',
15
+ 'abc-efg',
16
+ '-abc-efg-',
17
+ '67abc123-efg12',
18
+ 'REFERENCE-0001'
19
+ ].each do |line|
20
+ it { is_expected.to(match(line)) }
21
+ end
22
+
23
+ it { expect(regexp.match('67abc123-efg12')[:backref]).to(eq('67abc123-efg12')) }
24
+
25
+ context 'when not valid id' do
26
+ [
27
+ '&abcg',
28
+ 'ab@cg',
29
+ 'abc12:3-efg'
30
+ ].each do |line|
31
+ it { is_expected.not_to(match(line)) }
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ describe 'SINGLE_LINE_COMMENT' do
38
+ subject { described_class::SINGLE_LINE_COMMENT }
39
+
40
+ context 'when the string is a single line comment' do
41
+ [
42
+ '// This is a comment',
43
+ '// This is a // comment'
44
+ ].each do |the_line|
45
+ it { is_expected.to(match(the_line)) }
46
+ end
47
+ end
48
+
49
+ context 'when the string is not a single line comment' do
50
+ [
51
+ 'This is not a comment',
52
+ ' // This is not a comment'
53
+ ].each do |the_bad_line|
54
+ it { is_expected.not_to(match(the_bad_line)) }
55
+ end
56
+ end
57
+ end
58
+
59
+ describe 'DEF_KEYWORD' do
60
+ subject(:regexp) { Regexp.new("^#{described_class::DEF_KEYWORD}$", Regexp::EXTENDED) }
61
+
62
+ context 'with valid definition keyword' do
63
+ [
64
+ 'define',
65
+ ' define',
66
+ ' define '
67
+ ].each do |line|
68
+ it { is_expected.to(match(line)) }
69
+ end
70
+ end
71
+
72
+ context 'with invalid definition keyword' do
73
+ it { is_expected.not_to(match('defoune')) }
74
+ end
75
+ end
76
+
77
+ describe 'DEF_TYPE' do
78
+ subject(:regexp) { Regexp.new("^#{described_class::DEF_TYPE}$", Regexp::EXTENDED) }
79
+
80
+ context 'with valid definition type' do
81
+ [
82
+ ', a_type',
83
+ ', a-type',
84
+ ', a-type '
85
+ ].each do |line|
86
+ it { is_expected.to(match(line)) }
87
+ end
88
+
89
+ it { expect(regexp.match(', a-type ')[:type]).to(eq('a-type')) }
90
+ end
91
+
92
+ context 'with invalid definition type' do
93
+ it { is_expected.not_to(match(' , a_type')) }
94
+ it { is_expected.not_to(match(', a type with blank ')) }
95
+ end
96
+ end
97
+
98
+ describe 'DEF_BEFORE_REF' do
99
+ subject(:regexp) { Regexp.new("#{described_class::DEF_BEFORE_REF}$", Regexp::EXTENDED) }
100
+
101
+ context 'when valid definitions beginning' do
102
+ [
103
+ '[define,def_type,',
104
+ ' [define,def_type,',
105
+ ' [ define,def_type,',
106
+ ' [ define, def_type,',
107
+ ' [ define, def_type, '
108
+ ].each do |def_beg|
109
+ it { is_expected.to(match(def_beg)) }
110
+ it { expect(regexp.match(def_beg)[:type]).to(eq('def_type')) }
111
+ end
112
+ end
113
+
114
+ context 'when does not match invalid definitions beginning' do
115
+ [
116
+ 'define def_type,',
117
+ '[define def_type,',
118
+ '[define, def_type',
119
+ 'something [define, def_type'
120
+ ].each do |bad_def_beg|
121
+ it { is_expected.not_to(match(bad_def_beg)) }
122
+ end
123
+ end
124
+ end
125
+
126
+ describe 'DEF_AFTER_REF' do
127
+ subject(:regexp) { Regexp.new("^#{described_class::DEF_AFTER_REF}$", Regexp::EXTENDED) }
128
+
129
+ context 'when valid definitions end' do
130
+ [
131
+ ']',
132
+ ',[label1]]',
133
+ ', a nice summary,[label1]]',
134
+ ', a nice summary]',
135
+ ', "a nice summary, with comma"]'
136
+ ].each do |def_end|
137
+ it { is_expected.to(match(def_end)) }
138
+ end
139
+
140
+ it { expect(regexp.match(' ,[ label1 , label2 ] ]')[:labels]).to(eq('label1 , label2')) }
141
+ it { expect(regexp.match(' ,[ label1 , label2 ] ]')[:summary]).to(be_nil) }
142
+ it { expect(regexp.match(', a summary ]')[:summary]).to(eq('a summary')) }
143
+ it { expect(regexp.match(', a summary ]')[:labels]).to(be_nil) }
144
+ it { expect(regexp.match(', "a, summary" ]')[:summary]).to(eq('a, summary')) }
145
+ end
146
+
147
+ context 'when invalid definitions end' do
148
+ it { is_expected.not_to(match('whatever')) }
149
+ it { is_expected.not_to(match(',[label1]')) }
150
+ it { is_expected.not_to(match('[label1]]')) }
151
+ it { is_expected.not_to(match(',label1,label2]]')) }
152
+ end
153
+ end
154
+
155
+ describe 'DEF_VERSION_AND_CHECKSUM' do
156
+ subject(:regexp) { Regexp.new("^#{described_class::DEF_VERSION_AND_CHECKSUM}$", Regexp::EXTENDED) }
157
+
158
+ context 'when valid input' do
159
+ context 'when version without checksum' do
160
+ it { is_expected.to(match('(abc)')) }
161
+ it { expect(regexp.match('(abc)')[:version_and_checksum]).to(eq('(abc)')) }
162
+ it { expect(regexp.match('(abc)')[:explicit_version]).to(eq('abc')) }
163
+ it { expect(regexp.match('(abc)')[:explicit_checksum]).to(be_nil) }
164
+ end
165
+
166
+ context 'when checksum without version' do
167
+ it { is_expected.to(match('(~abcd1234)')) }
168
+ it { expect(regexp.match('(~abcd1234)')[:version_and_checksum]).to(eq('(~abcd1234)')) }
169
+ it { expect(regexp.match('(~abcd1234)')[:explicit_version]).to(be_nil) }
170
+ it { expect(regexp.match('(~abcd1234)')[:explicit_checksum]).to(eq('~abcd1234')) }
171
+ it { expect(regexp.match('(~ABCD1234)')[:explicit_checksum]).to(eq('~ABCD1234')) }
172
+ end
173
+
174
+ context 'when version and checksum' do
175
+ it { is_expected.to(match('(abc~abcd1234)')) }
176
+ it { expect(regexp.match('(abc~abcd1234)')[:version_and_checksum]).to(eq('(abc~abcd1234)')) }
177
+ it { expect(regexp.match('(abc~abcd1234)')[:explicit_version]).to(eq('abc')) }
178
+ it { expect(regexp.match('(abc~abcd1234)')[:explicit_checksum]).to(eq('~abcd1234')) }
179
+ end
180
+ end
181
+
182
+ context 'when invalid input' do
183
+ it { is_expected.not_to(match('whatever')) }
184
+ it { is_expected.not_to(match('(abc~ghij1234)')) }
185
+ end
186
+ end
187
+
188
+ describe 'REFERENCE' do
189
+ subject(:regexp) { Regexp.new("^#{described_class::REFERENCE}$", Regexp::EXTENDED) }
190
+
191
+ context 'when valid definition reference' do
192
+ [
193
+ 'abc',
194
+ 'abc_efg',
195
+ '_abc_efg_',
196
+ 'abc-efg',
197
+ '-abc-efg-',
198
+ '67abc123-efg12',
199
+ 'REFERENCE-0001'
200
+ ].each do |line|
201
+ it { is_expected.to(match(line)) }
202
+ end
203
+
204
+ it { expect(regexp.match('67abc123-efg12')[:reference]).to(eq('67abc123-efg12')) }
205
+ end
206
+
207
+ context 'when not valid definition reference' do
208
+ [
209
+ '&abcg',
210
+ 'ab@cg',
211
+ 'abc12:3-efg'
212
+ ].each do |line|
213
+ it { is_expected.not_to(match(line)) }
214
+ end
215
+ end
216
+ end
217
+
218
+ describe 'DEF_SUMMARY' do
219
+ subject(:regexp) { Regexp.new("^#{described_class::DEF_SUMMARY}$", Regexp::EXTENDED) }
220
+
221
+ context 'with valid definition summary' do
222
+ [
223
+ '',
224
+ ', bla bla bli',
225
+ ', bla bla bli ',
226
+ ' , bla bla bli ',
227
+ ', bla: bla bli',
228
+ ', "bla bla, bli"',
229
+ ', " bla bla , bli "'
230
+ ].each do |line|
231
+ it { is_expected.to(match(line)) }
232
+ end
233
+
234
+ it { expect(regexp.match('')[:summary]).to(be_nil) }
235
+ it { expect(regexp.match(', bla: bla bli ')[:summary]).to(eq('bla: bla bli')) }
236
+ it { expect(regexp.match(', " bla bla , bli "')[:summary]).to(eq(' bla bla , bli ')) }
237
+ end
238
+
239
+ context 'with invalid definition summary' do
240
+ it { is_expected.not_to(match('blabla without coma')) }
241
+ it { is_expected.not_to(match(', [bla bla bli')) }
242
+ it { is_expected.not_to(match(', bla bla bli]')) }
243
+ it { is_expected.not_to(match(', "bla bla bli]')) }
244
+ it { is_expected.not_to(match(', bla bla bli"]')) }
245
+ it { is_expected.not_to(match(', ""bla bla bli]')) }
246
+ it { is_expected.not_to(match(',')) }
247
+ it { is_expected.not_to(match(', ')) }
248
+ it { is_expected.not_to(match(',,')) }
249
+ end
250
+ end
251
+
252
+ describe 'DEF_LABELS' do
253
+ subject(:regexp) { Regexp.new("^#{described_class::DEF_LABELS}$", Regexp::EXTENDED) }
254
+
255
+ context 'with valid definition labels' do
256
+ [
257
+ '',
258
+ ', [ label1 ]',
259
+ ', [ label1, label2 ]',
260
+ ', [ label1 , label2 ]',
261
+ ', [ label with blank ]'
262
+ ].each do |line|
263
+ it { is_expected.to(match(line)) }
264
+ end
265
+
266
+ it { expect(regexp.match('')[:labels]).to(be_nil) }
267
+ it { expect(regexp.match(', [ label1 , label2 ]')[:labels]).to(eq('label1 , label2')) }
268
+ end
269
+
270
+ context 'with invalid definition summary' do
271
+ it { is_expected.not_to(match(' , [ label1 , label2 ]')) }
272
+ it { is_expected.not_to(match(', [ label1 , label2 ] ')) }
273
+ it { is_expected.not_to(match(', label1 , label2 ')) }
274
+ end
275
+ end
276
+
277
+ describe 'DEFINITION' do
278
+ subject(:regexp) { described_class::DEFINITION }
279
+
280
+ context 'with valid definition lines' do
281
+ [
282
+ '[ define, definition_type, REFERENCE_0001(abcd~abcdef) ]',
283
+ '[define , definition_type, REFERENCE-0001]',
284
+ '[ define,def-type , 001-REFERENCE, [ label1, label2 ] ] ',
285
+ '[ define, def-type , REFERENCE-001 , [ label1, label2 ] ]',
286
+ '[ define, def-type , REFERENCE-001 , a summary, [ label1, label2 ] ]',
287
+ '[ define, def-type , REFERENCE-001 , "a, summary, comma", [ label1, label2 ] ]'
288
+ ].each do |line|
289
+ it { is_expected.to(match(line)) }
290
+ end
291
+
292
+ let(:one_match) { regexp.match('[define,type,REF_01(a~1234),a summary,[a,b]]') }
293
+
294
+ it { expect(one_match[:type]).to(eq('type')) }
295
+ it { expect(one_match[:reference]).to(eq('REF_01')) }
296
+ it { expect(one_match[:explicit_version]).to(eq('a')) }
297
+ it { expect(one_match[:explicit_checksum]).to(eq('~1234')) }
298
+ it { expect(one_match[:summary]).to(eq('a summary')) }
299
+ it { expect(one_match[:labels]).to(eq('a,b')) }
300
+
301
+ it { expect(regexp.match('[define,t,R," a , comma "]')[:summary]).to(eq(' a , comma ')) }
302
+ end
303
+
304
+ context 'with invalid definition lines' do
305
+ [
306
+ 'define, type, ref',
307
+ '[define type , ref]',
308
+ '[defineeee, type , ref]',
309
+ '[defineeee, type , ref, pouet, [tagada, tsointsoin]]',
310
+ '[defineeee, type , ref, [tagada, tsointsoin], pouet]'
311
+ ].each do |line|
312
+ it { is_expected.not_to(match(line)) }
313
+ end
314
+ end
315
+ end
316
+
317
+ describe 'VARIABLE_DEF' do
318
+ subject(:regexp) { described_class::VARIABLE_DEF }
319
+
320
+ context 'with valid variable definitions' do
321
+ [
322
+ ':my_var: value',
323
+ ' :my_var: value',
324
+ ':var_with_underscores: another_value',
325
+ ':var-with_dash: another_value',
326
+ ':var_with_leading_space: value',
327
+ ':var_with_trailing_space: value '
328
+ ].each do |line|
329
+ it { is_expected.to(match(line)) }
330
+ end
331
+
332
+ let(:one_match) { regexp.match(':my_nice-var: nice value ') }
333
+
334
+ it { expect(one_match[:varname]).to(eq('my_nice-var')) }
335
+ it { expect(one_match[:value]).to(eq('nice value')) }
336
+ end
337
+
338
+ context 'with invalid variable definitions' do
339
+ [
340
+ ':var_@: value',
341
+ ':var space: value',
342
+ ':var_space : value',
343
+ ':var_with:: value'
344
+ ].each do |line|
345
+ it { is_expected.not_to(match(line)) }
346
+ end
347
+ end
348
+ end
349
+
350
+ describe 'VARIABLE_USE' do
351
+ subject(:regexp) { described_class::VARIABLE_USE }
352
+
353
+ context 'with valid variable utilization' do
354
+ [
355
+ '{my_var}',
356
+ ' {my_var} ',
357
+ '{var-with_dash}',
358
+ '[define, requirement, TOTO-0001, A nice {a_variable}]'
359
+ ].each do |line|
360
+ it { is_expected.to(match(line)) }
361
+ end
362
+
363
+ let(:one_match) { regexp.match(' {my_nice-var} ') }
364
+
365
+ it { expect(one_match[:varname]).to(eq('my_nice-var')) }
366
+ end
367
+
368
+ context 'with invalid variable definitions' do
369
+ [
370
+ '{var_@}',
371
+ '{var space}',
372
+ '{var_space }',
373
+ '{var_with:}'
374
+ ].each do |line|
375
+ it { is_expected.not_to(match(line)) }
376
+ end
377
+ end
378
+ end
379
+
380
+ describe 'EREF_CONFIG' do
381
+ subject(:regexp) { described_class::EREF_CONFIG }
382
+
383
+ context 'with valid external ref configuration' do
384
+ let(:one_match_prefix) { regexp.match(' :eref-something-prefix: a_prefix ') }
385
+ let(:one_match_url) { regexp.match(':eref-something-url: an url ') }
386
+
387
+ [
388
+ ':eref-something-prefix: a_prefix',
389
+ ':eref-something-url: a_url',
390
+ ' :eref-something-url: a_url'
391
+ ].each do |line|
392
+ it { is_expected.to(match(line)) }
393
+ end
394
+
395
+ it { expect(one_match_prefix[:reference]).to(eq('something')) }
396
+ it { expect(one_match_prefix[:symb]).to(eq('prefix')) }
397
+ it { expect(one_match_prefix[:value]).to(eq('a_prefix')) }
398
+
399
+ it { expect(one_match_url[:reference]).to(eq('something')) }
400
+ it { expect(one_match_url[:symb]).to(eq('url')) }
401
+ it { expect(one_match_url[:value]).to(eq('an url')) }
402
+ end
403
+
404
+ context 'with invalid ref configuration' do
405
+ [
406
+ ':eref-something-plop: a_prefix',
407
+ ': eref-something-prefix: a_prefix',
408
+ ':eref-something-prefix : a_prefix',
409
+ ':eref- something-prefix: a_prefix',
410
+ ':eref-something -prefix: a_prefix',
411
+ ':eref-something- prefix: a_prefix'
412
+ ].each do |line|
413
+ it { is_expected.not_to(match(line)) }
414
+ end
415
+ end
416
+ end
417
+
418
+ describe 'EREF_DEF' do
419
+ subject(:regexp) { described_class::EREF_DEF }
420
+
421
+ let(:one_match) { regexp.match('defs:eref[abcdef, [ABC, EDF]]') }
422
+
423
+ context 'with valid external ref' do
424
+ [
425
+ 'defs:eref[abcdef, [ABC, EDF]]',
426
+ ' defs:eref[abcdef, [ABC, EDF]]',
427
+ 'defs:eref[ abcdef, [ABC, EDF]]',
428
+ 'defs:eref[abcdef,[ABC,EDF]]',
429
+ 'defs:eref[abcdef, [ABC, EDF] ]',
430
+ 'defs:eref[abcdef, [ABC, EDF ]]',
431
+ 'defs:eref[abcdef, [ABC]]'
432
+ ].each do |line|
433
+ it { is_expected.to(match(line)) }
434
+ end
435
+
436
+ it { expect(one_match[:reference]).to(eq('abcdef')) }
437
+ it { expect(one_match[:extrefs]).to(eq('ABC, EDF')) }
438
+ end
439
+
440
+ context 'with invalid external ref' do
441
+ [
442
+ 'defs :eref[abcdef, [ABC, EDF]]',
443
+ 'defs: eref[abcdef, [ABC, EDF]]',
444
+ 'defs:eref [abcdef, [ABC, EDF]]'
445
+ ].each do |line|
446
+ it { is_expected.not_to(match(line)) }
447
+ end
448
+ end
449
+ end
450
+
451
+ describe 'BLOCK' do
452
+ subject(:regexp) { described_class::BLOCK }
453
+
454
+ context 'with valid block delimiter' do
455
+ it { is_expected.to(match('--')) }
456
+ it { is_expected.to(match('-- ')) }
457
+ end
458
+
459
+ context 'with invalid block delimiter' do
460
+ it { is_expected.not_to(match(' --')) }
461
+ it { is_expected.not_to(match('-- qsdqsd')) }
462
+ end
463
+ end
464
+
465
+ describe 'IREF_DEF_BEF' do
466
+ subject(:regexp) { Regexp.new("^#{described_class::IREF_DEF_BEF}$") }
467
+
468
+ context 'with valid IREF_DEF_BEF' do
469
+ it { is_expected.to(match('defs:iref[')) }
470
+ it { is_expected.to(match('defs:iref[ ')) }
471
+ end
472
+
473
+ context 'with invalid IREF_DEF_BEF' do
474
+ it { is_expected.not_to(match(' defs:iref[')) }
475
+ it { is_expected.not_to(match('defs :iref[')) }
476
+ it { is_expected.not_to(match('defs: iref[')) }
477
+ it { is_expected.not_to(match('defs:iref [')) }
478
+ it { is_expected.not_to(match('defs:iref[ a')) }
479
+ end
480
+ end
481
+
482
+ describe 'IREF_DEF_AFT' do
483
+ subject(:regexp) { Regexp.new("^#{described_class::IREF_DEF_AFT}$") }
484
+
485
+ context 'with valid IREF_DEF_AFT' do
486
+ it { is_expected.to(match(']')) }
487
+ it { is_expected.to(match(' ]')) }
488
+ end
489
+
490
+ context 'with invalid IREF_DEF_AFT' do
491
+ it { is_expected.not_to(match('a]')) }
492
+ it { is_expected.not_to(match('] ')) }
493
+ end
494
+ end
495
+
496
+ describe 'IREF_DEF' do
497
+ subject(:regexp) { described_class::IREF_DEF }
498
+
499
+ context 'with valid IREF_DEF' do
500
+ it { is_expected.to(match('defs:iref[blabla]')) }
501
+ it { is_expected.to(match('defs:iref[bla-bla]')) }
502
+ it { is_expected.to(match('defs:iref[bla_bla]')) }
503
+ it { is_expected.to(match(' defs:iref[bla_bla]')) }
504
+ it { is_expected.to(match(' defs:iref[ bla_bla]')) }
505
+ it { is_expected.to(match(' defs:iref[ bla_bla ]')) }
506
+ it { is_expected.to(match(' defs:iref[ bla_bla ] ')) }
507
+
508
+ it { expect(regexp.match(' defs:iref[ bla_bla ] ')[:intref]).to(eq('bla_bla')) }
509
+ end
510
+
511
+ context 'with invalid IREF_DEF' do
512
+ it { is_expected.not_to(match('defs :iref[blabla]')) }
513
+ it { is_expected.not_to(match('defs: iref[blabla]')) }
514
+ it { is_expected.not_to(match('defs:iref [blabla]')) }
515
+ end
516
+ end
517
+
518
+ describe 'ATTR_CONFIG' do
519
+ subject(:regexp) { described_class::ATTR_CONFIG }
520
+
521
+ context 'when valid attribute configuration' do
522
+ it { is_expected.to(match(':attr-my_attribute-prefix: my_prefix')) }
523
+ it { is_expected.to(match(':attr-my-attribute-prefix: my blala prefix')) }
524
+ it { expect(regexp.match(':attr-my_attribute-prefix: my_prefix')[:attr]).to(eq('my_attribute')) }
525
+ it { expect(regexp.match(':attr-my_attribute-prefix: my_prefix')[:prefix]).to(eq('my_prefix')) }
526
+ it { expect(regexp.match(':attr-my_attribute-prefix: with blank: ')[:prefix]).to(eq('with blank:')) }
527
+ end
528
+
529
+ context 'when invalid attribute configuration' do
530
+ it { is_expected.not_to(match('attr-my_attribute-prefix: my_prefix')) }
531
+ it { is_expected.not_to(match(':atttr-my_attribute-prefix: my_prefix')) }
532
+ it { is_expected.not_to(match(':attr-my_attribute-prefixx: my_prefix')) }
533
+ it { is_expected.not_to(match(':attr-my_attribute-prefix : my_prefix')) }
534
+ it { is_expected.not_to(match(':attr-my_attribute-prefix: ')) }
535
+ end
536
+ end
537
+
538
+ describe 'ATTR_SET' do
539
+ subject(:regexp) { described_class::ATTR_SET }
540
+
541
+ context 'when valid attribute setting' do
542
+ it { is_expected.to(match('defs:attribute[my-attribute, attr value]')) }
543
+ it { is_expected.to(match('defs:attribute[ my-attribute, attr value]')) }
544
+ it { is_expected.to(match('defs:attribute[my-attribute , attr value]')) }
545
+ it { is_expected.to(match('defs:attribute[my-attribute, attr value ]')) }
546
+ it { is_expected.to(match('defs:attribute[ my-attribute , attr value ]')) }
547
+ it { expect(regexp.match('defs:attribute[ my-attribute , attr value ]')[:attr]).to(eq('my-attribute')) }
548
+ it { expect(regexp.match('defs:attribute[ my-attribute , attr value ]')[:value]).to(eq('attr value')) }
549
+ end
550
+
551
+ context 'when invalid attribute setting' do
552
+ it { is_expected.not_to(match('defs :attribute[my-attribute, attr value]')) }
553
+ it { is_expected.not_to(match('defs: attribute[my-attribute, attr value]')) }
554
+ it { is_expected.not_to(match('defs:attribute [my-attribute, attr value]')) }
555
+ it { is_expected.not_to(match('defs:attribute[my@attribute, attr value]')) }
556
+ end
557
+ end
558
+
559
+ describe 'EMPTY_LINE' do
560
+ subject(:regexp) { described_class::EMPTY_LINE }
561
+
562
+ context 'when valid empty line' do
563
+ it { is_expected.to(match('')) }
564
+ it { is_expected.to(match(' ')) }
565
+ it { is_expected.to(match(" \t ")) }
566
+ end
567
+
568
+ context 'when invalid empty match' do
569
+ it { is_expected.not_to(match(' a ')) }
570
+ end
571
+ end
572
+
573
+ describe 'WHATEVER' do
574
+ subject(:regexp) { described_class::WHATEVER }
575
+
576
+ context 'when matching everything' do
577
+ it { is_expected.to(match('')) }
578
+ it { is_expected.to(match('qsdqsd')) }
579
+ it { is_expected.to(match(" \t qsdqsd \n qsdqsd ")) }
580
+ end
581
+ end
582
+
583
+ describe 'INCLUDE_KEYWORD' do
584
+ subject(:regexp) { Regexp.new("#{described_class::INCLUDE_KEYWORD}$") }
585
+
586
+ context 'when matching include keyword' do
587
+ it { is_expected.to(match('include::')) }
588
+ it { is_expected.to(match(' include::')) }
589
+ end
590
+
591
+ context 'when not matching bad include keyword' do
592
+ it { is_expected.not_to(match(' _include::')) }
593
+ it { is_expected.not_to(match(' a include::')) }
594
+ it { is_expected.not_to(match(' -include::')) }
595
+ end
596
+ end
597
+
598
+ describe 'INCLUDE_PATH' do
599
+ subject(:regexp) { Regexp.new("^#{described_class::INCLUDE_PATH}$") }
600
+
601
+ context 'when matching include path' do
602
+ it { is_expected.to(match('')) }
603
+ it { is_expected.to(match('bla bla/')) }
604
+ it { is_expected.to(match('bla //// bla/')) }
605
+ it { is_expected.to(match(' bla //// bla/')) }
606
+ it { expect(regexp.match(' bla //// bla/')[:path]).to(eq(' bla //// bla/')) }
607
+ it { expect(regexp.match('')[:path]).to(be_nil) }
608
+ end
609
+
610
+ context 'when not matching bad include path' do
611
+ it { is_expected.not_to(match('bla bla')) }
612
+ it { is_expected.not_to(match('bla bla/ ')) }
613
+ end
614
+ end
615
+
616
+ describe 'INCLUDE_FILENAME' do
617
+ subject(:regexp) { Regexp.new("^#{described_class::INCLUDE_FILENAME}$") }
618
+
619
+ context 'when matching valid filename' do
620
+ it { is_expected.to(match('bla bla @ -')) }
621
+ it { expect(regexp.match('bla bla @ -')[:filename]).to(eq('bla bla @ -')) }
622
+ end
623
+
624
+ context 'when not matching bad filename' do
625
+ it { is_expected.not_to(match('')) }
626
+ it { is_expected.not_to(match('bla / bla')) }
627
+ it { is_expected.not_to(match('bla \ bla ')) }
628
+ end
629
+ end
630
+
631
+ describe 'INCLUDE_OPTIONS' do
632
+ subject(:regexp) { Regexp.new("^#{described_class::INCLUDE_OPTIONS}$") }
633
+
634
+ context 'when matching include options' do
635
+ it { is_expected.to(match('[]')) }
636
+ it { is_expected.to(match('[whatever qsddl qmlsdkml qsdl]')) }
637
+ it { expect(regexp.match('[]')[:options]).to(eq('')) }
638
+ it { expect(regexp.match('[whatever blabla ]')[:options]).to(eq('whatever blabla ')) }
639
+ end
640
+
641
+ context 'when not matching bad include options' do
642
+ it { is_expected.not_to(match('[whatever]]')) }
643
+ it { is_expected.not_to(match('[whate]ver]')) }
644
+ end
645
+ end
646
+
647
+ describe 'INCLUDE' do
648
+ subject(:regexp) { described_class::INCLUDE }
649
+
650
+ context 'when matching include statement' do
651
+ let(:line) { 'include::my path/my filename[my options]' }
652
+
653
+ it { is_expected.to(match(line)) }
654
+ it { expect(regexp.match(line)[:path]).to(eq('my path/')) }
655
+ it { expect(regexp.match(line)[:filename]).to(eq('my filename')) }
656
+ it { expect(regexp.match(line)[:options]).to(eq('my options')) }
657
+ end
658
+
659
+ context 'when not matching bad include statement' do
660
+ it { is_expected.not_to(match('a include::my path/my filename[my options]')) }
661
+ it { is_expected.not_to(match('include::my path/my\ filename[my options]')) }
662
+ it { is_expected.not_to(match('include::my path/[my options]')) }
663
+ end
664
+ end
665
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: defmastership-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jérôme Arbez-Gindre
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-11-16 00:00:00.000000000 Z
11
+ date: 2025-01-04 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: jeromearbezgindre@gmail.com
@@ -32,6 +32,7 @@ files:
32
32
  - lib/defmastership/core/parsing_state.rb
33
33
  - lib/defmastership/core/version.rb
34
34
  - spec/spec_helper.rb
35
+ - spec/unit/defmastership/core/dm_regexp_spec.rb
35
36
  - spec/unit/defmastership/core/parsing_state_spec.rb
36
37
  - spec/unit/defmastership/core_spec.rb
37
38
  - tasks/code_quality.rake