aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cargo/config1
-rw-r--r--CONTRIBUTING.md88
-rw-r--r--crates/ra_syntax/src/ast/generated.rs3
-rw-r--r--crates/ra_syntax/src/ast/generated.rs.tera5
-rw-r--r--crates/ra_syntax/src/grammar.ron5
-rw-r--r--crates/ra_syntax/src/syntax_kinds/generated.rs3
-rw-r--r--crates/ra_syntax/src/syntax_kinds/generated.rs.tera5
-rw-r--r--editors/code/package.json2
-rw-r--r--editors/code/src/extension.ts47
9 files changed, 112 insertions, 47 deletions
diff --git a/.cargo/config b/.cargo/config
index 767045bdb..ac7470c7e 100644
--- a/.cargo/config
+++ b/.cargo/config
@@ -1,4 +1,5 @@
1[alias] 1[alias]
2# Automatically generates the ast and syntax kinds files
2gen-kinds = "run --package tools -- gen-kinds" 3gen-kinds = "run --package tools -- gen-kinds"
3gen-tests = "run --package tools -- gen-tests" 4gen-tests = "run --package tools -- gen-tests"
4install-code = "run --package tools -- install-code" 5install-code = "run --package tools -- install-code"
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 41954c02e..c952078cf 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,38 +1,58 @@
1The project is in its early stages: contributions are welcome and 1The project is in its early stages: contributions are welcome and would be
2would be **very** helpful, but the project is not *yet* optimized for 2**very** helpful, but the project is not _yet_ optimized for contribution.
3contribution. Moreover, it is doubly experimental, so there's no 3Moreover, it is doubly experimental, so there's no guarantee that any work here
4guarantee that any work here would reach production. That said, here 4would reach production. That said, here are some areas where contributions would
5are some areas where contributions would be **especially** welcome: 5be **especially** welcome:
6 6
7 7- Designing internal data structures: RFC only outlines the constraints, it's an
8* Designing internal data structures: RFC only outlines the 8 open question how to satisfy them in the optimal way. See `ARCHITECTURE.md`
9 constraints, it's an open question how to satisfy them in the 9 for current design questions.
10 optimal way. See `ARCHITECTURE.md` for current design questions. 10
11 11- Porting libsyntax parser to rust-analyzer: currently rust-analyzer parses only
12* Porting libsyntax parser to rust-analyzer: currently rust-analyzer parses 12 a tiny subset of Rust. This should be fixed by porting parsing functions from
13 only a tiny subset of Rust. This should be fixed by porting parsing 13 libsyntax one by one. Take a look at the [libsyntax parser] for "what to port"
14 functions from libsyntax one by one. Take a look at the 14 and at the [Kotlin parser] for "how to port".
15 [libsyntax parser](https://github.com/rust-lang/rust/blob/6b99adeb11313197f409b4f7c4083c2ceca8a4fe/src/libsyntax/parse/parser.rs) 15
16 for "what to port" and at the 16- Writing validators: by design, rust-analyzer is very lax about the input. For
17 [Kotlin parser](https://github.com/JetBrains/kotlin/blob/4d951de616b20feca92f3e9cc9679b2de9e65195/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinParsing.java) 17 example, the lexer happily accepts unclosed strings. The idea is that there
18 for "how to port". 18 should be a higher level visitor, which walks the syntax tree after parsing
19 19 and produces all the warnings. Alas, there's no such visitor yet :( Would you
20* Writing validators: by design, rust-analyzer is very lax about the 20 like to write one? :)
21 input. For example, the lexer happily accepts unclosed strings. The 21
22 idea is that there should be a higher level visitor, which walks the 22- Creating tests: it would be tremendously helpful to read each of libsyntax and
23 syntax tree after parsing and produces all the warnings. Alas, 23 rust-analyzer parser functions and crate a small separate test cases to cover
24 there's no such visitor yet :( Would you like to write one? :) 24 each and every edge case.
25 25
26* Creating tests: it would be tremendously helpful to read each of 26- Building stuff with rust-analyzer: it would be really cool to compile
27 libsyntax and rust-analyzer parser functions and crate a small separate 27 rust-analyzer to WASM and add _client side_ syntax validation to rust
28 test cases to cover each and every edge case.
29
30* Building stuff with rust-analyzer: it would be really cool to compile
31 rust-analyzer to WASM and add *client side* syntax validation to rust
32 playground! 28 playground!
33 29
34
35Do take a look at the issue tracker. 30Do take a look at the issue tracker.
36 31
37If you don't know where to start, or have *any* questions or suggestions, 32If you don't know where to start, or have _any_ questions or suggestions, don't
38don't hesitate to chat at [Gitter](https://gitter.im/libsyntax2/Lobby)! 33hesitate to chat at [Gitter]!
34
35# Code generation
36
37Some of the components of this repository are generated through automatic
38processes. These are outlined below:
39
40- `gen-kinds`: The kinds of tokens are reused in several places, so a generator
41 is used. This process uses [tera] to generate, using data in [grammar.ron],
42 the files:
43 - [ast/generated.rs][ast generated] in `ra_syntax` based on
44 [ast/generated.tera.rs][ast source]
45 - [syntax_kinds/generated.rs][syntax_kinds generated] in `ra_syntax` based on
46 [syntax_kinds/generated.tera.rs][syntax_kinds source]
47
48[libsyntax parser]:
49 https://github.com/rust-lang/rust/blob/6b99adeb11313197f409b4f7c4083c2ceca8a4fe/src/libsyntax/parse/parser.rs
50[kotlin parser]:
51 https://github.com/JetBrains/kotlin/blob/4d951de616b20feca92f3e9cc9679b2de9e65195/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinParsing.java
52[gitter]: https://gitter.im/libsyntax2/Lobby
53[tera]: https://tera.netlify.com/
54[grammar.ron]: ./crates/ra_syntax/src/grammar.ron
55[ast generated]: ./crates/ra_syntax/src/ast/generated.rs
56[ast source]: ./crates/ra_syntax/src/ast/generated.tera.rs
57[syntax_kinds generated]: ./crates/ra_syntax/src/syntax_kinds/generated.rs
58[syntax_kinds source]: ./crates/ra_syntax/src/syntax_kinds/generated.tera.rs
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index c945c094a..2db6dff1b 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -1,3 +1,6 @@
1// This file is automatically generated based on the file `./generated.rs.tera` when `cargo gen-kinds` is run
2// Do not edit manually
3
1use { 4use {
2 ast, 5 ast,
3 SyntaxNodeRef, AstNode, 6 SyntaxNodeRef, AstNode,
diff --git a/crates/ra_syntax/src/ast/generated.rs.tera b/crates/ra_syntax/src/ast/generated.rs.tera
index a72e9b732..ceb2cd7e2 100644
--- a/crates/ra_syntax/src/ast/generated.rs.tera
+++ b/crates/ra_syntax/src/ast/generated.rs.tera
@@ -1,3 +1,8 @@
1{# THIS File is not automatically generated:
2the below applies to the result of this template
3#}// This file is automatically generated based on the file `./generated.rs.tera` when `cargo gen-kinds` is run
4// Do not edit manually
5
1use { 6use {
2 ast, 7 ast,
3 SyntaxNodeRef, AstNode, 8 SyntaxNodeRef, AstNode,
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 77ae4c7db..4b990fd8d 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -1,3 +1,5 @@
1// Stores definitions which must be used in multiple places
2// See `cargo gen-kinds` (defined in crates/tools/src/main.rs)
1Grammar( 3Grammar(
2 single_byte_tokens: [ 4 single_byte_tokens: [
3 [";", "SEMI"], 5 [";", "SEMI"],
@@ -23,8 +25,9 @@ Grammar(
23 ["^", "CARET"], 25 ["^", "CARET"],
24 ["%", "PERCENT"], 26 ["%", "PERCENT"],
25 ], 27 ],
28 // TODO: Confirm surmision: the tokens which cannot be recorded in a single UTF-8 byte
26 multi_byte_tokens: [ 29 multi_byte_tokens: [
27 [".", "DOT"], 30 [".", "DOT"], // Note: DOT is here because <TODO: REASON>
28 ["..", "DOTDOT"], 31 ["..", "DOTDOT"],
29 ["...", "DOTDOTDOT"], 32 ["...", "DOTDOTDOT"],
30 ["..=", "DOTDOTEQ"], 33 ["..=", "DOTDOTEQ"],
diff --git a/crates/ra_syntax/src/syntax_kinds/generated.rs b/crates/ra_syntax/src/syntax_kinds/generated.rs
index 7882bded9..11e9150bb 100644
--- a/crates/ra_syntax/src/syntax_kinds/generated.rs
+++ b/crates/ra_syntax/src/syntax_kinds/generated.rs
@@ -1,3 +1,6 @@
1// This file is automatically generated based on the file `./generated.rs.tera` when `cargo gen-kinds` is run
2// Do not edit manually
3
1#![allow(bad_style, missing_docs, unreachable_pub)] 4#![allow(bad_style, missing_docs, unreachable_pub)]
2#![cfg_attr(rustfmt, rustfmt_skip)] 5#![cfg_attr(rustfmt, rustfmt_skip)]
3use super::SyntaxInfo; 6use super::SyntaxInfo;
diff --git a/crates/ra_syntax/src/syntax_kinds/generated.rs.tera b/crates/ra_syntax/src/syntax_kinds/generated.rs.tera
index 90618721a..018564b8a 100644
--- a/crates/ra_syntax/src/syntax_kinds/generated.rs.tera
+++ b/crates/ra_syntax/src/syntax_kinds/generated.rs.tera
@@ -1,3 +1,8 @@
1{# THIS File is not automatically generated:
2the below applies to the result of this template
3#}// This file is automatically generated based on the file `./generated.rs.tera` when `cargo gen-kinds` is run
4// Do not edit manually
5
1#![allow(bad_style, missing_docs, unreachable_pub)] 6#![allow(bad_style, missing_docs, unreachable_pub)]
2#![cfg_attr(rustfmt, rustfmt_skip)] 7#![cfg_attr(rustfmt, rustfmt_skip)]
3use super::SyntaxInfo; 8use super::SyntaxInfo;
diff --git a/editors/code/package.json b/editors/code/package.json
index 305d6eaf1..9f05fe91a 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -111,7 +111,7 @@
111 ], 111 ],
112 "configuration": { 112 "configuration": {
113 "type": "object", 113 "type": "object",
114 "title": "Rust Analyzer configuration", 114 "title": "Rust Analyzer",
115 "properties": { 115 "properties": {
116 "ra-lsp.highlightingOn": { 116 "ra-lsp.highlightingOn": {
117 "type": "boolean", 117 "type": "boolean",
diff --git a/editors/code/src/extension.ts b/editors/code/src/extension.ts
index dc1792e94..fde6a480d 100644
--- a/editors/code/src/extension.ts
+++ b/editors/code/src/extension.ts
@@ -11,10 +11,22 @@ let uris = {
11let highlightingOn = true; 11let highlightingOn = true;
12 12
13export function activate(context: vscode.ExtensionContext) { 13export function activate(context: vscode.ExtensionContext) {
14 let config = vscode.workspace.getConfiguration('ra-lsp'); 14 let applyHighlightingOn = () => {
15 if (config.has('highlightingOn')) { 15 let config = vscode.workspace.getConfiguration('ra-lsp');
16 highlightingOn = config.get('highlightingOn') as boolean; 16 if (config.has('highlightingOn')) {
17 } 17 highlightingOn = config.get('highlightingOn') as boolean;
18 };
19
20 if (!highlightingOn) {
21 removeHighlights();
22 }
23 };
24
25 // Apply the highlightingOn config now and whenever the config changes
26 applyHighlightingOn();
27 vscode.workspace.onDidChangeConfiguration(_ => {
28 applyHighlightingOn();
29 });
18 30
19 let textDocumentContentProvider = new TextDocumentContentProvider() 31 let textDocumentContentProvider = new TextDocumentContentProvider()
20 let dispose = (disposable: vscode.Disposable) => { 32 let dispose = (disposable: vscode.Disposable) => {
@@ -130,7 +142,7 @@ export function activate(context: vscode.ExtensionContext) {
130 }) 142 })
131 }, null, context.subscriptions) 143 }, null, context.subscriptions)
132 vscode.window.onDidChangeActiveTextEditor(async (editor) => { 144 vscode.window.onDidChangeActiveTextEditor(async (editor) => {
133 if (!editor || editor.document.languageId != 'rust') return 145 if (!highlightingOn || !editor || editor.document.languageId != 'rust') return
134 let params: lc.TextDocumentIdentifier = { 146 let params: lc.TextDocumentIdentifier = {
135 uri: editor.document.uri.toString() 147 uri: editor.document.uri.toString()
136 } 148 }
@@ -179,7 +191,7 @@ function startServer() {
179 let editor = vscode.window.visibleTextEditors.find( 191 let editor = vscode.window.visibleTextEditors.find(
180 (editor) => editor.document.uri.toString() == params.uri 192 (editor) => editor.document.uri.toString() == params.uri
181 ) 193 )
182 if (editor == null) return; 194 if (!highlightingOn || !editor) return;
183 setHighlights( 195 setHighlights(
184 editor, 196 editor,
185 params.decorations, 197 params.decorations,
@@ -213,10 +225,11 @@ class TextDocumentContentProvider implements vscode.TextDocumentContentProvider
213 } 225 }
214} 226}
215 227
228let decorations: { [index: string]: vscode.TextEditorDecorationType } = {};
216 229
217const decorations: { [index: string]: vscode.TextEditorDecorationType } = (() => { 230function initDecorations() {
218 const decor = (obj: any) => vscode.window.createTextEditorDecorationType({ color: obj }) 231 const decor = (obj: any) => vscode.window.createTextEditorDecorationType({ color: obj })
219 return { 232 decorations = {
220 background: decor("#3F3F3F"), 233 background: decor("#3F3F3F"),
221 error: vscode.window.createTextEditorDecorationType({ 234 error: vscode.window.createTextEditorDecorationType({
222 borderColor: "red", 235 borderColor: "red",
@@ -232,14 +245,26 @@ const decorations: { [index: string]: vscode.TextEditorDecorationType } = (() =>
232 attribute: decor("#BFEBBF"), 245 attribute: decor("#BFEBBF"),
233 literal: decor("#DFAF8F"), 246 literal: decor("#DFAF8F"),
234 } 247 }
235})() 248}
249
250function removeHighlights() {
251 for (let tag in decorations) {
252 decorations[tag].dispose();
253 }
254
255 decorations = {};
256}
236 257
237function setHighlights( 258function setHighlights(
238 editor: vscode.TextEditor, 259 editor: vscode.TextEditor,
239 highlights: Array<Decoration> 260 highlights: Array<Decoration>
240) { 261) {
241 if (!highlightingOn) { 262 // Initialize decorations if necessary
242 return; 263 //
264 // Note: decoration objects need to be kept around so we can dispose them
265 // if the user disables syntax highlighting
266 if (Object.keys(decorations).length === 0) {
267 initDecorations();
243 } 268 }
244 269
245 let byTag: Map<string, vscode.Range[]> = new Map() 270 let byTag: Map<string, vscode.Range[]> = new Map()