Skip to content

Commit

Permalink
Add defensive code when computing tooltip text
Browse files Browse the repository at this point in the history
In particular we should not even try to compute the variables'
declarations if the root project could not be parsed.

Add automatic test for this.

For eng/ide/gnatstudio#345
  • Loading branch information
AnthonyLeonardoGracio committed Jul 18, 2024
1 parent 9b94c68 commit f56621f
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 10 deletions.
11 changes: 6 additions & 5 deletions source/gpr/lsp-gpr_documents.adb
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,11 @@ package body LSP.GPR_Documents is
----------------

function Has_Errors
(Self : Document)
(Self : Document)
return Boolean is
begin
return Self.Tree.Log_Messages.Has_Error;
return Self.Tree.Log_Messages.Has_Error
or else not Self.Tree.Root_Project.Is_Defined;
end Has_Errors;

----------------
Expand Down Expand Up @@ -300,7 +301,7 @@ package body LSP.GPR_Documents is

begin
if LSP.GPR_Files.References.Is_Variable_Reference (Reference)
and then not Self.Tree.Log_Messages.Has_Error
and then not Self.Has_Errors
then
declare
File : constant LSP.GPR_Files.File_Access :=
Expand Down Expand Up @@ -373,7 +374,7 @@ package body LSP.GPR_Documents is

begin
if LSP.GPR_Files.References.Is_Attribute_Reference (Reference)
and then not Self.Tree.Log_Messages.Has_Error
and then not Self.Has_Errors
then
declare
File : constant LSP.GPR_Files.File_Access :=
Expand Down Expand Up @@ -446,7 +447,7 @@ package body LSP.GPR_Documents is

begin
if LSP.GPR_Files.References.Is_Type_Reference (Reference)
and then not Self.Tree.Log_Messages.Has_Error
and then not Self.Has_Errors
then
declare
File : constant LSP.GPR_Files.File_Access :=
Expand Down
3 changes: 2 additions & 1 deletion source/gpr/lsp-gpr_documents.ads
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ package LSP.GPR_Documents is
function Has_Errors
(Self : Document)
return Boolean;
-- Returns True when errors found during document parsing.
-- Returns True when errors found during document parsing or if
-- the tree could not be parsed properly (no defined root project).

-----------------------
-- Document_Provider --
Expand Down
5 changes: 1 addition & 4 deletions source/gpr/lsp-gpr_handlers.adb
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,6 @@ package body LSP.GPR_Handlers is
Documentation_Text : VSS.Strings.Virtual_String;
Location_Text : VSS.Strings.Virtual_String;
begin

