Haystack-Ada allows users to perform Abstract Syntax Tree (AST)-based search and replace operations on Ada files within GNAT Studio. The search patterns must be compilable Ada code, but due to the nature of AST-based searching, formatting of the search pattern does not matter. This allows one to match code in multiple locations at the same time even if the code fragments themselves are also formatted differently.
To assist in matching a wide variety of code fragments in one go, Haystack supports the use of wildcards. There are two types of wildcards, those starting with "$S" and those starting with "$M".
"$S" wildcards allow one to match a single thing, be that a single expression, a single statement or anything else. As long as Ada parses it to a single AST node, the "$S" wildcard can match it.
"$M_" wildcards allow one to match zero or more things. This makes these types of wildcards more flexible but also more unpredictable.
Wildcards must start with either "$S" or "$M" and any alphanumeric string is allowed to follow.
If a wildcard was used to match code in the search pattern, it can be re-used in the replace pattern to copy over what was matched. Simply write the wildcard identically to how it was written in the search pattern.
Say you have the following code fragment:
if A /= B then
Put_Line ("A does not equal B");
A := B;
else
Put_Line ("A equals B");
end if;
If you decide you want to flip the if statement, you could write the following search query to match the code fragment:
if $S_A /= $S_B then
$M_stmts_false;
else
$M_stmts_true;
end if;
and the following replace statement:
if $S_A = $S_B then
$M_stmts_true;
else
$M_stmts_false;
end if;
Then the result would look like:
if A = B then
Put_Line ("A equals B");
else
Put_Line ("A does not equal B");
A := B;
end if;
There are two requirements:
You can check what version of python your version of GNAT Studio supports by opening up the python console and typing:
>>> import sys
>>> sys.version
libadalang is typically included in GNAT Studio binaries from AdaCore. This can also be checked in GNAT Studio's python console by typing:
>>> import libadalang
If a ModuleNotFoundError is returned libadalang is not yet installed and you will need to do that yourself by buliding from source: https://github.com/AdaCore/libadalang/blob/master/user_manual/building.rst
There are three methods to launch GNAT Studio with the plug-in installed:
Copy haystack_plugin.py and the Haystack folder to $HOME/.gnatstudio/plug-ins/ on Linux or macOS or %USERPROFILE%\.gnatstudio\plug-ins on Windows
Add the root folder of Haystack-Ada to the GNATSTUDIO_CUSTOM_PATH environment variable.
For a temporary installation of the plug-in, you can launch GNAT Studio from the command line:
$ gnatstudio --load=python:path/to/haystack_plugin.py
Once the haystack back-end and plug-in are installed, it can be found in GNAT Studio under the dropdown menu "Find/Find AST"
This is what the Haystack plug-in will look like once it is launched. It is composed of two main textboxes:
The other things included in the window are as follows:
Finally the buttons:
Haystack-Ada was initially developed by a team of students from the University of Twente as a response to an assignment posted by ESI and ITEC, an independent subsidiary of Nexperia.