1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 10:16:03 +02:00

Follow-up fix for 185712: Invalid indenting of code template

This commit is contained in:
Anton Leherbauer 2007-07-13 11:33:50 +00:00
parent 268346e7e6
commit b1a7c95e56
2 changed files with 86 additions and 14 deletions

View file

@ -31,6 +31,7 @@ import org.eclipse.jface.text.TypedPosition;
import org.eclipse.jface.text.rules.FastPartitioner;
import org.eclipse.jface.text.source.LineRange;
import org.eclipse.jface.text.templates.DocumentTemplateContext;
import org.eclipse.jface.text.templates.GlobalTemplateVariables;
import org.eclipse.jface.text.templates.TemplateBuffer;
import org.eclipse.jface.text.templates.TemplateContext;
import org.eclipse.jface.text.templates.TemplateVariable;
@ -95,7 +96,7 @@ public class CFormatter {
VariableTracker tracker= new VariableTracker(buffer);
IDocument document= tracker.getDocument();
internalFormat(document, context);
internalFormat(document, context, buffer);
convertLineDelimiters(document);
convertTabs(document);
if (isReplacedAreaEmpty(context))
@ -110,21 +111,21 @@ public class CFormatter {
/**
* @param document
* @param context
* @param buffer
* @throws BadLocationException
*/
private void internalFormat(IDocument document, TemplateContext context) throws BadLocationException {
private void internalFormat(IDocument document, TemplateContext context, TemplateBuffer buffer) throws BadLocationException {
if (fUseCodeFormatter) {
// try to format and fall back to indenting
try {
format(document, (TranslationUnitContext) context);
return;
} catch (BadLocationException e) {
indent(document);
} catch (MalformedTreeException e) {
indent(document);
}
} else {
indent(document);
}
// fallback: indent
indent(document, buffer);
}
private void convertLineDelimiters(IDocument document) throws BadLocationException {
@ -182,11 +183,17 @@ public class CFormatter {
}
private void trimStart(IDocument document) throws BadLocationException {
int i= 0;
while ((i != document.getLength()) && Character.isWhitespace(document.getChar(i)))
trimAtOffset(0, document);
}
private String trimAtOffset(int offset, IDocument document) throws BadLocationException {
int i= offset;
while ((i < document.getLength()) && Character.isWhitespace(document.getChar(i)))
i++;
document.replace(0, i, ""); //$NON-NLS-1$
String trim= document.get(offset, i - offset);
document.replace(offset, i - offset, ""); //$NON-NLS-1$
return trim;
}
private boolean isReplacedAreaEmpty(TemplateContext context) {
@ -221,12 +228,56 @@ public class CFormatter {
edit.apply(doc, TextEdit.UPDATE_REGIONS);
}
private void indent(IDocument document) throws BadLocationException, MalformedTreeException {
private void indent(IDocument document, TemplateBuffer buffer) throws BadLocationException, MalformedTreeException {
String indent = CodeFormatterUtil.createIndentString(fInitialIndentLevel, fProject);
prefixSelectionLines(document, buffer);
int lineCount= document.getNumberOfLines();
IndentUtil.indentLines(document, new LineRange(0, lineCount), indent);
}
/**
* Prefix each line of <code>line_selection</code> substitutions with
* the prefix of the first line.
*
* @param document
* @param buffer
*/
private void prefixSelectionLines(IDocument document, TemplateBuffer buffer) {
TemplateVariable[] variables= buffer.getVariables();
for (int i = 0; i < variables.length; i++) {
if (variables[i].getName().equals(GlobalTemplateVariables.LineSelection.NAME)) {
if (variables[i].getLength() > 0) {
final int tabWidth= CodeFormatterUtil.getTabWidth(fProject);
int delta= 0;
int[] offsets= variables[i].getOffsets();
for (int j= 0; j < offsets.length; j++) {
final int offset = offsets[j] + delta;
try {
int startLine= document.getLineOfOffset(offset);
int startOffset= document.getLineOffset(startLine);
int endLine= document.getLineOfOffset(offset+variables[i].getLength() - 1);
String prefix= document.get(startOffset, offset - startOffset);
String shift= trimAtOffset(offset, document);
delta -= shift.length();
if (shift.length() > 0 && startLine < endLine) {
int shiftWidth= IndentUtil.computeVisualLength(shift, tabWidth);
for (int line= startLine + 1; line <= endLine; ++line) {
delta -= IndentUtil.cutIndent(document, line, shiftWidth, tabWidth);
int lineOffset= document.getLineOffset(line);
document.replace(lineOffset, 0, prefix);
delta += prefix.length();
}
}
} catch (BadLocationException exc) {
break;
}
}
}
break;
}
}
}
/**
* Wraps a {@link TemplateBuffer} and tracks the variable offsets while changes to the buffer
* occur. Whitespace variables are also tracked.

View file

@ -219,6 +219,7 @@ public final class IndentUtil {
* @param line the line
* @param indent the indentation to insert
* @param commentlines
* @param relative
* @param indentInsideLineComments option whether to indent inside line comments starting at column 0
* @throws BadLocationException on concurrent document modification
*/
@ -239,18 +240,36 @@ public final class IndentUtil {
document.replace(insert, 0, indent.toString());
}
/**
* Cuts the visual equivalent of <code>toDelete</code> characters out of the
* indentation of line <code>line</code> in <code>document</code>.
*
* @param document
* @param line
* @param shiftWidth
* @param tabWidth
* @return number of characters deleted
* @throws BadLocationException
*/
public static int cutIndent(IDocument document, int line, int shiftWidth, int tabWidth) throws BadLocationException {
return cutIndent(document, line, shiftWidth, tabWidth, new boolean[1], 0, false);
}
/**
* Cuts the visual equivalent of <code>toDelete</code> characters out of the
* indentation of line <code>line</code> in <code>document</code>. Leaves
* leading comment signs alone.
* leading comment signs alone if desired.
*
* @param document the document
* @param line the line
* @param toDelete the number of space equivalents to delete.
* @param commentLines
* @param relative
* @param indentInsideLineComments option whether to indent inside line comments starting at column 0
* @return number of characters deleted
* @throws BadLocationException on concurrent document modification
*/
private static void cutIndent(IDocument document, int line, int toDelete, int tabSize, boolean[] commentLines, int relative, boolean indentInsideLineComments) throws BadLocationException {
private static int cutIndent(IDocument document, int line, int toDelete, int tabSize, boolean[] commentLines, int relative, boolean indentInsideLineComments) throws BadLocationException {
IRegion region= document.getLineInformation(line);
int from= region.getOffset();
int endOffset= region.getOffset() + region.getLength();
@ -276,7 +295,8 @@ public final class IndentUtil {
if (endOffset > to + 1 && document.get(to, 2).equals(SLASHES))
commentLines[relative]= true;
document.replace(from, to - from, null);
document.replace(from, to - from, ""); //$NON-NLS-1$
return to - from;
}
/**
@ -322,7 +342,7 @@ public final class IndentUtil {
* @param seq the string to measure
* @return the visual length of <code>seq</code>
*/
private static int computeVisualLength(CharSequence seq, int tablen) {
public static int computeVisualLength(CharSequence seq, int tablen) {
int size= 0;
for (int i= 0; i < seq.length(); i++) {
@ -597,4 +617,5 @@ public final class IndentUtil {
computed= new StringBuffer(previousIndent);
return computed.toString();
}
}