LSP.GPR_Documentation.Get_Tooltip_Text
(Self => File,
URI => Value.textDocument.uri,
Expand Down Expand Up @@ -620,9 +619,7 @@ package body LSP.GPR_Handlers is
declare
Message : constant VSS.Strings.Virtual_String :=
VSS.Strings.Conversions.To_Virtual_String
("Exception: " &
Ada.Exceptions.Exception_Name (E) & " (" &
Ada.Exceptions.Exception_Message (E) & ")");
("Exception: " & Ada.Exceptions.Exception_Information (E));

begin
Self.Tracer.Trace_Exception (E, "On_Server_Request");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
project Prj1 is
for Source_Dirs use ("src");
package Compiler is
for Switches ("Ada") use ();
end Compiler;
package IDE is
for Artifacts_Dir use "";
end IDE;
end Prj1;
16 changes: 16 additions & 0 deletions testsuite/gpr_lsp/hover.no_exception_when_failed_to_load/prj3.gpr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
with "unknown";
project Prj3 is
type T is ("project.Var value ");
Var : T := "project.Var value ";
package Builder is
Var := "project.Builder.Var value ";
for Global_Configuration_Pragmas use "project.Builder'Global_Configuration_Pragmas value ";
end Builder;
Var1 := Var & project.Var & project.Builder.Var & project'Name & Prj3'Name & Prj3.Builder'Global_Configuration_Pragmas;
package Compiler is
for Switches ("main.adb") use ("value1");
for Switches ("main.adb" at 1) use ("value2");
for Switches (others) use ("value3");
Var := Compiler'Switches ("main.adb") & Compiler'Switches (others);
end Compiler;
end Prj3;
168 changes: 168 additions & 0 deletions testsuite/gpr_lsp/hover.no_exception_when_failed_to_load/test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
[
{
"comment": [
"Check that we don't get any exception when computing variables'",
"tooltips on non-valid projects"
]
},
{
"start": {
"cmd": ["${ALS}", "--language-gpr"]
}
},
{
"send": {
"request": {
"jsonrpc": "2.0",
"id": "init",
"method": "initialize",
"params": {
"processId": 441587,
"rootUri": "$URI{.}",
"capabilities": {
"workspace": {
"applyEdit": true,
"workspaceEdit": {},
"didChangeConfiguration": {},
"didChangeWatchedFiles": {},
"executeCommand": {}
},
"textDocument": {
"synchronization": {},
"completion": {
"dynamicRegistration": true,
"completionItem": {
"snippetSupport": true,
"documentationFormat": ["plaintext", "markdown"]
}
},
"hover": {},
"signatureHelp": {},
"declaration": {},
"definition": {},
"typeDefinition": {},
"implementation": {},
"references": {},
"documentHighlight": {},
"documentSymbol": {
"hierarchicalDocumentSymbolSupport": true
},
"codeLens": {},
"colorProvider": {},
"formatting": {
"dynamicRegistration": false
},
"rangeFormatting": {
"dynamicRegistration": false
},
"onTypeFormatting": {
"dynamicRegistration": false
},
"foldingRange": {
"lineFoldingOnly": true
},
"selectionRange": {},
"linkedEditingRange": {},
"callHierarchy": {},
"moniker": {}
}
}
}
},
"wait": [
{
"jsonrpc": "2.0",
"id": "init",
"result": {
"capabilities": {
"textDocumentSync": {
"openClose": true,
"change": 1
}
}
}
}
]
}
},
{
"send": {
"request": {
"jsonrpc": "2.0",
"method": "initialized"
},
"wait": []
}
},
{
"send": {
"request": {
"jsonrpc": "2.0",
"method": "textDocument/didOpen",
"params": {
"textDocument": {
"uri": "$URI{prj3.gpr}",
"languageId": "Gpr",
"version": 1,
"text": "with \"unknown\";\nproject Prj3 is\n type T is (\"project.Var value \");\n Var : T := \"project.Var value \";\n package Builder is\n Var := \"project.Builder.Var value \";\n for Global_Configuration_Pragmas use \"project.Builder'Global_Configuration_Pragmas value \";\n end Builder;\n Var1 := Var & project.Var & project.Builder.Var & project'Name & Prj3'Name & Prj3.Builder'Global_Configuration_Pragmas;\n package Compiler is\n for Switches (\"main.adb\") use (\"value1\");\n for Switches (\"main.adb\" at 1) use (\"value2\");\n for Switches (others) use (\"value3\");\n Var := Compiler'Switches (\"main.adb\") & Compiler'Switches (others);\n end Compiler;\nend Prj3;\n"
}
}
},
"wait": []
}
},
{
"send": {
"request": {
"params": {
"position": {
"line": 3,
"character": 3
},
"textDocument": {
"uri": "$URI{prj3.gpr}"
}
},
"jsonrpc": "2.0",
"id": 9,
"method": "textDocument/hover"
},
"wait": [
{
"id": 9,
"result": null
}
]
}
},
{
"send": {
"request": {
"jsonrpc": "2.0",
"id": "shutdown",
"method": "shutdown",
"params": null
},
"wait": [
{
"id": "shutdown",
"result": null
}
]
}
},
{
"send": {
"request": {
"jsonrpc": "2.0",
"method": "exit"
},
"wait": []
}
},
{
"stop": {
"exit_code": 0
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
title: 'hover.no_exception_when_failed_to_load'
skip:
- ['SKIP', 'env.build.os.name not in ("linux","windows")']

0 comments on commit f56621f

Please sign in to comment.