1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 18:26:01 +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.rules.FastPartitioner;
import org.eclipse.jface.text.source.LineRange; import org.eclipse.jface.text.source.LineRange;
import org.eclipse.jface.text.templates.DocumentTemplateContext; 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.TemplateBuffer;
import org.eclipse.jface.text.templates.TemplateContext; import org.eclipse.jface.text.templates.TemplateContext;
import org.eclipse.jface.text.templates.TemplateVariable; import org.eclipse.jface.text.templates.TemplateVariable;
@ -95,7 +96,7 @@ public class CFormatter {
VariableTracker tracker= new VariableTracker(buffer); VariableTracker tracker= new VariableTracker(buffer);
IDocument document= tracker.getDocument(); IDocument document= tracker.getDocument();
internalFormat(document, context); internalFormat(document, context, buffer);
convertLineDelimiters(document); convertLineDelimiters(document);
convertTabs(document); convertTabs(document);
if (isReplacedAreaEmpty(context)) if (isReplacedAreaEmpty(context))
@ -110,21 +111,21 @@ public class CFormatter {
/** /**
* @param document * @param document
* @param context * @param context
* @param buffer
* @throws BadLocationException * @throws BadLocationException
*/ */
private void internalFormat(IDocument document, TemplateContext context) throws BadLocationException { private void internalFormat(IDocument document, TemplateContext context, TemplateBuffer buffer) throws BadLocationException {
if (fUseCodeFormatter) { if (fUseCodeFormatter) {
// try to format and fall back to indenting // try to format and fall back to indenting
try { try {
format(document, (TranslationUnitContext) context); format(document, (TranslationUnitContext) context);
return;
} catch (BadLocationException e) { } catch (BadLocationException e) {
indent(document);
} catch (MalformedTreeException e) { } catch (MalformedTreeException e) {
indent(document);
} }
} else {
indent(document);
} }
// fallback: indent
indent(document, buffer);
} }
private void convertLineDelimiters(IDocument document) throws BadLocationException { private void convertLineDelimiters(IDocument document) throws BadLocationException {
@ -182,11 +183,17 @@ public class CFormatter {
} }
private void trimStart(IDocument document) throws BadLocationException { private void trimStart(IDocument document) throws BadLocationException {
int i= 0; trimAtOffset(0, document);
while ((i != document.getLength()) && Character.isWhitespace(document.getChar(i))) }
private String trimAtOffset(int offset, IDocument document) throws BadLocationException {
int i= offset;
while ((i < document.getLength()) && Character.isWhitespace(document.getChar(i)))
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) { private boolean isReplacedAreaEmpty(TemplateContext context) {
@ -221,12 +228,56 @@ public class CFormatter {
edit.apply(doc, TextEdit.UPDATE_REGIONS); 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); String indent = CodeFormatterUtil.createIndentString(fInitialIndentLevel, fProject);
prefixSelectionLines(document, buffer);
int lineCount= document.getNumberOfLines(); int lineCount= document.getNumberOfLines();
IndentUtil.indentLines(document, new LineRange(0, lineCount), indent); 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 * Wraps a {@link TemplateBuffer} and tracks the variable offsets while changes to the buffer
* occur. Whitespace variables are also tracked. * occur. Whitespace variables are also tracked.

View file

@ -219,6 +219,7 @@ public final class IndentUtil {
* @param line the line * @param line the line
* @param indent the indentation to insert * @param indent the indentation to insert
* @param commentlines * @param commentlines
* @param relative
* @param indentInsideLineComments option whether to indent inside line comments starting at column 0 * @param indentInsideLineComments option whether to indent inside line comments starting at column 0
* @throws BadLocationException on concurrent document modification * @throws BadLocationException on concurrent document modification
*/ */
@ -239,18 +240,36 @@ public final class IndentUtil {
document.replace(insert, 0, indent.toString()); 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 * Cuts the visual equivalent of <code>toDelete</code> characters out of the
* indentation of line <code>line</code> in <code>document</code>. Leaves * 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 document the document
* @param line the line * @param line the line
* @param toDelete the number of space equivalents to delete. * @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 * @param indentInsideLineComments option whether to indent inside line comments starting at column 0
* @return number of characters deleted
* @throws BadLocationException on concurrent document modification * @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); IRegion region= document.getLineInformation(line);
int from= region.getOffset(); int from= region.getOffset();
int endOffset= region.getOffset() + region.getLength(); int endOffset= region.getOffset() + region.getLength();
@ -276,7 +295,8 @@ public final class IndentUtil {
if (endOffset > to + 1 && document.get(to, 2).equals(SLASHES)) if (endOffset > to + 1 && document.get(to, 2).equals(SLASHES))
commentLines[relative]= true; 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 * @param seq the string to measure
* @return the visual length of <code>seq</code> * @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; int size= 0;
for (int i= 0; i < seq.length(); i++) { for (int i= 0; i < seq.length(); i++) {
@ -597,4 +617,5 @@ public final class IndentUtil {
computed= new StringBuffer(previousIndent); computed= new StringBuffer(previousIndent);
return computed.toString(); return computed.toString();
} }
} }