Code Monkey home page Code Monkey logo

lxtk's Introduction

LXTK: Language Client/Server Toolkit Build

LXTK is an open source toolkit for implementing language clients talking to language servers according to the Language Server Protocol (LSP). Currently, it targets Java and Eclipse IDE, and as such, sits between Eclipse LSP4J and Eclipse LSP4E in its abstraction level: it is built using LSP4J, while LSP4E could in theory have been built using LXTK. In other words, it provides a higher level of abstraction than LSP4J and more flexibility than LSP4E.

Why LXTK?

  • Object-oriented: Can be incrementally specialized in numerous ways to cater for different requirements.

  • Not opinionated: Provides a set of bricks combinable to a complete structure that is right for you.

  • API centric: Every aspect can be controlled, extended or replaced as needed, reliably.

  • Robust: Shown to be reliable and effective by being used in a widely distributed commercial product.

  • Fully dynamic: Support for dynamic capability registration built right into the core.

  • Integrated with Eclipse Handly: Can be used to build a handle-based model as a pillar for an Eclipse-based IDE.

  • Comes with realistic examples: Includes JSON and TypeScript sample editors.

Features

The current LXTK version (0.4) provides client-side support for the following LSP features:

Architectural Overview

Currently, there are two main architectural layers in LXTK:

  • LXTK Core Framework

  • LXTK Integration for Eclipse (LX4E)

LXTK Core Framework (org.lxtk bundle) is a Java class library for building LSP clients. It is built on top of LSP4J. Rather than exposing LSP4J services directly, LXTK provides its own service layer. This layer is somewhat similar to the Extension API of Visual Studio Code, but is tailored specifically to LSP. In particular, its API directly reuses protocol data types of LSP4J. The Core Framework can be used in any Java-based client (Eclipse, IntelliJ, etc.)

LXTK Integration for Eclipse (LX4E) is subdivided into the Core layer (org.lxtk.lx4e bundle) and the UI layer (org.lxtk.lx4e.ui bundle). LX4E is not a tool, i.e. it does not provide a generic LSP client for Eclipse. Instead, it provides a platform for building Eclipse-based development tools using LSP-based services provided by the Core Framework. To that end, it extends the Core Framework and integrates it with the Eclipse Platform. Although LX4E can be used for building a generic LSP client for Eclipse, its main goal is to facilitate tight integration of specific language servers in a full-featured custom Eclipse-based IDE.

LX4E includes several examples (org.lxtk.lx4e.examples.* bundles) that demonstrate main aspects of its usage.

For additional information on how to use some of the features of LXTK Core Framework and LX4E, see FAQ.

For an overview of the API provided by LXTK Core Framework and LX4E, please see the Javadocs for the exported packages of the respective bundles.

Developer Resources

  • Building: How to build LXTK locally.

  • Contributing: How to report bugs, set up a developer workspace, issue pull requests, etc.

Contacts

License

LXTK is licensed under the Eclipse Public License 2.0. See LICENSE for the full license text.

lxtk's People

Contributors

1c-company avatar masofcon avatar pisv avatar xcariba avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

otymko

lxtk's Issues

[lx4e] IllegalArgumentException when deleting a project

java.lang.IllegalArgumentException
	at org.lxtk.FileDeleteEvent.<init>(FileDeleteEvent.java:32)
	at org.lxtk.lx4e.refactoring.FileOperationParticipantSupport$2.send(FileOperationParticipantSupport.java:114)
	at org.lxtk.lx4e.requests.Request$Handler.sendAndReceive(Request.java:344)
	at org.lxtk.lx4e.requests.Request.sendAndReceive(Request.java:279)
	at org.lxtk.lx4e.refactoring.FileOperationParticipantSupport.computePreDeleteChange(FileOperationParticipantSupport.java:122)
	at org.lxtk.lx4e.refactoring.DeleteResourceParticipant.createPreChange(DeleteResourceParticipant.java:74)
	at org.eclipse.ltk.core.refactoring.participants.ProcessorBasedRefactoring.createChange(ProcessorBasedRefactoring.java:305)
	at org.eclipse.ltk.core.refactoring.CreateChangeOperation.run(CreateChangeOperation.java:125)
	at org.eclipse.ltk.core.refactoring.PerformChangeOperation.run(PerformChangeOperation.java:210)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2313)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2338)
	at org.eclipse.ltk.internal.ui.refactoring.WorkbenchRunnableAdapter.run(WorkbenchRunnableAdapter.java:89)
	at org.eclipse.jface.operation.ModalContext$ModalContextThread.run(ModalContext.java:122)

