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.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.
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue