This is an automated email from the ASF dual-hosted git repository. matthiasblaesing pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/master by this push: new 952f6a9 Only register LSP based formatting if MimePath has language server new 8da7ae9 Merge pull request #1996 from matthiasblaesing/lsp_formatting_fix 952f6a9 is described below commit 952f6a909b77ab5a7dfd253b988b81c912e2869a Author: Matthias Bläsing <mblaes...@doppel-helix.eu> AuthorDate: Sun Mar 1 21:05:04 2020 +0100 Only register LSP based formatting if MimePath has language server It was observed that XML formatting did not work after enabling LSP formatting. The problem was caused by the MimeLookup for application/xml that returned two ReformatTask.Factory implementations. One was the right factory, the other the Formatter provided by the LSP Client module. Instead of registering the ReformatTask.Factory of the LSP client module on the empty mime path, it is now dynamically registered by a MimeDataProvider (LspMimeDataProvider). That MimeDataProvider ensures that the lsp based formatter is only registered if a LanguageServerProvider is present on the targetted mime path. As an implementation note the LspMimeDataProvider is registered with a position, which ensures, that it is registered with higher priority than LegacyFormattersProvider which unconditionally registers a formatter. Having a higher priority (any position has higher priority than no position) ensures LspMimeDataProvider is queried first. --- .../modules/lsp/client/bindings/Formatter.java | 16 ++-- .../lsp/client/bindings/LspMimeDataProvider.java | 86 ++++++++++++++++++++++ 2 files changed, 96 insertions(+), 6 deletions(-) diff --git a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/Formatter.java b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/Formatter.java index f399461..045e490 100644 --- a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/Formatter.java +++ b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/Formatter.java @@ -19,7 +19,6 @@ package org.netbeans.modules.lsp.client.bindings; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.logging.Level; @@ -32,7 +31,6 @@ import org.eclipse.lsp4j.FormattingOptions; import org.eclipse.lsp4j.Range; import org.eclipse.lsp4j.TextDocumentIdentifier; import org.eclipse.lsp4j.TextEdit; -import org.netbeans.api.editor.mimelookup.MimeRegistration; import org.netbeans.modules.editor.NbEditorUtilities; import org.netbeans.modules.editor.indent.api.IndentUtils; import org.netbeans.modules.editor.indent.spi.Context; @@ -47,12 +45,18 @@ public class Formatter implements ReformatTask { private static final Logger LOG = Logger.getLogger(Formatter.class.getName()); - @MimeRegistration(mimeType = "", service = ReformatTask.Factory.class) public static class Factory implements ReformatTask.Factory { @Override public ReformatTask createTask(Context context) { - return new Formatter(context); + FileObject file = NbEditorUtilities.getFileObject(context.document()); + if (file != null) { + LSPBindings bindings = LSPBindings.getBindings(file); + if (bindings != null) { + return new Formatter(context); + } + } + return null; } } @@ -66,7 +70,7 @@ public class Formatter implements ReformatTask { @Override public void reformat() throws BadLocationException { FileObject file = NbEditorUtilities.getFileObject(ctx.document()); - if(file != null) { + if (file != null) { LSPBindings bindings = LSPBindings.getBindings(file); if (bindings != null) { Boolean documentFormatting = bindings.getInitResult().getCapabilities().getDocumentFormattingProvider(); @@ -120,7 +124,7 @@ public class Formatter implements ReformatTask { } private void applyTextEdits(List<TextEdit> edits) { - if(ctx.document() instanceof StyledDocument) { + if (ctx.document() instanceof StyledDocument) { NbDocument.runAtomic((StyledDocument) ctx.document(), () -> { Utils.applyEditsNoLock(ctx.document(), edits, ctx.startOffset(), ctx.endOffset()); }); diff --git a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/LspMimeDataProvider.java b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/LspMimeDataProvider.java new file mode 100644 index 0000000..9f97b1a --- /dev/null +++ b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/LspMimeDataProvider.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.lsp.client.bindings; + +import java.util.concurrent.atomic.AtomicBoolean; +import org.netbeans.api.editor.mimelookup.MimeLookup; +import org.netbeans.api.editor.mimelookup.MimePath; +import org.netbeans.modules.editor.indent.spi.ReformatTask; +import org.netbeans.modules.lsp.client.bindings.Formatter.Factory; +import org.netbeans.modules.lsp.client.spi.LanguageServerProvider; +import org.netbeans.spi.editor.mimelookup.MimeDataProvider; +import org.openide.util.Lookup; +import org.openide.util.LookupEvent; +import org.openide.util.LookupListener; +import org.openide.util.lookup.Lookups; +import org.openide.util.lookup.ProxyLookup; +import org.openide.util.lookup.ServiceProvider; + +/** + * LspMimeDataProvider allows dynamically registering the lsp based formatter + * into a MimeLookup if a matching LanguageServerProvider is found on the + * MimeLookup. + * + * <p>The assumption is: if a LanguageServerProvider is present, we want to + * provide the Formatting from it.</p> + */ +@ServiceProvider(service = MimeDataProvider.class, position = 1000) +public class LspMimeDataProvider implements MimeDataProvider { + + private static final Factory lspFormatter = new Formatter.Factory(); + private static final Lookup lspFormatterLookup = Lookups.fixed(lspFormatter); + + @Override + public Lookup getLookup(MimePath mimePath) { + return new MimeLookupMonitoringLookup(mimePath); + } + + private static class MimeLookupMonitoringLookup extends ProxyLookup implements LookupListener { + private final AtomicBoolean initialized = new AtomicBoolean(); + private final Result<LanguageServerProvider> lspResult; + + public MimeLookupMonitoringLookup(MimePath mimePath) { + // Monitor the MimeLookup - if it changes, the lookup we provided + // needs to be updated on the next query + lspResult = MimeLookup.getLookup(mimePath) + .lookupResult(LanguageServerProvider.class); + lspResult.addLookupListener(this); + } + + @Override + public void resultChanged(LookupEvent ev) { + initialized.set(false); + } + + @Override + protected void beforeLookup(Lookup.Template<?> template) { + super.beforeLookup(template); + final Class<?> clz = template.getType(); + if (ReformatTask.Factory.class.isAssignableFrom(clz)) { + if (!initialized.getAndSet(true)) { + if (lspResult.allInstances().isEmpty()) { + setLookups(); + } else { + setLookups(lspFormatterLookup); + } + } + } + } + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org For additional commands, e-mail: commits-h...@netbeans.apache.org For further information about the NetBeans mailing lists, visit: https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists