You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by ma...@apache.org on 2020/02/29 09:34:56 UTC
[netbeans] branch master updated: Hook formating/rangeFormating
into LSP Client
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 c464af0 Hook formating/rangeFormating into LSP Client
new a5aae4a Merge pull request #1955 from matthiasblaesing/lsp_formating
c464af0 is described below
commit c464af06b7a0b94f65fa8cdd5d2533863a9746a3
Author: Matthias Bläsing <mb...@doppel-helix.eu>
AuthorDate: Tue Feb 18 22:30:04 2020 +0100
Hook formating/rangeFormating into LSP Client
---
.../src/org/netbeans/modules/lsp/client/Utils.java | 41 ++++++-
.../modules/lsp/client/bindings/Formatter.java | 136 +++++++++++++++++++++
2 files changed, 174 insertions(+), 3 deletions(-)
diff --git a/ide/lsp.client/src/org/netbeans/modules/lsp/client/Utils.java b/ide/lsp.client/src/org/netbeans/modules/lsp/client/Utils.java
index c67722b..278cfbc 100644
--- a/ide/lsp.client/src/org/netbeans/modules/lsp/client/Utils.java
+++ b/ide/lsp.client/src/org/netbeans/modules/lsp/client/Utils.java
@@ -24,6 +24,7 @@ import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
+import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
@@ -140,15 +141,37 @@ public class Utils {
}
public static void applyEditsNoLock(Document doc, List<? extends TextEdit> edits) {
+ applyEditsNoLock(doc, edits, null, null);
+ }
+
+ /**
+ * Apply edits to the document. The edits can be filtered to only cover
+ * parts of the documents.
+ *
+ * @param doc {@link Document} the edits shall be applied to
+ * @param edits list {@link TextEdit} to apply
+ * @param startLimit if not {@code null} only edits with a {@code start}
+ * larger than or equals to this offset are considered.
+ * The offset is expected to be apply to the original
+ * state of the document.
+ * @param endLimit if not {@code null} only edits with an {@code end}
+ * lower than this offset are considered. The offset is
+ * expected to be apply to the original state of the
+ * document.
+ */
+ public static void applyEditsNoLock(Document doc, List<? extends TextEdit> edits, Integer startLimit, Integer endLimit) {
edits
.stream()
- .sorted((te1, te2) -> te1.getRange().getEnd().getLine() == te2.getRange().getEnd().getLine() ? te1.getRange().getEnd().getCharacter() - te2.getRange().getEnd().getCharacter() : te1.getRange().getEnd().getLine() - te2.getRange().getEnd().getLine())
+ .sorted(rangeReverseSort)
.forEach(te -> {
try {
int start = Utils.getOffset(doc, te.getRange().getStart());
int end = Utils.getOffset(doc, te.getRange().getEnd());
- doc.remove(start, end - start);
- doc.insertString(start, te.getNewText(), null);
+ if ((startLimit == null || start >= startLimit)
+ && (endLimit == null || end < endLimit)) {
+ doc.remove(start, end - start);
+ doc.insertString(start, te.getNewText(), null);
+ }
} catch (BadLocationException ex) {
Exceptions.printStackTrace(ex);
}
@@ -247,4 +270,16 @@ public class Utils {
Exceptions.printStackTrace(ex);
}
}
+
+ private static final Comparator<TextEdit> rangeReverseSort = (s1, s2) -> {
+ int l1 = s1.getRange().getEnd().getLine();
+ int l2 = s2.getRange().getEnd().getLine();
+ int c1 = s1.getRange().getEnd().getCharacter();
+ int c2 = s2.getRange().getEnd().getCharacter();
+ if (l1 != l2) {
+ return l2 - l1;
+ } else {
+ return c2 - c1;
+ }
+ };
}
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
new file mode 100644
index 0000000..f399461
--- /dev/null
+++ b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/Formatter.java
@@ -0,0 +1,136 @@
+/*
+ * 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.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.StyledDocument;
+import org.eclipse.lsp4j.DocumentFormattingParams;
+import org.eclipse.lsp4j.DocumentRangeFormattingParams;
+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;
+import org.netbeans.modules.editor.indent.spi.ExtraLock;
+import org.netbeans.modules.editor.indent.spi.ReformatTask;
+import org.netbeans.modules.lsp.client.LSPBindings;
+import org.netbeans.modules.lsp.client.Utils;
+import org.openide.filesystems.FileObject;
+import org.openide.text.NbDocument;
+
+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);
+ }
+
+ }
+
+ private final Context ctx;
+
+ public Formatter(Context ctx) {
+ this.ctx = ctx;
+ }
+
+ @Override
+ public void reformat() throws BadLocationException {
+ FileObject file = NbEditorUtilities.getFileObject(ctx.document());
+ if(file != null) {
+ LSPBindings bindings = LSPBindings.getBindings(file);
+ if (bindings != null) {
+ Boolean documentFormatting = bindings.getInitResult().getCapabilities().getDocumentFormattingProvider();
+ Boolean rangeFormatting = bindings.getInitResult().getCapabilities().getDocumentRangeFormattingProvider();
+ if (rangeFormatting != null && rangeFormatting) {
+ rangeFormat(file, bindings);
+ } else if (documentFormatting != null && documentFormatting) {
+ documentFormat(file, bindings);
+ }
+ }
+ }
+ }
+
+ private void rangeFormat(FileObject fo, LSPBindings bindings) throws BadLocationException {
+ DocumentRangeFormattingParams drfp = new DocumentRangeFormattingParams();
+ drfp.setTextDocument(new TextDocumentIdentifier(Utils.toURI(fo)));
+ drfp.setOptions(new FormattingOptions(
+ IndentUtils.indentLevelSize(ctx.document()),
+ IndentUtils.isExpandTabs(ctx.document())));
+ drfp.setRange(new Range(
+ Utils.createPosition(ctx.document(), ctx.startOffset()),
+ Utils.createPosition(ctx.document(), ctx.endOffset())));
+ List<TextEdit> edits = new ArrayList<>();
+ try {
+ edits = new ArrayList<>(bindings.getTextDocumentService().rangeFormatting(drfp).get());
+ } catch (InterruptedException | ExecutionException ex) {
+ LOG.log(Level.INFO,
+ String.format("LSP document rangeFormat failed for {0}", fo),
+ ex);
+ }
+
+ applyTextEdits(edits);
+ }
+
+ private void documentFormat(FileObject fo, LSPBindings bindings) throws BadLocationException {
+ DocumentFormattingParams dfp = new DocumentFormattingParams();
+ dfp.setTextDocument(new TextDocumentIdentifier(Utils.toURI(fo)));
+ dfp.setOptions(new FormattingOptions(
+ IndentUtils.indentLevelSize(ctx.document()),
+ IndentUtils.isExpandTabs(ctx.document())));
+ List<TextEdit> edits = new ArrayList<>();
+ try {
+ edits.addAll(bindings.getTextDocumentService().formatting(dfp).get());
+ } catch (InterruptedException | ExecutionException ex) {
+ LOG.log(Level.INFO,
+ String.format("LSP document format failed for {0}", fo),
+ ex);
+ }
+
+ applyTextEdits(edits);
+ }
+
+ private void applyTextEdits(List<TextEdit> edits) {
+ if(ctx.document() instanceof StyledDocument) {
+ NbDocument.runAtomic((StyledDocument) ctx.document(), () -> {
+ Utils.applyEditsNoLock(ctx.document(), edits, ctx.startOffset(), ctx.endOffset());
+ });
+ } else {
+ Utils.applyEditsNoLock(ctx.document(), edits, ctx.startOffset(), ctx.endOffset());
+ }
+ }
+
+ @Override
+ public ExtraLock reformatLock() {
+ return null;
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists