Get ts-plugin working with Emacs and LSP
This commit is contained in:
parent
78834dfb07
commit
edbe7bcdac
|
@ -1,6 +1,17 @@
|
||||||
((typescript-mode
|
((typescript-mode
|
||||||
. ((eval . (setq tide-tsserver-executable
|
. ((eval
|
||||||
|
. (progn
|
||||||
|
;; For TIDE:
|
||||||
|
(setq tide-tsserver-executable
|
||||||
(concat
|
(concat
|
||||||
(let ((d (dir-locals-find-file ".")))
|
(let ((d (dir-locals-find-file ".")))
|
||||||
(if (stringp d) d (car d)))
|
(if (stringp d) d (car d)))
|
||||||
"node_modules/typescript/lib/tsserver.js"))))))
|
"node_modules/typescript/lib/tsserver.js"))
|
||||||
|
;; For LSP:
|
||||||
|
(require 'lsp-javascript)
|
||||||
|
(lsp-dependency 'typescript
|
||||||
|
`(:system ,(concat
|
||||||
|
(let ((d (dir-locals-find-file ".")))
|
||||||
|
(if (stringp d) d (car d)))
|
||||||
|
"node_modules/typescript/lib/tsserver.js"))))
|
||||||
|
))))
|
||||||
|
|
|
@ -45,7 +45,7 @@ a `typescript/` subdirectory.
|
||||||
|
|
||||||
If no such `typescript/` subdirectory exists in `node_modules`, then
|
If no such `typescript/` subdirectory exists in `node_modules`, then
|
||||||
because
|
because
|
||||||
[tsserver loads plugins from relative to tsserver.js rather than tsconfig.json](https://github.com/microsoft/TypeScript/issues/42688),
|
[tsserver loads plugins from relative to tsserver.js rather than tsconfig.json][tsserver-plugin-loading-problem],
|
||||||
you will have to tell `tide-mode` about where your project's
|
you will have to tell `tide-mode` about where your project's
|
||||||
`tsserver` lives.
|
`tsserver` lives.
|
||||||
|
|
||||||
|
@ -82,6 +82,52 @@ If you use the `.dir-locals.el` methods, you may need to run
|
||||||
`tide-restart-server` once after opening the first TypeScript file in
|
`tide-restart-server` once after opening the first TypeScript file in
|
||||||
your project (and then close and re-open that TypeScript file).
|
your project (and then close and re-open that TypeScript file).
|
||||||
|
|
||||||
|
### Emacs with LSP
|
||||||
|
|
||||||
|
LSP will, by default, use its own `tsserver`, no matter what is in the
|
||||||
|
local `node_modules`. Because of the [issue with tsserver's approach
|
||||||
|
to plugin loading][tsserver-plugin-loading-problem], this means that
|
||||||
|
by default it will not load the Syndicate plugin.
|
||||||
|
|
||||||
|
Overriding the `tsserver` location is similar to the way it's done for
|
||||||
|
Tide, but instead of a variable value change, a function has to be
|
||||||
|
called. One good way to do it is to use `.dir-locals.el`, as above:
|
||||||
|
|
||||||
|
```elisp
|
||||||
|
((typescript-mode
|
||||||
|
. ((eval . (progn
|
||||||
|
(require 'lsp-javascript)
|
||||||
|
(lsp-dependency
|
||||||
|
'typescript
|
||||||
|
`(:system ,(concat
|
||||||
|
(let ((d (dir-locals-find-file ".")))
|
||||||
|
(if (stringp d) d (car d)))
|
||||||
|
"node_modules/typescript/lib/tsserver.js"))))))))
|
||||||
|
```
|
||||||
|
|
||||||
|
And, of course, you can make changes for both Tide and LSP at once, if
|
||||||
|
you like:
|
||||||
|
|
||||||
|
```elisp
|
||||||
|
((typescript-mode
|
||||||
|
. ((eval
|
||||||
|
. (progn
|
||||||
|
;; For TIDE:
|
||||||
|
(setq tide-tsserver-executable
|
||||||
|
(concat
|
||||||
|
(let ((d (dir-locals-find-file ".")))
|
||||||
|
(if (stringp d) d (car d)))
|
||||||
|
"node_modules/typescript/lib/tsserver.js"))
|
||||||
|
;; For LSP:
|
||||||
|
(require 'lsp-javascript)
|
||||||
|
(lsp-dependency 'typescript
|
||||||
|
`(:system ,(concat
|
||||||
|
(let ((d (dir-locals-find-file ".")))
|
||||||
|
(if (stringp d) d (car d)))
|
||||||
|
"node_modules/typescript/lib/tsserver.js"))))
|
||||||
|
))))
|
||||||
|
```
|
||||||
|
|
||||||
### Visual Studio Code
|
### Visual Studio Code
|
||||||
|
|
||||||
After `yarn install`, if you have a `node_modules/typescript`
|
After `yarn install`, if you have a `node_modules/typescript`
|
||||||
|
@ -106,6 +152,8 @@ file containing:
|
||||||
|
|
||||||
## Debugging
|
## Debugging
|
||||||
|
|
||||||
|
### Emacs with Tide
|
||||||
|
|
||||||
You can get verbose logs from Tide's tsserver by setting the Emacs
|
You can get verbose logs from Tide's tsserver by setting the Emacs
|
||||||
variable `tide-tsserver-process-environment`:
|
variable `tide-tsserver-process-environment`:
|
||||||
|
|
||||||
|
@ -125,3 +173,12 @@ Finally, you can set these options in a `.dir-locals.el` file, too:
|
||||||
((typescript-mode
|
((typescript-mode
|
||||||
. ((tide-tsserver-process-environment . ("TSS_LOG=-level verbose -file /tmp/tss.log")))))
|
. ((tide-tsserver-process-environment . ("TSS_LOG=-level verbose -file /tmp/tss.log")))))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Emacs with LSP
|
||||||
|
|
||||||
|
`lsp-mode` helpfully puts logs in a `.log/` directory in your project
|
||||||
|
root! So you can follow `.log/tsserver.log`. There are also `lsp-mode`
|
||||||
|
options for changing the `tsserver` logging level, but I haven't
|
||||||
|
explored them yet.
|
||||||
|
|
||||||
|
[tsserver-plugin-loading-problem]: https://github.com/microsoft/TypeScript/issues/42688
|
||||||
|
|
|
@ -50,6 +50,9 @@ const boot: tslib.server.PluginModuleFactory = ({ typescript: ts }) => {
|
||||||
return p.firstItem.start.pos + p.offset;
|
return p.firstItem.start.pos + p.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
span(s: ts.TextSpan): ts.TextSpan;
|
||||||
|
span(s: undefined): undefined;
|
||||||
|
span(s: ts.TextSpan | undefined): ts.TextSpan | undefined;
|
||||||
span(s: ts.TextSpan | undefined): ts.TextSpan | undefined {
|
span(s: ts.TextSpan | undefined): ts.TextSpan | undefined {
|
||||||
if (s !== void 0) {
|
if (s !== void 0) {
|
||||||
const newStart = this.loc(s.start);
|
const newStart = this.loc(s.start);
|
||||||
|
@ -485,7 +488,16 @@ const boot: tslib.server.PluginModuleFactory = ({ typescript: ts }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
getNavigationTree(fileName: string): ts.NavigationTree {
|
getNavigationTree(fileName: string): ts.NavigationTree {
|
||||||
throw new Error('Method not implemented.');
|
const t = this.inner.getNavigationTree(fileName);
|
||||||
|
return withFileName(fileName, () => t, (fixup) => {
|
||||||
|
function fixupNavigationTree(t: ts.NavigationTree) {
|
||||||
|
fixup.span(t.nameSpan);
|
||||||
|
t.spans.forEach(s => fixup.span(s));
|
||||||
|
t.childItems?.forEach(fixupNavigationTree);
|
||||||
|
}
|
||||||
|
fixupNavigationTree(t);
|
||||||
|
return t;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareCallHierarchy(fileName: string, position: number): ts.CallHierarchyItem | ts.CallHierarchyItem[] | undefined {
|
prepareCallHierarchy(fileName: string, position: number): ts.CallHierarchyItem | ts.CallHierarchyItem[] | undefined {
|
||||||
|
@ -610,7 +622,7 @@ const boot: tslib.server.PluginModuleFactory = ({ typescript: ts }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
getApplicableRefactors(fileName: string, positionOrRange: number | ts.TextRange, preferences: ts.UserPreferences | undefined, triggerReason?: ts.RefactorTriggerReason): ts.ApplicableRefactorInfo[] {
|
getApplicableRefactors(fileName: string, positionOrRange: number | ts.TextRange, preferences: ts.UserPreferences | undefined, triggerReason?: ts.RefactorTriggerReason): ts.ApplicableRefactorInfo[] {
|
||||||
throw new Error('Method not implemented.');
|
return this.inner.getApplicableRefactors(fileName, positionOrRange, preferences, triggerReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
getEditsForRefactor(fileName: string, formatOptions: ts.FormatCodeSettings, positionOrRange: number | ts.TextRange, refactorName: string, actionName: string, preferences: ts.UserPreferences | undefined): ts.RefactorEditInfo | undefined {
|
getEditsForRefactor(fileName: string, formatOptions: ts.FormatCodeSettings, positionOrRange: number | ts.TextRange, refactorName: string, actionName: string, preferences: ts.UserPreferences | undefined): ts.RefactorEditInfo | undefined {
|
||||||
|
|
Loading…
Reference in New Issue