@@ -41,7 +41,9 @@ package body Langkit_Support.Token_Data_Handlers is
4141 with package Element_Vectors is new Langkit_Support.Vectors (<>);
4242
4343 with function Compare
44- (K : Key_Type; E_Index : Positive; E : Element_Vectors.Element_Type)
44+ (K : Key_Type;
45+ E_Index : Positive;
46+ E : Element_Vectors.Element_Type)
4547 return Relative_Position is <>;
4648 -- Tell where K is with respect to E (E_Index is the index of E in the
4749 -- vector).
@@ -117,19 +119,22 @@ package body Langkit_Support.Token_Data_Handlers is
117119 -- Initialize --
118120 -- --------------
119121
120- procedure Initialize (TDH : out Token_Data_Handler; Symbols : Symbol_Table)
121- is
122+ procedure Initialize
123+ (TDH : out Token_Data_Handler;
124+ Symbols : Symbol_Table;
125+ Tab_Stop : Positive := Default_Tab_Stop) is
122126 begin
123- TDH := (Source_Buffer => null ,
124- Source_First => <>,
125- Source_Last => <>,
126- Filename => <>,
127- Charset => <>,
128- Tokens => <>,
129- Symbols => Symbols,
130- Tokens_To_Trivias => <>,
131- Trivias => <>,
132- Lines_Starts => <>);
127+ TDH := (Source_Buffer => null ,
128+ Source_First => <>,
129+ Source_Last => <>,
130+ Filename => <>,
131+ Charset => <>,
132+ Tokens => <>,
133+ Symbols => Symbols,
134+ Tokens_To_Trivias => <>,
135+ Trivias => <>,
136+ Lines_Starts => <>,
137+ Tab_Stop => Tab_Stop);
133138 end Initialize ;
134139
135140 -- ---------
@@ -217,7 +222,8 @@ package body Langkit_Support.Token_Data_Handlers is
217222 Symbols => No_Symbol_Table,
218223 Tokens_To_Trivias => <>,
219224 Trivias => <>,
220- Lines_Starts => <>);
225+ Lines_Starts => <>,
226+ Tab_Stop => <>);
221227 end Move ;
222228
223229 -- ------------------------
@@ -537,11 +543,12 @@ package body Langkit_Support.Token_Data_Handlers is
537543 declare
538544 Triv_Index : constant Natural := Natural (Key_Trivia);
539545 Tok_Index : constant Natural := Element_Index - 1 ;
540- Key_Start_Sloc : constant Source_Location := Start_Sloc
541- (TDH.Trivias.Get (Triv_Index).T.Sloc_Range );
546+ Key_Start_Sloc : constant Source_Location := Sloc_Start
547+ (TDH, TDH .Trivias.Get (Triv_Index).T);
542548 begin
543549 return Compare
544- (TDH.Tokens.Get (Tok_Index).Sloc_Range, Key_Start_Sloc);
550+ (Sloc_Range (TDH, TDH.Tokens.Get (Tok_Index)),
551+ Key_Start_Sloc);
545552 end ;
546553 end if ;
547554
@@ -582,13 +589,13 @@ package body Langkit_Support.Token_Data_Handlers is
582589 (Sloc : Source_Location;
583590 Dummy_Index : Positive;
584591 Token : Stored_Token_Data) return Relative_Position
585- is (Compare (Token. Sloc_Range, Sloc));
592+ is (Compare (Sloc_Range (TDH, Token) , Sloc));
586593
587594 function Compare
588595 (Sloc : Source_Location;
589596 Dummy_Index : Positive;
590597 Trivia : Trivia_Node) return Relative_Position
591- is (Compare (Trivia.T.Sloc_Range , Sloc));
598+ is (Compare (Sloc_Range (TDH, Trivia.T) , Sloc));
592599
593600 function Token_Floor is new Floor
594601 (Key_Type => Source_Location,
@@ -617,7 +624,7 @@ package body Langkit_Support.Token_Data_Handlers is
617624
618625 declare
619626 function SS (Token : Stored_Token_Data) return Source_Location is
620- (Start_Sloc ( Token.Sloc_Range ));
627+ (Sloc_Start (TDH, Token));
621628
622629 Tok_Sloc : constant Source_Location := SS (TDH.Tokens.Get (Token));
623630 Triv_Sloc : constant Source_Location :=
@@ -681,16 +688,121 @@ package body Langkit_Support.Token_Data_Handlers is
681688 begin
682689 -- Return slice from...
683690 return
684- TDH.Source_Buffer (
685- -- The first character in the requested line
686- TDH.Lines_Starts.Get (Line_Number)
691+ TDH.Source_Buffer
692+ (
693+ -- The first character in the requested line
694+ TDH.Lines_Starts.Get (Line_Number)
695+
696+ ..
687697
688- ..
698+ -- The character before the LF that precedes the first character of
699+ -- the next line.
700+ TDH.Lines_Starts.Get (Line_Number + 1 ) - 2
701+ );
689702
690- -- The character before the LF that precedes the first character of
691- -- the next line.
692- TDH.Lines_Starts.Get (Line_Number + 1 ) - 2
693- );
694703 end Get_Line ;
695704
705+ -- ------------
706+ -- Get_Sloc --
707+ -- ------------
708+
709+ function Get_Sloc
710+ (TDH : Token_Data_Handler; Index : Natural) return Source_Location
711+ is
712+ function Compare
713+ (Sought : Positive;
714+ Dummy_Index : Positive;
715+ Line_Start : Positive) return Relative_Position
716+ is
717+ (if Sought > Line_Start then After
718+ elsif Sought = Line_Start then Inside
719+ else Before);
720+
721+ function Get_Line_Index is new Floor (Positive, Index_Vectors);
722+ -- Return the index of the first character of Line `N` in a given
723+ -- `TDH.Line_Starts` vector.
724+
725+ Column : Natural := 0 ;
726+ -- 0 based column number
727+
728+ Tab_Stop : Positive renames TDH.Tab_Stop;
729+ begin
730+ -- Allow 0 as an offset because it's a common value when the text buffer
731+ -- is empty: in that case just return a null source location.
732+ if Index = 0 then
733+ return No_Source_Location;
734+ end if ;
735+
736+ declare
737+ Line_Index : constant Positive :=
738+ Get_Line_Index (Index, TDH.Lines_Starts);
739+ Line_Offset : constant Positive := TDH.Lines_Starts.Get (Line_Index);
740+ begin
741+ -- Allow a sloc pointing at the EOL char (hence the + 1)
742+ if Index > TDH.Source_Buffer'Last + 1 then
743+ raise Constraint_Error with " out of bound access" ;
744+ end if ;
745+
746+ -- Make horizontal tabulations move by stride of Tab_Stop columns, as
747+ -- usually implemented in code editors.
748+ for I in Line_Offset .. Natural'Min (Index, TDH.Source_Last) - 1 loop
749+ if TDH.Source_Buffer (I) = Chars.HT then
750+ Column := (Column + Tab_Stop) / Tab_Stop * Tab_Stop;
751+ else
752+ Column := Column + 1 ;
753+ end if ;
754+ end loop ;
755+
756+ return Source_Location'
757+ (Line => Line_Number (Line_Index),
758+ Column =>
759+ Column_Number
760+ (Natural'Max (Column + 1 , Index - Line_Offset + 1 )));
761+ end ;
762+ end Get_Sloc ;
763+
764+ -- --------------
765+ -- Sloc_Start --
766+ -- --------------
767+
768+ function Sloc_Start
769+ (TDH : Token_Data_Handler;
770+ Token : Stored_Token_Data) return Source_Location is
771+ begin
772+ return Get_Sloc (TDH, Token.Source_First);
773+ end Sloc_Start ;
774+
775+ -- ------------
776+ -- Sloc_End --
777+ -- ------------
778+
779+ function Sloc_End
780+ (TDH : Token_Data_Handler;
781+ Token : Stored_Token_Data) return Source_Location is
782+ begin
783+ return Get_Sloc
784+ (TDH,
785+ (if Token.Source_Last < Token.Source_First
786+ -- This is a special case for when the range is negative: in that
787+ -- case we want to propagate that behavior to the sloc itself,
788+ -- because negative ranges are used for tokens that have no
789+ -- "width", and shouldn't be lookup-able, like the termination
790+ -- token.
791+ then Token.Source_Last
792+ -- For regular cases, we want the sloc_end to be one column after
793+ -- the end of the token.
794+ else Token.Source_Last + 1 ));
795+ end Sloc_End ;
796+
797+ -- --------------
798+ -- Sloc_Range --
799+ -- --------------
800+
801+ function Sloc_Range
802+ (TDH : Token_Data_Handler;
803+ Token : Stored_Token_Data) return Source_Location_Range is
804+ begin
805+ return Make_Range (Sloc_Start (TDH, Token), Sloc_End (TDH, Token));
806+ end Sloc_Range ;
807+
696808end Langkit_Support.Token_Data_Handlers ;
0 commit comments