Happens when deleting a project without deleting project contents.

Adopt LSP4J 0.9

LXTK 0.2.0 will require LSP4J 0.9.0 as the minimum version.

As noted in the CHANGELOG, LSP4J 0.9.0 introduces a number of breaking API changes, some of which will cause breaking changes in LXTK API.

Cannot start more than one instance of a language server that provides commands

This can be reproduced using the TypeScript Example and a workspace with at least two projects containing TypeScript files:

  1. Open a TypeScript file in a project. The first server instance is started.
  2. Open a TypeScript file in another project. The second server instance fails to start. The exception is

java.lang.IllegalArgumentException: Command already exists: _typescript.applyWorkspaceEdit
at org.lxtk.DefaultCommandService.addCommand(DefaultCommandService.java:43)
at org.lxtk.client.ExecuteCommandFeature.register(ExecuteCommandFeature.java:127)
at org.lxtk.client.ExecuteCommandFeature.initialize(ExecuteCommandFeature.java:96)
at org.lxtk.client.AbstractLanguageClient.initialize(AbstractLanguageClient.java:127)
at org.lxtk.client.AbstractLanguageClientController$1.lambda$0(AbstractLanguageClientController.java:227)
at org.lxtk.util.SafeRun.lambda$0(SafeRun.java:47)
at org.lxtk.util.SafeRun.runWithResult(SafeRun.java:64)
at org.lxtk.util.SafeRun.run(SafeRun.java:45)
at org.lxtk.client.AbstractLanguageClientController$1.connect(AbstractLanguageClientController.java:176)
at org.lxtk.util.connect.AbstractConnectable.lambda$0(AbstractConnectable.java:78)
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)

Text selection is not replaced when proposal is applied

When text is selected in text editor and proposal is applied proposal is inserted after cursor and selection is ignored

Steps to reproduce:

  1. Write something like MyObject.FirstField
  2. Select FirstField with cursor between dot and F so FirstField text is selected
  3. Call content-assist
  4. Select and apply any proposal (for example SecondField)
  5. Selection will be ignored. Result will be MyObject.SeconfFieldFirstField

Cater for code action resolve support

LSP 3.16 introduces Code Action resolve support. This would break some of the LX4E API related to code actions. Essentially, we would need to store a reference to the CodeActionProvider that provided an (unresolved) code action and use it to resolve the code action when needed. This is similar to how we currently resolve code lenses.

It seems that it would be better to cater for this change sooner rather than later.

SignatureHelp with empty parameter list throws IndexOutOfBoundsException

If active signature has no parameters and has activeParameter set to 0 (default value) error occures, but specification says that if signature has no parameters this property should be ignored.
exception:

Caused by: java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
	at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
	at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
	at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
	at java.base/java.util.Objects.checkIndex(Objects.java:372)
	at java.base/java.util.ArrayList.get(ArrayList.java:459)
	at org.lxtk.lx4e.ui.completion.ContentAssistProcessor$SignatureContextInformationValidator.updatePresentation(ContentAssistProcessor.java:478)

LXTK throws illegal state exception if there is only one exit position in snippet

Snippet text example:

MyMethod($0)

When you apply this snippet it throws exception

