Skip to content

Commit 1677268

Browse files
felixfbeckersqs
authored andcommitted
files extension: workspace/files and textDocument/content
1 parent 7302a81 commit 1677268

File tree

1 file changed

+145
-0
lines changed

1 file changed

+145
-0
lines changed

extension-files.md

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# Files extensions to LSP
2+
3+
The files extension to the Language Server Protocol (LSP) allows a language server to operate without sharing a physical file system with the client. Instead of consulting its local disk, the language server can query the client for a list of all files and for the contents of specific files.
4+
5+
Use cases:
6+
7+
* In some deployment settings, the workspace exists on the client in archived form only, such as a bare Git repository or a .zip file. Using virtual file system access allows the language server to request the minimum set of files necessary to satisfy the request, instead of writing the entire workspace to disk.
8+
* In multitenant deployments, the local disk may not be secure enough to store private data on. (Perhaps an attacker could craft a workspace with malicious `import` statements in code and reveal portions of any file on the file system.) Using a virtual file system enforces that the language server can operate without writing private code files to disk.
9+
* In some deployment settings, language servers must avoid shelling out to untrusted (or sometimes any) programs, for security and performance reasons. Using a virtual file system helps enforce this by making it less likely that another programmer could change the language server to invoke an external program (since it would not be able to read any of the files anyway).
10+
* For testing and reproducibility, it is helpful to isolate the inputs to the language server. This is easier to do if you can guarantee that the language server will not access the file system.
11+
12+
## Protocol
13+
14+
Note that unlike other requests in LSP, these requests are sent by the language server to the client, not vice versa. The client, not the language server, is assumed to have full access to the workspace's contents.
15+
16+
The language server is allowed to request file paths outside of the workspace root. (This is common for, e.g., system dependencies.) The client may choose whether or not to satisfy these requests.
17+
18+
### Initialization
19+
20+
`ClientCapabilities` may contain two new fields to indicate client-side support for this extension:
21+
22+
```typescript
23+
interface ClientCapabilities {
24+
/* ... all fields from the base ClientCapabilities ... */
25+
26+
/**
27+
* The client provides support for workspace/files.
28+
*/
29+
filesProvider?: boolean;
30+
/**
31+
* The client provides support for textDocument/content.
32+
*/
33+
contentProvider?: boolean;
34+
}
35+
```
36+
37+
### Content Request
38+
39+
The content request is sent from the server to the client to request the current content of any text document. This allows language servers to operate without accessing the file system directly.
40+
41+
_Request_:
42+
* method: 'textDocument/content'
43+
* params: `ContentParams` defined as follows:
44+
45+
```typescript
46+
interface ContentParams {
47+
/**
48+
* The text document to receive the content for.
49+
*/
50+
textDocument: TextDocumentIdentifier;
51+
}
52+
```
53+
54+
_Response_:
55+
* result: `TextDocumentItem`
56+
* error: code and message set in case an exception occurs
57+
58+
### Files Request
59+
60+
The files request is sent from the server to the client to request a list of all files in the workspace or inside the directory of the `base` parameter, if given.
61+
62+
A language server can use the result to index files by filtering and doing a content request for each text document of interest.
63+
64+
_Request_:
65+
* method: 'workspace/files'
66+
* params: `FilesParams` defined as follows:
67+
68+
```typescript
69+
interface FilesParams {
70+
/**
71+
* The URI of a directory to search.
72+
* Can be relative to the rootPath.
73+
* If not given, defaults to rootPath.
74+
*/
75+
base?: string;
76+
}
77+
```
78+
79+
_Response_:
80+
* result: `TextDocumentIdentifier[]`
81+
* error: code and message set in case an exception occurs
82+
83+
Examples:
84+
85+
Relative (`rootPath` is `file:///some/project`):
86+
87+
```json
88+
{
89+
"jsonrpc": "2.0",
90+
"id": 1,
91+
"method": "workspace/files"
92+
}
93+
```
94+
95+
```json
96+
{
97+
"jsonrpc": "2.0",
98+
"id": 1,
99+
"result": [
100+
{"uri": "file:///some/project/.gitignore"},
101+
{"uri": "file:///some/project/composer.json"}
102+
{"uri": "file:///some/project/folder/1.php"},
103+
{"uri": "file:///some/project/folder/folder/2.php"}
104+
]
105+
}
106+
```
107+
108+
Absolute:
109+
110+
```json
111+
{
112+
"jsonrpc": "2.0",
113+
"id": 1,
114+
"method": "workspace/files",
115+
"params": {
116+
"base": "file:///usr/local/go"
117+
}
118+
}
119+
```
120+
121+
```json
122+
{
123+
"jsonrpc": "2.0",
124+
"id": 1,
125+
"result": [
126+
{"uri": "file:///usr/local/go/1.go"},
127+
{"uri": "file:///usr/local/go/folder/"},
128+
{"uri": "file:///usr/local/go/folder/2.go"},
129+
{"uri": "file:///usr/local/go/folder/folder/"},
130+
{"uri": "file:///usr/local/go/folder/folder/3.go"}
131+
]
132+
}
133+
```
134+
135+
## Design notes
136+
137+
* The protocol uses URIs, not file paths, to be consistent with the rest of LSP.
138+
* Matching the `base` parameter relative to the `rootPath` permits the server to request files outside the workspace even if the workspace is on a remote host and/or uses an arbitrary protocol.
139+
* Usage of `TextDocumentIdentifier` in `workspace/files` allows to easily extend the result with more properties in the future without breaking backward compatibility.
140+
141+
142+
## Known issues
143+
144+
* There is no way to get directories
145+
* Results have to be filtered on the server side. In the future this request may allow filtering through glob patterns.

0 commit comments

Comments
 (0)