Skip to content

Commit 957581a

Browse files
committed
refactor: consider a space as the footer separator token
1 parent a5262a4 commit 957581a

File tree

3 files changed

+46
-18
lines changed

3 files changed

+46
-18
lines changed

src/main/kotlin/com/github/lppedd/cc/parser/ConventionalCommitParser.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ internal fun parseConventionalCommit(message: String, lenient: Boolean = false):
105105
while (reader.current?.type == CCToken.Type.FOOTER_TYPE) {
106106
val footerType = reader.takeAndAdvance()
107107

108-
// Consume/skip the separator, if present
108+
// Consume/skip the separator (':' or ' '), if present
109109
reader.consume(CCToken.Type.SEPARATOR)
110110

111111
// Allow a missing footer value, even in non-lenient mode

src/main/kotlin/com/github/lppedd/cc/parser/strictConventionalCommit.flex

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,29 @@ package com.github.lppedd.cc.parser;
2929
return value;
3030
}
3131

32-
private int getWsPushback() {
33-
final int length = yylength();
32+
private int getFooterTypePushback() {
33+
int i = yylength() - 1;
34+
int pushback = 0;
3435

35-
for (int i = length - 1, count = 0; i >= 0; i--, count++) {
36-
if (!Character.isWhitespace(yycharat(i))) {
37-
return count;
36+
// Push back trailing whitespace
37+
for (; i >= 0 && Character.isWhitespace(yycharat(i)); i--, pushback++);
38+
39+
// Check whether we now have a trailing '#'
40+
while (i >= 0 && yycharat(i) == '#') {
41+
// If '#' is attached (e.g., 'Something#'), keep it as part of the type and stop
42+
if (i - 1 >= 0 && !Character.isWhitespace(yycharat(i - 1))) {
43+
break;
3844
}
45+
46+
// Since the '#' char is preceeded by a whitespace, push it back
47+
i--;
48+
pushback++;
49+
50+
// Push back any whitespace before the '#' we have just encountered
51+
for (; i >= 0 && Character.isWhitespace(yycharat(i)); i--, pushback++);
3952
}
4053

41-
return length;
54+
return pushback;
4255
}
4356

4457
private CCToken token(final CCToken.Type type) {
@@ -66,6 +79,7 @@ FooterType = [^\s:][^:\r\n]*
6679
%state BODY_OR_FOOTERS
6780
%state BODY
6881
%state FOOTERS
82+
%state FOOTER_HASH_SEPARATOR
6983
%state FOOTER_VALUE
7084

7185
%%
@@ -136,9 +150,9 @@ FooterType = [^\s:][^:\r\n]*
136150

137151
// Closes #16
138152
^{FooterType}{WS} / #.* {
139-
// Push back any terminating whitespace, which should be part of the footer value instead
140-
yypushback(getWsPushback());
141-
yybegin(FOOTER_VALUE);
153+
// Push back any trailing whitespace or '#'
154+
yypushback(getFooterTypePushback());
155+
yybegin(FOOTER_HASH_SEPARATOR);
142156
return token(CCToken.Type.FOOTER_TYPE);
143157
}
144158

@@ -181,9 +195,9 @@ FooterType = [^\s:][^:\r\n]*
181195

182196
// Closes #16
183197
^{FooterType}{WS} / #.* {
184-
// Push back any terminating whitespace, which should be part of the footer value instead
185-
yypushback(getWsPushback());
186-
yybegin(FOOTER_VALUE);
198+
// Push back any trailing whitespace or '#'
199+
yypushback(getFooterTypePushback());
200+
yybegin(FOOTER_HASH_SEPARATOR);
187201
return token(CCToken.Type.FOOTER_TYPE);
188202
}
189203

@@ -201,6 +215,15 @@ FooterType = [^\s:][^:\r\n]*
201215
}
202216
}
203217

218+
<FOOTER_HASH_SEPARATOR> {
219+
// Lex exactly one whitespace as the footer separator token ' '.
220+
// Additional whitespace will be lexed as part of the footer value.
221+
{WS} {
222+
yybegin(FOOTER_VALUE);
223+
return token(CCToken.Type.SEPARATOR);
224+
}
225+
}
226+
204227
<FOOTER_VALUE> {
205228
// Closes #16 | .+
206229
// multiline footer | ({NewLine}{Space}+([^\s]+{Space}*)+)*

src/test/kotlin/com/github/lppedd/cc/parser/ConventionalCommitParserTest.kt

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ class ConventionalCommitParserTest {
166166
|
167167
|Closes: example 1
168168
|Fixes #12
169+
|Fixes # # #12
169170
|[Author]
170171
|Refs: example 2
171172
""".trimMargin()
@@ -177,7 +178,7 @@ class ConventionalCommitParserTest {
177178
assertEquals("refactor", message.type)
178179
assertEquals("scope", message.scope)
179180
assertEquals("foo", message.subject.trim())
180-
assertEquals(4, message.footers.size)
181+
assertEquals(5, message.footers.size)
181182

182183
val (type1, value1) = message.footers[0]
183184
assertEquals("Closes", type1)
@@ -188,12 +189,16 @@ class ConventionalCommitParserTest {
188189
assertEquals("#12", value2.trim())
189190

190191
val (type3, value3) = message.footers[2]
191-
assertEquals("[Author] ", type3)
192-
assertEquals("", value3)
192+
assertEquals("Fixes", type3)
193+
assertEquals("# # #12", value3.trim())
193194

194195
val (type4, value4) = message.footers[3]
195-
assertEquals("Refs", type4)
196-
assertEquals("example 2", value4.trim())
196+
assertEquals("[Author] ", type4)
197+
assertEquals("", value4)
198+
199+
val (type5, value5) = message.footers[4]
200+
assertEquals("Refs", type5)
201+
assertEquals("example 2", value5.trim())
197202

198203
assertFalse(message.isBreakingChange)
199204
}

0 commit comments

Comments
 (0)