ace-linters 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -40
- package/components/description-tooltip.ts +37 -30
- package/index.ts +1 -3
- package/language-provider.ts +68 -22
- package/message-controller-ws.ts +95 -99
- package/message-controller.ts +12 -12
- package/message-types.ts +30 -12
- package/package.json +2 -1
- package/services/base-service.ts +38 -69
- package/services/css/css-service.ts +29 -42
- package/services/html/html-service.ts +24 -36
- package/services/json/json-service.ts +39 -51
- package/services/lua/lua-service.ts +20 -15
- package/services/service-manager.ts +43 -38
- package/services/typescript/typescript-service.ts +42 -40
- package/type-converters/common-converters.ts +34 -0
- package/type-converters/lsp-converters.ts +69 -31
- package/type-converters/typescript-converters.ts +51 -49
- package/types/index.d.ts +0 -4
- package/types/language-service.d.ts +19 -19
- package/types/message-controller-interface.d.ts +8 -8
- package/build/ace-linters.js +0 -33007
- package/build/css-service.js +0 -73636
- package/build/html-service.js +0 -51337
- package/build/json-service.js +0 -41679
- package/build/lua-service.js +0 -3017
- package/build/service-manager.js +0 -1994
- package/build/typescript-service.js +0 -192262
package/README.md
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# Ace Linters (Ace Language Client)
|
|
2
2
|
|
|
3
|
-
Ace linters is a library that brings language-aware features to the Ace editor. It includes a number of language
|
|
3
|
+
Ace linters is a library that brings language-aware features to the Ace editor. It includes a number of language
|
|
4
|
+
services, each of which provides support for a specific language, such as JSON, HTML, CSS, and Typescript.
|
|
4
5
|
|
|
5
6
|
Ace linters works in two modes: **WebSockets** and **WebWorkers**.
|
|
6
7
|
|
|
7
8
|
## Features
|
|
8
9
|
|
|
9
10
|
With Ace linters, you can easily add the following language-aware features to your Ace editor:
|
|
11
|
+
|
|
10
12
|
- Error checking
|
|
11
13
|
- Code completion
|
|
12
14
|
- Type checking
|
|
@@ -16,6 +18,7 @@ With Ace linters, you can easily add the following language-aware features to yo
|
|
|
16
18
|
## Supported languages
|
|
17
19
|
|
|
18
20
|
Ace linters supports the following languages by default with webworkers approach:
|
|
21
|
+
|
|
19
22
|
- JSON, JSON5 (with JsonService)
|
|
20
23
|
- HTML (with HtmlService)
|
|
21
24
|
- CSS, SCSS, LESS (with CssService)
|
|
@@ -23,6 +26,7 @@ Ace linters supports the following languages by default with webworkers approach
|
|
|
23
26
|
- Lua (with LuaService)
|
|
24
27
|
|
|
25
28
|
For WebSockets you could connect any of your Language Server folowing LSP
|
|
29
|
+
|
|
26
30
|
## Installation
|
|
27
31
|
|
|
28
32
|
To install Ace linters, you can use the following command:
|
|
@@ -31,29 +35,32 @@ To install Ace linters, you can use the following command:
|
|
|
31
35
|
npm install ace-linters
|
|
32
36
|
```
|
|
33
37
|
|
|
34
|
-
## Usage with WebWorker
|
|
38
|
+
## Usage with WebWorker (JSON-RPC)
|
|
35
39
|
|
|
36
40
|
To use Ace linters with WebWorker, you will first need to include it in your project and create an instance of the Ace
|
|
37
|
-
editor
|
|
38
|
-
and
|
|
39
|
-
an instance of LanguageProvider. Then, LanguageProvider will use the appropriate language service based on the mode being used:
|
|
41
|
+
editor and an instance of LanguageProvider.
|
|
40
42
|
|
|
41
43
|
*client.js*:
|
|
44
|
+
|
|
42
45
|
```javascript
|
|
43
46
|
import * as ace from "ace-code";
|
|
44
47
|
import {Mode as TypescriptMode} from "ace-code/src/mode/typescript";
|
|
45
|
-
import {registerStyles, LanguageProvider
|
|
46
|
-
import {
|
|
48
|
+
import {registerStyles, LanguageProvider} from "ace-linters";
|
|
49
|
+
import {ScriptTarget, JsxEmit} from "ace-linters/type-converters/typescript-converters";
|
|
47
50
|
|
|
48
|
-
//
|
|
49
|
-
registerStyles();
|
|
50
|
-
|
|
51
|
-
// Create a web worker and a message controller
|
|
51
|
+
// Create a web worker
|
|
52
52
|
let worker = new Worker(new URL('./webworker.js', import.meta.url));
|
|
53
|
-
|
|
53
|
+
|
|
54
|
+
// Create an Ace editor
|
|
55
|
+
let editor = ace.edit("container", {
|
|
56
|
+
mode: new TypescriptMode() // Set the mode of the editor to Typescript
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Create a language provider for web worker
|
|
60
|
+
let languageProvider = LanguageProvider.for(worker);
|
|
54
61
|
|
|
55
62
|
// Set global options for the Typescript service
|
|
56
|
-
|
|
63
|
+
languageProvider.setGlobalOptions("typescript", {
|
|
57
64
|
compilerOptions: {
|
|
58
65
|
allowJs: true,
|
|
59
66
|
target: ScriptTarget.ESNext,
|
|
@@ -61,25 +68,19 @@ messageController.setGlobalOptions("typescript", {
|
|
|
61
68
|
}
|
|
62
69
|
});
|
|
63
70
|
|
|
64
|
-
// Create an Ace editor
|
|
65
|
-
let editor = ace.edit("container");
|
|
66
|
-
|
|
67
|
-
// Set the mode of the editor to Typescript
|
|
68
|
-
editor.session.setMode(new TypescriptMode());
|
|
69
|
-
|
|
70
|
-
// Create a language provider
|
|
71
|
-
let languageProvider = new LanguageProvider(messageController);
|
|
72
|
-
|
|
73
71
|
// Register the editor with the language provider
|
|
74
72
|
languageProvider.registerEditor(editor);
|
|
75
73
|
|
|
76
74
|
```
|
|
75
|
+
|
|
77
76
|
In WebWorkers mode, you need to register
|
|
78
77
|
services on the webworker side. Like this:
|
|
79
78
|
|
|
80
79
|
*webworker.js*
|
|
80
|
+
|
|
81
81
|
```javascript
|
|
82
82
|
import {ServiceManager} from "ace-linters/services/service-manager";
|
|
83
|
+
|
|
83
84
|
let manager = new ServiceManager(self);
|
|
84
85
|
manager.registerService("typescript", {
|
|
85
86
|
module: () => import("ace-linters/services/typescript/typescript-service"),
|
|
@@ -88,37 +89,31 @@ manager.registerService("typescript", {
|
|
|
88
89
|
});
|
|
89
90
|
```
|
|
90
91
|
|
|
91
|
-
[Example client](https://github.com/mkslanc/ace-linters/blob/main/packages/demo/webworker-
|
|
92
|
+
[Example client](https://github.com/mkslanc/ace-linters/blob/main/packages/demo/webworker-json-rpc/demo.ts)
|
|
92
93
|
|
|
93
|
-
[Example web worker](https://github.com/mkslanc/ace-linters/blob/main/packages/demo/webworker-
|
|
94
|
+
[Example web worker](https://github.com/mkslanc/ace-linters/blob/main/packages/demo/webworker-json-rpc/webworker.ts)
|
|
95
|
+
|
|
96
|
+
## Usage with WebSocket (JSON-RPC)
|
|
94
97
|
|
|
95
|
-
## Usage with WebSocket
|
|
96
98
|
In WebSockets mode, you need to start a language server on any port and connect to it.
|
|
97
99
|
|
|
98
100
|
Here's an example client:
|
|
101
|
+
|
|
99
102
|
```javascript
|
|
100
103
|
import * as ace from "ace-code";
|
|
101
104
|
import {Mode as JSONMode} from "ace-code/src/mode/json"; //any mode you want
|
|
102
|
-
import {
|
|
103
|
-
import { ScriptTarget, JsxEmit } from "ace-linters/type-converters/typescript-converters";
|
|
104
|
-
|
|
105
|
-
// Register custom styles for the hover tooltip
|
|
106
|
-
registerStyles();
|
|
105
|
+
import {LanguageProvider} from "ace-linters";
|
|
107
106
|
|
|
108
|
-
// Create a web socket
|
|
107
|
+
// Create a web socket
|
|
109
108
|
const webSocket = new WebSocket("ws://localhost:3000/exampleServer"); // adress of your websocket server
|
|
110
109
|
|
|
111
|
-
//Message controller for web sockets
|
|
112
|
-
let messageController = new MessageControllerWS(webSocket);
|
|
113
|
-
|
|
114
110
|
// Create an Ace editor
|
|
115
|
-
let editor = ace.edit("container"
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
editor.session.setMode(new JSONMode());
|
|
111
|
+
let editor = ace.edit("container", {
|
|
112
|
+
mode: new JSONMode() // Set the mode of the editor to JSON
|
|
113
|
+
});
|
|
119
114
|
|
|
120
|
-
// Create a language provider
|
|
121
|
-
let languageProvider =
|
|
115
|
+
// Create a language provider for web socket
|
|
116
|
+
let languageProvider = LanguageProvider.for(webSocket);
|
|
122
117
|
|
|
123
118
|
// Register the editor with the language provider
|
|
124
119
|
languageProvider.registerEditor(editor);
|
|
@@ -127,5 +122,11 @@ languageProvider.registerEditor(editor);
|
|
|
127
122
|
[Example client](https://github.com/mkslanc/ace-linters/blob/main/packages/demo/websockets-lsp/client.ts)
|
|
128
123
|
|
|
129
124
|
[Example server](https://github.com/mkslanc/ace-linters/tree/main/packages/demo/websockets-lsp/server)
|
|
125
|
+
|
|
126
|
+
## Usage with WebWorker (other format)
|
|
127
|
+
|
|
128
|
+
You can use Ace linters with pre-defined services by looking at the "Ace linters with WebWorker demo (with default services)" example on GitHub:
|
|
129
|
+
[Example](https://github.com/mkslanc/ace-linters/blob/main/packages/demo/webworker-lsp/)
|
|
130
130
|
## License
|
|
131
|
+
|
|
131
132
|
Ace linters is released under the [MIT License](https://opensource.org/licenses/MIT).
|
|
@@ -20,7 +20,7 @@ export class DescriptionTooltip extends Tooltip {
|
|
|
20
20
|
this.provider = provider;
|
|
21
21
|
Tooltip.call(this, document.body);
|
|
22
22
|
|
|
23
|
-
event.addListener(this.getElement(), "mouseout", this.
|
|
23
|
+
event.addListener(this.getElement(), "mouseout", this.onMouseOut);
|
|
24
24
|
|
|
25
25
|
this.getElement().style.pointerEvents = "auto";
|
|
26
26
|
this.getElement().style.whiteSpace = "pre-wrap";
|
|
@@ -30,14 +30,25 @@ export class DescriptionTooltip extends Tooltip {
|
|
|
30
30
|
editor.on("mousemove", this.onMouseMove);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
private $
|
|
33
|
+
private $activateEditor(editor: Ace.Editor) {
|
|
34
34
|
this.$activeEditor = editor;
|
|
35
|
-
editor.on("change", this.$hide);
|
|
36
|
-
editor.on("mousewheel", this.$hide);
|
|
37
|
-
//@ts-ignore
|
|
38
|
-
editor.on("mousedown", this.$hide);
|
|
39
35
|
|
|
40
|
-
|
|
36
|
+
this.$activeEditor.container.addEventListener("mouseout", this.onMouseOut);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private $inactivateEditor() {
|
|
40
|
+
if (!this.$activeEditor)
|
|
41
|
+
return;
|
|
42
|
+
this.$activeEditor.container.removeEventListener("mouseout", this.onMouseOut);
|
|
43
|
+
|
|
44
|
+
this.$activeEditor = null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private $registerEditorEvents() {
|
|
48
|
+
this.$activeEditor.on("change", this.$hide);
|
|
49
|
+
this.$activeEditor.on("mousewheel", this.$hide);
|
|
50
|
+
//@ts-ignore
|
|
51
|
+
this.$activeEditor.on("mousedown", this.$hide);
|
|
41
52
|
}
|
|
42
53
|
|
|
43
54
|
private $removeEditorEvents() {
|
|
@@ -46,7 +57,7 @@ export class DescriptionTooltip extends Tooltip {
|
|
|
46
57
|
//@ts-ignore
|
|
47
58
|
this.$activeEditor.off("mousedown", this.$hide);
|
|
48
59
|
|
|
49
|
-
this.$activeEditor.container.removeEventListener("mouseout", this.
|
|
60
|
+
this.$activeEditor.container.removeEventListener("mouseout", this.onMouseOut);
|
|
50
61
|
this.$activeEditor = null;
|
|
51
62
|
}
|
|
52
63
|
|
|
@@ -54,24 +65,23 @@ export class DescriptionTooltip extends Tooltip {
|
|
|
54
65
|
clearTimeout(this.$mouseMoveTimer);
|
|
55
66
|
clearTimeout(this.$showTimer);
|
|
56
67
|
if (this.isOpen) {
|
|
57
|
-
this.doHover(
|
|
68
|
+
this.doHover();
|
|
58
69
|
} else {
|
|
59
70
|
this.$mouseMoveTimer = setTimeout(() => {
|
|
60
|
-
this
|
|
71
|
+
this.$inactivateEditor();
|
|
72
|
+
this.$activateEditor(editor);
|
|
73
|
+
this.doHover();
|
|
61
74
|
this.$mouseMoveTimer = null;
|
|
62
75
|
}, 500);
|
|
63
76
|
|
|
64
77
|
}
|
|
65
78
|
};
|
|
66
79
|
|
|
67
|
-
doHover = (
|
|
68
|
-
|
|
69
|
-
console.log(editor);
|
|
70
|
-
}
|
|
71
|
-
let renderer = editor.renderer;
|
|
80
|
+
doHover = () => {
|
|
81
|
+
let renderer = this.$activeEditor.renderer;
|
|
72
82
|
let screenPos = renderer.pixelToScreenCoordinates(this.x, this.y);
|
|
73
83
|
|
|
74
|
-
let session =
|
|
84
|
+
let session = this.$activeEditor.session;
|
|
75
85
|
|
|
76
86
|
this.provider.doHover(session, screenPos, (hover) => {
|
|
77
87
|
let description = this.provider.getTooltipText(hover);
|
|
@@ -99,21 +109,21 @@ export class DescriptionTooltip extends Tooltip {
|
|
|
99
109
|
this.column = column;
|
|
100
110
|
|
|
101
111
|
if (this.$mouseMoveTimer) {
|
|
102
|
-
this.$show(
|
|
112
|
+
this.$show();
|
|
103
113
|
} else {
|
|
104
114
|
this.$showTimer = setTimeout(() => {
|
|
105
|
-
this.$show(
|
|
115
|
+
this.$show();
|
|
106
116
|
this.$showTimer = null;
|
|
107
117
|
}, 500);
|
|
108
118
|
}
|
|
109
119
|
});
|
|
110
120
|
}
|
|
111
121
|
|
|
112
|
-
$show = (
|
|
113
|
-
let renderer =
|
|
122
|
+
$show = () => {
|
|
123
|
+
let renderer = this.$activeEditor.renderer;
|
|
114
124
|
let position = renderer.textToScreenCoordinates(this.row, this.column);
|
|
115
125
|
|
|
116
|
-
let cursorPos =
|
|
126
|
+
let cursorPos = this.$activeEditor.getCursorPosition();
|
|
117
127
|
|
|
118
128
|
this.show(null, position.pageX, position.pageY);
|
|
119
129
|
|
|
@@ -138,7 +148,7 @@ export class DescriptionTooltip extends Tooltip {
|
|
|
138
148
|
else
|
|
139
149
|
position.pageY += renderer.lineHeight;
|
|
140
150
|
|
|
141
|
-
this.$registerEditorEvents(
|
|
151
|
+
this.$registerEditorEvents();
|
|
142
152
|
|
|
143
153
|
this.getElement().style.maxWidth = rect.width - (position.pageX - rect.left) + "px";
|
|
144
154
|
this.show(null, position.pageX, position.pageY);
|
|
@@ -151,12 +161,8 @@ export class DescriptionTooltip extends Tooltip {
|
|
|
151
161
|
};
|
|
152
162
|
|
|
153
163
|
onMouseOut = (e: MouseEvent) => {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
this.$hide();
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
onTooltipMouseOut = (e: MouseEvent) => {
|
|
164
|
+
clearTimeout(this.$mouseMoveTimer);
|
|
165
|
+
clearTimeout(this.$showTimer);
|
|
160
166
|
if (!e.relatedTarget || e.relatedTarget == this.getElement())
|
|
161
167
|
return;
|
|
162
168
|
|
|
@@ -169,14 +175,15 @@ export class DescriptionTooltip extends Tooltip {
|
|
|
169
175
|
}
|
|
170
176
|
|
|
171
177
|
$hide = () => {
|
|
172
|
-
clearTimeout(this.$
|
|
178
|
+
clearTimeout(this.$mouseMoveTimer);
|
|
179
|
+
clearTimeout(this.$showTimer);
|
|
173
180
|
this.$removeEditorEvents();
|
|
174
181
|
this.hide();
|
|
175
182
|
}
|
|
176
183
|
|
|
177
184
|
destroy() {
|
|
178
185
|
this.$hide();
|
|
179
|
-
event.removeListener(this.getElement(), "mouseout", this.
|
|
186
|
+
event.removeListener(this.getElement(), "mouseout", this.onMouseOut);
|
|
180
187
|
};
|
|
181
188
|
|
|
182
189
|
}
|
package/index.ts
CHANGED
|
@@ -2,9 +2,7 @@ import {MessageController} from "./message-controller";
|
|
|
2
2
|
import * as lintersCSS from "./css/linters.css";
|
|
3
3
|
import * as dom from "ace-code/src/lib/dom";
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
dom.importCssString(lintersCSS, "linters.css");
|
|
7
|
-
}
|
|
5
|
+
dom.importCssString(lintersCSS, "linters.css");
|
|
8
6
|
|
|
9
7
|
export {LanguageProvider} from "./language-provider";
|
|
10
8
|
export {MessageController} from "./message-controller";
|
package/language-provider.ts
CHANGED
|
@@ -2,7 +2,6 @@ import {Ace, Range as AceRange} from "ace-code";
|
|
|
2
2
|
import {DescriptionTooltip} from "./components/description-tooltip";
|
|
3
3
|
import {AceLinters} from "./types";
|
|
4
4
|
import Tooltip = AceLinters.Tooltip;
|
|
5
|
-
import TextEdit = AceLinters.TextEdit;
|
|
6
5
|
import {FormattingOptions} from "vscode-languageserver-protocol";
|
|
7
6
|
import {MarkDownConverter} from "./types";
|
|
8
7
|
import {CommonConverter} from "./type-converters/common-converters";
|
|
@@ -11,7 +10,20 @@ import ServiceOptions = AceLinters.ServiceOptions;
|
|
|
11
10
|
import Editor = Ace.Editor;
|
|
12
11
|
import EditSession = Ace.EditSession;
|
|
13
12
|
import Completion = Ace.Completion;
|
|
14
|
-
import
|
|
13
|
+
import {MessageControllerWS} from "./message-controller-ws";
|
|
14
|
+
import ServiceOptionsMap = AceLinters.ServiceOptionsMap;
|
|
15
|
+
import {MessageController} from "./message-controller";
|
|
16
|
+
import {
|
|
17
|
+
fromAceDelta,
|
|
18
|
+
fromPoint,
|
|
19
|
+
fromRange,
|
|
20
|
+
toAnnotations,
|
|
21
|
+
toCompletionItem,
|
|
22
|
+
toCompletions,
|
|
23
|
+
toRange, toResolvedCompletion,
|
|
24
|
+
toTooltip
|
|
25
|
+
} from "./type-converters/lsp-converters";
|
|
26
|
+
import * as lsp from "vscode-languageserver-protocol";
|
|
15
27
|
|
|
16
28
|
let showdown = require('showdown');
|
|
17
29
|
|
|
@@ -20,15 +32,37 @@ export class LanguageProvider {
|
|
|
20
32
|
private $descriptionTooltip: DescriptionTooltip;
|
|
21
33
|
private readonly $markdownConverter: MarkDownConverter;
|
|
22
34
|
private readonly $messageController: IMessageController;
|
|
23
|
-
private $sessionLanguageProviders: {[sessionID: string]: SessionLanguageProvider} = {};
|
|
35
|
+
private $sessionLanguageProviders: { [sessionID: string]: SessionLanguageProvider } = {};
|
|
24
36
|
private $editors: Editor[] = [];
|
|
25
37
|
|
|
26
|
-
constructor(messageController: IMessageController, markdownConverter?: MarkDownConverter) {
|
|
38
|
+
private constructor(messageController: IMessageController, markdownConverter?: MarkDownConverter) {
|
|
27
39
|
this.$messageController = messageController;
|
|
28
40
|
this.$markdownConverter = markdownConverter ?? new showdown.Converter();
|
|
29
41
|
this.$descriptionTooltip = new DescriptionTooltip(this);
|
|
30
42
|
}
|
|
31
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Creates LanguageProvider for any Language Server to connect with JSON-RPC (webworker, websocket)
|
|
46
|
+
* @param {Worker | WebSocket} mode
|
|
47
|
+
* @param markdownConverter
|
|
48
|
+
*/
|
|
49
|
+
static for(mode: Worker | WebSocket, markdownConverter?: MarkDownConverter) { //TODO:
|
|
50
|
+
let messageController = new MessageControllerWS(mode);
|
|
51
|
+
return new LanguageProvider(messageController, markdownConverter);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Creates LanguageProvider using our transport protocol with ability to register different services on same
|
|
56
|
+
* webworker
|
|
57
|
+
* @param {Worker} worker
|
|
58
|
+
* @param markdownConverter
|
|
59
|
+
*/
|
|
60
|
+
static default(worker: Worker, markdownConverter?: MarkDownConverter) {
|
|
61
|
+
let messageController: IMessageController;
|
|
62
|
+
messageController = new MessageController(worker);
|
|
63
|
+
return new LanguageProvider(messageController, markdownConverter);
|
|
64
|
+
}
|
|
65
|
+
|
|
32
66
|
private $registerSession = (session?: EditSession, options?: ServiceOptions) => {
|
|
33
67
|
if (!session)
|
|
34
68
|
return;
|
|
@@ -66,14 +100,19 @@ export class LanguageProvider {
|
|
|
66
100
|
sessionLanguageProvider.setOptions(options);
|
|
67
101
|
}
|
|
68
102
|
|
|
103
|
+
setGlobalOptions<T extends keyof ServiceOptionsMap>(serviceName: T, options: ServiceOptionsMap[T], merge = false) {
|
|
104
|
+
this.$messageController.setGlobalOptions(serviceName, options, merge);
|
|
105
|
+
}
|
|
106
|
+
|
|
69
107
|
doHover(session: EditSession, position: Ace.Point, callback?: (hover: Tooltip) => void) {
|
|
70
|
-
this.$messageController.doHover(this.$getFileName(session), position, callback);
|
|
108
|
+
this.$messageController.doHover(this.$getFileName(session), fromPoint(position), (hover) => callback(toTooltip(hover)));
|
|
71
109
|
}
|
|
72
110
|
|
|
73
111
|
getTooltipText(hover: Tooltip) {
|
|
74
112
|
if (!hover)
|
|
75
113
|
return;
|
|
76
|
-
let text = hover.content.type === CommonConverter.TooltipType.markdown ?
|
|
114
|
+
let text = hover.content.type === CommonConverter.TooltipType.markdown ?
|
|
115
|
+
CommonConverter.cleanHtml(this.$markdownConverter.makeHtml(hover.content.text)) : hover.content.text;
|
|
77
116
|
return {text: text, range: hover.range}
|
|
78
117
|
}
|
|
79
118
|
|
|
@@ -82,9 +121,10 @@ export class LanguageProvider {
|
|
|
82
121
|
sessionLanguageProvider.format();
|
|
83
122
|
}
|
|
84
123
|
|
|
85
|
-
doComplete(editor: Editor, session: EditSession, callback: (CompletionList: Completion[]) => void) {
|
|
124
|
+
doComplete(editor: Editor, session: EditSession, callback: (CompletionList: Completion[] | null) => void) {
|
|
86
125
|
let cursor = editor.getCursorPosition();
|
|
87
|
-
this.$messageController.doComplete(this.$getFileName(session), cursor,
|
|
126
|
+
this.$messageController.doComplete(this.$getFileName(session), fromPoint(cursor),
|
|
127
|
+
(completionList) => callback(toCompletions(completionList)));
|
|
88
128
|
}
|
|
89
129
|
|
|
90
130
|
$registerCompleters(editor: Editor) {
|
|
@@ -93,14 +133,17 @@ export class LanguageProvider {
|
|
|
93
133
|
getCompletions: async (editor, session, pos, prefix, callback) => {
|
|
94
134
|
this.doComplete(editor, session, (completions) => {
|
|
95
135
|
let fileName = this.$getFileName(session);
|
|
136
|
+
if (!completions)
|
|
137
|
+
return;
|
|
96
138
|
completions.forEach((item) => item["fileName"] = fileName);
|
|
97
139
|
callback(null, CommonConverter.normalizeRanges(completions));
|
|
98
140
|
});
|
|
99
141
|
},
|
|
100
142
|
getDocTooltip: (item) => {
|
|
101
143
|
if (!item["isResolved"]) {
|
|
102
|
-
this.$messageController.doResolve(item["fileName"], item, (
|
|
144
|
+
this.$messageController.doResolve(item["fileName"], toCompletionItem(item), (completionItem) => {
|
|
103
145
|
item["isResolved"] = true;
|
|
146
|
+
let completion = toResolvedCompletion(item, completionItem);
|
|
104
147
|
item.docText = completion.docText;
|
|
105
148
|
if (completion.docHTML) {
|
|
106
149
|
item.docHTML = completion.docHTML;
|
|
@@ -139,12 +182,14 @@ class SessionLanguageProvider {
|
|
|
139
182
|
this.$messageController = messageController;
|
|
140
183
|
this.session = session;
|
|
141
184
|
this.initFileName();
|
|
185
|
+
|
|
186
|
+
session.doc["version"] = 0;
|
|
142
187
|
session.doc.on("change", this.$changeListener, true);
|
|
143
188
|
|
|
144
189
|
// @ts-ignore
|
|
145
190
|
session.on("changeMode", this.$changeMode);
|
|
146
191
|
|
|
147
|
-
this.$messageController.init(this.fileName, session.
|
|
192
|
+
this.$messageController.init(this.fileName, session.doc, this.$mode, options, this.$connected, this.$showAnnotations);
|
|
148
193
|
}
|
|
149
194
|
|
|
150
195
|
private $connected = () => {
|
|
@@ -187,13 +232,12 @@ class SessionLanguageProvider {
|
|
|
187
232
|
}
|
|
188
233
|
|
|
189
234
|
private $changeListener = (delta) => {
|
|
235
|
+
this.session.doc["version"]++;
|
|
190
236
|
if (!this.$deltaQueue) {
|
|
191
237
|
this.$deltaQueue = [];
|
|
192
238
|
setTimeout(this.$sendDeltaQueue, 0);
|
|
193
239
|
}
|
|
194
|
-
|
|
195
|
-
this.$deltaQueue.push(delta.start, delta.lines);
|
|
196
|
-
else this.$deltaQueue.push(delta.start, delta.end);
|
|
240
|
+
this.$deltaQueue.push(delta);
|
|
197
241
|
}
|
|
198
242
|
|
|
199
243
|
private $sendDeltaQueue = () => {
|
|
@@ -201,11 +245,13 @@ class SessionLanguageProvider {
|
|
|
201
245
|
if (!deltas) return;
|
|
202
246
|
this.$deltaQueue = null;
|
|
203
247
|
if (deltas.length)
|
|
204
|
-
this.$messageController.change(this.fileName, deltas
|
|
248
|
+
this.$messageController.change(this.fileName, deltas.map((delta) =>
|
|
249
|
+
fromAceDelta(delta, this.session.doc.getNewLineCharacter())), this.session.doc);
|
|
205
250
|
};
|
|
206
251
|
|
|
207
|
-
private $showAnnotations = (
|
|
252
|
+
private $showAnnotations = (diagnostics) => {
|
|
208
253
|
this.session.clearAnnotations();
|
|
254
|
+
let annotations = toAnnotations(diagnostics)
|
|
209
255
|
if (annotations && annotations.length > 0) {
|
|
210
256
|
this.session.setAnnotations(annotations);
|
|
211
257
|
}
|
|
@@ -232,19 +278,19 @@ class SessionLanguageProvider {
|
|
|
232
278
|
selectionRanges = [new AceRange(0, 0, row, column)];
|
|
233
279
|
}
|
|
234
280
|
for (let range of selectionRanges) {
|
|
235
|
-
this.$messageController.format(this.fileName, range, $format, this.$applyFormat);
|
|
281
|
+
this.$messageController.format(this.fileName, fromRange(range), $format, this.$applyFormat);
|
|
236
282
|
}
|
|
237
283
|
}
|
|
238
284
|
|
|
239
|
-
private $applyFormat = (edits: TextEdit[]) => {
|
|
240
|
-
for (let edit of edits) {
|
|
241
|
-
this.session.doc.replace(
|
|
242
|
-
// mirror Range
|
|
285
|
+
private $applyFormat = (edits: lsp.TextEdit[]) => {
|
|
286
|
+
for (let edit of edits.reverse()) {
|
|
287
|
+
this.session.doc.replace(toRange(edit.range), edit.newText);
|
|
243
288
|
}
|
|
244
289
|
}
|
|
245
290
|
|
|
246
291
|
doComplete(editor: Editor, callback: (CompletionList) => void) {
|
|
247
292
|
let cursor = editor.getCursorPosition();
|
|
248
|
-
this.$messageController.doComplete(this.fileName, cursor,
|
|
293
|
+
this.$messageController.doComplete(this.fileName, fromPoint(cursor),
|
|
294
|
+
(completionList) => callback(toCompletions(completionList)));
|
|
249
295
|
}
|
|
250
|
-
}
|
|
296
|
+
}
|