AdaCore / ada_language_server

Server implementing the Microsoft Language Protocol for Ada and SPARK
GNU General Public License v3.0
230 stars 54 forks source link

Preprocessor Directives #1140

Closed smbrown077 closed 5 months ago

smbrown077 commented 1 year ago

How do you define preprocessor directives so that the code will be active/inactive? I see that the advanced syntax highlighter supports preprocessor directives but I do not know where/how to define them so that they will be recognized.

For example:

procedure Example is

if MYVAR'DEFINED then

 begin
      Put_Line("Hello");

else

 begin
      Put_Line("Hi");

end if;

end Example;

All of this code is always considered active regardless of whether I have MYVAR defined. It is breaking Intellisense because there are preprocessor directives around begin statements and it thinks there are 2 begin statements.

AnthonyLeonardoGracio commented 1 year ago

Hello,

Indeed, we don't properly handle the absence of symbol definition in preprocessor directives. As a workaround, you can use more explicit directives like #if MYVAR="true" then, and set the -gnateDMYVAR=true (or -gnateDMYVAR=false) switch in your .gpr file, as follows:

   package Compiler is
      for Default_Switches ("Ada") use ("-gnateDMYVAR=false");
   end Compiler;

In the mean time, we'll see if we can improve preprocessing handling to support your example.

Regards,

AnthonyLeonardoGracio commented 1 year ago

Hello @smbrown077,

Which compiler switches are you using to enable the preprocessing? Because without any switch gprbuild fails to build this example. Could you share the switches you are using with us please?

Regards,

smbrown077 commented 1 year ago

I am calling gbuild in a task instead of gprbuild so I do not have the compiler switches implemented currently. I have a gpj file that has -DMYVAR in the [PROGRAM] section. However I did add a gpr file just so that Intellisense would work for me. It looks like this at the moment.

project Intellisense is
     for Main use ("main.ada");
     for Object_Dir use "objs";
     for Source_Dirs use ("src/**");

     package Naming is
          for Spec_Suffix ("ada") use "_.ada";
          for Body_Suffix ("ada") use ".ada";
          for Separate_Suffix use ".ada";
     end Naming;

end Intellisense;

I want the Intellisense to be able to determine active vs inactive code without needing to compile. So if I could just add the compiler switches to the gpr file (through the prep.def files) and have them be recognized automatically then that would be great. But if they could be recognized from the gpj file in the -DMYVAR format then that would be even better. But of course I will take whatever I can get. If I were to get my code to compile with gprbuild, my new gpr file would look like this (You have to use 2 prep.def files):

project Intellisense is
     for Main use ("main.ada");
     for Object_Dir use "objs";
     for Source_Dirs use ("src/**");

     package Naming is
          for Spec_Suffix ("ada") use "_.ada";
          for Body_Suffix ("ada") use ".ada";
          for Separate_Suffix use ".ada";
     end Naming;

     package Compiler is
          for Switches ("ada") use ("-g", "-gnat95", "-gnatwA", "-gnatep=" & project'Project_Dir & "prep.def");
     end Compiler;

end Intellisense;

And then inside prep.def at the top project level where your gpr file is located (C:/testing/prep.def): * "C:/testing/src/prep2.def" -u (can use a relative path instead but I am just trying to make it clear)

And then inside prep2.def inside the src directory (C:/testing/src/prep2.def) you just put the preprocessor directives:

MYVAR_1
MYVAR_2
MYVAR_3
AnthonyLeonardoGracio commented 1 year ago

Hi again,

You won't need to compiler your project if the preprocessor switches that set/unset your variables are correctly specified in your .gpr file. Using the -gnateDMYVAR should work too, you don't need to have .def files for that.