25
25
import com .fasterxml .jackson .core .JsonToken ;
26
26
import java .io .IOException ;
27
27
import java .util .HashMap ;
28
+ import java .util .LinkedHashMap ;
28
29
import java .util .Map ;
29
30
30
31
public class IpynbNotebookParser {
@@ -91,7 +92,9 @@ private boolean parseSourceArray(JsonParser jParser, JsonToken jsonToken) throws
91
92
}
92
93
while (jParser .nextToken () != JsonToken .END_ARRAY ) {
93
94
String sourceLine = jParser .getValueAsString ();
94
- addLineToSource (sourceLine , jParser .currentTokenLocation ());
95
+ var tokenLocation = jParser .currentTokenLocation ();
96
+ var countEscapedChar = countEscapeCharacters (sourceLine , new LinkedHashMap <>(), tokenLocation .getColumnNr ());
97
+ addLineToSource (sourceLine , tokenLocation , countEscapedChar );
95
98
}
96
99
// Account for the last cell delimiter
97
100
addDelimiterToSource ();
@@ -104,19 +107,29 @@ private boolean parseSourceMultilineString(JsonParser jParser, JsonToken jsonTok
104
107
}
105
108
String sourceLine = jParser .getValueAsString ();
106
109
JsonLocation tokenLocation = jParser .currentTokenLocation ();
110
+ var previousLen = 0 ;
111
+ var previousExtraChars = 0 ;
107
112
108
113
for (String line : sourceLine .lines ().toList ()) {
109
- aggregatedSource .append (line );
110
- addLineToSource ("\n " , tokenLocation );
114
+ var countEscapedChar = countEscapeCharacters (line , new LinkedHashMap <>(), tokenLocation .getColumnNr ());
115
+ var currentCount = countEscapedChar .get (-1 );
116
+ addLineToSource (line , new IPythonLocation (tokenLocation .getLineNr (),
117
+ tokenLocation .getColumnNr () + previousLen + previousExtraChars + 1 , countEscapedChar ));
118
+ previousLen = line .length () + 2 ;
119
+ previousExtraChars = currentCount ;
111
120
}
112
121
// Account for the last cell delimiter
113
122
addDelimiterToSource ();
114
123
return true ;
115
124
}
116
125
117
- private void addLineToSource (String sourceLine , JsonLocation tokenLocation ) {
126
+ private void addLineToSource (String sourceLine , JsonLocation tokenLocation , Map <Integer , Integer > colOffset ) {
127
+ addLineToSource (sourceLine , new IPythonLocation (tokenLocation .getLineNr (), tokenLocation .getColumnNr (), colOffset ));
128
+ }
129
+
130
+ private void addLineToSource (String sourceLine , IPythonLocation location ) {
118
131
aggregatedSource .append (sourceLine );
119
- locationMap .put (aggregatedSourceLine , new IPythonLocation ( tokenLocation . getLineNr (), tokenLocation . getColumnNr ()) );
132
+ locationMap .put (aggregatedSourceLine , location );
120
133
aggregatedSourceLine ++;
121
134
}
122
135
@@ -125,10 +138,36 @@ private void addDelimiterToSource() {
125
138
aggregatedSourceLine ++;
126
139
}
127
140
141
+ private static Map <Integer , Integer > countEscapeCharacters (String sourceLine , Map <Integer , Integer > colMap , int colOffSet ) {
142
+ int count = 0 ;
143
+ var numberOfExtraChars = 0 ;
144
+ var arr = sourceLine .toCharArray ();
145
+ for (int i = 1 ; i < sourceLine .length (); ++i ) {
146
+ char c = arr [i ];
147
+ switch (c ) {
148
+ case '"' , '\'' , '/' :
149
+ // + 1 as we do have to count the open quote.
150
+ colMap .put (i , i + colOffSet + count + 1 );
151
+ if (c != '/' ) {
152
+ numberOfExtraChars ++;
153
+ }
154
+ break ;
155
+ case '\\' , '\b' , '\f' , '\n' , '\r' , '\t' :
156
+ count += 2 ;
157
+ numberOfExtraChars ++;
158
+ break ;
159
+ default :
160
+ break ;
161
+ }
162
+ }
163
+ colMap .put (-1 , numberOfExtraChars );
164
+ return colMap ;
165
+ }
166
+
128
167
public record ParseResult (PythonInputFile inputFile , String aggregatedSource , Map <Integer , IPythonLocation > locationMap ) {
129
168
}
130
169
131
- public record IPythonLocation (int line , int column ) {
170
+ public record IPythonLocation (int line , int column , Map < Integer , Integer > colOffset ) {
132
171
}
133
172
134
173
}
0 commit comments