Cleanup
This commit is contained in:
@ -57,6 +57,10 @@ public interface Document {
|
||||
CharSequence subSequence(TextRegion region);
|
||||
|
||||
|
||||
/** Returns a mutable document that uses the given replace handler. */
|
||||
MutableDocument newMutableDoc(ReplaceHandler out);
|
||||
|
||||
|
||||
static Document forFile(final Path file, final Charset charset) throws IOException {
|
||||
byte[] bytes = Files.readAllBytes(requireNonNull(file));
|
||||
String text = new String(bytes, requireNonNull(charset));
|
||||
@ -65,7 +69,7 @@ public interface Document {
|
||||
|
||||
|
||||
static Document forCode(final String source) {
|
||||
return new DocumentImpl(source, ReplaceFunction.NOOP);
|
||||
return new DocumentImpl(source, ReplaceHandler.NOOP);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,17 +17,22 @@ import net.sourceforge.pmd.lang.ast.SourceCodePositioner;
|
||||
|
||||
class DocumentImpl implements MutableDocument {
|
||||
|
||||
private ReplaceFunction out;
|
||||
private ReplaceHandler out;
|
||||
/** The positioner has the original source file. */
|
||||
private SourceCodePositioner positioner;
|
||||
private SortedMap<Integer, Integer> accumulatedOffsets = new TreeMap<>();
|
||||
|
||||
|
||||
public DocumentImpl(final String source, final ReplaceFunction writer) {
|
||||
DocumentImpl(final String source, final ReplaceHandler writer) {
|
||||
this.out = writer;
|
||||
positioner = new SourceCodePositioner(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutableDocument newMutableDoc(ReplaceHandler out) {
|
||||
return new DocumentImpl(getText().toString(), out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(int beginLine, int beginColumn, final String textToInsert) {
|
||||
insert(positioner.offsetFromLineColumn(beginLine, beginColumn), textToInsert);
|
||||
@ -55,14 +60,20 @@ class DocumentImpl implements MutableDocument {
|
||||
|
||||
private RegionByOffset shiftOffset(RegionByOffset origCoords, int lenDiff) {
|
||||
ArrayList<Integer> keys = new ArrayList<>(accumulatedOffsets.keySet());
|
||||
int idx = Collections.binarySearch(keys, origCoords.getOffset());
|
||||
int idx = Collections.binarySearch(keys, origCoords.getStartOffset());
|
||||
|
||||
if (idx < 0) {
|
||||
// there is no entry exactly for this offset, so that binarySearch
|
||||
// returns the correct insertion index (but inverted)
|
||||
idx = -(idx + 1);
|
||||
} else {
|
||||
// there is an exact entry
|
||||
// since the loop below stops at idx, increment it to take that last entry into account
|
||||
idx++;
|
||||
}
|
||||
|
||||
// compute the shift accumulated by the mutations that have occurred
|
||||
// left of the start index
|
||||
int shift = 0;
|
||||
for (int i = 0; i < idx; i++) {
|
||||
shift += accumulatedOffsets.get(keys.get(i));
|
||||
@ -70,10 +81,10 @@ class DocumentImpl implements MutableDocument {
|
||||
|
||||
RegionByOffset realPos = shift == 0
|
||||
? origCoords
|
||||
// don't check it
|
||||
: new RegionByOffsetImp(origCoords.getOffset() + shift, origCoords.getLength());
|
||||
// don't check the bounds
|
||||
: new RegionByOffsetImpl(origCoords.getStartOffset() + shift, origCoords.getLength());
|
||||
|
||||
accumulatedOffsets.compute(origCoords.getOffset(), (k, v) -> {
|
||||
accumulatedOffsets.compute(origCoords.getStartOffset(), (k, v) -> {
|
||||
int s = v == null ? lenDiff : v + lenDiff;
|
||||
return s == 0 ? null : s; // delete mapping if shift is 0
|
||||
});
|
||||
@ -83,8 +94,8 @@ class DocumentImpl implements MutableDocument {
|
||||
|
||||
@Override
|
||||
public RegionByLine mapToLine(RegionByOffset region) {
|
||||
int bline = positioner.lineNumberFromOffset(region.getOffset());
|
||||
int bcol = positioner.columnFromOffset(bline, region.getOffset());
|
||||
int bline = positioner.lineNumberFromOffset(region.getStartOffset());
|
||||
int bcol = positioner.columnFromOffset(bline, region.getStartOffset());
|
||||
int eline = positioner.lineNumberFromOffset(region.getOffsetAfterEnding());
|
||||
int ecol = positioner.columnFromOffset(eline, region.getOffsetAfterEnding());
|
||||
|
||||
@ -103,7 +114,7 @@ class DocumentImpl implements MutableDocument {
|
||||
@Override
|
||||
public RegionByLine createRegion(int beginLine, int beginColumn, int endLine, int endColumn) {
|
||||
// TODO checks, positioner should return -1
|
||||
return TextRegion.newRegionByLine(beginLine, beginColumn, endLine, endColumn);
|
||||
return new RegionByLineImpl(beginLine, beginColumn, endLine, endColumn);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -114,7 +125,7 @@ class DocumentImpl implements MutableDocument {
|
||||
}
|
||||
|
||||
|
||||
return new RegionByOffsetImp(offset, length);
|
||||
return new RegionByOffsetImpl(offset, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -125,9 +136,10 @@ class DocumentImpl implements MutableDocument {
|
||||
@Override
|
||||
public CharSequence subSequence(TextRegion region) {
|
||||
RegionByOffset byOffset = region.toOffset(this);
|
||||
return getText().subSequence(byOffset.getOffset(), byOffset.getOffsetAfterEnding());
|
||||
return getText().subSequence(byOffset.getStartOffset(), byOffset.getOffsetAfterEnding());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CharSequence getUncommittedText() {
|
||||
return out.getCurrentText(this);
|
||||
|
@ -5,12 +5,9 @@
|
||||
|
||||
package net.sourceforge.pmd.document;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
@ -62,24 +59,13 @@ public interface MutableDocument extends Document, Closeable {
|
||||
CharSequence getText();
|
||||
|
||||
|
||||
/** Returns the uncommitted text. */
|
||||
/** Returns the uncommitted text, that will be committed by {@link #close()}. */
|
||||
CharSequence getUncommittedText();
|
||||
|
||||
|
||||
static MutableDocument forFile(final Path file, final Charset charset) throws IOException {
|
||||
byte[] bytes = Files.readAllBytes(requireNonNull(file));
|
||||
String text = new String(bytes, requireNonNull(charset));
|
||||
return forCode(text, ReplaceFunction.bufferedFile(text, file, charset));
|
||||
}
|
||||
|
||||
|
||||
static MutableDocument forFile(String code, final Path file, final Charset charset) {
|
||||
return forCode(code, ReplaceFunction.bufferedFile(code, file, charset));
|
||||
}
|
||||
|
||||
|
||||
static MutableDocument forCode(final String source, final ReplaceFunction writer) {
|
||||
return new DocumentImpl(source, writer);
|
||||
Document doc = Document.forFile(file, charset);
|
||||
return doc.newMutableDoc(ReplaceHandler.bufferedFile(doc.getText(), file, charset));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,14 +7,14 @@ package net.sourceforge.pmd.document;
|
||||
/**
|
||||
* Immutable implementation of the {@link TextRegion.RegionByLine} interface.
|
||||
*/
|
||||
class RegionByLineImp implements TextRegion.RegionByLine {
|
||||
class RegionByLineImpl implements TextRegion.RegionByLine {
|
||||
|
||||
private final int beginLine;
|
||||
private final int endLine;
|
||||
private final int beginColumn;
|
||||
private final int endColumn;
|
||||
|
||||
RegionByLineImp(final int beginLine, final int beginColumn, final int endLine, final int endColumn) {
|
||||
RegionByLineImpl(final int beginLine, final int beginColumn, final int endLine, final int endColumn) {
|
||||
this.beginLine = requireOver1(beginLine);
|
||||
this.endLine = requireOver1(endLine);
|
||||
this.beginColumn = requireOver1(beginColumn);
|
||||
@ -58,11 +58,6 @@ class RegionByLineImp implements TextRegion.RegionByLine {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RegionByLineImp{"
|
||||
+ "beginLine=" + beginLine
|
||||
+ ", endLine=" + endLine
|
||||
+ ", beginColumn=" + beginColumn
|
||||
+ ", endColumn=" + endColumn
|
||||
+ '}';
|
||||
return "Region(bl=" + beginLine + ", el=" + endLine + ", bc=" + beginColumn + ", ec=" + endColumn + ')';
|
||||
}
|
||||
}
|
@ -7,11 +7,11 @@ package net.sourceforge.pmd.document;
|
||||
/**
|
||||
* Immutable implementation of the {@link TextRegion.RegionByOffset} interface.
|
||||
*/
|
||||
class RegionByOffsetImp implements TextRegion.RegionByOffset {
|
||||
class RegionByOffsetImpl implements TextRegion.RegionByOffset {
|
||||
private final int offset;
|
||||
private final int length;
|
||||
|
||||
RegionByOffsetImp(final int offset, final int length) {
|
||||
RegionByOffsetImpl(final int offset, final int length) {
|
||||
this.offset = requireNonNegative(offset);
|
||||
this.length = requireNonNegative(length);
|
||||
}
|
||||
@ -25,7 +25,7 @@ class RegionByOffsetImp implements TextRegion.RegionByOffset {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOffset() {
|
||||
public int getStartOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
@ -34,4 +34,8 @@ class RegionByOffsetImp implements TextRegion.RegionByOffset {
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Region(start=" + offset + ", len=" + length + ")";
|
||||
}
|
||||
}
|
@ -12,10 +12,11 @@ import java.nio.file.Path;
|
||||
|
||||
import net.sourceforge.pmd.document.TextRegion.RegionByOffset;
|
||||
|
||||
public interface ReplaceFunction {
|
||||
/** Handles text updates for a {@link MutableDocument}. */
|
||||
public interface ReplaceHandler {
|
||||
|
||||
|
||||
ReplaceFunction NOOP = new ReplaceFunction() {
|
||||
/** Does nothing. */
|
||||
ReplaceHandler NOOP = new ReplaceHandler() {
|
||||
@Override
|
||||
public CharSequence getCurrentText(MutableDocument doc) {
|
||||
return doc.getText();
|
||||
@ -27,7 +28,7 @@ public interface ReplaceFunction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReplaceFunction commit() {
|
||||
public ReplaceHandler commit() {
|
||||
return NOOP;
|
||||
}
|
||||
};
|
||||
@ -39,24 +40,26 @@ public interface ReplaceFunction {
|
||||
void replace(RegionByOffset region, String text);
|
||||
|
||||
|
||||
/** Gets the latest text. */
|
||||
CharSequence getCurrentText(MutableDocument doc);
|
||||
|
||||
|
||||
/**
|
||||
* Commit the document (eg writing it to disk), and returns a new
|
||||
* document corresponding to the new document.
|
||||
*
|
||||
* @return An updated replace function
|
||||
*/
|
||||
ReplaceFunction commit() throws IOException;
|
||||
ReplaceHandler commit() throws IOException;
|
||||
|
||||
|
||||
/**
|
||||
* Write updates into an in-memory buffer, commit writes to disk.
|
||||
* This doesn't use any IO resources outside of the commit method.
|
||||
*/
|
||||
static ReplaceFunction bufferedFile(String originalBuffer, Path path, Charset charSet) {
|
||||
static ReplaceHandler bufferedFile(CharSequence originalBuffer, Path path, Charset charSet) {
|
||||
|
||||
return new ReplaceFunction() {
|
||||
return new ReplaceHandler() {
|
||||
|
||||
private StringBuilder builder = new StringBuilder(originalBuffer);
|
||||
|
||||
@ -67,11 +70,11 @@ public interface ReplaceFunction {
|
||||
|
||||
@Override
|
||||
public void replace(RegionByOffset region, String text) {
|
||||
builder.replace(region.getOffset(), region.getOffsetAfterEnding(), text);
|
||||
builder.replace(region.getStartOffset(), region.getOffsetAfterEnding(), text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReplaceFunction commit() throws IOException {
|
||||
public ReplaceHandler commit() throws IOException {
|
||||
String done = builder.toString();
|
||||
byte[] bytes = done.getBytes(charSet);
|
||||
Files.write(path, bytes);
|
@ -22,12 +22,7 @@ public interface TextRegion {
|
||||
*
|
||||
* @throws IndexOutOfBoundsException If the argument does not identify a valid region in the document
|
||||
*/
|
||||
RegionByLine toLine(Document document);
|
||||
|
||||
|
||||
static RegionByLine newRegionByLine(final int beginLine, final int beginColumn, final int endLine, final int endColumn) {
|
||||
return new RegionByLineImp(beginLine, beginColumn, endLine, endColumn);
|
||||
}
|
||||
RegionByLine toLineColumn(Document document);
|
||||
|
||||
|
||||
/**
|
||||
@ -66,7 +61,7 @@ public interface TextRegion {
|
||||
|
||||
|
||||
@Override
|
||||
default RegionByLine toLine(Document document) {
|
||||
default RegionByLine toLineColumn(Document document) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -82,12 +77,12 @@ public interface TextRegion {
|
||||
*/
|
||||
interface RegionByOffset extends TextRegion, Comparable<RegionByOffset> {
|
||||
|
||||
Comparator<RegionByOffset> COMPARATOR = Comparator.comparingInt(RegionByOffset::getOffset)
|
||||
Comparator<RegionByOffset> COMPARATOR = Comparator.comparingInt(RegionByOffset::getStartOffset)
|
||||
.thenComparingInt(RegionByOffset::getLength);
|
||||
|
||||
|
||||
/** 0-based, inclusive index. */
|
||||
int getOffset();
|
||||
int getStartOffset();
|
||||
|
||||
|
||||
/** Length of the region. */
|
||||
@ -96,12 +91,12 @@ public interface TextRegion {
|
||||
|
||||
/** 0-based, exclusive index. */
|
||||
default int getOffsetAfterEnding() {
|
||||
return getOffset() + getLength();
|
||||
return getStartOffset() + getLength();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
default RegionByLine toLine(Document document) {
|
||||
default RegionByLine toLineColumn(Document document) {
|
||||
return document.mapToLine(this);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user