java.lang.IllegalStateException: must specify at least one linked position
	at org.eclipse.jface.text.link.LinkedModeModel.enforceNotEmpty(LinkedModeModel.java:530)
	at org.eclipse.jface.text.link.LinkedModeModel.install(LinkedModeModel.java:484)
	at org.eclipse.jface.text.link.LinkedModeModel.forceInstall(LinkedModeModel.java:441)
	at org.lxtk.lx4e.ui.completion.LSIncompleteCompletionProposal.apply(Unknown Source)
	at org.lxtk.lx4e.ui.completion.LSCompletionProposal.apply(LSCompletionProposal.java:88)

Cannot undo refactoring operation if file was changed externally

If file content was changed externally after applying code action lxtk throws exception when you try to undo operation.

Steps to reproduce:

  1. Open file
  2. Edit it
  3. Apply Code Action to refactor some code. Do not save file
  4. Open file with any external text editor, change file and save it
  5. Press Ctrl+Z to undo code action text change

LXTK will throw exception. Maybe it is better to inform user that this operation is not possible if its impossible to undo operation in that case.

org.eclipse.core.commands.ExecutionException: The conent of 'foo/bar/file.lsp' has changed
 at org.eclipse.ltk.internal.core.refactoring.UndoableOperation2ChangeAdapter.undo(UndoableOperation2ChangeAdapter.java:212)
 at org.eclipse.core.commands.operations.TriggeredOperations.undo(TriggeredOperations.java:214)
 at org.eclipse.core.commands.operations.DefaultOperationHistory.doUndo(DefaultOperationHistory.java:407)
 at org.eclipse.core.commands.operations.DefaultOperationHistory.undo(DefaultOperationHistory.java:1149)
 at org.eclipse.ui.operations.UndoActionHandler.runCommand(UndoActionHandler.java:86)
 at org.eclipse.ui.operations.OperationHistoryActionHandler.lambda$0(OperationHistoryActionHandler.java:288)
 at org.eclipse.jface.operation.ModalContext.runInCurrentThread(ModalContext.java:436)
 at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:352)
 at org.eclipse.jface.dialogs.ProgressMonitorDialog.run(ProgressMonitorDialog.java:469)
 at org.eclipse.ui.internal.operations.TimeTriggeredProgressMonitorDialog.access$6(TimeTriggeredProgressMonitorDialog.java:1)
 at org.eclipse.ui.internal.operations.TimeTriggeredProgressMonitorDialog.lambda$0(TimeTriggeredProgressMonitorDialog.java:155)
 at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:72)
 at org.eclipse.ui.internal.operations.TimeTriggeredProgressMonitorDialog.run(TimeTriggeredProgressMonitorDialog.java:167)
 at org.eclipse.ui.operations.OperationHistoryActionHandler.run(OperationHistoryActionHandler.java:301)
 at org.eclipse.jface.action.Action.runWithEvent(Action.java:474)
 at org.eclipse.jface.commands.ActionHandler.execute(ActionHandler.java:121)
 at org.eclipse.ui.internal.handlers.E4HandlerProxy.execute(E4HandlerProxy.java:97)
 at jdk.internal.reflect.GeneratedMethodAccessor41.invoke(Unknown Source)
 at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.base/java.lang.reflect.Method.invoke(Method.java:566)
 at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:58)
 at org.eclipse.e4.core.internal.di.InjectorImpl.invokeUsingClass(InjectorImpl.java:319)
 at org.eclipse.e4.core.internal.di.InjectorImpl.invoke(InjectorImpl.java:253)
 at org.eclipse.e4.core.contexts.ContextInjectionFactory.invoke(ContextInjectionFactory.java:173)
 at org.eclipse.e4.core.commands.internal.HandlerServiceHandler.execute(HandlerServiceHandler.java:156)
 at org.eclipse.core.commands.Command.executeWithChecks(Command.java:488)
 at org.eclipse.core.commands.ParameterizedCommand.executeWithChecks(ParameterizedCommand.java:487)
 at org.eclipse.e4.core.commands.internal.HandlerServiceImpl.executeHandler(HandlerServiceImpl.java:213)
 at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.executeCommand(KeyBindingDispatcher.java:308)
 at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.press(KeyBindingDispatcher.java:584)
 at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.processKeyEvent(KeyBindingDispatcher.java:653)
 at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.filterKeySequenceBindings(KeyBindingDispatcher.java:443)
 at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.access$2(KeyBindingDispatcher.java:386)
 at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher$KeyDownFilter.handleEvent(KeyBindingDispatcher.java:96)
 at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89)
 at org.eclipse.swt.widgets.Display.filterEvent(Display.java:1248)
 at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1036)
 at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1061)
 at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1046)
 at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1088)
 at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1084)
 at org.eclipse.swt.widgets.Widget.wmChar(Widget.java:1471)
 at org.eclipse.swt.widgets.Control.WM_CHAR(Control.java:4862)
 at org.eclipse.swt.widgets.Canvas.WM_CHAR(Canvas.java:345)
 at org.eclipse.swt.widgets.Control.windowProc(Control.java:4740)
 at org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:340)
 at org.eclipse.swt.widgets.Display.windowProc(Display.java:4923)
 at org.eclipse.swt.internal.win32.OS.DispatchMessage(Native Method)
 at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3628)
 at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1158)
 at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
 at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1047)
 at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
 at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:658)
 at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
 at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:557)
 at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:154)
 at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:150)
 at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
 at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137)
 at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107)
 at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
 at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.base/java.lang.reflect.Method.invoke(Method.java:566)
 at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:657)
 at org.eclipse.equinox.launcher.Main.basicRun(Main.java:594)
 at org.eclipse.equinox.launcher.Main.run(Main.java:1447)
