3131
3232public class IpynbNotebookParser {
3333
34- public static final String SONAR_PYTHON_NOTEBOOK_CELL_DELIMITER = "#SONAR_PYTHON_NOTEBOOK_CELL_DELIMITER\n " ;
34+ public static final String SONAR_PYTHON_NOTEBOOK_CELL_DELIMITER = "#SONAR_PYTHON_NOTEBOOK_CELL_DELIMITER" ;
3535
3636 public static GeneratedIPythonFile parseNotebook (PythonInputFile inputFile ) {
3737 try {
@@ -50,7 +50,9 @@ private IpynbNotebookParser(PythonInputFile inputFile) {
5050
5151 // Keys are the aggregated source line number
5252 private final Map <Integer , IPythonLocation > locationMap = new HashMap <>();
53- private int aggregatedSourceLine = 1 ;
53+ private int aggregatedSourceLine = 0 ;
54+ private int lastPythonLine = 0 ;
55+ private boolean isFirstCell = true ;
5456
5557 public GeneratedIPythonFile parseNotebook () throws IOException {
5658 String content = inputFile .wrappedFile ().contents ();
@@ -68,12 +70,15 @@ public GeneratedIPythonFile parseNotebook() throws IOException {
6870 }
6971 }
7072 }
73+ // Account for EOF token
74+ addDefaultLocation (lastPythonLine , jParser .currentTokenLocation ());
7175 }
7276
7377 return new GeneratedIPythonFile (inputFile .wrappedFile (), aggregatedSource .toString (), locationMap );
7478 }
7579
7680 private void processCodeCell (JsonParser jParser ) throws IOException {
81+
7782 while (!jParser .isClosed ()) {
7883 JsonToken jsonToken = jParser .nextToken ();
7984 if (JsonToken .FIELD_NAME .equals (jsonToken ) && "source" .equals (jParser .currentName ())) {
@@ -87,26 +92,38 @@ private void processCodeCell(JsonParser jParser) throws IOException {
8792 }
8893 }
8994
95+ private void appendNewLineAfterPreviousCellDelimiter () {
96+ if (!isFirstCell ) {
97+ aggregatedSource .append ("\n " );
98+ } else {
99+ isFirstCell = false ;
100+ }
101+ }
102+
90103 private boolean parseSourceArray (JsonParser jParser , JsonToken jsonToken ) throws IOException {
91104 if (jsonToken != JsonToken .START_ARRAY ) {
92105 return false ;
93106 }
107+ appendNewLineAfterPreviousCellDelimiter ();
108+ JsonLocation tokenLocation = jParser .currentTokenLocation ();
94109 while (jParser .nextToken () != JsonToken .END_ARRAY ) {
95110 String sourceLine = jParser .getValueAsString ();
96- var tokenLocation = jParser .currentTokenLocation ();
111+ tokenLocation = jParser .currentTokenLocation ();
97112 var countEscapedChar = countEscapeCharacters (sourceLine , new LinkedHashMap <>(), tokenLocation .getColumnNr ());
98113 addLineToSource (sourceLine , tokenLocation , countEscapedChar );
99114 }
100115 aggregatedSource .append ("\n " );
101116 // Account for the last cell delimiter
102- addDelimiterToSource ();
117+ addDelimiterToSource (tokenLocation );
118+ lastPythonLine = aggregatedSourceLine ;
103119 return true ;
104120 }
105121
106122 private boolean parseSourceMultilineString (JsonParser jParser , JsonToken jsonToken ) throws IOException {
107123 if (jsonToken != JsonToken .VALUE_STRING ) {
108124 return false ;
109125 }
126+ appendNewLineAfterPreviousCellDelimiter ();
110127 String sourceLine = jParser .getValueAsString ();
111128 JsonLocation tokenLocation = jParser .currentTokenLocation ();
112129 var previousLen = 0 ;
@@ -122,7 +139,8 @@ private boolean parseSourceMultilineString(JsonParser jParser, JsonToken jsonTok
122139 previousExtraChars = currentCount ;
123140 }
124141 // Account for the last cell delimiter
125- addDelimiterToSource ();
142+ addDelimiterToSource (tokenLocation );
143+ lastPythonLine = aggregatedSourceLine ;
126144 return true ;
127145 }
128146
@@ -132,13 +150,18 @@ private void addLineToSource(String sourceLine, JsonLocation tokenLocation, Map<
132150
133151 private void addLineToSource (String sourceLine , IPythonLocation location ) {
134152 aggregatedSource .append (sourceLine );
135- locationMap .put (aggregatedSourceLine , location );
136153 aggregatedSourceLine ++;
154+ locationMap .put (aggregatedSourceLine , location );
137155 }
138156
139- private void addDelimiterToSource () {
157+ private void addDelimiterToSource (JsonLocation tokenLocation ) {
140158 aggregatedSource .append (SONAR_PYTHON_NOTEBOOK_CELL_DELIMITER );
141159 aggregatedSourceLine ++;
160+ addDefaultLocation (aggregatedSourceLine , tokenLocation );
161+ }
162+
163+ private void addDefaultLocation (int line , JsonLocation tokenLocation ) {
164+ locationMap .putIfAbsent (line , new IPythonLocation (tokenLocation .getLineNr (), tokenLocation .getColumnNr (), Map .of (-1 , 0 )));
142165 }
143166
144167 private static Map <Integer , Integer > countEscapeCharacters (String sourceLine , Map <Integer , Integer > colMap , int colOffSet ) {
0 commit comments