Copy LineTracker related code from eclipse
This commit is contained in:
@@ -26,4 +26,8 @@ public class Assert {
|
||||
}
|
||||
}
|
||||
|
||||
public static void isTrue(boolean b) {
|
||||
isLegal(b);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,297 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2000, 2015 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.util.text.linetracker;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.ide.vscode.commons.util.BadLocationException;
|
||||
import org.springframework.ide.vscode.commons.util.text.IRegion;
|
||||
|
||||
/**
|
||||
* Abstract implementation of <code>ILineTracker</code>. It lets the definition of line
|
||||
* delimiters to subclasses. Assuming that '\n' is the only line delimiter, this abstract
|
||||
* implementation defines the following line scheme:
|
||||
* <ul>
|
||||
* <li> "" -> [0,0]
|
||||
* <li> "a" -> [0,1]
|
||||
* <li> "\n" -> [0,1], [1,0]
|
||||
* <li> "a\n" -> [0,2], [2,0]
|
||||
* <li> "a\nb" -> [0,2], [2,1]
|
||||
* <li> "a\nbc\n" -> [0,2], [2,3], [5,0]
|
||||
* </ul>
|
||||
* <p>
|
||||
* This class must be subclassed.
|
||||
* </p>
|
||||
*/
|
||||
public abstract class AbstractLineTracker implements ILineTracker, ILineTrackerExtension {
|
||||
|
||||
/**
|
||||
* Tells whether this class is in debug mode.
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
private static final boolean DEBUG= false;
|
||||
|
||||
/**
|
||||
* Combines the information of the occurrence of a line delimiter. <code>delimiterIndex</code>
|
||||
* is the index where a line delimiter starts, whereas <code>delimiterLength</code>,
|
||||
* indicates the length of the delimiter.
|
||||
*/
|
||||
protected static class DelimiterInfo {
|
||||
public int delimiterIndex;
|
||||
public int delimiterLength;
|
||||
public String delimiter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Representation of replace and set requests.
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
protected static class Request {
|
||||
public final int offset;
|
||||
public final int length;
|
||||
public final String text;
|
||||
|
||||
public Request(int offset, int length, String text) {
|
||||
this.offset= offset;
|
||||
this.length= length;
|
||||
this.text= text;
|
||||
}
|
||||
|
||||
public Request(String text) {
|
||||
this.offset= -1;
|
||||
this.length= -1;
|
||||
this.text= text;
|
||||
}
|
||||
|
||||
public boolean isReplaceRequest() {
|
||||
return this.offset > -1 && this.length > -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The active rewrite session.
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
private DocumentRewriteSession fActiveRewriteSession;
|
||||
|
||||
/**
|
||||
* The list of pending requests.
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
private List<Request> fPendingRequests;
|
||||
/**
|
||||
* The implementation that this tracker delegates to.
|
||||
*
|
||||
* @since 3.2
|
||||
*/
|
||||
private ILineTracker fDelegate= new ListLineTracker() {
|
||||
@Override
|
||||
public String[] getLegalLineDelimiters() {
|
||||
return AbstractLineTracker.this.getLegalLineDelimiters();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DelimiterInfo nextDelimiterInfo(String text, int offset) {
|
||||
return AbstractLineTracker.this.nextDelimiterInfo(text, offset);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Whether the delegate needs conversion when the line structure is modified.
|
||||
*/
|
||||
private boolean fNeedsConversion= true;
|
||||
|
||||
/**
|
||||
* Creates a new line tracker.
|
||||
*/
|
||||
protected AbstractLineTracker() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int computeNumberOfLines(String text) {
|
||||
return fDelegate.computeNumberOfLines(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLineDelimiter(int line) throws BadLocationException {
|
||||
checkRewriteSession();
|
||||
return fDelegate.getLineDelimiter(line);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRegion getLineInformation(int line) throws BadLocationException {
|
||||
checkRewriteSession();
|
||||
return fDelegate.getLineInformation(line);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRegion getLineInformationOfOffset(int offset) throws BadLocationException {
|
||||
checkRewriteSession();
|
||||
return fDelegate.getLineInformationOfOffset(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLineLength(int line) throws BadLocationException {
|
||||
checkRewriteSession();
|
||||
return fDelegate.getLineLength(line);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLineNumberOfOffset(int offset) throws BadLocationException {
|
||||
checkRewriteSession();
|
||||
return fDelegate.getLineNumberOfOffset(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLineOffset(int line) throws BadLocationException {
|
||||
checkRewriteSession();
|
||||
return fDelegate.getLineOffset(line);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfLines() {
|
||||
try {
|
||||
checkRewriteSession();
|
||||
} catch (BadLocationException x) {
|
||||
// TODO there is currently no way to communicate that exception back to the document
|
||||
}
|
||||
return fDelegate.getNumberOfLines();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfLines(int offset, int length) throws BadLocationException {
|
||||
checkRewriteSession();
|
||||
return fDelegate.getNumberOfLines(offset, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(String text) {
|
||||
if (hasActiveRewriteSession()) {
|
||||
fPendingRequests.clear();
|
||||
fPendingRequests.add(new Request(text));
|
||||
return;
|
||||
}
|
||||
|
||||
fDelegate.set(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replace(int offset, int length, String text) throws BadLocationException {
|
||||
if (hasActiveRewriteSession()) {
|
||||
fPendingRequests.add(new Request(offset, length, text));
|
||||
return;
|
||||
}
|
||||
|
||||
checkImplementation();
|
||||
|
||||
fDelegate.replace(offset, length, text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the implementation to be a {@link TreeLineTracker} if it isn't yet.
|
||||
*
|
||||
* @since 3.2
|
||||
*/
|
||||
private void checkImplementation() {
|
||||
if (fNeedsConversion) {
|
||||
fNeedsConversion= false;
|
||||
fDelegate= new TreeLineTracker((ListLineTracker) fDelegate) {
|
||||
@Override
|
||||
protected DelimiterInfo nextDelimiterInfo(String text, int offset) {
|
||||
return AbstractLineTracker.this.nextDelimiterInfo(text, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getLegalLineDelimiters() {
|
||||
return AbstractLineTracker.this.getLegalLineDelimiters();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the information about the first delimiter found in the given text starting at the
|
||||
* given offset.
|
||||
*
|
||||
* @param text the text to be searched
|
||||
* @param offset the offset in the given text
|
||||
* @return the information of the first found delimiter or <code>null</code>
|
||||
*/
|
||||
protected abstract DelimiterInfo nextDelimiterInfo(String text, int offset);
|
||||
|
||||
@Override
|
||||
public final void startRewriteSession(DocumentRewriteSession session) {
|
||||
if (fActiveRewriteSession != null)
|
||||
throw new IllegalStateException();
|
||||
fActiveRewriteSession= session;
|
||||
fPendingRequests= new ArrayList<>(20);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void stopRewriteSession(DocumentRewriteSession session, String text) {
|
||||
if (fActiveRewriteSession == session) {
|
||||
fActiveRewriteSession= null;
|
||||
fPendingRequests= null;
|
||||
set(text);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether there's an active rewrite session.
|
||||
*
|
||||
* @return <code>true</code> if there is an active rewrite session, <code>false</code>
|
||||
* otherwise
|
||||
* @since 3.1
|
||||
*/
|
||||
protected final boolean hasActiveRewriteSession() {
|
||||
return fActiveRewriteSession != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the active rewrite session.
|
||||
*
|
||||
* @throws BadLocationException in case the recorded requests cannot be processed correctly
|
||||
* @since 3.1
|
||||
*/
|
||||
protected final void flushRewriteSession() throws BadLocationException {
|
||||
if (DEBUG)
|
||||
System.out.println("AbstractLineTracker: Flushing rewrite session: " + fActiveRewriteSession); //$NON-NLS-1$
|
||||
|
||||
Iterator<Request> e= fPendingRequests.iterator();
|
||||
|
||||
fPendingRequests= null;
|
||||
fActiveRewriteSession= null;
|
||||
|
||||
while (e.hasNext()) {
|
||||
Request request= e.next();
|
||||
if (request.isReplaceRequest())
|
||||
replace(request.offset, request.length, request.text);
|
||||
else
|
||||
set(request.text);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the presence of a rewrite session and flushes it.
|
||||
*
|
||||
* @throws BadLocationException in case flushing does not succeed
|
||||
* @since 3.1
|
||||
*/
|
||||
protected final void checkRewriteSession() throws BadLocationException {
|
||||
if (hasActiveRewriteSession())
|
||||
flushRewriteSession();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package org.springframework.ide.vscode.commons.util.text.linetracker;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Standard implementation of {@link org.eclipse.jface.text.ILineTracker}.
|
||||
* <p>
|
||||
* The line tracker considers the three common line delimiters which are '\n',
|
||||
* '\r', '\r\n'.
|
||||
* <p>
|
||||
* This class is not intended to be subclassed.
|
||||
* </p>
|
||||
* @noextend This class is not intended to be subclassed by clients.
|
||||
*/
|
||||
public class DefaultLineTracker extends AbstractLineTracker {
|
||||
|
||||
/** The predefined delimiters of this tracker */
|
||||
public final static String[] DELIMITERS= { "\r", "\n", "\r\n" }; //$NON-NLS-3$ //$NON-NLS-1$ //$NON-NLS-2$
|
||||
/** A predefined delimiter information which is always reused as return value */
|
||||
private DelimiterInfo fDelimiterInfo= new DelimiterInfo();
|
||||
|
||||
|
||||
/**
|
||||
* Creates a standard line tracker.
|
||||
*/
|
||||
public DefaultLineTracker() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getLegalLineDelimiters() {
|
||||
return Arrays.copyOf(DELIMITERS, DELIMITERS.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DelimiterInfo nextDelimiterInfo(String text, int offset) {
|
||||
|
||||
char ch;
|
||||
int length= text.length();
|
||||
for (int i= offset; i < length; i++) {
|
||||
|
||||
ch= text.charAt(i);
|
||||
if (ch == '\r') {
|
||||
|
||||
if (i + 1 < length) {
|
||||
if (text.charAt(i + 1) == '\n') {
|
||||
fDelimiterInfo.delimiter= DELIMITERS[2];
|
||||
fDelimiterInfo.delimiterIndex= i;
|
||||
fDelimiterInfo.delimiterLength= 2;
|
||||
return fDelimiterInfo;
|
||||
}
|
||||
}
|
||||
|
||||
fDelimiterInfo.delimiter= DELIMITERS[0];
|
||||
fDelimiterInfo.delimiterIndex= i;
|
||||
fDelimiterInfo.delimiterLength= 1;
|
||||
return fDelimiterInfo;
|
||||
|
||||
} else if (ch == '\n') {
|
||||
|
||||
fDelimiterInfo.delimiter= DELIMITERS[1];
|
||||
fDelimiterInfo.delimiterIndex= i;
|
||||
fDelimiterInfo.delimiterLength= 1;
|
||||
return fDelimiterInfo;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2000, 2005 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.util.text.linetracker;
|
||||
|
||||
|
||||
/**
|
||||
* A document rewrite session.
|
||||
*
|
||||
* @see org.eclipse.jface.text.IDocument
|
||||
* @see org.eclipse.jface.text.IDocumentExtension4
|
||||
* @see org.eclipse.jface.text.IDocumentRewriteSessionListener
|
||||
* @since 3.1
|
||||
*/
|
||||
public class DocumentRewriteSession {
|
||||
|
||||
private DocumentRewriteSessionType fSessionType;
|
||||
|
||||
/**
|
||||
* Prohibit package external object creation.
|
||||
*
|
||||
* @param sessionType the type of this session
|
||||
*/
|
||||
protected DocumentRewriteSession(DocumentRewriteSessionType sessionType) {
|
||||
fSessionType= sessionType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of this session.
|
||||
*
|
||||
* @return the type of this session
|
||||
*/
|
||||
public DocumentRewriteSessionType getSessionType() {
|
||||
return fSessionType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuffer().append(hashCode()).toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2000, 2008 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.util.text.linetracker;
|
||||
|
||||
|
||||
/**
|
||||
* A document rewrite session type.
|
||||
* <p>
|
||||
* Allowed values are:
|
||||
* <ul>
|
||||
* <li>{@link DocumentRewriteSessionType#UNRESTRICTED}</li>
|
||||
* <li>{@link DocumentRewriteSessionType#UNRESTRICTED_SMALL} (since 3.3)</li>
|
||||
* <li>{@link DocumentRewriteSessionType#SEQUENTIAL}</li>
|
||||
* <li>{@link DocumentRewriteSessionType#STRICTLY_SEQUENTIAL}</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* @see org.eclipse.jface.text.IDocument
|
||||
* @see org.eclipse.jface.text.IDocumentExtension4
|
||||
* @see org.eclipse.jface.text.IDocumentRewriteSessionListener
|
||||
* @since 3.1
|
||||
*/
|
||||
public class DocumentRewriteSessionType {
|
||||
|
||||
/**
|
||||
* An unrestricted rewrite session is a sequence of unrestricted replace operations. This
|
||||
* session type should only be used for <em>large</em> operations that touch more than about
|
||||
* fifty lines. Use {@link #UNRESTRICTED_SMALL} for small operations.
|
||||
*/
|
||||
public final static DocumentRewriteSessionType UNRESTRICTED= new DocumentRewriteSessionType();
|
||||
/**
|
||||
* An small unrestricted rewrite session is a short sequence of unrestricted replace operations.
|
||||
* This should be used for changes that touch less than about fifty lines.
|
||||
*
|
||||
* @since 3.3
|
||||
*/
|
||||
public final static DocumentRewriteSessionType UNRESTRICTED_SMALL= new DocumentRewriteSessionType();
|
||||
/**
|
||||
* A sequential rewrite session is a sequence of non-overlapping replace
|
||||
* operations starting at an arbitrary document offset.
|
||||
*/
|
||||
public final static DocumentRewriteSessionType SEQUENTIAL= new DocumentRewriteSessionType();
|
||||
/**
|
||||
* A strictly sequential rewrite session is a sequence of non-overlapping
|
||||
* replace operations from the start of the document to its end.
|
||||
*/
|
||||
public final static DocumentRewriteSessionType STRICTLY_SEQUENTIAL= new DocumentRewriteSessionType();
|
||||
|
||||
|
||||
/**
|
||||
* Prohibit external object creation.
|
||||
*/
|
||||
private DocumentRewriteSessionType() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2000, 2009 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.util.text.linetracker;
|
||||
|
||||
import org.springframework.ide.vscode.commons.util.BadLocationException;
|
||||
import org.springframework.ide.vscode.commons.util.text.IRegion;
|
||||
|
||||
/**
|
||||
* A line tracker maps character positions to line numbers and vice versa.
|
||||
* Initially the line tracker is informed about its underlying text in order to
|
||||
* initialize the mapping information. After that, the line tracker is informed
|
||||
* about all changes of the underlying text allowing for incremental updates of
|
||||
* the mapping information. It is the client's responsibility to actively inform
|
||||
* the line tacker about text changes. For example, when using a line tracker in
|
||||
* combination with a document the document controls the line tracker.
|
||||
* <p>
|
||||
* In order to provide backward compatibility for clients of <code>ILineTracker</code>, extension
|
||||
* interfaces are used to provide a means of evolution. The following extension interfaces
|
||||
* exist:
|
||||
* <ul>
|
||||
* <li> {@link org.springframework.ide.org.springframework.ide.vscode.commons.util.linetracker.ILineTrackerExtension} since version 3.1 introducing the concept
|
||||
* of rewrite sessions.</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* Clients may implement this interface or use the standard implementation
|
||||
* </p>
|
||||
* {@link org.eclipse.jface.text.DefaultLineTracker}or
|
||||
* {@link org.eclipse.jface.text.ConfigurableLineTracker}.
|
||||
*/
|
||||
public interface ILineTracker {
|
||||
|
||||
/**
|
||||
* Returns the strings this tracker considers as legal line delimiters.
|
||||
*
|
||||
* @return the legal line delimiters
|
||||
*/
|
||||
String[] getLegalLineDelimiters();
|
||||
|
||||
/**
|
||||
* Returns the line delimiter of the specified line. Returns <code>null</code> if the
|
||||
* line is not closed with a line delimiter.
|
||||
*
|
||||
* @param line the line whose line delimiter is queried
|
||||
* @return the line's delimiter or <code>null</code> if line does not have a delimiter
|
||||
* @exception BadLocationException if the line number is invalid in this tracker's line structure
|
||||
*/
|
||||
String getLineDelimiter(int line) throws BadLocationException;
|
||||
|
||||
/**
|
||||
* Computes the number of lines in the given text.
|
||||
*
|
||||
* @param text the text whose number of lines should be computed
|
||||
* @return the number of lines in the given text
|
||||
*/
|
||||
int computeNumberOfLines(String text);
|
||||
|
||||
/**
|
||||
* Returns the number of lines.
|
||||
* <p>
|
||||
* Note that a document always has at least one line.
|
||||
* </p>
|
||||
*
|
||||
* @return the number of lines in this tracker's line structure
|
||||
*/
|
||||
int getNumberOfLines();
|
||||
|
||||
/**
|
||||
* Returns the number of lines which are occupied by a given text range.
|
||||
*
|
||||
* @param offset the offset of the specified text range
|
||||
* @param length the length of the specified text range
|
||||
* @return the number of lines occupied by the specified range
|
||||
* @exception BadLocationException if specified range is unknown to this tracker
|
||||
*/
|
||||
int getNumberOfLines(int offset, int length) throws BadLocationException;
|
||||
|
||||
/**
|
||||
* Returns the position of the first character of the specified line.
|
||||
*
|
||||
* @param line the line of interest
|
||||
* @return offset of the first character of the line
|
||||
* @exception BadLocationException if the line is unknown to this tracker
|
||||
*/
|
||||
int getLineOffset(int line) throws BadLocationException;
|
||||
|
||||
/**
|
||||
* Returns length of the specified line including the line's delimiter.
|
||||
*
|
||||
* @param line the line of interest
|
||||
* @return the length of the line
|
||||
* @exception BadLocationException if line is unknown to this tracker
|
||||
*/
|
||||
int getLineLength(int line) throws BadLocationException;
|
||||
|
||||
/**
|
||||
* Returns the line number the character at the given offset belongs to.
|
||||
*
|
||||
* @param offset the offset whose line number to be determined
|
||||
* @return the number of the line the offset is on
|
||||
* @exception BadLocationException if the offset is invalid in this tracker
|
||||
*/
|
||||
int getLineNumberOfOffset(int offset) throws BadLocationException;
|
||||
|
||||
/**
|
||||
* Returns a line description of the line at the given offset.
|
||||
* The description contains the start offset and the length of the line
|
||||
* excluding the line's delimiter.
|
||||
*
|
||||
* @param offset the offset whose line should be described
|
||||
* @return a region describing the line
|
||||
* @exception BadLocationException if offset is invalid in this tracker
|
||||
*/
|
||||
IRegion getLineInformationOfOffset(int offset) throws BadLocationException;
|
||||
|
||||
/**
|
||||
* Returns a line description of the given line. The description
|
||||
* contains the start offset and the length of the line excluding the line's
|
||||
* delimiter.
|
||||
*
|
||||
* @param line the line that should be described
|
||||
* @return a region describing the line
|
||||
* @exception BadLocationException if line is unknown to this tracker
|
||||
*/
|
||||
IRegion getLineInformation(int line) throws BadLocationException;
|
||||
|
||||
/**
|
||||
* Informs the line tracker about the specified change in the tracked text.
|
||||
*
|
||||
* @param offset the offset of the replaced text
|
||||
* @param length the length of the replaced text
|
||||
* @param text the substitution text
|
||||
* @exception BadLocationException if specified range is unknown to this tracker
|
||||
*/
|
||||
void replace(int offset, int length, String text) throws BadLocationException;
|
||||
|
||||
/**
|
||||
* Sets the tracked text to the specified text.
|
||||
*
|
||||
* @param text the new tracked text
|
||||
*/
|
||||
void set(String text);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2000, 2005 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.util.text.linetracker;
|
||||
|
||||
/**
|
||||
* Extension interface for {@link org.eclipse.jface.text.ILineTracker}. Adds the
|
||||
* concept of rewrite sessions. A rewrite session is a sequence of replace
|
||||
* operations that form a semantic unit.
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public interface ILineTrackerExtension {
|
||||
|
||||
/**
|
||||
* Tells the line tracker that a rewrite session started. A rewrite session
|
||||
* is a sequence of replace operations that form a semantic unit. The line
|
||||
* tracker is allowed to use that information for internal optimization.
|
||||
*
|
||||
* @param session the rewrite session
|
||||
* @throws IllegalStateException in case there is already an active rewrite
|
||||
* session
|
||||
*/
|
||||
void startRewriteSession(DocumentRewriteSession session) throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Tells the line tracker that the rewrite session has finished. This method
|
||||
* is only called when <code>startRewriteSession</code> has been called
|
||||
* before. The text resulting from the rewrite session is passed to the line
|
||||
* tracker.
|
||||
*
|
||||
* @param session the rewrite session
|
||||
* @param text the text with which to re-initialize the line tracker
|
||||
*/
|
||||
void stopRewriteSession(DocumentRewriteSession session, String text);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2000, 2006 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.util.text.linetracker;
|
||||
|
||||
import org.springframework.ide.vscode.commons.util.text.IRegion;
|
||||
|
||||
/**
|
||||
* Describes a line as a particular number of characters beginning at
|
||||
* a particular offset, consisting of a particular number of characters,
|
||||
* and being closed with a particular line delimiter.
|
||||
*/
|
||||
final class Line implements IRegion {
|
||||
|
||||
/** The offset of the line */
|
||||
public int offset;
|
||||
/** The length of the line */
|
||||
public int length;
|
||||
/** The delimiter of this line */
|
||||
public final String delimiter;
|
||||
|
||||
/**
|
||||
* Creates a new Line.
|
||||
*
|
||||
* @param offset the offset of the line
|
||||
* @param end the last including character offset of the line
|
||||
* @param delimiter the line's delimiter
|
||||
*/
|
||||
public Line(int offset, int end, String delimiter) {
|
||||
this.offset= offset;
|
||||
this.length= (end - offset) +1;
|
||||
this.delimiter= delimiter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Line.
|
||||
*
|
||||
* @param offset the offset of the line
|
||||
* @param length the length of the line
|
||||
*/
|
||||
public Line(int offset, int length) {
|
||||
this.offset= offset;
|
||||
this.length= length;
|
||||
this.delimiter= null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,342 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2000, 2008 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.util.text.linetracker;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.ide.vscode.commons.util.BadLocationException;
|
||||
import org.springframework.ide.vscode.commons.util.text.IRegion;
|
||||
import org.springframework.ide.vscode.commons.util.text.Region;
|
||||
import org.springframework.ide.vscode.commons.util.text.linetracker.AbstractLineTracker.DelimiterInfo;
|
||||
|
||||
/**
|
||||
* Abstract, read-only implementation of <code>ILineTracker</code>. It lets the definition of
|
||||
* line delimiters to subclasses. Assuming that '\n' is the only line delimiter, this abstract
|
||||
* implementation defines the following line scheme:
|
||||
* <ul>
|
||||
* <li> "" -> [0,0]
|
||||
* <li> "a" -> [0,1]
|
||||
* <li> "\n" -> [0,1], [1,0]
|
||||
* <li> "a\n" -> [0,2], [2,0]
|
||||
* <li> "a\nb" -> [0,2], [2,1]
|
||||
* <li> "a\nbc\n" -> [0,2], [2,3], [5,0]
|
||||
* </ul>
|
||||
* This class must be subclassed.
|
||||
*
|
||||
* @since 3.2
|
||||
*/
|
||||
abstract class ListLineTracker implements ILineTracker {
|
||||
|
||||
/** The line information */
|
||||
private final List<Line> fLines= new ArrayList<>();
|
||||
/** The length of the tracked text */
|
||||
private int fTextLength;
|
||||
|
||||
/**
|
||||
* Creates a new line tracker.
|
||||
*/
|
||||
protected ListLineTracker() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Binary search for the line at a given offset.
|
||||
*
|
||||
* @param offset the offset whose line should be found
|
||||
* @return the line of the offset
|
||||
*/
|
||||
private int findLine(int offset) {
|
||||
|
||||
if (fLines.size() == 0)
|
||||
return -1;
|
||||
|
||||
int left= 0;
|
||||
int right= fLines.size() - 1;
|
||||
int mid= 0;
|
||||
Line line= null;
|
||||
|
||||
while (left < right) {
|
||||
|
||||
mid= (left + right) / 2;
|
||||
|
||||
line= fLines.get(mid);
|
||||
if (offset < line.offset) {
|
||||
if (left == mid)
|
||||
right= left;
|
||||
else
|
||||
right= mid - 1;
|
||||
} else if (offset > line.offset) {
|
||||
if (right == mid)
|
||||
left= right;
|
||||
else
|
||||
left= mid + 1;
|
||||
} else if (offset == line.offset) {
|
||||
left= right= mid;
|
||||
}
|
||||
}
|
||||
|
||||
line= fLines.get(left);
|
||||
if (line.offset > offset)
|
||||
--left;
|
||||
return left;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of lines covered by the specified text range.
|
||||
*
|
||||
* @param startLine the line where the text range starts
|
||||
* @param offset the start offset of the text range
|
||||
* @param length the length of the text range
|
||||
* @return the number of lines covered by this text range
|
||||
* @exception BadLocationException if range is undefined in this tracker
|
||||
*/
|
||||
private int getNumberOfLines(int startLine, int offset, int length) throws BadLocationException {
|
||||
|
||||
if (length == 0)
|
||||
return 1;
|
||||
|
||||
int target= offset + length;
|
||||
|
||||
Line l= fLines.get(startLine);
|
||||
|
||||
if (l.delimiter == null)
|
||||
return 1;
|
||||
|
||||
if (l.offset + l.length > target)
|
||||
return 1;
|
||||
|
||||
if (l.offset + l.length == target)
|
||||
return 2;
|
||||
|
||||
return getLineNumberOfOffset(target) - startLine + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int getLineLength(int line) throws BadLocationException {
|
||||
int lines= fLines.size();
|
||||
|
||||
if (line < 0 || line > lines)
|
||||
throw new BadLocationException();
|
||||
|
||||
if (lines == 0 || lines == line)
|
||||
return 0;
|
||||
|
||||
Line l= fLines.get(line);
|
||||
return l.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int getLineNumberOfOffset(int position) throws BadLocationException {
|
||||
if (position < 0 || position > fTextLength)
|
||||
throw new BadLocationException();
|
||||
|
||||
if (position == fTextLength) {
|
||||
|
||||
int lastLine= fLines.size() - 1;
|
||||
if (lastLine < 0)
|
||||
return 0;
|
||||
|
||||
Line l= fLines.get(lastLine);
|
||||
return (l.delimiter != null ? lastLine + 1 : lastLine);
|
||||
}
|
||||
|
||||
return findLine(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final IRegion getLineInformationOfOffset(int position) throws BadLocationException {
|
||||
if (position > fTextLength)
|
||||
throw new BadLocationException();
|
||||
|
||||
if (position == fTextLength) {
|
||||
int size= fLines.size();
|
||||
if (size == 0)
|
||||
return new Region(0, 0);
|
||||
Line l= fLines.get(size - 1);
|
||||
return (l.delimiter != null ? new Line(fTextLength, 0) : new Line(fTextLength - l.length, l.length));
|
||||
}
|
||||
|
||||
return getLineInformation(findLine(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final IRegion getLineInformation(int line) throws BadLocationException {
|
||||
int lines= fLines.size();
|
||||
|
||||
if (line < 0 || line > lines)
|
||||
throw new BadLocationException();
|
||||
|
||||
if (lines == 0)
|
||||
return new Line(0, 0);
|
||||
|
||||
if (line == lines) {
|
||||
Line l= fLines.get(line - 1);
|
||||
return new Line(l.offset + l.length, 0);
|
||||
}
|
||||
|
||||
Line l= fLines.get(line);
|
||||
return (l.delimiter != null ? new Line(l.offset, l.length - l.delimiter.length()) : l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int getLineOffset(int line) throws BadLocationException {
|
||||
int lines= fLines.size();
|
||||
|
||||
if (line < 0 || line > lines)
|
||||
throw new BadLocationException();
|
||||
|
||||
if (lines == 0)
|
||||
return 0;
|
||||
|
||||
if (line == lines) {
|
||||
Line l= fLines.get(line - 1);
|
||||
if (l.delimiter != null)
|
||||
return l.offset + l.length;
|
||||
throw new BadLocationException();
|
||||
}
|
||||
|
||||
Line l= fLines.get(line);
|
||||
return l.offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int getNumberOfLines() {
|
||||
int lines= fLines.size();
|
||||
|
||||
if (lines == 0)
|
||||
return 1;
|
||||
|
||||
Line l= fLines.get(lines - 1);
|
||||
return (l.delimiter != null ? lines + 1 : lines);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int getNumberOfLines(int position, int length) throws BadLocationException {
|
||||
|
||||
if (position < 0 || position + length > fTextLength)
|
||||
throw new BadLocationException();
|
||||
|
||||
if (length == 0) // optimization
|
||||
return 1;
|
||||
|
||||
return getNumberOfLines(getLineNumberOfOffset(position), position, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int computeNumberOfLines(String text) {
|
||||
int count= 0;
|
||||
int start= 0;
|
||||
DelimiterInfo delimiterInfo= nextDelimiterInfo(text, start);
|
||||
while (delimiterInfo != null && delimiterInfo.delimiterIndex > -1) {
|
||||
++count;
|
||||
start= delimiterInfo.delimiterIndex + delimiterInfo.delimiterLength;
|
||||
delimiterInfo= nextDelimiterInfo(text, start);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getLineDelimiter(int line) throws BadLocationException {
|
||||
int lines= fLines.size();
|
||||
|
||||
if (line < 0 || line > lines)
|
||||
throw new BadLocationException();
|
||||
|
||||
if (lines == 0)
|
||||
return null;
|
||||
|
||||
if (line == lines)
|
||||
return null;
|
||||
|
||||
Line l= fLines.get(line);
|
||||
return l.delimiter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the information about the first delimiter found in the given text starting at the
|
||||
* given offset.
|
||||
*
|
||||
* @param text the text to be searched
|
||||
* @param offset the offset in the given text
|
||||
* @return the information of the first found delimiter or <code>null</code>
|
||||
*/
|
||||
protected abstract DelimiterInfo nextDelimiterInfo(String text, int offset);
|
||||
|
||||
/**
|
||||
* Creates the line structure for the given text. Newly created lines are inserted into the line
|
||||
* structure starting at the given position. Returns the number of newly created lines.
|
||||
*
|
||||
* @param text the text for which to create a line structure
|
||||
* @param insertPosition the position at which the newly created lines are inserted into the
|
||||
* tracker's line structure
|
||||
* @param offset the offset of all newly created lines
|
||||
* @return the number of newly created lines
|
||||
*/
|
||||
private int createLines(String text, int insertPosition, int offset) {
|
||||
|
||||
int count= 0;
|
||||
int start= 0;
|
||||
DelimiterInfo delimiterInfo= nextDelimiterInfo(text, 0);
|
||||
|
||||
while (delimiterInfo != null && delimiterInfo.delimiterIndex > -1) {
|
||||
|
||||
int index= delimiterInfo.delimiterIndex + (delimiterInfo.delimiterLength - 1);
|
||||
|
||||
if (insertPosition + count >= fLines.size())
|
||||
fLines.add(new Line(offset + start, offset + index, delimiterInfo.delimiter));
|
||||
else
|
||||
fLines.add(insertPosition + count, new Line(offset + start, offset + index, delimiterInfo.delimiter));
|
||||
|
||||
++count;
|
||||
start= index + 1;
|
||||
delimiterInfo= nextDelimiterInfo(text, start);
|
||||
}
|
||||
|
||||
if (start < text.length()) {
|
||||
if (insertPosition + count < fLines.size()) {
|
||||
// there is a line below the current
|
||||
Line l= fLines.get(insertPosition + count);
|
||||
int delta= text.length() - start;
|
||||
l.offset-= delta;
|
||||
l.length+= delta;
|
||||
} else {
|
||||
fLines.add(new Line(offset + start, offset + text.length() - 1, null));
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void replace(int position, int length, String text) throws BadLocationException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void set(String text) {
|
||||
fLines.clear();
|
||||
if (text != null) {
|
||||
fTextLength= text.length();
|
||||
createLines(text, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the internal data structure, a {@link List} of {@link Line}s. Used only by
|
||||
* {@link TreeLineTracker#TreeLineTracker(ListLineTracker)}.
|
||||
*
|
||||
* @return the internal list of lines.
|
||||
*/
|
||||
final List<Line> getLines() {
|
||||
return fLines;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user