Caused by: org.eclipse.core.runtime.CoreException: The conent of 'foo/bar/file.lsp' has changed
 at org.lxtk.lx4e.refactoring.UndoTextFileChange.perform(UndoTextFileChange.java:117)
 at org.eclipse.ltk.core.refactoring.CompositeChange.perform(CompositeChange.java:281)
 at org.eclipse.ltk.core.refactoring.CompositeChange.perform(CompositeChange.java:281)
 at org.eclipse.ltk.core.refactoring.CompositeChange.perform(CompositeChange.java:281)
 at org.eclipse.ltk.internal.core.refactoring.UndoableOperation2ChangeAdapter.lambda$0(UndoableOperation2ChangeAdapter.java:329)
 at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2292)
 at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2312)
 at org.eclipse.ltk.internal.core.refactoring.UndoableOperation2ChangeAdapter.executeChange(UndoableOperation2ChangeAdapter.java:351)
 at org.eclipse.ltk.internal.core.refactoring.UndoableOperation2ChangeAdapter.undo(UndoableOperation2ChangeAdapter.java:196) ... 69 more
Caused by: org.eclipse.handly.snapshot.StaleSnapshotException
 at org.eclipse.handly.buffer.BufferChangeOperation.checkChange(BufferChangeOperation.java:140)
 at org.eclipse.handly.buffer.BufferChangeOperation.applyChange(BufferChangeOperation.java:111)
 at org.eclipse.handly.buffer.BufferChangeOperation.execute(BufferChangeOperation.java:100)
 at org.eclipse.handly.buffer.UiBufferChangeRunner.run(UiBufferChangeRunner.java:83)
 at org.eclipse.handly.buffer.TextFileBuffer.applyChange(TextFileBuffer.java:213)
 at org.lxtk.lx4e.refactoring.UndoTextFileChange.perform(UndoTextFileChange.java:112) ... 77 more

LXTK saves diagnostic json in marker in wrong format

LXTK serializes diagnostic markers in wrong format.
If you have code field in Diagnostic class with type Either which has its own serializer and deserializer inside lsp4j. You have to use EitherTypeAdapter if you want to work with them properly. My project uses this diagnostics and deserializer crashes if code field is present.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.