Skip to content

Commit a1bad88

Browse files
joke1196ghislainpiot
authored andcommitted
SONARPY-2033: Adapt Highlighter for Jupyter Notebooks (#1899)
1 parent 6e0631e commit a1bad88

File tree

5 files changed

+165
-73
lines changed

5 files changed

+165
-73
lines changed

python-frontend/src/main/java/org/sonar/python/TestPythonVisitorRunner.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.nio.charset.StandardCharsets;
2626
import java.nio.file.Files;
2727
import java.util.List;
28+
import java.util.Map;
2829
import javax.annotation.Nullable;
2930
import org.sonar.plugins.python.api.PythonCheck;
3031
import org.sonar.plugins.python.api.PythonFile;
@@ -52,6 +53,14 @@ public static PythonVisitorContext scanFile(File file, PythonCheck... visitors)
5253
return context;
5354
}
5455

56+
public static PythonVisitorContext scanNotebookFile(File file, Map<Integer, IPythonLocation> locations, String content, PythonCheck... visitors) {
57+
PythonVisitorContext context = createNotebookContext(file, locations, content, "", ProjectLevelSymbolTable.empty(), CacheContextImpl.dummyCache());
58+
for (PythonCheck visitor : visitors) {
59+
visitor.scanFile(context);
60+
}
61+
return context;
62+
}
63+
5564
public static PythonVisitorContext createContext(File file) {
5665
return createContext(file, null);
5766
}
@@ -67,6 +76,13 @@ public static PythonVisitorContext createContext(File file, @Nullable File worki
6776
return new PythonVisitorContext(rootTree, pythonFile, workingDirectory, packageName, projectLevelSymbolTable, cacheContext);
6877
}
6978

79+
public static PythonVisitorContext createNotebookContext(File file, Map<Integer, IPythonLocation> locations, String content, String packageName,
80+
ProjectLevelSymbolTable projectLevelSymbolTable, CacheContext cacheContext) {
81+
TestPythonFile pythonFile = new TestPythonFile(file);
82+
FileInput rootTree = parseNotebookFile(locations, content);
83+
return new PythonVisitorContext(rootTree, pythonFile, null, packageName, projectLevelSymbolTable, cacheContext);
84+
}
85+
7086
public static ProjectLevelSymbolTable globalSymbols(List<File> files, File baseDir) {
7187
ProjectLevelSymbolTable projectLevelSymbolTable = new ProjectLevelSymbolTable();
7288
for (File file : files) {
@@ -81,9 +97,16 @@ public static ProjectLevelSymbolTable globalSymbols(List<File> files, File baseD
8197
return projectLevelSymbolTable;
8298
}
8399

100+
private static FileInput parseNotebookFile(Map<Integer, IPythonLocation> locations, String content) {
101+
var parser = PythonParser.createIPythonParser();
102+
var treeMaker = new IPythonTreeMaker(locations);
103+
var astNode = parser.parse(content);
104+
return treeMaker.fileInput(astNode);
105+
}
106+
84107
private static FileInput parseFile(TestPythonFile file) {
85108
var parser = file.isIPython() ? PythonParser.createIPythonParser() : PythonParser.create();
86-
var treeMaker = file.isIPython() ? new IPythonTreeMaker() : new PythonTreeMaker();
109+
var treeMaker = file.isIPython() ? new IPythonTreeMaker(Map.of()) : new PythonTreeMaker();
87110

88111
var astNode = parser.parse(file.content());
89112
return treeMaker.fileInput(astNode);

python-frontend/src/test/java/org/sonar/python/TestPythonVisitorRunnerTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.io.IOException;
2424
import java.nio.file.Files;
2525
import java.util.List;
26+
import java.util.Map;
2627
import org.junit.jupiter.api.Test;
2728
import org.sonar.plugins.python.api.PythonCheck;
2829
import org.sonar.plugins.python.api.PythonVisitorContext;
@@ -75,4 +76,12 @@ void globalSymbolsIPython() {
7576
.extracting(Symbol::name)
7677
.containsExactlyInAnyOrder("hello", "A");
7778
}
79+
80+
@Test
81+
void scanNotebookFile() throws IOException {
82+
File tmpFile = Files.createTempFile("foo", ".ipynb").toFile();
83+
var check = (PythonCheck) visitorContect -> {};
84+
PythonVisitorContext context = TestPythonVisitorRunner.scanNotebookFile(tmpFile, Map.of(), "", check);
85+
assertThat(context.pythonFile().uri()).isEqualTo(tmpFile.toURI());
86+
}
7887
}

sonar-python-plugin/src/main/java/org/sonar/plugins/python/PythonHighlighter.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,14 @@
8989
public class PythonHighlighter extends PythonSubscriptionCheck {
9090

9191
private NewHighlighting newHighlighting;
92-
9392
private Set<Token> docStringTokens;
93+
private PythonInputFile inputFile;
9494

9595
public PythonHighlighter(SensorContext context, PythonInputFile inputFile) {
9696
docStringTokens = new HashSet<>();
9797
newHighlighting = context.newHighlighting();
9898
newHighlighting.onFile(inputFile.wrappedFile());
99+
this.inputFile = inputFile;
99100
}
100101

101102
@Override
@@ -137,8 +138,10 @@ private void visitToken(Token token) {
137138

138139
}
139140

140-
for (Trivia trivia : token.trivia()) {
141-
highlight(trivia.token(), TypeOfText.COMMENT);
141+
if (inputFile.kind() == PythonInputFile.Kind.PYTHON) {
142+
for (Trivia trivia : token.trivia()) {
143+
highlight(trivia.token(), TypeOfText.COMMENT);
144+
}
142145
}
143146
}
144147

0 commit comments

Comments
 (0)