Closed mickaelistria closed 8 years ago
Maybe we have to put some more customization into the Gson parser.
Or maybe have some more flexible parser, allowing unexpected fields and not necessarily failing on missing ones.
For example, in that case, a more flexible parser would log the parsing error (ok so far), return a Hover object without MarkedString[] set, but which would allow to allow to fail back to the JSon object and let customer do something else. For example hover.getJSonObject().get("contents")
.
IMHO, this approach of giving a way to get the JSon object for a response/request could allow to more easily workaround such cases and be able to somehow support new fields without need to change code immediately.
I think it should parse the MarkedString and turn it into a java list, as the specification defines MarkedString | MarkedString[]
in Java there is no equivalent type, but we can map it to a list always.
I now get
UT: 2.0
{"id":"1","method":"textDocument/hover","params":{"textDocument":{"uri":"file:/home/mistria/git/3dLocalizer/test.css"},"uri":"file:/home/mistria/git/3dLocalizer/test.css","position":{"line":12,"character":5}},"jsonrpc":"2.0"}
Could not parse response: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING
io.typefox.lsapi.services.json.InvalidMessageException: Could not parse response: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING
at io.typefox.lsapi.services.json.MessageJsonHandler.parseResponse(MessageJsonHandler.xtend:223)
at io.typefox.lsapi.services.json.MessageJsonHandler.parseMessage(MessageJsonHandler.xtend:160)
at io.typefox.lsapi.services.json.MessageJsonHandler.parseMessage(MessageJsonHandler.xtend:149)
at io.typefox.lsapi.services.json.LanguageServerProtocol.handleMessage(LanguageServerProtocol.xtend:72)
at io.typefox.lsapi.services.json.LanguageServerProtocol$IOHandler.handleMessage(LanguageServerProtocol.xtend:267)
at io.typefox.lsapi.services.json.LanguageServerProtocol$IOHandler.run(LanguageServerProtocol.xtend:203)
at io.typefox.lsapi.services.json.LanguageServerProtocol$IOHandler.run(LanguageServerProtocol.xtend:163)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:221)
at io.typefox.lsapi.services.json.adapters.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.xtend:29)
at io.typefox.lsapi.services.json.adapters.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.xtend:67)
at io.typefox.lsapi.services.json.adapters.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.xtend)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:117)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:217)
at com.google.gson.Gson.fromJson(Gson.java:861)
at com.google.gson.Gson.fromJson(Gson.java:926)
at com.google.gson.Gson.fromJson(Gson.java:899)
at io.typefox.lsapi.services.json.MessageJsonHandler.parseResponse(MessageJsonHandler.xtend:210)
... 11 more
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING
at com.google.gson.internal.bind.JsonTreeReader.expect(JsonTreeReader.java:139)
at com.google.gson.internal.bind.JsonTreeReader.beginObject(JsonTreeReader.java:70)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:210)
... 20 more
error: Could not parse response: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING
OUT: 2.0
{"id":"1","error":{"code":-32600,"message":"Could not parse response: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING"},"jsonrpc":"2.0"}
java.util.concurrent.TimeoutException
at java.util.concurrent.CompletableFuture.timedGet(CompletableFuture.java:1771)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1915)
at org.eclipse.languageserver.LSBasedHover.getHoverRegion(LSBasedHover.java:80)
at org.eclipse.jface.text.TextViewerHoverManager.computeInformation(TextViewerHoverManager.java:138)
at org.eclipse.jface.text.AbstractInformationControlManager.doShowInformation(AbstractInformationControlManager.java:1144)
at org.eclipse.jface.text.AbstractHoverInformationControlManager$MouseTracker.mouseHover(AbstractHoverInformationControlManager.java:518)
at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:209)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Display.sendEvent(Display.java:5219)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1340)
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4553)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:4143)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$4.run(PartRenderingEngine.java:1121)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:336)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1022)
at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:150)
at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:687)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:336)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:604)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:148)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:138)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:388)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:243)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:673)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:610)
at org.eclipse.equinox.launcher.Main.run(Main.java:1519)
at org.eclipse.equinox.launcher.Main.main(Main.java:1492)
Can we reopen this issue or should I create a new one?
@akosyakov Can you please add the bug
label?
In general, I'm wondering whether ls-api could be more tolerant with this kind of issues: if result is expected to be an array, and is an object or a string, automatically wrapp it into a single-element collection.
In https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md#hover-request
type MarkedString = string | { language: string; value: string };
So I tried to add a custom TypeAdapterFactory
and JsonDeserializer
to MessageJsonHandler.getDefaultGsonBuilder()
but those always get ignored.
Indeed, the TypeAdapterRuntimeTypeWrapper
will always call the delegate ReflectiveTypeAdapterFactory
rather than the one I set.
Is there a way to force my deserializer to have higher priority? Or, for sure better, is it possible to add a specific rule to allow deserializing a String to MarkedString directly in ls-api?
@spoenemann @svenefftinge
See https://github.com/eclipselabs/eclipse-language-service/commit/fd67c62eb1b02b2d5b7c051db0cab98b12616791 for the workaround I did set up on Eclipse's side.
Fixed with https://github.com/TypeFox/ls-api/commit/c7ad588a078d94ba4228b8ec7e95cd40d04f2c3c (tried it successfully for https://github.com/eclipselabs/eclipse-language-service )
I'm using the ls-api against a locally started Language Server for CSS or JSON, the ones used and included in VSCode, hacked to transport on stdin/stdout. It's working fine for completion and diagnostics, but I'm having troubles to get hover working. It seems like the return message doesn't get correctly parsed:
Seems like the ls-api client doesn't handle the case "contents: MarkedString | MarkedString[];" for Hover results.