6. Source Navigation¶
6.1. Support for Cross-References¶
GPS provides cross-reference navigation for program entities defined in your application such as types, procedures, functions, and variables. This support relies on compiler-generated cross-reference information, so you need to compile your project before being able to navigate within it. Similarly, if you have modified your sources, you need to rebuild and recompute the xref information it you want your changes to be taken into account by GPS.
Here is language specific information about source navigation:
Ada
By default, GPS uses the GNAT compiler to generate the cross-reference information it needs. However, if you are using the -gnatD or -gnatx switches, no cross reference information is available to GPS.
If you need to navigate through sources that do not compile (such as after modifications or while porting or initially developing an application), GNAT generates partial cross-reference information if you specify the -gnatQ switch. Using this along with the -k switch of gnatmake generates as much relevant information from your non-compilable sources as possible.
Sometimes GPS cannot find the external files (called
ALI files
) containing the cross-reference information. Most likely, this is either because you have not compiled your sources yet or because the sources changed since theALI files
were generated. Another possibility is that you have not included the object directories that contain theALI files
in the project.In addition, GPS cannot automatically handle one special case, when you have separate units whose file names have been crunched by the gnatkr command.
C/C++
You need to use the GCC C and C++ compilers that come with GNAT to generate the cross-references information needed by GPS and to call them with the -fdump-xref switch, so you need to first add that switch to your project’s switches for C and C++ sources and compile your application before you browse through the cross-references. If your sources have been modified, recompile the modified files.
6.1.1. Ada cross-reference heuristics¶
GPS provides basic navigation support for Ada, C, and C++ sources even in the absence of information coming from the compiler by using a built-in parser, parsing the files both at startup and when they are modified. This provides basic navigation in simple cases.
In this mode, GPS can navigate to an entity body from the declaration and vice versa. For other references, GPS can navigate to the declaration only if the heuristics provides the necessary information without ambiguity, which may not be the case with overloaded entities.
GPS also uses this parser to provide the Ada outline view, code completion and entity view, but these heuristics are not used in global reference searching operations or to generate call graphs.
6.1.2. The cross-reference database¶
GPS parses the cross-reference information generated by the compiler (the
.ali
) files into one or several sqlite databases (e.g: if
your project uses Ada and C). These database files can become quite large and
should preferably be on a fast local disk.
By default, GPS places these database files in the object directory of the currently-loaded root project, or, if specified, in the directory designated by the relative or absolute path given by the Artifacts_Dir attribute of the IDE package of your project file:
-- assume this is in /home/user1/work/default.gpr
project Default is
for Object_Dir use "obj";
package IDE is
for Artifacts_Dir use "artifacts";
-- All the artifacts generated by GPS (including the xref databases)
-- will be put in the /home/user1/work/artifacts/ directory.
--
-- We could also have specified an absolute path here
-- (e.g: for Artifacts_Dir use "/home/user1/work/artifacts/").
end IDE;
end Default;
If you want to have more advanced control regarding the naming of the Ada cross-references database file, you can use the Xref_Database in the IDE package of your project file, either as an absolute path or a path relative to the location of the project file. We recommend this path to be specific to each use, and to each project this user might be working on, as in the following examples:
-- assume this is in /home/user1/work/default.gpr
project Default is
for Object_Dir use "obj";
package IDE is
for Xref_Database use "xref_database.db";
-- This would be /home/user1/work/xref_database.db
for Xref_Database use Project'Object_Dir & "/xref_database.db";
-- This would be /home/user1/work/obj/xref_database.db
-- This is the default when this attribute is not specified
for Xref_Database use external("HOME") & "/prj1/database.db";
-- This would be /home/user1/prj1/database.db
end IDE;
end Default;
One drawback in altering the default location is that gprclean will not remove these database files when you clean your project. But it might speed up GPS if your project is not on a fast local disk and you can put the databases there.
WARNING: You should not store this file in a directory that is accessed via a network filesystem, like NFS, or Clearcase’s MVFS. If your obj directory is on such a filesystem, be sure to specify a local directory for IDE’Artifacts_Dir project attribute or, if you project only uses Ada, a custom local file path for the IDE’Xref_Database project attribute.
6.1.3. Cross-references and partially compiled projects¶
The cross-reference engine works best when the cross-reference
information generated by the compiler (the .ali
files) is
fully up to date.
If you start from such a state and then modify the spec or body of an Ada package and recompile only that file, any reference to entities declared in that spec in other packages might no longer be found (until you recompile those other packages, as gprbuild would).
This is because GPS has no way to know for sure whether an entity
Foo
in the spec is the same entity as before or is a new one with
the same name. It uses an approximate algorithm where the references are
only preserved if an entity with the same name remains at precisely the
same location in the new version of the source. But if a blank line in the
file will change the declaration line for all entities declared further in
the file, so those will lose their references from other source files.
6.1.4. Cross-reference and GNAT runtime¶
By default, GPS does not parse the GNAT runtime files because there is a
large number of them and doing so would significantly slow down GPS, while
producing only a minimal gain for most users. However, the location of
subprograms in those runtime files is available from the .ali
files
corresponding to the sources of your project.
From your own sources, you can navigate to one of the runtime files (for
example, if you have a reference to Put_Line()
, you will jump to its
declaration in a-textio.ads
). But you cannot perform
cross-reference queries from a runtime file itself.
If you need this capability, enable the preference Project/Cross References in Runtime Files.
6.2. Contextual Menus for Source Navigation¶
This contextual menu is available from any source editor. If you right-click on an entity or selected text, the contextual menu applies to the selection or entity. Most of these menus requires support for cross-references.
Goto declaration of *entity*
Go to the declaration (spec) of entity.
Goto declarations of *entity*
This entry appears when clicking on a dispatching subprogram call. In that case, GPS cannot know what subprogram will actually be called at run time, so it gives you a list of all entities in the tagged type hierarchy and lets you choose which of the declarations you want to jump to. See also the
methods.py
plugin (enabled by default) which, given an object, lists all its primitive operations in a contextual menu so you can easily jump to them. See also the References ‣ Find References To… contextual menu, which allows you to find all calls to a subprogram or one of its overriding subprograms.Goto full declaration of *entity*
This entry appears for a private or limited private types. Go to the full declaration (spec) of entity.
Goto type declaration of *entity*
Go to the type declaration of entity.
Display type hierarchy for *entity*
This entry appears for derived or access types. Put the type hierarchy for entity into the Location view.
Goto body of *entity*
Go to the body (implementation of entity.) If entity is the declaration of an Ada subprogram imported from C, go to the location where the C function is defined.
Goto bodies of *entity*
Similar to Goto declarations of, but applies to the bodies of entities.
Goto file spec/body
Open the corresponding spec file if the current edited file is a body file, or the body file otherwise. This entry is only available for the Ada language.
*Entity* calls
Display a list of all subprograms called by entity in a tree view. This is generally more convenient than using the corresponding Browsers/ submenu if you expect many references. See The Call trees view and Callgraph browser.
*Entity* is called by
Display a list of all subprograms calling entity in a tree view. This is generally more convenient than using the corresponding Browsers/ submenu if you expect many references. See The Call trees view and Callgraph browser.
References ‣ Find all references
Find all references to entity in all the files in the project.
References ‣ Find all references…
Similar to the entry above except you can select more precisely what kind of reference should be displayed. You can also specify the scope of the search and whether the context (or caller) at each reference should be displayed.
The option Include overriding and overridden operations includes references to overridden or overriding entities. This is particularly useful if you need to know whether you can easily modify the profile of a primitive operation or method since you can see which other entities would also be changed. If you select only the declaration check box, you see the list of all related primitive operations.
This dialog allows you to determine which entities are imported from a given file or unit. Click on any entity from that file (for example on the with line for Ada code) and select the All entities imported from same file toggle, which displays in the Location view the list of all entities imported from the same file.
Selecting the Show context option produces a list of all the references to these entities within the file. If it is not selected, you just get a pointer to the declaration of the imported entities.
References ‣ Find all local references to *entity*
Find all references to entity in the current file (or in the current top level unit for Ada sources).
References ‣ Variables used in *entity*
Find all variables (local or global) used in entity and list each first reference in the locations window.
References ‣ Non Local variables used in *entity*
Find all non-local variables used in the entity.
References ‣ Methods of *entity*
This entry is only visible if you activated the plugin
methods.py
(the default) and when you click on a tagged type or an instance of a tagged type. It lists all the primitive operations or methods of that type, allowing you to jump to the declaration of any of these operations or methods.Browsers ‣ *Entity* calls
Open or raise the Callgraph browser on the specified entity and display all the subprograms called by it. See Callgraph browser.
Browsers ‣ *Entity* calls (recursively)
Open or raise the Callgraph browser on the specified entity and display all the subprograms called by entity, transitively for all subprograms. Since this can take a long time to compute and generate a very large graph, an intermediate dialog is displayed to limit the number of subprograms to display (1000 by default). See Callgraph browser.
*Entity* is called by
Open or raise the Callgraph browser on the specified entity and display all the subprograms calling entity. See Callgraph browser.
Expanded code
Present for Ada files only. Generates a
.dg
file by calling the GNAT compiler with the :index:command:-gnatGL`` switch and displaying the expanded code. Use this when investigating low-level issues and tracing how your source code is transformed by the GNAT front-end.Expanded code ‣ Show subprogram
Display expanded code for the current subprogram in the current editor.
Expanded code ‣ Show file
Display expanded code for the current file in the current editor.
Expanded code ‣ Show in separate editor
Display expanded code for the current file in a new editor.
Expanded code ‣ Clear
Remove expanded code from the current editor.
Open *filename*
When you click on a filename (for example, a C #include, or an error message in a log file), this entry opens that file. If the file name is followed by
:
and a line number, the cursor points to that line.
6.3. Navigating with hyperlinks¶
When you press the Control key and start moving the mouse, entities in the editors under the pointer become hyperlinks and the form of the pointer changes.
Left-clicking on a reference to an entity opens a source editor on the declaration of the entity and left-clicking on an entity declaration opens an editor on the implementation of the entity. Left-clicking on the Ada declaration of a subprogram imported from C opens a source editor on the definition of the corresponding C entity. This capability requires support for cross-references.
Middle-clicking on either a reference to an entity or the declaration of an entity jumps to the implementation (or type completion) of the entity.
For efficiency, GPS may create hyperlinks for some entities which have no associated cross reference. In this case, clicking has no effect even though a hyperlink is displayed.
This behavior is controlled by the General ‣ Hyper links preference.
6.4. Highlighting dispatching calls¶
By default, GPS highlights dispatching calls in Ada and C++ source code via
the dispatching.py
plugin. Based on the cross-reference
information, this plugin highlights (with a special color you can
configure in the preferences dialog) all Ada dispatching calls or calls to
virtual methods in C++. A dispatching call in Ada is a subprogram call
where the actual subprogram called is not known until run time and is
chosen based on the tag of the object.
Disable this highlighting (which may be slow if you have large sources) by
using the Edit ‣ Preferences… menu, going to the Plugins
section and disabling the dispatching.py
plugin.