Skip to content

Commit

Permalink
Get tabWidth / insertSpaces from editor preferences store
Browse files Browse the repository at this point in the history
Fixes eclipse#245

Signed-off-by: azerr <azerr@redhat.com>
  • Loading branch information
angelozerr committed Apr 3, 2023
1 parent e49962d commit 092bf5f
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,30 @@
*******************************************************************************/
package org.eclipse.lsp4e.test.format;

import static org.eclipse.lsp4e.test.TestUtils.numberOfChangesIs;
import static org.eclipse.lsp4e.test.TestUtils.waitForAndAssertCondition;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.ArrayList;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutionException;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.lsp4e.LSPEclipseUtils;
import org.eclipse.lsp4e.VersionedEdits;
import org.eclipse.lsp4e.operations.format.LSPFormatter;
import org.eclipse.lsp4e.test.AllCleanRule;
import org.eclipse.lsp4e.test.TestUtils;
import org.eclipse.lsp4e.tests.mock.MockLanguageServer;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.texteditor.ITextEditor;
import org.junit.Before;
import org.junit.Rule;
Expand All @@ -60,94 +51,71 @@ public void setUp() throws CoreException {
}

@Test
public void testFormattingInvalidDocument() throws Exception {
public void testFormattingInvalidDocument() throws InterruptedException, ExecutionException {
LSPFormatter formatter = new LSPFormatter();
ITextSelection selection = TextSelection.emptySelection();

Optional<VersionedEdits> edits = formatter.requestFormatting(new Document(), selection).get();
assertTrue(edits.isEmpty());
List<? extends TextEdit> edits = formatter.requestFormatting(new Document(), selection, null).get();
assertEquals(0, edits.size());
}

@Test
public void testFormattingNoChanges() throws Exception {
public void testFormattingNoChanges()
throws CoreException, InterruptedException, ExecutionException {
MockLanguageServer.INSTANCE.setFormattingTextEdits(Collections.emptyList());

IFile file = TestUtils.createUniqueTestFile(project, "Formatting Other Text");
IEditorPart editor = TestUtils.openEditor(file);
ITextViewer viewer = LSPEclipseUtils.getTextViewer(editor);
ITextEditor textEditor = (ITextEditor) TestUtils.openEditor(file);
ITextViewer viewer = LSPEclipseUtils.getTextViewer(textEditor);

LSPFormatter formatter = new LSPFormatter();
ISelection selection = viewer.getSelectionProvider().getSelection();

Optional<VersionedEdits> edits = formatter.requestFormatting(viewer.getDocument(), (ITextSelection) selection).get();
assertTrue(edits.isPresent());
editor.getSite().getShell().getDisplay().syncExec(() -> {
try {
edits.get().apply();
} catch (ConcurrentModificationException | BadLocationException e) {
fail(e.getMessage());
}
});
ITextEditor textEditor = (ITextEditor) editor;
List<? extends TextEdit> edits = formatter.requestFormatting(viewer.getDocument(), (ITextSelection) selection, textEditor)
.get();
textEditor.getSite().getShell().getDisplay().syncExec(() -> formatter.applyEdits(viewer.getDocument(), edits));

textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
assertEquals("Formatting Other Text", viewer.getDocument().get());

TestUtils.closeEditor(editor, false);
TestUtils.closeEditor(textEditor, false);
}

@Test
public void testFormatting()
throws Exception {
throws CoreException, InterruptedException, ExecutionException {
List<TextEdit> formattingTextEdits = new ArrayList<>();
formattingTextEdits.add(new TextEdit(new Range(new Position(0, 0), new Position(0, 1)), "MyF"));
formattingTextEdits.add(new TextEdit(new Range(new Position(0, 10), new Position(0, 11)), ""));
formattingTextEdits.add(new TextEdit(new Range(new Position(0, 21), new Position(0, 21)), " Second"));
MockLanguageServer.INSTANCE.setFormattingTextEdits(formattingTextEdits);

IFile file = TestUtils.createUniqueTestFile(project, "Formatting Other Text");
IEditorPart editor = TestUtils.openEditor(file);
ITextViewer viewer = LSPEclipseUtils.getTextViewer(editor);
ITextEditor textEditor = (ITextEditor) TestUtils.openEditor(file);
ITextViewer viewer = LSPEclipseUtils.getTextViewer(textEditor);

LSPFormatter formatter = new LSPFormatter();
ISelection selection = viewer.getSelectionProvider().getSelection();

Optional<VersionedEdits> edits = formatter.requestFormatting(viewer.getDocument(), (ITextSelection) selection).get();
assertTrue(edits.isPresent());
editor.getSite().getShell().getDisplay().syncExec(() -> {
try {
edits.get().apply();
} catch (ConcurrentModificationException | BadLocationException e) {
fail(e.getMessage());
}
});

ITextEditor textEditor = (ITextEditor) editor;
List<? extends TextEdit> edits = formatter.requestFormatting(viewer.getDocument(), (ITextSelection) selection, textEditor)
.get();
textEditor.getSite().getShell().getDisplay().syncExec(() -> formatter.applyEdits(viewer.getDocument(), edits));

textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
assertEquals("MyFormattingOther Text Second", viewer.getDocument().get());

TestUtils.closeEditor(editor, false);
TestUtils.closeEditor(textEditor, false);
}

@Test
public void testOutdatedFormatting()
throws CoreException, InterruptedException, ExecutionException, BadLocationException {
MockLanguageServer.INSTANCE.setFormattingTextEdits(Collections.emptyList());

IFile file = TestUtils.createUniqueTestFile(project, "Formatting Other Text");
IEditorPart editor = TestUtils.openEditor(file);
ITextViewer viewer = LSPEclipseUtils.getTextViewer(editor);

public void testNullFormatting() {
IDocument document = new Document("Formatting Other Text");
LSPFormatter formatter = new LSPFormatter();
ISelection selection = viewer.getSelectionProvider().getSelection();

Optional<VersionedEdits> edits = formatter.requestFormatting(viewer.getDocument(), (ITextSelection) selection).get();
assertTrue(edits.isPresent());
viewer.getDocument().replace(0, 0, "Hello");
waitForAndAssertCondition(1_000, numberOfChangesIs(1));

assertThrows(ConcurrentModificationException.class, () -> edits.get().apply());
// null is an acceptable response for no changes
formatter.applyEdits(document, null);

TestUtils.closeEditor(editor, false);
assertEquals("Formatting Other Text", document.get());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ protected void formatFile(final @NonNull IFile file, final IProgressMonitor moni

monitor.setTaskName(NLS.bind(Messages.LSPFormatFilesHandler_FormattingFile, file.getFullPath()));
final Optional<VersionedEdits> formatting = formatter.requestFormatting(doc,
new TextSelection(0, 0)).get(SINGLE_FILE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
new TextSelection(0, 0), null).get(SINGLE_FILE_TIMEOUT_MS, TimeUnit.MILLISECONDS);

formatting.ifPresent(edits -> {
docProvider.aboutToChange(doc);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import java.util.ConcurrentModificationException;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jface.text.BadLocationException;
Expand All @@ -23,16 +24,16 @@
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.lsp4e.LSPEclipseUtils;
import org.eclipse.lsp4e.LanguageServerPlugin;
import org.eclipse.lsp4e.LanguageServers;
import org.eclipse.lsp4e.ServerMessageHandler;
import org.eclipse.lsp4e.internal.LSPDocumentAbstractHandler;
import org.eclipse.lsp4e.ui.Messages;
import org.eclipse.lsp4e.ui.UI;
import org.eclipse.lsp4j.MessageParams;
import org.eclipse.lsp4j.MessageType;
import org.eclipse.ui.handlers.HandlerUtil;
import org.eclipse.ui.texteditor.ITextEditor;

public class LSPFormatHandler extends LSPDocumentAbstractHandler {
public class LSPFormatHandler extends AbstractHandler {

private final LSPFormatter formatter = new LSPFormatter();

Expand All @@ -50,7 +51,7 @@ public Object execute(final ExecutionEvent event) throws ExecutionException {
return null;

try {
formatter.requestFormatting(doc, textSelection)
formatter.requestFormatting(doc, textSelection, textEditor)
.thenAcceptAsync(result -> {
result.ifPresent(edits -> {
try {
Expand All @@ -72,7 +73,22 @@ public Object execute(final ExecutionEvent event) throws ExecutionException {
}

@Override
public void setEnabled(Object evaluationContext) {
setEnabled(LSPFormatter::supportsFormatting, this::hasSelection);
public boolean isEnabled() {
final ITextEditor textEditor = UI.getActiveTextEditor();
if (textEditor == null)
return false;

final ISelection selection = textEditor.getSelectionProvider().getSelection();
if (!(selection instanceof ITextSelection) || selection.isEmpty())
return false;

final IDocument doc = LSPEclipseUtils.getDocument(textEditor);
if (doc == null)
return false;

return LanguageServers
.forDocument(doc)
.withFilter(LSPFormatter::supportsFormatting)
.anyMatching();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,17 @@
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
import org.eclipse.ui.texteditor.ITextEditor;

public class LSPFormatter {
public CompletableFuture<Optional<VersionedEdits>> requestFormatting(@NonNull IDocument document, @NonNull ITextSelection textSelection) throws BadLocationException {

public CompletableFuture<Optional<VersionedEdits>> requestFormatting(@NonNull IDocument document, @NonNull ITextSelection textSelection, ITextEditor textEditor) throws BadLocationException {
URI uri = LSPEclipseUtils.toUri(document);
if (uri == null) {
return CompletableFuture.completedFuture(Optional.empty());
}
LanguageServerDocumentExecutor executor = LanguageServers.forDocument(document).withFilter(LSPFormatter::supportsFormatting);
FormattingOptions formatOptions = getFormatOptions();
FormattingOptions formatOptions = getFormatOptions(textEditor);
TextDocumentIdentifier docId = new TextDocumentIdentifier(uri.toString());

DocumentRangeFormattingParams rangeParams = getRangeFormattingParams(document, textSelection, formatOptions,
Expand Down Expand Up @@ -90,13 +92,27 @@ private DocumentRangeFormattingParams getRangeFormattingParams(IDocument documen
return rangeParams;
}

private FormattingOptions getFormatOptions() {
IPreferenceStore store = EditorsUI.getPreferenceStore();
int tabWidth = store.getInt(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH);
boolean insertSpaces = store.getBoolean(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS);
private static FormattingOptions getFormatOptions(@NonNull ITextEditor textEditor) {
IPreferenceStore editorPreferenceStore = textEditor != null ? textEditor.getAdapter(IPreferenceStore.class) : null;
int tabWidth = getInt(editorPreferenceStore, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH);
boolean insertSpaces = getBoolean(editorPreferenceStore, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS);
return new FormattingOptions(tabWidth, insertSpaces);
}

private static int getInt(IPreferenceStore editorPreferenceStore, String name) {
if (editorPreferenceStore != null && editorPreferenceStore.contains(name)) {
return editorPreferenceStore.getInt(name);
}
return EditorsUI.getPreferenceStore().getInt(name);
}

private static boolean getBoolean(IPreferenceStore editorPreferenceStore, String name) {
if (editorPreferenceStore != null && editorPreferenceStore.contains(name)) {
return editorPreferenceStore.getBoolean(name);
}
return EditorsUI.getPreferenceStore().getBoolean(name);
}

private static boolean isDocumentRangeFormattingSupported(ServerCapabilities capabilities) {
return LSPEclipseUtils.hasCapability(capabilities.getDocumentRangeFormattingProvider());
}
Expand Down

0 comments on commit 092bf5f

Please sign in to comment.