Skip to content

Commit 8c759f6

Browse files
modocachetkremenek
authored andcommitted
[SourceKit] Convert Protocol docs to Markdown (#2392)
- Convert `Protocol.txt` to `Protocol.md`, and use valid Markdown syntax. - Spruce up the documentation in the "code completion": more details on how to test via the REPL, clearer sentences, etc. - Fix an error in which `sourcekitd-test -req=complete -offset=<offset>` used the incorrect option `-cc-offset`.
1 parent 87e1ab5 commit 8c759f6

File tree

2 files changed

+338
-252
lines changed

2 files changed

+338
-252
lines changed

tools/SourceKit/docs/Protocol.md

Lines changed: 338 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,338 @@
1+
# The SourceKit Protocol
2+
3+
This documents the request/response API as it is currently implemented.
4+
For specific details related to Swift, see `SwiftSupport.md`.
5+
6+
The protocol is documented in the following format:
7+
8+
```
9+
{
10+
<KEY>: (type) // comments
11+
}
12+
```
13+
14+
- `"{ }"` indicates a dictionary
15+
- `"[ ]"` indicates an array.
16+
- `"[opt]"` indicates an optional key.
17+
- Specific UIDs are written as `<UID string>`.
18+
19+
20+
# Requests
21+
22+
## Code-Completion
23+
24+
SourceKit is capable of providing code completion suggestions. To do so, it
25+
must be given either the path to a file (`key.sourcefile`), or some text
26+
(`key.sourcetext`). `key.sourcefile` is ignored when `key.sourcetext` is also
27+
provided.
28+
29+
### Request
30+
31+
```
32+
{
33+
<key.request>: (UID) <source.request.codecomplete>
34+
[opt] <key.sourcetext>: (string) // Source contents.
35+
[opt] <key.sourcefile>: (string) // Absolute path to the file.
36+
<key.offset>: (int64) // Byte offset of code-completion point inside the source contents.
37+
[opt] <key.compilerargs> [string*] // Array of zero or more strings for the compiler arguments,
38+
// e.g ["-sdk", "/path/to/sdk"]. If key.sourcefile is provided,
39+
// these must include the path to that file.
40+
[opt] <key.not_recommended> [bool] // True if this result is to be avoided, e.g. because
41+
// the declaration is unavailable.
42+
}
43+
```
44+
45+
### Response
46+
47+
```
48+
{
49+
<key.results>: (array) [completion-result*] // array of zero or more completion-result dictionaries
50+
}
51+
```
52+
53+
```
54+
completion-result ::=
55+
{
56+
<key.description>: (string) // Text to be displayed in code-completion window.
57+
<key.kind>: (UID) // UID for the declaration kind (function, class, etc.).
58+
<key.sourcetext>: (string) // Text to be inserted in source.
59+
<key.typename>: (string) // Text describing the type of the result.
60+
<key.doc.brief>: (string) // Brief documentation comment attached to the entity.
61+
<key.context>: (UID) // Semantic context of the code completion result.
62+
<key.num_bytes_to_erase>: (int64) // Number of bytes to the left of the cursor that should be erased before inserting this completion result.
63+
}
64+
```
65+
66+
### Testing
67+
68+
```
69+
$ sourcekitd-test -req=complete -offset=<offset> <file> [-- <compiler args>]
70+
```
71+
72+
For example, to get a code completion suggestion for the 58th character in an
73+
ASCII file at `path/to/file.swift`:
74+
75+
```
76+
$ sourcekitd-test -req=complete -offset=58 /path/to/file.swift -- /path/to/file.swift
77+
```
78+
79+
You could also issue the following request in the `sourcekitd-repl`:
80+
81+
```
82+
$ sourcekitd-repl
83+
Welcome to SourceKit. Type ':help' for assistance.
84+
(SourceKit) {
85+
key.request: source.request.codecomplete,
86+
key.sourcefile: "/path/to/file.swift",
87+
key.offset: 57,
88+
key.compilerargs: ["/path/to/file.swift"]
89+
}
90+
```
91+
92+
## Indexing
93+
94+
SourceKit is capable of "indexing" source code, responding with which ranges
95+
of text contain what kinds of source code. In other words, SourceKit is
96+
capable of telling you that "the source code on line 2, column 9, is a
97+
reference to a struct".
98+
99+
To index source code, SourceKit must be given either the path to a file
100+
(`key.sourcefile`), or some text (`key.sourcetext`). `key.sourcefile` is
101+
ignored when `key.sourcetext` is also provided.
102+
103+
A hash (`key.hash`) may be provided in order to determine whether the source
104+
code has changed since the last time it was indexed. If the provided hash
105+
matches the one generated from the source code, the response will omit entries
106+
that have already been returned.
107+
108+
### Request
109+
110+
```
111+
{
112+
<key.request>: (UID) <source.request.indexsource>
113+
[opt] <key.sourcetext>: (string) // Source contents.
114+
[opt] <key.sourcefile>: (string) // Absolute path to the file.
115+
[opt] <key.compilerargs> [string*] // Array of zero or more strings for the compiler arguments
116+
// e.g ["-sdk", "/path/to/sdk"]. If key.sourcefile is provided,
117+
// these must include the path to that file.
118+
[opt] <key.hash>: (string) // Known hash for the indexed file, used to determine whether
119+
// the file has changed since the last time it was indexed.
120+
}
121+
```
122+
123+
### Response
124+
125+
```
126+
{
127+
<key.dependencies>: (array) [dependency*] // Array of zero or more dependencies.
128+
<key.hash>: (string) // Hash associated with the indexed file.
129+
[opt] <key.entities>: (array) [entity*] // Array of zero or more top-level indexed entities.
130+
// If the key.hash provided in the request matches the
131+
// one in the response, this key will not be included in
132+
// the response.
133+
}
134+
```
135+
136+
```
137+
entity ::=
138+
{
139+
<key.kind>: (UID) // UID for the declaration or reference kind (function, class, etc.).
140+
<key.name>: (string) // Displayed name for the entity.
141+
<key.usr>: (string) // USR string for the entity.
142+
<key.line>: (int64) // Line of the position of the entity in source contents.
143+
<key.column>: (int64) // Column of the position of the entity in source contents.
144+
[opt] <key.entities>: (array) [entity+] // One or more entities contained in the particular entity (sub-classes, references, etc.).
145+
[opt] <key.related>: (array) [entity+] // One or more entities related with the particular entity (inherited classes, protocols, etc.).
146+
}
147+
```
148+
149+
```
150+
dependency ::=
151+
{
152+
<key.kind>: (UID) // UID for the kind (import of a swift module, etc.).
153+
<key.name>: (string) // Displayed name for dependency.
154+
<key.filepath>: (string) // Path to the file.
155+
[opt] <key.hash>: (string) // Hash associated with this dependency.
156+
}
157+
```
158+
159+
### Testing
160+
161+
```
162+
$ sourcekitd-test -req=index <file> [-- <compiler args>]
163+
```
164+
165+
For example, to index a file at `path/to/file.swift`:
166+
167+
```
168+
$ sourcekitd-test -req=index /path/to/file.swift -- /path/to/file.swift
169+
```
170+
171+
You could also issue the following request in the `sourcekitd-repl`:
172+
173+
```
174+
$ sourcekitd-repl
175+
Welcome to SourceKit. Type ':help' for assistance.
176+
(SourceKit) {
177+
key.request: source.request.index,
178+
key.sourcefile: "/path/to/file.swift",
179+
key.compilerargs: ["/path/to/file.swift"]
180+
}
181+
```
182+
183+
## DocInfo
184+
185+
```
186+
{
187+
"key.request": source.request.docinfo,
188+
"key.modulename": "Foundation",
189+
"key.compilerargs": ["-sdk", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk"]
190+
}
191+
```
192+
193+
This will return:
194+
195+
- `key.sourcetext`: The pretty-printed module interface in swift source code
196+
- `key.annotations`: An array of annotations for the tokens of source text, they refer to the text via offset+length entries. This includes syntactic annotations (e.g. keywords) and semantic ones. The semantic ones include the name and USR of the referenced symbol.
197+
- `key.entities`: A structure of the symbols, similar to what the indexing request returns (a class has its methods as sub-entities, etc.). This includes the function parameters and their types as entities. Each entity refers to the range of the original text via offset+length entries.
198+
199+
200+
For source text (you can also pass a source filename with `key.sourcefile`):
201+
202+
```
203+
{
204+
"key.request": source.request.docinfo,
205+
"key.sourcefile": "/whatever/virtual/path",
206+
"key.sourcetext": "import Foundation\n var s: NSString\n",
207+
"key.compilerargs": ["/whatever/virtual/path", "-sdk", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk"]
208+
}
209+
```
210+
211+
This will return
212+
213+
- `key.annotations`
214+
- `key.entities`
215+
216+
...which will refer to the original text, and:
217+
218+
- `key.diagnostics`
219+
220+
...for any compiler diagnostics during parsing.
221+
222+
## Module interface generation
223+
224+
### Request
225+
226+
```
227+
{
228+
<key.request>: (UID) <source.request.editor.open.interface>
229+
<key.name>: (string) // virtual name/path to associate with the interface document
230+
<key.modulename>: (string) // Full module name, e.g. "Foundation.NSArray"
231+
[opt] <key.compilerargs> [string*] // array of zero or more strings for the compiler arguments
232+
// e.g ["-sdk", "/path/to/sdk"]
233+
}
234+
```
235+
236+
### Response
237+
238+
This will return the Swift interface of the specified module.
239+
240+
- `key.sourcetext`: The pretty-printed module interface in swift source code
241+
- `key.syntaxmap`: An array of syntactic annotations, same as the one returned for the source.request.editor.open request.
242+
- `key.annotations`: An array of semantic annotations, same as the one returned for the source.request.editor.open request.
243+
244+
All SourceKit requests that don't modify the source buffer should work on the
245+
opened document, by passing the associated 'name' for the document.
246+
247+
If pointing at a symbol which came from a clang module or the stdlib, then the
248+
response for the cursor-info request will have an entry for the module name:
249+
250+
```
251+
key.modulename: "<module-name>"
252+
```
253+
254+
Also if there is already a generated-interface document for this module
255+
previously opened, there will be an entry with the "virtual name" associated
256+
with this document (from the previous 'editor.open.interface' request):
257+
258+
```
259+
key.module_interface_name: "<virtual name for interface document>"
260+
```
261+
262+
After 'opening' the module interface, to 'jump' to the location of a declaration
263+
with a particular USR, use the 'find_usr' request:
264+
265+
```
266+
{
267+
<key.request>: (UID) <source.request.editor.find_usr>
268+
<key.usr>: (string) // USR to look for.
269+
<key.sourcefile>: (string) // virtual name/path associated with the interface document
270+
}
271+
```
272+
273+
This returns the byte offset if the USR is found, or an empty response otherwise:
274+
275+
```
276+
key.offset: <byte offset in the interface source>
277+
```
278+
279+
# Diagnostics
280+
281+
Diagnostic entries occur as part of the responses for editor requests.
282+
If there is a diagnostic, `<key.diagnostics>` is present and contains an array
283+
of diagnostic entries. A diagnostic entry has this format:
284+
285+
```
286+
{
287+
<key.severity>: (UID) // severity of error
288+
<key.offset>: (int64) // error location
289+
<key.description>: (string) // error description
290+
[opts] <key.fixits>: (array) [fixit+] // one or more entries for fixits
291+
[opts] <key.ranges>: (array) [range+] // one or more entries for ranges
292+
[opts] <key.diagnostics>: (array) [diagnostic+] // one or more sub-diagnostic entries
293+
}
294+
```
295+
296+
Where `key.severity` can be one of:
297+
298+
- `source.diagnostic.severity.note`
299+
- `source.diagnostic.severity.warning`
300+
- `source.diagnostic.severity.error`
301+
302+
```
303+
fixit ::=
304+
{
305+
<key.offset>: (int64) // location of the fixit range
306+
<key.length>: (int64) // length of the fixit range
307+
<key.sourcetext>: (string) // text to replace the range with
308+
}
309+
```
310+
311+
```
312+
range ::=
313+
{
314+
<key.offset>: (int64) // location of the range
315+
<key.length>: (int64) // length of the range
316+
}
317+
```
318+
319+
Sub-diagnostics are only diagnostic notes currently.
320+
321+
# UIDs
322+
323+
## Keys
324+
325+
- `key.column`
326+
- `key.compilerargs`
327+
- `key.description`
328+
- `key.kind`
329+
- `key.line`
330+
- `key.name`
331+
- `key.offset`
332+
- `key.results`
333+
- `key.request`
334+
- `key.sourcefile`
335+
- `key.sourcetext`
336+
- `key.typename`
337+
- `key.usr`
338+

0 commit comments

Comments
 (0)