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:
parent
268346e7e6
commit
b1a7c95e56
2 changed files with 86 additions and 14 deletions
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue