Skip to content

Commit c3ebab7

Browse files
committed
Merge branch 'mr/1622-understanding-codebases-with-lsp' into 'master'
Implement Graph Visualization based on LSP request See merge request eng/ide/ada_language_server!1968
2 parents b50aca5 + 6727aab commit c3ebab7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+20100
-4193
lines changed

doc/settings.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,3 +430,8 @@ Controls the maximum number of trace files preserved in the ALS log directory (w
430430
When this threshold is reached, old trace files get deleted automatically.
431431
The default number of preserved trace files is `10`.
432432
See the documentation on [ALS Traces](traces.md) for more information.
433+
434+
### enableExperimentalFeatures
435+
436+
This option enable the use of experimental features which are still under development.
437+

integration/vscode/ada/.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
/*.vsix
33
/out/
44
/.vscode-test/
5+
/.wdio-vscode-service/
6+
/.vscode/
57

68
# Locations of ALS executable in VS Code extension. VS Code is supported on arm,
79
# arm64 and x64 so we only consider those architectures.
@@ -15,4 +17,4 @@
1517
/darwin/
1618

1719
# Generated by ANCR
18-
/.env
20+
/.env
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
<!-- markdownlint-disable MD030 -->
2+
3+
# Code Visualizer for Visual Studio Code
4+
5+
This extension provide a tool allowing to display the code base as an interactive graph using LSP requests.
6+
7+
## Features
8+
9+
This extension relies on LSP to gather data for the graphs which means most of the extension should work on any language as long as there is a Language Server implemented for it and linked to VS Code.
10+
11+
/!\ All Languages Servers differs in their implementation of the Language Server Protocol which means that some features might not work optimally for all languages, the implementation being made to work on _most language_.
12+
13+
To counter this issue, it is possible to add [language-specific features](#multi-language-handler).
14+
15+
### Graph
16+
17+
The main feature of this extension is the graph.
18+
19+
There are several kinds of graphs available:
20+
21+
#### Call Graph
22+
23+
The most basic kind of graph is the Call Graph, which allows the user to visualize the relationship between the different function calls of the project.
24+
25+
To use it, you can simply right-click on the function symbol you wish to visualize and select the option `Show Call Hierarchy (graph)`.
26+
27+
This will open a new tab on the side of your IDE with a view containing the created graph. You can then interact with it, move the nodes around and use the different features listed below.
28+
29+
#### Type Graph
30+
31+
You can also generate Type Graph which allow the user to visualize the hierarchies between the different types of your project.
32+
33+
To use it, the process is the same as with the Call Graph: right-click on the type symbol you wish to visualize and select the option `Show Type Hierarchy (graph)`.
34+
35+
#### File Dependency Graph (Ada)
36+
37+
Some graph types can also be available to specific languages. For example, when on an Ada file, you can right-click anywhere in the editor and then on `Show File Dependency (graph)` to generate a graph representing the different files of your project and their relationship between them.
38+
39+
#### GPR Dependency Graph (GPR)
40+
41+
The last kind of graph available allows you to see the relationships between the different GPR files composing a project. Again, to use it, you can click anywhere in a GPR file and then click on `Show GPR Dependency (graph)`.
42+
43+
The graph generated will be composed of different kinds of nodes and edges:
44+
For imported projects, the edges will be dotted.
45+
46+
For extended projects, the edges will be plain.
47+
48+
For aggregated projects, the node representing the aggregate project will be transformed into a sub-graph containing its aggregated project to better understand their relationship.
49+
50+
### ViewPort
51+
52+
The nodes are placed on a viewport that the user can interact with.
53+
54+
It is possible to move around by dragging the viewport, zoom in and out by using the scroll wheel.
55+
56+
On the bottom left corner of the viewport, the user has access to a set of buttons that summarize its features.
57+
58+
- A button to zoom in.
59+
- A button to zoom out.
60+
- A button to fit the whole graph into the view.
61+
- A button to lock the graph interactivity, preventing the user from moving the nodes around.
62+
- A button that takes the user back to the center of the graph (0,0) in case he went too far and can't find the graph on the port.
63+
- Additionally, a button can be found allowing the user to layout the graph, toggling between orienting the graph to the right or downside.
64+
65+
### Expansion
66+
67+
To prevent lag or slowness, the graph initially only displays the required symbols and their direct relations, but you can then interact with the buttons on the side of each node to either get the parent symbols or the child symbols for a specific node.
68+
69+
If you want to discover a large part of the graph, you can hold the _Control Key_ to recursively unravel the graph and see the graph expand in real time.
70+
This process can be stopped at any moment by clicking the cancel notification at the bottom right of the window.
71+
72+
### Folding
73+
74+
Once a node has children, the button to get those children is replaced by a button used to fold the children in the node, hiding them from the user view.
75+
76+
When folded, the user can re-click on the button to redisplay the nodes stored in the parent node.
77+
78+
### Layouting
79+
80+
When nodes are added to the graph, it is automatically layouted to make sure each node is visible to the user and well placed.
81+
If the graph is disconnected, the program will try to re-layout only the sub-part that was modified.
82+
In either case, when adding nodes, the overall order of the nodes in the graph may be drastically reordered, but the view will be focused on the node from which the other nodes were added to help the user keep track of its position in the graph.
83+
84+
You can also manually trigger the layout by clicking the `Layout Graph` button on the bottom left side, which will also change the direction of the graph on screen (toggling between top-bottom to left-right).
85+
86+
### Search Bar
87+
88+
As the graph grows bigger, the user might find it hard to locate himself in the graph or to find specific nodes.
89+
To help with that, he has access to a search bar on the top right corner allowing him to find nodes based on their name and to be taken to them.
90+
91+
Once some characters have been entered, a list of node names will appear.
92+
The user can then either click on a list item or use the `arrow` key or the `tab` key to go through the list.
93+
When going through the list, the graph will focus on the node linked to the current list item.
94+
When satisfied, the user can either press the `Enter` key or click outside the search bar range to close it.
95+
96+
### Node Context Menu
97+
98+
When right clicking on a node, you can get access to a menu summarizing all the requests that can be made from a node.
99+
You can find the following features :
100+
101+
- `Refresh node`: Refresh the information of a node, [see Node Refresh](#node-refresh)
102+
- `Go To Definition`: Take the user to the definition of the symbol represented by the node, [see Go To Definition](#go-to-definition)
103+
- `Go To Implementation`: Take the user to the implementation of the symbol represented by the node, [see Go To Implementation](#go-to-implementation)
104+
- `Delete Node`: Delete the node associated with the context menu, [see Node Deletion](#node-deletion)
105+
- `Get Super Hierarchy`: The label of this button changes on the hierarchy of the graph and allows the user to request the parents of the node to be added to the graph, [see Expansion](#expansion)
106+
- `Get Sub Hierarchy`: The label of this button changes on the hierarchy of the graph and allows the user to request the children of the node to be added to the graph, [see Expansion](#expansion)
107+
- `Go To References`: Lists the references of the symbol in the code base and then takes the user to the chosen reference of the symbol in the code base, [see Go To Implementation](#go-to-implementation)
108+
109+
### Node Selection
110+
111+
The user can select nodes by either clicking on one, holding the `control` key and clicking on multiple nodes for multiple selections or holding the `shift` key and then dragging the mouse to select an area of the graph.
112+
113+
### Node Deletion
114+
115+
The user also has the option to delete nodes from the graph by selecting nodes and then pressing the `Backspace` key or the `Del` key.
116+
This will remove the nodes from the graph and from the extension internal storage, along with all the edges connected to them.
117+
118+
The user can also hold the `Control` key while deleting nodes to also delete all of their children recursively.
119+
In case of a cycle, only the node not connected to any parent of a deleted node will be deleted.
120+
For example in a configuration `A -> B -> C -> A`, recursively deleting node B will only remove B as C is a parent of A which is a parent of B.
121+
122+
### Node Refresh
123+
124+
When modifying the code base while the graph is open, the location of some symbol might change, invalidating the node as LSP requests depends on location.
125+
126+
To fix this issue the user can refresh the node by accessing it from the context menu under the label `Refresh Node`.
127+
128+
/!\ The tool was mainly developed as a way to visualize a code base, understand how different parts of the code interact with each other,...
129+
It was not thought as a way to assist during active development so modifying the code base while the graph is open might invalidate a lot of nodes causing a part of the graph to not respond to requests anymore.
130+
131+
### Jump To Code
132+
133+
When using the graph the user might want to see to which part of the code the node is related.
134+
135+
To help with that, the application provides a few ways to access the code from the graph.
136+
137+
#### Go To Definition
138+
139+
First, by `double clicking` (or through the context menu), the user will be taken to the definition of the symbol in the code base.
140+
If the editor is already open, it will only be focused on the right position.
141+
If the editor was not open, it will first be opened in a column next to the graph view.
142+
143+
#### Go To Implementation
144+
145+
In the same vein, the user can also jump to the implementation of a symbol in a code base by holding the `control` key while double-clicking on a node (or, once again, through the context menu).
146+
147+
#### Go To References
148+
149+
Finally, the user can also jump to the references of a symbol in the code base.
150+
151+
This can be achieved through two ways with a slight difference:
152+
153+
- First, the user can hover or click on an edge to open a popup containing a list representing all the references of the symbol at the destination of the edge in the context of the symbol at the source of the edge.
154+
If we take the Call Graph as an example (which is the most interesting), hovering an edge linking `Bar` to `Foo` would create a list of all the function calls of `Foo` in the `Bar` function.
155+
- The user can also use the context menu from a node to get a list of all the references of the symbol in the code base, divided by a header indicating the name of the function and the file they can be found in.
156+
157+
In both cases, the user can move using either the `arrows` key or the `Tab` key and then press `Enter` to be taken to the references. It is also possible to click on a list item.
158+
When going through the list, the user will see in a column on the side of the graph view, the code symbol represented by the list item revealed in real time, giving him context about what the symbol refers to.
159+
160+
This feature is only available for the Type Graph and the Call Graph as GPR and Files Graph don't really have references.
161+
162+
### Out of Project Node
163+
164+
When requesting data from the LSP, you can sometimes get symbols not directly present in the code base but from the diverse standard, shared, static libraries of your project.
165+
166+
Those symbols, when detected, are still placed on the graph but in a different color from the regular node and have the border dotted to indicate to the user that it is not code present in the project.
167+
168+
/!\ The symbols that do not belong to the project might not have all the information necessary for the node to work correctly, so some features might not work as the extension might not be able to build the LSP request or the LSP might not be able to respond.
169+
170+
### Multi Language Handler
171+
172+
The goal of the extension was to provide a tool that would work on any language if they implemented a Language Server.
173+
174+
Unfortunately, each Language Server has its own implementation, which might differ from the others.
175+
Furthermore, each language has specificities that are not covered by the standard request of the LSP.
176+
177+
To handle those problems, this extension provides a _generic interface_ containing some feature implementations that should work for most languages.
178+
Those implementations can then be overloaded in sub-classes, allowing to handle behavior differently depending on the language the user is currently using.
179+
180+
This also allows implementing specific features for a specific language.
181+
For example, the _generic interface_ provides the Call Graph and the Type Graph, but when overloaded with an Ada class, it will additionally provide the File Dependency Graph.

integration/vscode/ada/eslint.config.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const compat = new FlatCompat({
1616
});
1717

1818
export default [{
19-
ignores: ["**/out", "**/*.d.ts"],
19+
ignores: ["**/out", "**/*.d.ts", "test/visualizer_test"],
2020
}, ...compat.extends(
2121
"eslint:recommended",
2222
"plugin:@typescript-eslint/recommended",

0 commit comments

Comments
 (0)