From 39908ec1039a00b468b3fae4c53c2fa425ebca13 Mon Sep 17 00:00:00 2001 From: Andrew Obuchowicz Date: Thu, 6 Feb 2020 10:44:08 -0500 Subject: [PATCH] Unregister language server extension on LS shutdown fix #605 Signed-off-by: Andrew Obuchowicz --- .../eclipse/lsp4xml/XMLLanguageServer.java | 3 +- .../extensions/XMLExtensionsRegistry.java | 12 ++++- .../ExtensionRegistryDisposeTest.java | 45 +++++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/services/extensions/ExtensionRegistryDisposeTest.java diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/XMLLanguageServer.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/XMLLanguageServer.java index f5f9774d53..63cce72ac1 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/XMLLanguageServer.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/XMLLanguageServer.java @@ -43,12 +43,12 @@ import org.eclipse.lsp4xml.services.IXMLDocumentProvider; import org.eclipse.lsp4xml.services.XMLLanguageService; import org.eclipse.lsp4xml.settings.AllXMLSettings; -import org.eclipse.lsp4xml.settings.XMLCompletionSettings; import org.eclipse.lsp4xml.settings.InitializationOptionsSettings; import org.eclipse.lsp4xml.settings.LogsSettings; import org.eclipse.lsp4xml.settings.ServerSettings; import org.eclipse.lsp4xml.settings.SharedSettings; import org.eclipse.lsp4xml.settings.XMLCodeLensSettings; +import org.eclipse.lsp4xml.settings.XMLCompletionSettings; import org.eclipse.lsp4xml.settings.XMLFormattingOptions; import org.eclipse.lsp4xml.settings.XMLGeneralClientSettings; import org.eclipse.lsp4xml.settings.XMLSymbolSettings; @@ -176,6 +176,7 @@ public synchronized void updateSettings(Object initializationOptionsSettings) { @Override public CompletableFuture shutdown() { + xmlLanguageService.dispose(); return computeAsync(cc -> new Object()); } diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/services/extensions/XMLExtensionsRegistry.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/services/extensions/XMLExtensionsRegistry.java index 36aba4f160..c85d95c693 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/services/extensions/XMLExtensionsRegistry.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/services/extensions/XMLExtensionsRegistry.java @@ -169,7 +169,7 @@ public void initializeIfNeeded() { } private synchronized void initialize() { - + if (initialized) { return; } @@ -198,6 +198,16 @@ void unregisterExtension(IXMLExtension extension) { extension.stop(this); } + /** + * Unregisters all registered extensions. + */ + public void dispose() { + // Copy the list of extensions to avoid ConcurrentModificationError + List extensionReferences = new ArrayList<>(); + extensions.forEach(extensionReferences::add); + extensionReferences.forEach(this::unregisterExtension); + } + public void registerCompletionParticipant(ICompletionParticipant completionParticipant) { completionParticipants.add(completionParticipant); } diff --git a/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/services/extensions/ExtensionRegistryDisposeTest.java b/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/services/extensions/ExtensionRegistryDisposeTest.java new file mode 100644 index 0000000000..d7a8f11d76 --- /dev/null +++ b/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/services/extensions/ExtensionRegistryDisposeTest.java @@ -0,0 +1,45 @@ +package org.eclipse.lsp4xml.services.extensions; + +import static org.junit.Assert.assertTrue; + +import org.eclipse.lsp4j.InitializeParams; +import org.eclipse.lsp4xml.services.extensions.save.ISaveContext; +import org.junit.Test; + +public class ExtensionRegistryDisposeTest { + + @Test + public void testExtensionRegistryDipose() { + XMLExtensionsRegistry registry = new XMLExtensionsRegistry(); + registry.initializeIfNeeded(); + MockXMLExtension extension = new MockXMLExtension(); + registry.registerExtension(extension); + assertTrue(!extension.isStopped()); + registry.dispose(); + assertTrue(extension.isStopped()); + assertTrue(registry.getExtensions().isEmpty()); + } +} + +class MockXMLExtension implements IXMLExtension { + boolean stopped; + + @Override + public void start(InitializeParams params, XMLExtensionsRegistry registry) { + stopped = false; + } + + @Override + public void stop(XMLExtensionsRegistry registry) { + stopped = true; + } + + @Override + public void doSave(ISaveContext context) { + } + + public boolean isStopped() { + return stopped; + } + +}