@@ -28,6 +28,7 @@ with LSP.Ada_Handlers.Formatting;
2828with LSP.Constants ;
2929with LSP.Enumerations ;
3030with LSP.Errors ;
31+ with LSP.Formatters.Fallback_Indenter ;
3132with LSP.Generic_Cancel_Check ;
3233with LSP.GPR_Completions ;
3334with LSP.GPR_Documentation ;
@@ -39,6 +40,7 @@ with LSP.Text_Documents.Langkit_Documents;
3940with LSP.Utils ;
4041
4142with Gpr_Parser.Common ;
43+ with VSS.Characters.Latin ;
4244with VSS.String_Vectors ;
4345with VSS.Strings ;
4446
@@ -409,7 +411,7 @@ package body LSP.GPR_Handlers is
409411 Response : LSP.Structures.InitializeResult;
410412 Capabilities : LSP.Structures.ServerCapabilities renames
411413 Response.capabilities;
412-
414+ use VSS.Strings;
413415 begin
414416 Self.File_Reader := LSP.GPR_File_Readers.Create (Self'Unchecked_Access);
415417
@@ -446,6 +448,11 @@ package body LSP.GPR_Handlers is
446448 (Is_Set => True, Value => (Is_Boolean => True, Boolean => True));
447449 Capabilities.documentFormattingProvider :=
448450 (Is_Set => True, Value => (Is_Boolean => True, Boolean => True));
451+ Capabilities.documentOnTypeFormattingProvider :=
452+ (Is_Set => True,
453+ Value =>
454+ (firstTriggerCharacter => 1 * VSS.Characters.Latin.Line_Feed,
455+ moreTriggerCharacter => <>));
449456
450457 Capabilities.textDocumentSync :=
451458 (Is_Set => True,
@@ -507,6 +514,39 @@ package body LSP.GPR_Handlers is
507514 others => <>)));
508515 end ;
509516
517+ -- If settings were given in initializationOptions, parse and apply them.
518+ if not Value.initializationOptions.Is_Empty then
519+ Self.Tracer.Trace
520+ (" Processing initializationOptions from initialize request" );
521+ declare
522+ New_Configuration : LSP.Ada_Configurations.Configuration :=
523+ Self.Configuration;
524+ -- Start from the existing configuration so that settings parsed
525+ -- from configuration files are preserved, and the settings from
526+ -- initialize request are applied on top.
527+
528+ Messages : VSS.String_Vectors.Virtual_String_Vector;
529+ begin
530+ -- Parse the configuration.
531+ New_Configuration.Read_JSON
532+ (Value.initializationOptions, Messages);
533+
534+ for Message of Messages loop
535+ Self.Sender.On_LogMessage_Notification
536+ ((LSP.Enumerations.Warning, Message));
537+ Self.Tracer.Trace_Text (Message);
538+ end loop ;
539+
540+ -- Set it as the current configuration.
541+ -- This will also save it as the initial configuration (if not done
542+ -- yet through config files) so that we can restore individual
543+ -- settings back to the initial state when
544+ -- 'onDidChangeConfiguration' provides null values.
545+ Self.Set_Configuration (New_Configuration);
546+ end ;
547+
548+ end if ;
549+
510550 Self.Sender.On_Initialize_Response (Id, Response);
511551 end On_Initialize_Request ;
512552
@@ -595,6 +635,76 @@ package body LSP.GPR_Handlers is
595635 end if ;
596636 end On_RangeFormatting_Request ;
597637
638+ -- -------------------------------
639+ -- On_OnTypeFormatting_Request --
640+ -- -------------------------------
641+
642+ overriding
643+ procedure On_OnTypeFormatting_Request
644+ (Self : in out Message_Handler;
645+ Id : LSP.Structures.Integer_Or_Virtual_String;
646+ Value : LSP.Structures.DocumentOnTypeFormattingParams)
647+ is
648+ use VSS.Strings;
649+ Response : LSP.Structures.TextEdit_Vector_Or_Null;
650+ Document : constant LSP.GPR_Documents.Document_Access :=
651+ Self.Get_Open_Document (Value.textDocument.uri);
652+ Options : constant Gnatformat.Configuration.Format_Options_Type :=
653+ Gnatformat.Configuration.Default_Format_Options;
654+
655+ Filename : constant GNATCOLL.VFS.Virtual_File :=
656+ Self.To_File (Value.textDocument.uri);
657+
658+ Indent_Array :
659+ constant LSP.Formatters.Fallback_Indenter.Indentation_Array :=
660+ LSP.Ada_Handlers.Formatting.Get_Indentation
661+ (Filename => Filename,
662+ Buffer =>
663+ Document.Slice (((0 , 0 ), (Value.position.line + 1 , 0 ))),
664+ Span =>
665+ ((0 , 0 ), (Value.position.line + 1 , 0 )),
666+ Options => Options);
667+ Indentation : constant VSS.Strings.Character_Count :=
668+ (if Indent_Array (Value.position.line + 1 ) = -1
669+ then 0
670+ else
671+ VSS.Strings.Character_Count
672+ (Indent_Array (Value.position.line + 1 )));
673+ begin
674+ -- First set the indentation for the new line
675+ Response.Append
676+ (LSP.Structures.TextEdit'
677+ (a_range =>
678+ (start => (Value.position.line, 0 ), an_end => Value.position),
679+ newText =>
680+ LSP.Ada_Handlers.Formatting.Handle_Tabs
681+ (Filename => Filename,
682+ Options => Options,
683+ S => Indentation * ' ' )));
684+
685+ -- If not in indent-only mode, re-indent the previous line too
686+ if not Self.Configuration.Indent_Only then
687+ declare
688+ Prev_Line : constant Natural :=
689+ Natural'Max (Value.position.line - 1 , 0 );
690+ Indentation : constant Natural :=
691+ (if Indent_Array (Prev_Line + 1 ) = -1
692+ then 0
693+ else Indent_Array (Prev_Line + 1 ));
694+ begin
695+ Response.Append
696+ (LSP.Ada_Handlers.Formatting.Reindent_Line
697+ (Filename => Filename,
698+ Line => Document.Get_Line (Prev_Line),
699+ Pos => (Prev_Line, 0 ),
700+ Options => Options,
701+ New_Indent => Indentation));
702+ end ;
703+ end if ;
704+
705+ Self.Sender.On_OnTypeFormatting_Response (Id, Response);
706+ end On_OnTypeFormatting_Request ;
707+
598708 -- -------------------------
599709 -- On_Completion_Request --
600710 -- -------------------------
0 commit comments