Skip to content

Commit 116c745

Browse files
authored
SONARPY-1995: Support Jupyter Delimiter in Notebooks lexer (#2047)
1 parent 225453f commit 116c745

File tree

4 files changed

+22
-5
lines changed

4 files changed

+22
-5
lines changed

python-frontend/src/main/java/org/sonar/python/lexer/IPynbCellDelimiterChannel.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
public class IPynbCellDelimiterChannel extends Channel<Lexer> {
3131

3232
private final StringBuilder tmpBuilder = new StringBuilder();
33-
private final Matcher matcher = Pattern.compile("#SONAR_PYTHON_NOTEBOOK_CELL_DELIMITER").matcher("");
33+
private final Matcher sonarLintVSCodeCellDelimiter = Pattern.compile("#SONAR_PYTHON_NOTEBOOK_CELL_DELIMITER").matcher("");
34+
private final Matcher cellDelimiter = Pattern.compile("#\\h?%%(\\h+\\w+)?").matcher("");
3435
private final Token.Builder tokenBuilder = Token.builder();
3536
private final LexerState lexerState;
3637

@@ -44,7 +45,7 @@ public boolean consume(CodeReader code, Lexer lexer) {
4445
// Cell delimiters must be at the beginning of a line
4546
return false;
4647
}
47-
if (code.popTo(matcher, tmpBuilder) > 0) {
48+
if (code.popTo(sonarLintVSCodeCellDelimiter, tmpBuilder) > 0 || code.popTo(cellDelimiter, tmpBuilder) > 0) {
4849
resetIndentationLevel(code, lexer);
4950
String value = tmpBuilder.toString();
5051

python-frontend/src/test/java/org/sonar/python/lexer/IPythonLexerTest.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import static org.hamcrest.MatcherAssert.assertThat;
3131
import static org.hamcrest.Matchers.not;
3232

33-
3433
class IPythonLexerTest {
3534
private static TestLexer lexer;
3635

@@ -50,9 +49,19 @@ List<Token> lex(String code) {
5049
}
5150

5251
@Test
53-
void cellDelimiterTest() {
52+
void sonarLintVSCodeCellDelimiterTest() {
5453
assertThat(lexer.lex("foo\n#SONAR_PYTHON_NOTEBOOK_CELL_DELIMITER"), hasToken(PythonTokenType.IPYNB_CELL_DELIMITER));
5554
assertThat(lexer.lex("foo #SONAR_PYTHON_NOTEBOOK_CELL_DELIMITER"), not(hasToken(PythonTokenType.IPYNB_CELL_DELIMITER)));
5655
assertThat(lexer.lex("if cond:\n foo()\n#SONAR_PYTHON_NOTEBOOK_CELL_DELIMITER"), hasToken(PythonTokenType.DEDENT));
5756
}
57+
58+
@Test
59+
void cellDelimiterTest() {
60+
assertThat(lexer.lex("#%%\ndef foo():\n pass\n#%%"), hasToken(PythonTokenType.IPYNB_CELL_DELIMITER));
61+
assertThat(lexer.lex("#%% md\nthis is text ="), hasToken(PythonTokenType.IPYNB_CELL_DELIMITER));
62+
assertThat(lexer.lex("foo\n#%%"), hasToken(PythonTokenType.IPYNB_CELL_DELIMITER));
63+
assertThat(lexer.lex("foo\n# %%"), hasToken(PythonTokenType.IPYNB_CELL_DELIMITER));
64+
assertThat(lexer.lex("foo #%% md"), not(hasToken(PythonTokenType.IPYNB_CELL_DELIMITER)));
65+
assertThat(lexer.lex("if cond:\n foo()\n# %% [markdown]"), hasToken(PythonTokenType.DEDENT));
66+
}
5867
}

python-frontend/src/test/java/org/sonar/python/parser/PythonParserTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ private static Collection<File> listFiles(String folderName) {
4848
return FileUtils.listFiles(dir, new String[]{"py"}, true);
4949
}
5050

51-
5251
@Test
5352
void test_notebook() throws Exception {
5453
Collection<File> files = listFiles("notebooks");
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#%%
2+
import collections
3+
collections.Counter??
4+
#%%
5+
def foo():
6+
pass
7+
# %%
8+
a = 3

0 commit comments

Comments
 (0)