Skip to content

Commit 925a0b2

Browse files
authored
(docs) Overview of the language-tools (#455)
1 parent 6855b2b commit 925a0b2

File tree

6 files changed

+122
-1
lines changed

6 files changed

+122
-1
lines changed

.github/ISSUE_TEMPLATE/bug_report.md

+4
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,7 @@ If applicable, add screenshots to help explain your problem.
3535

3636
**Additional context**
3737
Add any other context about the problem here.
38+
39+
<!-- Want to help us out? Read this to get started:
40+
https://github.com/sveltejs/language-tools#development
41+
-->

.github/ISSUE_TEMPLATE/feature_request.md

+4
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,7 @@ A clear and concise description of any alternative solutions or features you've
1818

1919
**Additional context**
2020
Add any other context or screenshots about the feature request here.
21+
22+
<!-- Want to help us out? Read this to get started:
23+
https://github.com/sveltejs/language-tools#development
24+
-->

.prettierignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
packages/svelte2tsx/*.d.ts
2-
packages/svelte2tsx/test/**
2+
packages/svelte2tsx/test/**
3+
.github/**

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ Converts a .svelte file into a legal TypeScript file. Built from [halfnelson/sve
7575

7676
Pull requests are encouraged and always welcome. [Pick an issue](https://github.com/sveltejs/language-tools/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc) and help us out!
7777

78+
To get an overview of the internals, [read here](./docs/internal/overview.md).
79+
7880
To install and work on these tools locally:
7981

8082
> Make sure to uninstall the extension from the marketplace to not have it clash with the local one.

docs/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,4 @@ Your default formatter for Svelte files may be wrong. Either it's set to the old
100100
## Internals
101101

102102
- [Notes about deployment](./internal/deployment.md)
103+
- [Overview of the language-tools and how things work together](./internal/overview.md)

docs/internal/overview.md

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Overview of the language-tools and how things work together
2+
3+
The `language-tools` repository is a monorepo containing several packages which are closely related to each other.
4+
5+
- `svelte2tsx` - transforms Svelte code into JSX/TSX code
6+
- `language-server` - a language server adhering to the [LSP](https://microsoft.github.io/language-server-protocol)
7+
- `svelte-check` - a command line tool to get diagnostics for Svelte code
8+
- `svelte-vscode` - the [Svelte for VSCode](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) extension
9+
10+
This is how they are related:
11+
12+
```
13+
svelte-vscode |
14+
|-> language-server -> svelte2tsx
15+
svelte-check |
16+
```
17+
18+
## language-server overview
19+
20+
As briefly touched already, this is a language-server adhering to the [Language Server Protocol (LSP)](https://microsoft.github.io/language-server-protocol).
21+
The protocol defines the communication between an editor or IDE and a language server that provides language features like auto complete, go to definition, find all references etc.
22+
23+
Our `language-server` can roughly be splitted into [four areas](/packages/language-server/src/plugins):
24+
25+
- CSS: Provides intellisense for the things inside `<style>`. Internally it mostly forwards stuff to the `vscode-css-languageservice`.
26+
- HTML: Provides intellisense for basic HTML tags like `div`, `a` etc. Internally it mostly forwards stuff to the `vscode-html-languageservice`. Svelte-specific template syntax is _NOT_ handled here.
27+
- Svelte: Provides the diagnostics of the Svelte compiler. If you use preprocessors, those are invoked beforehand - that's why we need the `svelte.config.js` to know how to preprocess your files. It also does the formatting through `prettier-plugin-svelte` and other cross-cutting concerns like the "Extract Component" refactoring.
28+
- TypeScript/JavaScript: Provides intellisense for all JS/TS related stuff. This not only includes code inside `<script>` but also inside the template the moment you use any of the Svelte specifics like bindings or template syntax. `svelte2tsx` is used in here, and only here.
29+
30+
The last area, TS/JS, is where most of the work is done. Svelte is a mix of JavaScript/TypeScript inside `script` and more of it within Svelte's template syntax. To get a holistic view of the file, we need to account for both.
31+
This is also the reason why preprocessors such as `svelte-preprocess` cannot do type checking because it produces wrong diagnostics. To preprocess the script content, it only gets the content from the script. Think of this situation:
32+
33+
```html
34+
<script lang="ts">
35+
let a: number = 1;
36+
</script>
37+
{a}
38+
```
39+
40+
`svelte-preprocess` only gets `let a = 1` and the diagnostics would output that `a` is never used, which is wrong.
41+
42+
To get that holistic view, we need `svelte2tsx`.
43+
44+
### svelte2tsx
45+
46+
To get a holistic view of Svelte files, we have two options:
47+
48+
1. Write a language service ourselves which is capable of doing things like auto complete, go to definition, rename etc.
49+
2. Convert the Svelte code to something an existing language service can process which then does auto complete, go to defintion, rename etc for us.
50+
51+
We chose the second option because TypeScript provides a language service which can do all the heavy lifting for us: We give it some files and then invoke methods like `getQuickInfoAtPosition` for hover info. These files need to be in a format the language service can understand: A form of JavaScript or TypeScript. `svelte2tsx` is the package which does this transformation: Pass in Svelte code and get back JSX or TSX code, depending on whether or not you use TS in Svelte. `svelte2tsx` uses some [ambient definitions](/packages/svelte2tsx/svelte-shims.d.ts) which are loaded by the language server, to do some of the transformations. It also provides [JSX definitions](/packages/svelte2tsx/svelte-jsx.d.ts) which are recognized by the TypeScript compiler and define intrinsic elements, attributes and events - so if you ever get an error that a DOM attribute is not assignable to a DOM element, it's likely a missing declaration in there.
52+
53+
The code generated by `svelte2tsx` is not runnable in any way and does not actually exist at runtime when you run your app, it purely exists for the intellisense. The code also returns source mappings so we know which position in the original code corresponds to which generated position.
54+
55+
### Integration of svelte2tsx into the language-server
56+
57+
This example shows how our `language-server` uses `svelte2tsx`:
58+
59+
**Svelte file changes:**
60+
61+
1. Svelte file comes in
62+
63+
```html
64+
<script>
65+
export let world = 'name';
66+
</script>
67+
68+
<h1>hello {world}</h1>
69+
```
70+
71+
2. Transform Svelte to TSX/JSX
72+
73+
```tsx
74+
<></>;
75+
function render() {
76+
// -- the transformed script:
77+
let world = 'name';
78+
// -- the transformed template
79+
<>
80+
<h1>hello {world}</h1>
81+
</>;
82+
// -- obtained props, slots and events,
83+
// to get intellisense for this component in other components
84+
return { props: { world }, slots: {}, events: {} };
85+
}
86+
// -- generate a class
87+
export default class _World_ extends createSvelte2TsxComponent(__sveltets_partial(render)) {}
88+
```
89+
90+
3. Pass that result to the TypeScript language service
91+
92+
**User wants hover info:**
93+
94+
1. User hovers over a component property in the template
95+
2. Get generated file from original file
96+
3. Transform the position (line, character) where the user hovers from the original to the generated position
97+
4. Invoke TypeScript language service's method for hover info with the generated position
98+
5. Hand back results to user
99+
100+
As you can see, the `language-server` is mostly doing position transformations and then handing the main work off to the TypeScript language service. Sometimes we also need to do post processing of the results and work around quirks.
101+
102+
## svelte-check
103+
104+
As mentioned above, preprocessors cannot do type checking. That's why we added `svelte-check`, a command line tool to get diagnostics for Svelte code.
105+
The tool is using the `language-server` to do this work. Inside the `language-server` we added an [entry point](/packages/language-server/src/svelte-check.ts) for `svelte-check` which spins up the language server and just executes diagnostics.
106+
107+
## svelte-vscode
108+
109+
This is the [Svelte for VSCode](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) extension most of you probably use. Syntax highlighting is provided through a [JSON file](/packages/svelte-vscode/syntaxes) which tells VSCode how to tokenize the input. To get all the intellisense capabilities, the extension uses the the `language-server`. VSCode implements the LSP and also provides a node library to do most of the wiring for us. Some things like special refactoring commands ("Extract Component") need some extra glue code, but that's all.

0 commit comments

Comments
 (0)