mirror of
https://github.com/microsoft/language-server-protocol.git
synced 2025-12-23 08:48:16 +00:00
Add LSIF specification to Web portal
This commit is contained in:
parent
332ff94ae6
commit
cf073e742a
10 changed files with 1282 additions and 11 deletions
60
_data/lsif-0-4-0-toc.yml
Normal file
60
_data/lsif-0-4-0-toc.yml
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
- title: Table of Contents
|
||||
children:
|
||||
- title: General
|
||||
anchor: _general
|
||||
children:
|
||||
- title: Introduction
|
||||
anchor: lsifIntro
|
||||
- title: Motivation
|
||||
anchor: lsifMotivation
|
||||
- title: Ranges
|
||||
anchor: ranges
|
||||
- title: Result Sets
|
||||
anchor: resultSet
|
||||
- title: Language Features
|
||||
anchor: _languageFeatures
|
||||
children:
|
||||
- title: definition
|
||||
anchor: definition
|
||||
- title: declaration
|
||||
anchor: declaration
|
||||
- title: hover
|
||||
anchor: hover
|
||||
- title: references
|
||||
anchor: references
|
||||
- title: implementation
|
||||
anchor: implementation
|
||||
- title: typeDefinition
|
||||
anchor: typeDefinition
|
||||
- title: foldingRange
|
||||
anchor: foldingRange
|
||||
- title: documentLink
|
||||
anchor: documentLink
|
||||
- title: documentSymbol
|
||||
anchor: documentSymbol
|
||||
- title: diagnostic
|
||||
anchor: diagnostic
|
||||
- title: project
|
||||
anchor: projectContext
|
||||
- title: Embedding Contents
|
||||
anchor: embeddingContents
|
||||
- title: Advanced Concepts
|
||||
anchor: _advancedConcpets
|
||||
children:
|
||||
- title: Events
|
||||
anchor: events
|
||||
- title: Exports and Imports
|
||||
anchor: exportsImports
|
||||
- title: Result Ranges
|
||||
anchor: resultRanges
|
||||
- title: Meta Data
|
||||
anchor: metaData
|
||||
- title: Emitting Contstraints
|
||||
anchor: emittingContstraints
|
||||
- title: Additional Information
|
||||
anchor: _additionalInformation
|
||||
children:
|
||||
- title: Tools
|
||||
anchor: tools
|
||||
- title: Open Questions
|
||||
anchor: openQuestions
|
||||
|
|
@ -1,6 +1,12 @@
|
|||
- title: Specifications Overview
|
||||
- title: LSP
|
||||
anchor: lsp
|
||||
children:
|
||||
- title: 3.15 (Current)
|
||||
url: /specifications/specification-current
|
||||
- title: 3.14 (Previous)
|
||||
url: /specifications/specification-3-14
|
||||
- title: LSIF
|
||||
anchor: lsif
|
||||
children:
|
||||
- title: 0.4.0
|
||||
url: /specifications/lsif/0.4.0/specification
|
||||
|
|
|
|||
|
|
@ -5,20 +5,30 @@ layout: default
|
|||
<div class="container">
|
||||
<div class="row single-page">
|
||||
<div class="col-lg-2 d-none d-lg-block lsp-sidebar">
|
||||
{% for specs in site.data.specifications %}
|
||||
<div class="card">
|
||||
<ul class="nav flex-column list-unstyled">
|
||||
{% for spec in specs.children %}
|
||||
<li {% if page.title==spec.title %} class="nav-item active" {% else %} class="nav-item" {% endif %}>
|
||||
<a class="nav-link" href="{{ spec.url | prepend: site.baseurl }}">
|
||||
{{ spec.title }}
|
||||
<div class="outlineAccordion" data-children=".item">
|
||||
{% for spec-group in site.data.specifications %}
|
||||
<div class="item">
|
||||
<a class="nav-link" data-toggle="collapse" data-parent="#outlineAccordion" href="#{{ spec-group.anchor }}"aria-expanded="true">
|
||||
{{ spec-group.title }}
|
||||
</a>
|
||||
</li>
|
||||
<div id="{{ spec-group.anchor }}" class="show" role="tabpanel">
|
||||
<ul class="nav toc flex-column" style="padding-left: 0.5rem">
|
||||
{% for spec in spec-group.children %}
|
||||
<li {% if page.title==spec.title %} class="nav-item active" {% else %} class="nav-item" {% endif %}>
|
||||
<a class="nav-link toc-link" href="{{ spec.url | prepend: site.baseurl }}">
|
||||
{{ spec.title }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="col-lg-8">
|
||||
<div id="markdown-content-container">{{ content }}</div>
|
||||
</div>
|
||||
|
|
@ -29,7 +39,7 @@ layout: default
|
|||
<div id="outlineAccordion" data-children=".item">
|
||||
{% for toc-l2 in toc-l1.children %}
|
||||
<div class="item">
|
||||
<a class="nav-link" data-toggle="collapse" data-parent="#outlineAccordion" href="#{{ toc-l2.anchor }}" aria-expanded="true" aria-controls="exampleAccordion1">
|
||||
<a class="nav-link" data-toggle="collapse" data-parent="#outlineAccordion" href="#{{ toc-l2.anchor }}" aria-expanded="true">
|
||||
{{ toc-l2.title }}
|
||||
</a>
|
||||
<div id="{{ toc-l2.anchor }}" class="collapse {% if toc-l2.anchor=='general' %}show{% endif%}" role="tabpanel">
|
||||
|
|
|
|||
BIN
_specifications/lsif/0.4.0/img/definitionResult.png
Normal file
BIN
_specifications/lsif/0.4.0/img/definitionResult.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
BIN
_specifications/lsif/0.4.0/img/foldingRange.png
Normal file
BIN
_specifications/lsif/0.4.0/img/foldingRange.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
BIN
_specifications/lsif/0.4.0/img/hoverResult.png
Normal file
BIN
_specifications/lsif/0.4.0/img/hoverResult.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
BIN
_specifications/lsif/0.4.0/img/referenceResult.png
Normal file
BIN
_specifications/lsif/0.4.0/img/referenceResult.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
BIN
_specifications/lsif/0.4.0/img/resultSet.png
Normal file
BIN
_specifications/lsif/0.4.0/img/resultSet.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
114
_specifications/lsif/0.4.0/implementation.md
Normal file
114
_specifications/lsif/0.4.0/implementation.md
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
# Building an LSIF exporter
|
||||
|
||||
With an LSIF (Language Server Index Format) exporter for your programming language of choice, you can use [Rich Code Navigation](https://code.visualstudio.com/blogs/2018/12/04/rich-navigation) on pull requests inside Visual Studio and Visual Studio Code. Users can navigate PRs with go-to-definition, find-all-references, and diagnostics, without requiring a local checkout.
|
||||
|
||||
In this guide, we cover how you can build an LSIF implementation that can be used for Rich Code Navigation. If you are new to LSIF, start with the [specification](specification.md), which covers motivation and implementation details of the protocol.
|
||||
|
||||
## The Rich Code Navigation scenario
|
||||
|
||||
With Rich Code Navigation, users use navigate features (peek definition, find all references, diagnostics, etc.) over PRs in their editor without having a local checkout. These navigation features are powered by a cloud language service, which uses an LSIF index. The index can be generated at a variety of places. For example, the index could be generated in a CI pipeline with the following steps:
|
||||
|
||||
1. User creates a new PR.
|
||||
1. The CI configured on the repo builds the PR.
|
||||
1. The LSIF exporter runs on CI and generates the LSIF index.
|
||||
|
||||
## LSIF exporters
|
||||
|
||||
| Language | Repository |
|
||||
|--|--|
|
||||
| TypeScript/JavaScript | [lsif-node](https://github.com/Microsoft/lsif-node) |
|
||||
| Java | [lsif-java](https://github.com/Microsoft/lsif-java) |
|
||||
| C# | |
|
||||
|
||||
> Are we missing an implementation? File a new issue on GitHub to add it here.
|
||||
|
||||
## LSIF exporter skeleton
|
||||
|
||||
As [detailed in the spec](specification.md#project-exports-and-external-imports), the LSIF exporter consists of two tools: the index exporter and the package linker.
|
||||
|
||||
### Index exporter
|
||||
|
||||
The index exporter generates an LSIF dump for a workspace by traversing through source files and storing LSP responses. For TypeScript/JavaScript, [`lsif-tsc`](https://github.com/Microsoft/lsif-node/tree/master/tsc) is the index exporter.
|
||||
|
||||
### Package linker
|
||||
|
||||
The package linker converts the LSIF output of the index exporter into a global friendly index. By using package metadata, export `moniker` vertices are linked to packages available on a registry. For instance, the `observable` export from the mobx dependency is linked to the mobx dependency available on NPM. The package metadata is used to create the `packageInformation` vertices that reference external packages.
|
||||
|
||||
For TypeScript/JavaScript, [`lsif-npm`](https://github.com/Microsoft/lsif-node/tree/master/npm) is the package manager linker for NPM.
|
||||
|
||||
## Testing and validation
|
||||
|
||||
### LSIF validation utility
|
||||
|
||||
The [`lsif-util`](https://github.com/microsoft/lsif-node/tree/master/util) tool can validate your generated LSIF output. Additionally, the tool can also be used to search the output and visualize via Graphviz.
|
||||
|
||||
### VS Code LSIF extension
|
||||
|
||||
With the [LSIF extension for VS Code](https://github.com/Microsoft/vscode-lsif-extension), you can dogfood an LSIF index to power navigation inside VS Code.
|
||||
|
||||
## Performance
|
||||
|
||||
Generating LSIF for a project is expected to take roughly the same time as compilation.
|
||||
|
||||
A primitive LSIF index exporter loops over source files, and for every symbol encountered, queries the language server for responses to LSP requests. With this approach, computing references can become very expensive: references are computed multiple times for the same symbol spread over files. This can be inefficient, depending on the language server implementation.
|
||||
|
||||
This approach can optimized by computing references only once for a symbol spread over files. The approach taken by the [lsif-tsc](https://github.com/Microsoft/lsif-node) tool is outlined below:
|
||||
|
||||
- Parse the project configuration to get source files
|
||||
- Loop over files, and run the following on the AST of each file
|
||||
- When you encounter a symbol, find out the binding of the symbol (declaration)
|
||||
- If the binding is local to the file, create a referencesResult data structure and add symbols with the same binding. When the parsing of the file is complete, we know that the referenceResult is complete and can be emitted.
|
||||
- If the binding is not local, keep result set in memory, and keep parsing other files.
|
||||
|
||||
## Recommended checklist
|
||||
|
||||
We have seen the following patterns work well in existing implementations.
|
||||
|
||||
### Method checklist
|
||||
|
||||
For an ideal integration with Rich Code Navigation, the following methods are required. For some languages, methods such as `textDocument/declaration` might not be applicable.
|
||||
|
||||
- [ ] `textDocument/hover`
|
||||
- [ ] `textDocument/definition`
|
||||
- [ ] `textDocument/references`
|
||||
- [ ] `textDocument/implementation`
|
||||
- [ ] `textDocument/declaration`
|
||||
- [ ] `textDocument/typeDefinition`
|
||||
- [ ] `textDocument/diagnostic`
|
||||
- [ ] Cross-repo navigation for dependencies
|
||||
|
||||
### Cross-platform
|
||||
|
||||
If the LSIF exporter does not work across platforms (Windows, Linux, Mac), platform dependencies should be called out.
|
||||
|
||||
### Output format
|
||||
|
||||
The LSIF exporter is expected to implement the [line-delimited JSON](https://en.wikipedia.org/wiki/JSON_streaming#Line-delimited_JSON) (also known as [JSON lines](http://jsonlines.org/)) output format: series of JSON objects (vertex or edge) separated by newline. Since JSON lines is suitable for streaming output and works better for larger repos, it is preferred over a JSON array output.
|
||||
|
||||
If an LSIF consumer requires a valid JSON array as input (for example, the VS Code LSIF extension), the JSON lines output can be converted into a JSON array by piping into a conversion tool.
|
||||
|
||||
```
|
||||
cat lsif.jsonl | sed '1s/^/[/;$!s/$/,/;$s/$/]/'
|
||||
```
|
||||
|
||||
If the LSIF exporter needs to log additional output, it is recommended to use `stderr`, since `stdout` is reserved for JSON line output.
|
||||
|
||||
### Project configuration
|
||||
|
||||
The LSIF index exporter can expose a flag to specify the root of the project directory. For example, the [TypeScript implementation](https://github.com/Microsoft/lsif-node) exposes the `--project` (`-p`) to specify the root of the tsconfig.json file.
|
||||
|
||||
```
|
||||
lsif-tsc --project ./frontend/tsconfig.json
|
||||
```
|
||||
|
||||
### Error behavior
|
||||
|
||||
The LSIF tool is expected to signal for error conditions, with a numeric exit code. A successful execution returns a 0, whereas error conditions (unable to build project, unable to find project file) return 1.
|
||||
|
||||
### Required documentation
|
||||
|
||||
Since LSIF is an evolving protocol, it is critical to document the [protocol version](specification.md#changelog) supported by the exporter.
|
||||
|
||||
## Support
|
||||
|
||||
Feel free to reach out to us for questions by raising an issue on GitHub.
|
||||
1081
_specifications/lsif/0.4.0/specification.md
Normal file
1081
_specifications/lsif/0.4.0/specification.md
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue