defmastership-core 1.2.0 → 1.4.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 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