Skip to content

Commit 53ef723

Browse files
committed
Add table of contents
1 parent 8c82d2a commit 53ef723

File tree

2 files changed

+90
-24
lines changed

2 files changed

+90
-24
lines changed

_data/lsif-0-4-0-toc.yml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
- title: Table of Contents
2+
children:
3+
- title: General
4+
anchor: _general
5+
children:
6+
- title: Introduction
7+
anchor: lsifIntro
8+
- title: Motivation
9+
anchor: lsifMotivation
10+
- title: Ranges
11+
anchor: ranges
12+
- title: Result Sets
13+
anchor: resultSet
14+
- title: Language Features
15+
anchor: _languageFeatures
16+
children:
17+
- title: definition
18+
anchor: definition
19+
- title: declaration
20+
anchor: declaration
21+
- title: hover
22+
anchor: hover
23+
- title: references
24+
anchor: references
25+
- title: implementation
26+
anchor: implementation
27+
- title: typeDefinition
28+
anchor: typeDefinition
29+
- title: foldingRange
30+
anchor: foldingRange
31+
- title: documentLink
32+
anchor: documentLink
33+
- title: documentSymbol
34+
anchor: documentSymbol
35+
- title: diagnostic
36+
anchor: diagnostic
37+
- title: project
38+
anchor: projectContext
39+
- title: Embedding Contents
40+
anchor: embeddingContents
41+
- title: Advanced Concepts
42+
anchor: _advancedConcpets
43+
children:
44+
- title: Events
45+
anchor: events
46+
- title: Exports and Imports
47+
anchor: exportsImports
48+
- title: Result Ranges
49+
anchor: resultRanges
50+
- title: Meta Data
51+
anchor: metaData
52+
- title: Emitting Contstraints
53+
anchor: emittingContstraints
54+
- title: Additional Information
55+
anchor: _additionalInformation
56+
children:
57+
- title: Tools
58+
anchor: tools
59+
- title: Open Questions
60+
anchor: openQuestions

_specifications/lsif/0.4.0/specification.md

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ index: 2
1111

1212
The 0.4.0 version of LSIF is currently under construction.
1313

14-
## Language Server Index Format
14+
## <a href="#lsifIntro" name="lsifIntro" class="anchor">Language Server Index Format</a>
1515

