11"""
2- SourceFile(code [; filename=nothing])
2+ SourceFile(code [; filename=nothing, first_line=1 ])
33
4- A UTF-8 source code string with associated file name and indexing structures.
4+ A UTF-8 source code string with associated file name and line number.
5+
6+ `SourceFile` stores the character positions of line starts to facilitate indexing.
57"""
68struct SourceFile
79 # We use `code::String` for now but it could be some other UTF-8 based
@@ -11,11 +13,12 @@ struct SourceFile
1113 # https://en.wikipedia.org/wiki/Rope_(data_structure)
1214 code:: String
1315 filename:: Union{Nothing,String}
16+ first_line:: Int
1417 # String index of start of every line
1518 line_starts:: Vector{Int}
1619end
1720
18- function SourceFile (code:: AbstractString ; filename= nothing )
21+ function SourceFile (code:: AbstractString ; filename= nothing , first_line = 1 )
1922 line_starts = Int[1 ]
2023 for i in eachindex (code)
2124 # The line is considered to start after the `\n`
@@ -25,31 +28,33 @@ function SourceFile(code::AbstractString; filename=nothing)
2528 if isempty (code) || last (code) != ' \n '
2629 push! (line_starts, ncodeunits (code)+ 1 )
2730 end
28- SourceFile (code, filename, line_starts)
31+ SourceFile (code, filename, first_line, line_starts)
2932end
3033
31- function SourceFile (; filename)
32- SourceFile (read (filename, String); filename= filename)
34+ function SourceFile (; filename, kwargs ... )
35+ SourceFile (read (filename, String); filename= filename, kwargs ... )
3336end
3437
3538# Get line number of the given byte within the code
36- function source_line (source:: SourceFile , byte_index)
37- line = searchsortedlast (source. line_starts, byte_index)
38- return (line < lastindex (source. line_starts)) ? line : line - 1
39+ function source_line_index (source:: SourceFile , byte_index)
40+ lineidx = searchsortedlast (source. line_starts, byte_index)
41+ return (lineidx < lastindex (source. line_starts)) ? lineidx : lineidx - 1
3942end
43+ _source_line (source:: SourceFile , lineidx) = lineidx + source. first_line - 1
44+ source_line (source:: SourceFile , byte_index) = _source_line (source, source_line_index (source, byte_index))
4045
4146"""
4247Get line number and character within the line at the given byte index.
4348"""
4449function source_location (source:: SourceFile , byte_index)
45- line = source_line (source, byte_index)
46- i = source. line_starts[line ]
50+ lineidx = source_line_index (source, byte_index)
51+ i = source. line_starts[lineidx ]
4752 column = 1
4853 while i < byte_index
4954 i = nextind (source. code, i)
5055 column += 1
5156 end
52- line , column
57+ _source_line (source, lineidx) , column
5358end
5459
5560"""
@@ -58,9 +63,9 @@ Get byte range of the source line at byte_index, buffered by
5863"""
5964function source_line_range (source:: SourceFile , byte_index;
6065 context_lines_before= 0 , context_lines_after= 0 )
61- line = source_line (source, byte_index)
62- fbyte = source. line_starts[max (line - context_lines_before, 1 )]
63- lbyte = source. line_starts[min (line + 1 + context_lines_after, end )] - 1
66+ lineidx = source_line_index (source, byte_index)
67+ fbyte = source. line_starts[max (lineidx - context_lines_before, 1 )]
68+ lbyte = source. line_starts[min (lineidx + 1 + context_lines_after, end )] - 1
6469 fbyte,lbyte
6570end
6671
0 commit comments