-
I am trying to integrate an language server with lxtk. I finally made it that completion calls are forwarded to my server but i am struggeling with resource events (create file, delete file ...). In my client I added something like |
Beta Was this translation helpful? Give feedback.
Replies: 9 comments
-
Ok seems that i found an solution. Not sure if this is the best. I had to create Participant implementations for the different operations and then register them as extensions. import org.lxtk.lx4e.refactoring.CreateResourceParticipant;
import org.lxtk.lx4e.refactoring.IFileOperationParticipantSupport;
import de.hetzge.eclipse.flix.FlixCore;
public class FlixCreateResourceParticipant extends CreateResourceParticipant {
@Override
protected IFileOperationParticipantSupport getFileOperationParticipantSupport() {
return FlixCore.FILE_OPERATION_PARTICIPANT_SUPPORT;
}
...
} <extension
point="org.eclipse.ltk.core.refactoring.createParticipants">
<createParticipant
class="de.hetzge.eclipse.flix.internal.FlixCreateResourceParticipant"
id="de.hetzge.eclipse.flix.createParticipant"
name="Flix create participant">
<enablement></enablement>
</createParticipant>
</extension> |
Beta Was this translation helpful? Give feedback.
-
Hi @hetzge, Yes, if you are interested in events for file operations introduced in LSP 3.16 (like <extension
point="org.eclipse.ltk.core.refactoring.deleteParticipants">
<deleteParticipant
id="exampleDeleteResourceParticipant"
name="Example Delete Resource Participant"
class="example.ExampleDeleteResourceParticipant">
<enablement>
<adapt
type="org.eclipse.core.resources.IResource">
</adapt>
</enablement>
</deleteParticipant>
</extension> where import org.lxtk.lx4e.refactoring.DeleteResourceParticipant;
import org.lxtk.lx4e.refactoring.IFileOperationParticipantSupport;
public class ExampleDeleteResourceParticipant
extends DeleteResourceParticipant
{
@Override
public String getName()
{
return "Example Delete Resource Participant";
}
@Override
protected IFileOperationParticipantSupport getFileOperationParticipantSupport()
{
return Activator.getDefault().getFileOperationParticipantSupport();
}
} Also, you need to wire the singletons for import static example.ExampleCore.DOCUMENT_SERVICE;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.lxtk.lx4e.refactoring.FileOperationParticipantSupport;
import org.lxtk.lx4e.refactoring.WorkspaceEditChangeFactory;
public class Activator
extends AbstractUIPlugin
{
...
private WorkspaceEditChangeFactory changeFactory;
private FileOperationParticipantSupport participantSupport;
public WorkspaceEditChangeFactory getWorkspaceEditChangeFactory()
{
return changeFactory;
}
public FileOperationParticipantSupport getFileOperationParticipantSupport()
{
return participantSupport;
}
@Override
public void start(BundleContext context) throws Exception
{
...
changeFactory = new WorkspaceEditChangeFactory(DOCUMENT_SERVICE);
participantSupport = new FileOperationParticipantSupport(changeFactory);
changeFactory.setFileOperationParticipantSupport(participantSupport);
...
}
...
} And last but not least you need to add the corresponding feature to your language client: import org.eclipse.lsp4j.services.LanguageServer;
import org.lxtk.client.AbstractLanguageClient;
import org.lxtk.client.Feature;
import org.lxtk.client.FileOperationsFeature;
import org.lxtk.lx4e.ui.EclipseLanguageClient;
import org.lxtk.lx4e.ui.EclipseLanguageClientController;
public class ExampleLanguageClient
extends EclipseLanguageClientController<LanguageServer>
{
...
@Override
protected AbstractLanguageClient<LanguageServer> getLanguageClient()
{
Collection<Feature<? super LanguageServer>> features = new ArrayList<>();
...
features.add(FileOperationsFeature.newInstance(
Activator.getDefault().getFileOperationParticipantSupport()));
return new EclipseLanguageClient<>(log(), diagnosticConsumer,
Activator.getDefault().getWorkspaceEditChangeFactory(), features)
{
...
};
}
...
} So, yes, I can confirm your findings are correct regarding this mechanism. There is also an older mechanism for watching file changes (based on Please let me know if you have any questions. Thank you for your interest in LXTK! |
Beta Was this translation helpful? Give feedback.
-
Thank you very much for the detailed and fast answer. Feels good to find out I am on a good way :) |
Beta Was this translation helpful? Give feedback.
-
I agree with you regarding the out-of-the-box experience, it could probably be better. Part of the problem is that LXTK is a lower level framework than LSP4E. This has its inherent advantages and disadvantages. Also, support for file operations is one of the newer and more advanced features provided, and unfortunately there is currently no example illustrating the usage. The problem is that to provide an example for a feature you need a server supporting that feature... (Locally, I have a heavily modified proto-language-server, which I use for testing such features, but it is not intended to be published.) I hope that once the TypeScript language server supports some of these newer features, they will be added to the corresponding example. Anyway, thank you very much for the feedback. I'm really happy to hear the voice of an early adopter! :) |
Beta Was this translation helpful? Give feedback.
-
Update: Only deleteParticipants and moveParticipants seems to get triggered. copyParticipants and createParticipants seems not to work out of the box. |
Beta Was this translation helpful? Give feedback.
-
Unfortunately, it looks like createParticipants and copyParticipants don't get called by the Eclipse Platform... There are only |
Beta Was this translation helpful? Give feedback.
-
Note: While the base Eclipse Platform does not call createParticipants and copyParticipants, they do get called by some of the JDT refactorings. There is even |
Beta Was this translation helpful? Give feedback.
-
For my usecase I have written now a own monitor that is firing the necessary events: import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.lxtk.FileCreate;
import org.lxtk.FileCreateEvent;
import org.lxtk.FileCreateEventSource;
import org.lxtk.FileDelete;
import org.lxtk.FileDeleteEvent;
import org.lxtk.FileDeleteEventSource;
import org.lxtk.util.EventEmitter;
import org.lxtk.util.EventStream;
public class ResourceMonitor implements IResourceChangeListener, FileCreateEventSource, FileDeleteEventSource {
private final EventEmitter<FileCreateEvent> onDidCreateFiles;
private final EventEmitter<FileDeleteEvent> onDidDeleteFiles;
public ResourceMonitor() {
this.onDidCreateFiles = new EventEmitter<>();
this.onDidDeleteFiles = new EventEmitter<>();
}
@Override
public void resourceChanged(IResourceChangeEvent event) {
handle(event.getDelta());
}
private void handle(IResourceDelta delta) {
final IResource resource = delta.getResource();
if (resource instanceof final IFile file) {
if (delta.getKind() == IResourceDelta.ADDED) {
this.onDidCreateFiles.emit(new FileCreateEvent(List.of(new FileCreate(file.getLocationURI()))), Activator::logError);
} else if (delta.getKind() == IResourceDelta.REMOVED) {
this.onDidDeleteFiles.emit(new FileDeleteEvent(List.of(new FileDelete(file.getLocationURI()))), Activator::logError);
}
}
final IResourceDelta[] affectedChildren = delta.getAffectedChildren();
for (final IResourceDelta childrenResourceDelta : affectedChildren) {
handle(childrenResourceDelta);
}
}
@Override
public EventStream<FileCreateEvent> onDidCreateFiles() {
return this.onDidCreateFiles;
}
@Override
public EventStream<FileDeleteEvent> onDidDeleteFiles() {
return this.onDidDeleteFiles;
}
} In the Activator: this.resourceMonitor = new ResourceMonitor();
ResourcesPlugin.getWorkspace().addResourceChangeListener(this.resourceMonitor, IResourceChangeEvent.POST_CHANGE); features.add(FileOperationsFeature.newInstance(Activator.getDefault().getResourceMonitor())); |
Beta Was this translation helpful? Give feedback.
-
Indeed, relying on workspace resource change events is a reasonable approach if you only need |
Beta Was this translation helpful? Give feedback.
Hi @hetzge,
Yes, if you are interested in events for file operations introduced in LSP 3.16 (like
workspace/willDeleteFiles
andworkspace/didDeleteFiles
), the implementation in LX4E is based on Eclipse refactoring participants, so indeed you need to register a participant for each operation you are interested in, e.g.