1616
The purpose of the Language Server Index Format (LSIF) is it to define a standard format for language servers or other programming tools to dump their knowledge about a workspace. This dump can later be used to answer language server [LSP](https://microsoft.github.io/language-server-protocol/) requests for the same workspace without running the language server itself. Since much of the information would be invalidated by a change to the workspace, the dumped information typically excludes requests used when mutating a document. So, for example, the result of a code complete request is typically not part of such a dump.
1717

@@ -23,7 +23,7 @@ Up to version 0.4.0 the focus of the LSIF format was to ease the generation of t
2323

2424
Since 0.4.0 changes some of the LSIF aspects more deeply an old 0.3.x version of the specification is available [here](./versions/specification-0-3-x.md)
2525

26-
### Motivation
26+
## <a href="#lsifMotivation" name="lsifMotivation" class="anchor">Motivation</a>
2727

2828
Principal design goals:
2929

@@ -85,7 +85,7 @@ The corresponding graph looks like this
8585

8686
<img src="../img/foldingRange.png" alt="Folding Range Result" style="max-width: 66%; max-height: 66%"/>
8787

88-
### Ranges
88+
### <a href="#ranges" name="ranges" class="anchor">Ranges</a>
8989

9090
For requests that take a position as its input, we need to store the position as well. Usually LSP requests return the same result for positions that point to the same word / name in a document. Take the following TypeScript example:
9191

@@ -143,7 +143,7 @@ If a position in a document is mapped to a range and more than one range covers
143143
1. end
144144
1. return `null`
145145

146-
### Result Set
146+
### <a href="#resultSet" name="resultSet" class="anchor">Result Set</a>
147147

148148
Usually the hover result is the same whether you hover over a definition of a function or over a reference of that function. The same is actually true for many LSP requests like `textDocument/definition`, `textDocument/references` or `textDocument/typeDefinition`. In a naïve model, each range would have outgoing edges for all these LSP requests and would point to the corresponding results. To optimize this and to make the graph easier to understand, the concept of a `ResultSet` is introduced. A result set acts as a hub to be able to store information common to a lot of ranges. The `ResultSet` itself doesn't carry any information. So it looks like this:
149149

@@ -181,7 +181,9 @@ The pattern of storing the result with the `ResultSet` will be used for other re
181181
1. end
182182
1. otherwise return `null`
183183
184-
### Request: `textDocument/definition`
184+
## <a href="#languageFeatures" name="languageFeatures" class="anchor">Language Features</a>
185+
186+
### <a href="#definition" name="definition" class="anchor">Request: `textDocument/definition`</a>
185187
186188
The same pattern of connecting a range, result set, or a document with a request edge to a method result is used for other requests as well. Let's next look at the `textDocument/definition` request using the following TypeScript sample:
187189
@@ -244,11 +246,11 @@ Running **Go to Definition** on `X` in `let x: X` will show a dialog which lets
244246
245247
The `item` edge as an additional property document which indicate in which document these declaration are. We added this information to still make it easy to emit the data but also make it easy to process the data to store it in a database. Without that information we would either need to specific an order in which data needs to be emitted (e.g. a item edge and only refer to a range that got already added to a document using a `containes` edge) or we force processing tools to keep a lot of vertices and edges in memory. The approach of having this `document` property looks like a fair balance.
246248
247-
### Request: `textDocument/declaration`
249+
### <a href="#declaration" name="declaration" class="anchor">Request: `textDocument/declaration`</a>
248250
249251
There are programming languages that have the concept of declarations and definitions (like C/C++). If this is the case, the dump can contain a corresponding `declarationResult` vertex and a `textDocument/declaration` edge to store the information. They are handled analogously to the entities emitted for the `textDocument/definition` request.
250252
251-
### More about Request: `textDocument/hover`
253+
### <a href="#hover" name="hover" class="anchor">More about Request: `textDocument/hover`</a>
252254
253255
In the LSP, the hover is defined as follows:
254256
@@ -276,7 +278,7 @@ This makes the hover different for every location so we can't really store it wi
276278
{ id: 6, type: "vertex", label: "hoverResult", result: { contents: [ { language: "typescript", value: "function bar(): void" } ], range: { line: 4, character: 2 }, end: { line: 4, character: 5 } } }
277279
```
278280
279-
### Request: `textDocument/references`
281+
### <a href="#references" name="references" class="anchor">Request: `textDocument/references`</a>
280282
281283
Storing references will be done in the same way as storing a hover or go to definition ranges. It uses a reference result vertex and `item` edges to add ranges to the result.
282284
@@ -461,7 +463,7 @@ In the above example, there will be three reference results
461463

462464
For Typescript, method references are recorded at their most abstract declaration and if methods are merged (`B#foo`), they are combined using a reference result pointing to other results.
463465

464-
### Request: `textDocument/implementation`
466+
### <a href="#references" name="implementation" class="anchor">Request: `textDocument/implementation`</a>
465467

466468
Supporting a `textDocument/implementation` request is done reusing what we implemented for a `textDocument/references` request. In most cases, the `textDocument/implementation` returns the declaration values of the reference result that a symbol declaration points to. For cases where the result differs, the LSIF provides an `ImplementationResult`. To nest implementation results the `item` edge supports a `property` value `"implementationResults"`.
467469

@@ -474,7 +476,7 @@ interface ImplementationResult {
474476
}
475477
```
476478

477-
### Request: `textDocument/typeDefinition`
479+
### <a href="#typeDefinition" name="typeDefinition" class="anchor">Request: `textDocument/typeDefinition`</a>
478480

479481
Supporting `textDocument/typeDefinition` is straightforward. The edge is either recorded at the range or at the `ResultSet`.
480482

@@ -520,11 +522,11 @@ The relevant emitted vertices and edges looks like this:
520522

521523
As with other results ranges get added using a `item` edge. In this case without a `property` since there is only on kind of range.
522524

523-
### Document requests
525+
## Document requests
524526

525527
The Language Server Protocol also supports requests for documents only (without any position information). These requests are `textDocument/foldingRange`, `textDocument/documentLink`, and `textDocument/documentSymbol`. We follow the same pattern as before to model these, the difference being that the result is linked to the document instead of to a range.
526528

527-
### Request: `textDocument/foldingRange`
529+
### <a href="#foldingRange" name="foldingRange" class="anchor">Request: `textDocument/foldingRange`</a>
528530

529531
For the folding range result this looks like this:
530532

@@ -563,7 +565,7 @@ export interface FoldingRangeResult {
563565
}
564566
```
565567

566-
### Request: `textDocument/documentLink`
568+
### <a href="#documentLink" name="documentLink" class="anchor">Request: `textDocument/documentLink`</a>
567569

568570
Again, for document links, we define a result type and a corresponding edge to link it to a document. Since the link location usually appear in comments, the ranges don't denote any symbol declarations or references. We therefore inline the range into the result like we do with folding ranges.
569571

@@ -575,7 +577,7 @@ export interface DocumentLinkResult {
575577
}
576578
```
577579

578-
### Request: `textDocument/documentSymbol`
580+
### <a href="#documentSymbol" name="documentSymbol" class="anchor">Request: `textDocument/documentSymbol`</a>
579581

580582
Next we look at the `textDocument/documentSymbol` request. This request usually returns an outline view of the document in hierarchical form. However, not all programming symbols declared or defined in a document are part of the result (for example, locals are usually omitted). In addition, an outline item needs to provide additional information like the full range and a symbol kind. There are two ways we can model this: either we do the same as we do for folding ranges and the document links and store the information in a document symbol result as literals, or we extend the range vertex with some additional information and refer to these ranges in the document symbol result. Since the additional information for ranges might be helpful in other scenarios as well, we support adding additional tags to these ranges by defining a `tag` property on the `range` vertex.
581583

@@ -744,7 +746,7 @@ Produces the following output:
744746
{ id: 40 , type: "edge", label: "textDocument/documentSymbol", outV: 2, inV: 39 }
745747
```
746748

747-
### Request: `textDocument/diagnostic`
749+
### <a href="#diagnostic" name="diagnostic" class="anchor">Request: `textDocument/diagnostic`</a>
748750

749751
The only information missing that is useful in a dump are the diagnostics associated with documents. Diagnostics in the LSP are modeled as a push notifications sent from the server to the client. This doesn't work well with a dump modeled on request method names. However, the push notification can be emulated as a request where the request's result is the value sent during the push as a parameter.
750752

@@ -782,7 +784,7 @@ Produces the following output:
782784

783785
Since diagnostics are not very common in dumps, no effort has been made to reuse ranges in diagnostics.
784786

785-
### The Project vertex
787+
### <a href="#projectContext" name="projectContext" class="anchor">The Project vertex</a>
786788

787789
Usually language servers operate in some sort of project context. In TypeScript, a project is defined using a `tsconfig.json` file. C# and C++ have their own means. The project file usually contains information about compile options and other parameters. Having these in the dump can be valuable. The LSIF therefore defines a project vertex. In addition, all documents that belong to that project are connected to the project using a `contains` edge. If there was a `tsconfig.json` in the previous examples, the first emitted edges and vertices would look like this:
788790

@@ -820,11 +822,13 @@ export interface Project extends V {
820822
}
821823
```
822824

823-
## Embedding contents
825+
### <a href="#embeddingContents" name="embeddingContents" class="anchor">Embedding contents</a>
824826

825827
It can be valuable to embed the contents of a document or project file into the dump as well. For example, if the content of the document is a virtual document generated from program meta data. The index format therefore supports an optional `contents` property on the `document` and `project` vertex. If used the content needs to be `base64` encoded.
826828

827-
## Events
829+
## <a href="#advancedConcpets" name="advancedConcpets" class="anchor">Advanced Concepts</a>
830+
831+
### <a href="#events" name="events" class="anchor">Events</a>
828832

829833
To ease the processing of an LSIF dump to for example import it into a database the dump emits begin and end events for documents and projects. After the end event of a document has been emitted the dump must not contain any further data referencing that document. For example no ranges from that document can be referenced in `item` edges. Nor can result sets or other vertices linked to the ranges in that document. The document can however be reference in a `contains` edge adding the document to a project. The begin / end events for documents look like this:
830834

@@ -851,7 +855,7 @@ The events for projects looks similar:
851855
{ id: 55, type: "vertex", label: "$event", kind: "end", scope: "project", data: 2 }
852856
```
853857

854-
## Project exports and external imports (Monikers)
858+
### <a href="#exportsImports" name="exportsImports" class="anchor">Project exports and external imports (Monikers)</a>
855859

856860
One use case of the LSIF is to create dumps for released versions of a product, either a library or a program. If a project **A** references a library **B**, it would also be useful if the information in these two dumps could be related. To make this possible, the LSIF introduces optional monikers which can be linked to ranges using a corresponding edge. The monikers can be used to describe what a project exports and what it imports. Let's first look at the export case.
857861

@@ -1002,7 +1006,7 @@ The moniker for `x` looks like this:
10021006
10031007
In addition to this moniker schemes starting with `$` are reserved and shouldn't be used by a LSIF tool.
10041008
1005-
## Result ranges
1009+
### <a href="#resultRanges" name="resultRanges" class="anchor">Result ranges</a>
10061010
10071011
Ranges in LSIF have currently two meanings:
10081012
@@ -1011,7 +1015,7 @@ Ranges in LSIF have currently two meanings:
10111015
10121016
To fulfil the first LSIF specifies that ranges can't overlap or be the same. However this constraint is not necessary for the second meaning. To support equal or overlapping target ranges we introduce a vertex `resultRange`. It is not allowed to use a `resultRange` as a target in a `contains` edge.
10131017
1014-
## Meta Data Vertex
1018+
### <a href="#metaData" name="metaData" class="anchor">Meta Data Vertex</a>
10151019
10161020
To support versioning the LSIF defines a meta data vertex as follows:
10171021
@@ -1053,7 +1057,7 @@ export interface MetaData {
10531057
}
10541058
```
10551059
1056-
## Emitting constraints
1060+
### <a href="#emittingContstraints" name="emittingContstraints" class="anchor">Emitting constraints</a>
10571061
10581062
The following emitting constraints (some of which have already mean mentioned in the document) exists:
10591063
@@ -1063,13 +1067,15 @@ The following emitting constraints (some of which have already mean mentioned in
10631067
- after a document end event has been emitted only result sets, reference or implementation results emitted through that document can be referenced in edges. It is for example not allowed to reference ranges or result ranges from that document. This also includes adding monikers to ranges or result sets. The document data so to speak can not be altered anymore.
10641068
- if ranges point to result sets and monikers are emitted, they must be emitted on the result set and can't be emitted on individual ranges.
10651069
1066-
## Tools
1070+
## <a href="#additionalInformation" name="additionalInformation" class="anchor">Additional Information </a>
1071+
1072+
### <a href="#tools" name="tools" class="anchor">Tools</a>
10671073
10681074
- [`lsif-protocol`](https://github.com/Microsoft/lsif-node/tree/master/protocol): Protocol defined as TypeScript interfaces
10691075
- [`lsif-util`](https://github.com/jumattos/lsif-util): Utility tools for LSIF development
10701076
- [`lsif-tsc`](https://github.com/Microsoft/lsif-node/tree/master/tsc): LSIF indexer for TypeScript
10711077
- [`lsif-npm`](https://github.com/Microsoft/lsif-node/tree/master/npm): Linker for NPM monikers
10721078
1073-
## Open Questions
1079+
### <a href="#openQuestions" name="openQuestions" class="anchor">Open Questions</a>
10741080
10751081
While implementing this for TypeScript and npm we collected a list of [open questions](https://github.com/Microsoft/lsif-typescript/labels/discussion) in form of GitHub issues we are already aware of.

0 commit comments

Comments
 (0)