mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-16 00:38:56 +00:00
[lsp] added server launcher to start a process that uses std in & out
This commit is contained in:
parent
b619a2314e
commit
16c9b7c56e
5 changed files with 139 additions and 9 deletions
|
@ -50,15 +50,14 @@ import io.typefox.lsapi.WorkspaceSymbolParams
|
|||
import java.util.List
|
||||
import org.eclipse.emf.common.util.URI
|
||||
import org.eclipse.xtend.lib.annotations.Accessors
|
||||
import org.eclipse.xtext.findReferences.IReferenceFinder.IResourceAccess
|
||||
import org.eclipse.xtext.ide.editor.contentassist.ContentAssistEntry
|
||||
import org.eclipse.xtext.ide.server.contentassist.ContentAssistService
|
||||
import org.eclipse.xtext.ide.server.findReferences.WorkspaceResourceAccess
|
||||
import org.eclipse.xtext.ide.server.symbol.DocumentSymbolService
|
||||
import org.eclipse.xtext.resource.IResourceServiceProvider
|
||||
import org.eclipse.xtext.validation.Issue
|
||||
|
||||
import static io.typefox.lsapi.util.LsapiFactories.*
|
||||
import org.eclipse.xtext.ide.server.findReferences.WorkspaceResourceAccess
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -69,16 +68,18 @@ import org.eclipse.xtext.ide.server.findReferences.WorkspaceResourceAccess
|
|||
InitializeParams params
|
||||
@Inject Provider<WorkspaceManager> workspaceManagerProvider
|
||||
WorkspaceManager workspaceManager
|
||||
IResourceAccess resourceAccess
|
||||
@Inject extension UriExtensions
|
||||
@Inject extension IResourceServiceProvider.Registry languagesRegistry
|
||||
|
||||
override InitializeResult initialize(InitializeParams params) {
|
||||
this.params = params
|
||||
workspaceManager = workspaceManagerProvider.get
|
||||
if (params.rootPath === null) {
|
||||
throw new IllegalArgumentException("Bad initialization request. rootPath must not be null.")
|
||||
}
|
||||
val rootURI = URI.createFileURI(params.rootPath)
|
||||
workspaceManager.initialize(rootURI)[this.publishDiagnostics($0, $1)]
|
||||
resourceAccess = new WorkspaceResourceAccess(workspaceManager)
|
||||
workspaceManager.initialize(rootURI)[this.publishDiagnostics($0, $1)]
|
||||
return new InitializeResultImpl => [
|
||||
capabilities = new ServerCapabilitiesImpl => [
|
||||
definitionProvider = true
|
||||
|
@ -160,6 +161,8 @@ import org.eclipse.xtext.ide.server.findReferences.WorkspaceResourceAccess
|
|||
// end file/content change events
|
||||
// validation stuff
|
||||
private List<NotificationCallback<PublishDiagnosticsParams>> diagnosticListeners = newArrayList()
|
||||
|
||||
WorkspaceResourceAccess resourceAccess
|
||||
|
||||
override onPublishDiagnostics(NotificationCallback<PublishDiagnosticsParams> callback) {
|
||||
diagnosticListeners.add(callback)
|
||||
|
@ -218,7 +221,6 @@ import org.eclipse.xtext.ide.server.findReferences.WorkspaceResourceAccess
|
|||
|
||||
// end completion stuff
|
||||
// symbols
|
||||
|
||||
override definition(TextDocumentPositionParams params) {
|
||||
val uri = params.textDocument.uri.toUri
|
||||
val resourceServiceProvider = uri.resourceServiceProvider
|
||||
|
@ -241,13 +243,12 @@ import org.eclipse.xtext.ide.server.findReferences.WorkspaceResourceAccess
|
|||
|
||||
return workspaceManager.doRead(uri) [ document, resource |
|
||||
val offset = document.getOffSet(params.position)
|
||||
|
||||
|
||||
val definitions = if (params.context.includeDeclaration)
|
||||
documentSymbolService.getDefinitions(resource, offset, resourceAccess)
|
||||
else
|
||||
|
||||
emptyList
|
||||
|
||||
|
||||
val indexData = workspaceManager.index
|
||||
val references = documentSymbolService.getReferences(resource, offset, resourceAccess, indexData)
|
||||
val result = definitions + references
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.server
|
||||
|
||||
import com.google.inject.Guice
|
||||
import com.google.inject.Inject
|
||||
import io.typefox.lsapi.NotificationMessage
|
||||
import io.typefox.lsapi.json.LanguageServerToJsonAdapter
|
||||
import io.typefox.lsapi.json.MessageMethods
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.FileOutputStream
|
||||
import java.io.PrintStream
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import org.apache.log4j.Logger
|
||||
|
||||
/**
|
||||
* @author Sven Efftinge - Initial contribution and API
|
||||
*/
|
||||
class ServerLauncher {
|
||||
|
||||
val LOG = Logger.getLogger(ServerLauncher)
|
||||
|
||||
def static void main(String[] args) {
|
||||
val launcher = Guice.createInjector(new ServerModule).getInstance(ServerLauncher)
|
||||
launcher.start()
|
||||
}
|
||||
|
||||
@Inject LanguageServerImpl languageServer
|
||||
|
||||
private final AtomicBoolean hasExitNotification = new AtomicBoolean(false)
|
||||
|
||||
def void start() {
|
||||
val stdin = System.in
|
||||
val stdout = System.out
|
||||
|
||||
System.setIn(new ByteArrayInputStream(newByteArrayOfSize(0)))
|
||||
System.setOut(new PrintStream(new FileOutputStream("out.log")))
|
||||
|
||||
System.err.println("Starting Xtext Language Server.")
|
||||
val messageAcceptor = new LanguageServerToJsonAdapter(languageServer) {
|
||||
override protected _doAccept(NotificationMessage message) {
|
||||
if (LOG.isDebugEnabled) {
|
||||
LOG.debug(message)
|
||||
}
|
||||
if (message.method == MessageMethods.EXIT) {
|
||||
hasExitNotification.set(true);
|
||||
}
|
||||
super._doAccept(message)
|
||||
}
|
||||
|
||||
override protected sendResponse(String responseId, Object resultValue) {
|
||||
if (LOG.isDebugEnabled) {
|
||||
LOG.debug("response : "+resultValue)
|
||||
}
|
||||
super.sendResponse(responseId, resultValue)
|
||||
}
|
||||
|
||||
override protected sendNotification(String methodId, Object parameter) {
|
||||
if (LOG.isDebugEnabled) {
|
||||
LOG.debug("id"+methodId)
|
||||
LOG.debug("notification : "+parameter)
|
||||
}
|
||||
super.sendNotification(methodId, parameter)
|
||||
}
|
||||
|
||||
override protected sendResponseError(String responseId, String errorMessage, int errorCode, Object errorData) {
|
||||
if (LOG.isDebugEnabled) {
|
||||
LOG.debug("id"+responseId)
|
||||
LOG.debug("error : "+errorMessage)
|
||||
}
|
||||
super.sendResponseError(responseId, errorMessage, errorCode, errorData)
|
||||
}
|
||||
|
||||
}
|
||||
messageAcceptor.connect(stdin, stdout)
|
||||
messageAcceptor.start
|
||||
System.err.println("started.")
|
||||
messageAcceptor.join
|
||||
while (!hasExitNotification.get) {
|
||||
Thread.sleep(10_000l)
|
||||
}
|
||||
System.err.println("Exit notification received. Good Bye!")
|
||||
}
|
||||
|
||||
}
|
|
@ -4,7 +4,7 @@ Bundle-Name: %pluginName
|
|||
Bundle-SymbolicName: org.eclipse.xtext.ide.tests;singleton:=true
|
||||
Bundle-Version: 2.10.0.qualifier
|
||||
Bundle-Localization: plugin
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Bundle-Vendor: %providerName
|
||||
Require-Bundle: org.eclipse.xtext;visibility:=reexport,
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 TypeFox GmbH (http://www.typefox.io) and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.ide.tests.server
|
||||
|
||||
import io.typefox.lsapi.InitializeParamsImpl
|
||||
import io.typefox.lsapi.json.JsonBasedLanguageServer
|
||||
import org.eclipse.xtext.ide.server.ServerLauncher
|
||||
import org.junit.Test
|
||||
import java.lang.ProcessBuilder.Redirect
|
||||
|
||||
/**
|
||||
* @author efftinge - Initial contribution and API
|
||||
*/
|
||||
class ServerLauncherTest {
|
||||
|
||||
@Test def void testServerLaunch() {
|
||||
val process = new ProcessBuilder("java","-cp",System.getProperty("java.class.path"), "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=1044", ServerLauncher.name).redirectInput(Redirect.PIPE).redirectOutput(Redirect.PIPE).start
|
||||
|
||||
try {
|
||||
val client = new JsonBasedLanguageServer()
|
||||
client.connect(process.inputStream, process.outputStream)
|
||||
|
||||
println(client.initialize(new InitializeParamsImpl() => [
|
||||
rootPath = "."
|
||||
]))
|
||||
} finally {
|
||||
process.destroy
|
||||
}
|
||||
}
|
||||
}
|
|
@ -39,6 +39,10 @@ class ServerTest extends AbstractLanguageServerTest {
|
|||
'''
|
||||
initialize
|
||||
assertEquals("Couldn't resolve reference to TypeDeclaration 'NonExisting'.", diagnostics.values.head.head?.message)
|
||||
assertEquals(1, diagnostics.values.head.head.range.start.line)
|
||||
assertEquals(4, diagnostics.values.head.head.range.start.character)
|
||||
assertEquals(1, diagnostics.values.head.head.range.end.line)
|
||||
assertEquals(15, diagnostics.values.head.head.range.end.character)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in a new issue