Closed jeanlucburot closed 6 years ago
Could you elaborate why do you want it?
You can create a new model to send textDocument/didOpen
and change it to send textDocument/didChange
. You can change a file to trigger workspace/didChangeWorkspaceFolders
.
The above suggested notifications and requests (textDocument/didOpen
, textDocument/didChange
, workspace/didChangeWorkspaceFolders
) are just examples. I created a custom language server with LSP4J and have integrated custom notifications and requests into it.
Now I need to be able to trigger these custom requests and notifications in Theia, preferably with a button click. Hence, I need a way to declare the custom requests and notifications, and then I need a way to access the results received from the language server after having sent some request.
What classes/interfaces must I create/implement/extend to send and receive those mentioned requests and notifications? You said to create a model. What model do you mean exactly?
I see, yes generally you can do it, e.g. look how java triggers the organize import command: https://github.com/theia-ide/theia/blob/e445a4cd7b09c4e68fa07bd393af12734267ff80/packages/java/src/browser/java-commands.ts#L76-L82
Sounds like the a possible way to go. I tried it out, but fail to inject the JavaClientContribution
using Inversify. The code compiles, but when running Theia, the browser gets stuck in the loading screen.
The console error is below the below code I wrote.
I created the file my-package-widget.tsx
:
import { JavaClientContribution } from "@theia/java/lib/browser";
import { ILanguageClient } from "@theia/languages/lib/common";
@injectable()
export class MyPackageWidget extends ReactWidget {
@inject(JavaClientContribution)
protected readonly javaClientContribution: JavaClientContribution;
private onButtonLanguageServerRequestClicked() {
const clientPromise: Promise<ILanguageClient> = this.javaClientContribution.languageClient;
clientPromise.then(res => {
this.messageService.info("Successfully connected to the Java language server.");
}).catch(err => {
this.messageService.error("Error connecting to the Java language server. " + err.message);
});
}
}
Error in the browser console:
Failed to start the frontend application.
| ./src-gen/frontend/index.js.module.exports.Promise.resolve.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.then.catch.reason | @ | index.js:69
-- | -- | -- | --
| Promise.catch (async) | |
| ./src-gen/frontend/index.js | @ | index.js:68
| __webpack_require__ | @ | bootstrap:63
| ../../node_modules/@phosphor/algorithm/lib/array.js.Object.defineProperty.value | @ | bootstrap:196
| (anonymous)
ReferenceError: monaco is not defined
at Object.../../packages/java/lib/browser/monaco-contribution/index.js (index.ts:20)
at __webpack_require__ (bootstrap:63)
at Object.../../packages/java/lib/browser/java-frontend-module.js (java-frontend-module.ts:31)
at __webpack_require__ (bootstrap:63)
at Object.../../packages/java/lib/browser/index.js (index.ts:22)
at __webpack_require__ (bootstrap:63)
at Object.../../packages/my-package/lib/browser/my-package-widget.js (my-package-widget.tsx:17)
at __webpack_require__ (bootstrap:63)
at Object.../../packages/my-package/lib/browser/my-package-frontend-module.js (my-package-frontend-module.ts:10)
at __webpack_require__ (bootstrap:63)
Any idea how I can access languageClient
? I guess injecting from one package to another is done differently? Is there a global registry I can access to get the language server from another package?
Are you sure that @theia/monaco
package is installed? Could you share package.json for your extension and application?
Ok, one question remains considering starting and stopping the language server. The current status I have is that the first thing to do to access a language server is to inject access to it.
@inject(JavaClientContribution) protected readonly javaClientContribution: JavaClientContribution
The second thing is to get client access to the language server, done by waiting for an ILanguageClient
object.
const client: ILanguageClient = await this.javaClientContribution.languageClient;
After that requests can be sent from the client to the language server, i.e. some completion request.
const result: CompletionResponse = await client.sendRequest<CompletionResponse>("textDocument/completion", {
textDocument: {
uri: uri
},
position: {
line: 0,
character: 0
}
});
If though the server has not been yet started, the above code gets stuck at requesting the client
object. To manually start the language server I found an activate()
method, that seems to do what I would expect it to. This has to be executed before creating the client
variable.
this.javaClientContribution.activate();
I could not find any method though to shutdown the language server. And I checked the process that is created for it. It remains open until I close the entire Theia IDE. Depending on the size of the language server this can eat up a lot of resources. Is there any way I can shutdown the language server again? I'm looking for something some counterpart of activate()
, i.e. something like
this.javaClientContribution.deactivate();
One should not activate or deactivate a language client manually. It is the responsibility of the language contribution to decide by customizing waitForActivation
: https://github.com/theia-ide/theia/blob/b81d6b1871a00f60fe6350d5e1737b4a73697a0d/packages/languages/src/browser/language-client-contribution.ts#L63-L86.
Ok, I am not sure if I really understand this method the right way. What I need is independence of open text documents when communicating with the language server. So what I did is basically overridden the waitForActivation
method by keeping everything as is, but uncommenting line 78 await p
. This way, I assume` the language server does not wait for an open document to be available, which is exactly what I need. So far it works.
So did I understand it right?
Is there a method to manually start a language server in Theia? I want to be able to send notifications or requests to the language server (i.e. the Java LSP) like
textDocument/didOpen
,textDocument/didChange
orworkspace/didChangeWorkspaceFolders
.Best case scenario would be something like this: