~damien/jedit-lsp

6a31cc80f238da92a94f792c6284362b6a7ac0aa — Damien Radtke 4 months ago a0cfdfc
Improve how text edits are applied
4 files changed, 34 insertions(+), 53 deletions(-)

A lsp/RangePositions.java
M lsp/Server.java
M lsp/Utils.java
M lsp/jEditLanguageClient.java
A lsp/RangePositions.java => lsp/RangePositions.java +23 -0
@@ 0,0 1,23 @@
package lsp;

import javax.swing.text.Position;
import org.gjt.sp.jedit.Buffer;
import org.eclipse.lsp4j.Range;

public class RangePositions {
	private Position start;
	private Position end;

	public RangePositions(Buffer buffer, Range range) {
		this.start = buffer.createPosition(Utils.getOffset(buffer, range.getStart()));
		this.end = buffer.createPosition(Utils.getOffset(buffer, range.getEnd()));
	}

	public Position getStart() {
		return this.start;
	}

	public Position getEnd() {
		return this.end;
	}
}

M lsp/Server.java => lsp/Server.java +2 -2
@@ 489,7 489,7 @@ public class Server {
			DocumentFormattingParams params = new DocumentFormattingParams(textDocument, options);

			CompletableFuture<List<? extends TextEdit>> future = this.handle.getRemoteProxy().getTextDocumentService().formatting(params);
			ThreadUtilities.runInBackground(new Task(Server.this.getName() + " format " + textDocument, () -> {
			ThreadUtilities.runInDispatchThread(() -> {
				try {
					List<? extends TextEdit> edits = future.get();
					if (edits != null && !edits.isEmpty()) {


@@ 500,7 500,7 @@ public class Server {
				} catch (Exception e) {
					log(Log.ERROR, "format failed", e);
				}
			}));
			});
		} catch (Exception e) {
			log(Log.ERROR, "format failed", e);
		}

M lsp/Utils.java => lsp/Utils.java +0 -32
@@ 400,36 400,4 @@ public class Utils {
			return false;
		});
	}

	public static class BufferLine {
		private Buffer buffer;
		private int line;

		public BufferLine(Buffer buffer, int line) {
			this.buffer = buffer;
			this.line = line;
		}

		public Buffer getBuffer() {
			return this.buffer;
		}

		public int getLine() {
			return this.line;
		}

		@Override
		public boolean equals(Object ob) {
			if (!(ob instanceof BufferLine)) {
				return false;
			}
			BufferLine other = (BufferLine) ob;
			return Objects.equals(this.buffer, other.getBuffer()) && Objects.equals(this.line, other.getLine());
		}

		@Override
		public int hashCode() {
			return Objects.hash(this.buffer, this.line);
		}
	}
}

M lsp/jEditLanguageClient.java => lsp/jEditLanguageClient.java +9 -19
@@ 536,33 536,23 @@ public class jEditLanguageClient implements LanguageClient {
	public void applyTextEdits(Buffer buffer, List<? extends TextEdit> edits) {
		boolean shouldSave = !buffer.isDirty();
		buffer.beginCompoundEdit();
		Map<Utils.BufferLine, Integer> adjustments = new HashMap<>();
		List<Integer> newAdjustments = new ArrayList<>(2);

		try {
			Map<TextEdit, RangePositions> positions = new HashMap<>();
			for (TextEdit edit : edits) {
				Utils.BufferLine bufferLine = new Utils.BufferLine(buffer, edit.getRange().getStart().getLine());
				adjustments.putIfAbsent(bufferLine, 0);
				positions.put(edit, new RangePositions(buffer, edit.getRange()));
			}

				int startOffset = Utils.getOffset(buffer, edit.getRange().getStart());
				int endOffset = Utils.getOffset(buffer, edit.getRange().getEnd());
			for (TextEdit edit : edits) {
				Log.log(Log.DEBUG, this, "applying text edit: " + edit.toString());
				int startOffset = positions.get(edit).getStart().getOffset();
				int endOffset = positions.get(edit).getEnd().getOffset();
				if (startOffset < endOffset) {
					int length = endOffset - startOffset;
					int adjustedOffset = startOffset + adjustments.get(bufferLine);
					Log.log(Log.DEBUG, this, "buffer.remove(" + startOffset + " + " + adjustments.get(bufferLine) + " = " + adjustedOffset + ", " + length + ");");
					buffer.remove(adjustedOffset, length);
					newAdjustments.add(-length);
					buffer.remove(startOffset, endOffset - startOffset);
				}
				if (edit.getNewText() != null && !edit.getNewText().isEmpty()) {
					int adjustedOffset = startOffset + adjustments.get(bufferLine);
					Log.log(Log.DEBUG, this, "buffer.insert(" + startOffset + " + " + adjustments.get(bufferLine) + " = " + adjustedOffset + ", \"" + edit.getNewText() + "\");");
					buffer.insert(adjustedOffset, edit.getNewText());
					newAdjustments.add(edit.getNewText().length());
				}
				for (Integer newAdjustment : newAdjustments) {
					adjustments.put(bufferLine, adjustments.get(bufferLine) + newAdjustment);
					buffer.insert(startOffset, edit.getNewText());
				}
				newAdjustments.clear();
			}
		} finally {
			buffer.endCompoundEdit();