diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterConstants.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterConstants.java index 3028278e4d1..898d60a67c4 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterConstants.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterConstants.java @@ -652,6 +652,17 @@ public class DefaultCodeFormatterConstants { * @see #FALSE */ public static final String FORMATTER_INDENT_EMPTY_LINES = CCorePlugin.PLUGIN_ID + ".formatter.indent_empty_lines"; //$NON-NLS-1$ + /** + *
+ * FORMATTER / Option to indent inside line comments at column 0 + * - option id: "org.eclipse.cdt.core.formatter.indent_inside_line_comments" + * - possible values: { TRUE, FALSE } + * - default: FALSE + *+ * @see #TRUE + * @see #FALSE + */ + public static final String FORMATTER_INDENT_INSIDE_LINE_COMMENTS = CCorePlugin.PLUGIN_ID + ".formatter.indent_inside_line_comments"; //$NON-NLS-1$ /** *
* FORMATTER / Option to indent statements inside a block diff --git a/core/org.eclipse.cdt.ui.tests/resources/indentation/sample/After.cpp b/core/org.eclipse.cdt.ui.tests/resources/indentation/sample/After.cpp index 1d7eae8de46..f0a58f151a3 100644 --- a/core/org.eclipse.cdt.ui.tests/resources/indentation/sample/After.cpp +++ b/core/org.eclipse.cdt.ui.tests/resources/indentation/sample/After.cpp @@ -36,11 +36,12 @@ const OtherStruct array[] = } }; +// single line outside scope void SimpleStruct_construct( struct SimpleStruct * const this ) { -// single line + // single line this->num = 1; this->name = "boo"; this->floatNum = 1.5; diff --git a/core/org.eclipse.cdt.ui.tests/resources/indentation/sample/Before.cpp b/core/org.eclipse.cdt.ui.tests/resources/indentation/sample/Before.cpp index dc77f8e7333..aa131f0da36 100644 --- a/core/org.eclipse.cdt.ui.tests/resources/indentation/sample/Before.cpp +++ b/core/org.eclipse.cdt.ui.tests/resources/indentation/sample/Before.cpp @@ -36,6 +36,7 @@ const OtherStruct array[] = } }; +// single line outside scope void SimpleStruct_construct( struct SimpleStruct * const this ) diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CAutoIndentTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CAutoIndentTest.java index 98e0cb660db..5cf597fe05f 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CAutoIndentTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CAutoIndentTest.java @@ -374,4 +374,26 @@ public class CAutoIndentTest extends TestCase { assertEquals("\t}", tester.getLine(1)); } + public void testPasteBlockCommentAutoIndent() throws BadLocationException { + AutoEditTester tester = createAutoEditTester(); //$NON-NLS-1$ + tester.type("class A {\n};"); //$NON-NLS-1$ + tester.goTo(1, 0); + tester.paste("/*\n" + + " * block comment\n" + + " */\n"); + tester.goTo(1, 0); + assertEquals("\t/*", tester.getLine(0)); //$NON-NLS-1$ + assertEquals("\t * block comment", tester.getLine(1)); //$NON-NLS-1$ + assertEquals("\t */", tester.getLine(2)); //$NON-NLS-1$ + } + + public void testPasteLineCommentAutoIndent() throws BadLocationException { + AutoEditTester tester = createAutoEditTester(); //$NON-NLS-1$ + tester.type("class A {\n};"); //$NON-NLS-1$ + tester.goTo(1, 0); + tester.paste("// int f;\n"); + tester.goTo(1, 0); + assertEquals("\t// int f;", tester.getLine(0)); //$NON-NLS-1$ + } + } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/IndentAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/IndentAction.java index 4b41473f328..b2cb54f94e1 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/IndentAction.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/IndentAction.java @@ -213,34 +213,36 @@ public class IndentAction extends TextEditorAction { indent= computePreprocessorIndent(document, line, startingPartition); } else if (!fIsTabAction && startingPartition.getOffset() == offset && startingPartition.getType().equals(ICPartitions.C_SINGLE_LINE_COMMENT)) { // line comment starting at position 0 -> indent inside - int max= document.getLength() - offset; - int slashes= 2; - while (slashes < max - 1 && document.get(offset + slashes, 2).equals("//")) //$NON-NLS-1$ - slashes+= 2; - - wsStart= offset + slashes; - - StringBuffer computed= indenter.computeIndentation(offset); - if (computed == null) - computed= new StringBuffer(0); - int tabSize= getTabSize(); - while (slashes > 0 && computed.length() > 0) { - char c= computed.charAt(0); - if (c == '\t') { - if (slashes > tabSize) - slashes-= tabSize; - else + if (indentInsideLineComments()) { + int max= document.getLength() - offset; + int slashes= 2; + while (slashes < max - 1 && document.get(offset + slashes, 2).equals("//")) //$NON-NLS-1$ + slashes+= 2; + + wsStart= offset + slashes; + + StringBuffer computed= indenter.computeIndentation(offset); + if (computed == null) + computed= new StringBuffer(0); + int tabSize= getTabSize(); + while (slashes > 0 && computed.length() > 0) { + char c= computed.charAt(0); + if (c == '\t') { + if (slashes > tabSize) + slashes-= tabSize; + else + break; + } else if (c == ' ') { + slashes--; + } else { break; - } else if (c == ' ') { - slashes--; - } else { - break; + } + + computed.deleteCharAt(0); } - computed.deleteCharAt(0); + indent= document.get(offset, wsStart - offset) + computed; } - - indent= document.get(offset, wsStart - offset) + computed; } } @@ -291,7 +293,7 @@ public class IndentAction extends TextEditorAction { } /** - * Computes and returns the indentation for a comment line. + * Computes and returns the indentation for a block comment line. * * @param document the document * @param line the line in document @@ -370,14 +372,23 @@ public class IndentAction extends TextEditorAction { } /** - * Returnstrue
if empty lines should be indented, false otherwise. + * Returnstrue
if empty lines should be indented,false
otherwise. * - * @returntrue
if empty lines should be indented, false otherwise + * @returntrue
if empty lines should be indented,false
otherwise */ private boolean indentEmptyLines() { return DefaultCodeFormatterConstants.TRUE.equals(getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_INDENT_EMPTY_LINES)); } + /** + * Returnstrue
if line comments at column 0 should be indented inside,false
otherwise. + * + * @returntrue
if line comments at column 0 should be indented inside,false
otherwise. + */ + private boolean indentInsideLineComments() { + return DefaultCodeFormatterConstants.TRUE.equals(getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_INDENT_INSIDE_LINE_COMMENTS)); + } + /** * Returns the possibly project-specific core preference defined underkey
. * diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/IndentUtil.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/IndentUtil.java index 8b9b5b07a36..96539e48278 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/IndentUtil.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/IndentUtil.java @@ -18,6 +18,8 @@ import org.eclipse.jface.text.ITypedRegion; import org.eclipse.jface.text.TextUtilities; import org.eclipse.jface.text.source.ILineRange; +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.ui.text.ICPartitions; @@ -91,14 +93,40 @@ public final class IndentUtil { CIndenter indenter= new CIndenter(document, scanner, project); boolean changed= false; int tabSize= CodeFormatterUtil.getTabWidth(project); + boolean indentInsideLineComments= indentInsideLineComments(project); for (int line= lines.getStartLine(), last= line + numberOfLines, i= 0; line < last; line++) { - changed |= indentLine(document, line, indenter, scanner, result.commentLinesAtColumnZero, i++, tabSize); + changed |= indentLine(document, line, indenter, scanner, result.commentLinesAtColumnZero, i++, tabSize, indentInsideLineComments); } result.hasChanged= changed; return result; } - + + /** + * Returnstrue
if line comments at column 0 should be indented inside,false
otherwise. + * + * @param project the project to get project specific options from + * @returntrue
if line comments at column 0 should be indented inside,false
otherwise. + */ + public static boolean indentInsideLineComments(ICProject project) { + return DefaultCodeFormatterConstants.TRUE.equals(getCoreOption(project, DefaultCodeFormatterConstants.FORMATTER_INDENT_INSIDE_LINE_COMMENTS)); + } + + /** + * Returns the possiblyproject
-specific core preference + * defined underkey
. + * + * @param project the project to get the preference from, or + *null
to get the global preference + * @param key the key of the preference + * @return the value of the preference + */ + private static String getCoreOption(ICProject project, String key) { + if (project == null) + return CCorePlugin.getOption(key); + return project.getOption(key, true); + } + /** * Shifts the line range specified bylines
in *document
. The amount that the lines get shifted @@ -133,7 +161,8 @@ public final class IndentUtil { CHeuristicScanner scanner= new CHeuristicScanner(document); CIndenter indenter= new CIndenter(document, scanner, project); - String current= getCurrentIndent(document, lines.getStartLine()); + boolean indentInsideLineComments= indentInsideLineComments(project); + String current= getCurrentIndent(document, lines.getStartLine(), indentInsideLineComments); StringBuffer correct= new StringBuffer(computeIndent(document, lines.getStartLine(), indenter, scanner)); if (correct == null) return result; // bail out @@ -146,17 +175,17 @@ public final class IndentUtil { return result; if (result.leftmostLine == -1) - result.leftmostLine= getLeftMostLine(document, lines, tabSize); + result.leftmostLine= getLeftMostLine(document, lines, tabSize, indentInsideLineComments); - int maxReduction= computeVisualLength(getCurrentIndent(document, result.leftmostLine + lines.getStartLine()), tabSize); + int maxReduction= computeVisualLength(getCurrentIndent(document, result.leftmostLine + lines.getStartLine(), indentInsideLineComments), tabSize); if (difference > 0) { for (int line= lines.getStartLine(), last= line + numberOfLines, i= 0; line < last; line++) - addIndent(document, line, addition, result.commentLinesAtColumnZero, i++); + addIndent(document, line, addition, result.commentLinesAtColumnZero, i++, indentInsideLineComments); } else { int reduction= Math.min(-difference, maxReduction); for (int line= lines.getStartLine(), last= line + numberOfLines, i= 0; line < last; line++) - cutIndent(document, line, reduction, tabSize, result.commentLinesAtColumnZero, i++); + cutIndent(document, line, reduction, tabSize, result.commentLinesAtColumnZero, i++, indentInsideLineComments); } result.hasChanged= true; @@ -173,17 +202,20 @@ public final class IndentUtil { * @param line the line * @param indent the indentation to insert * @param commentlines + * @param indentInsideLineComments option whether to indent inside line comments starting at column 0 * @throws BadLocationException on concurrent document modification */ - private static void addIndent(IDocument document, int line, CharSequence indent, boolean[] commentlines, int relative) throws BadLocationException { + private static void addIndent(IDocument document, int line, CharSequence indent, boolean[] commentlines, int relative, boolean indentInsideLineComments) throws BadLocationException { IRegion region= document.getLineInformation(line); int insert= region.getOffset(); int endOffset= region.getOffset() + region.getLength(); - // go behind line comments - if (!commentlines[relative]) { - while (insert < endOffset - 2 && document.get(insert, 2).equals(SLASHES)) - insert += 2; + if (indentInsideLineComments) { + // go behind line comments + if (!commentlines[relative]) { + while (insert < endOffset - 2 && document.get(insert, 2).equals(SLASHES)) + insert += 2; + } } // insert indent @@ -198,17 +230,20 @@ public final class IndentUtil { * @param document the document * @param line the line * @param toDelete the number of space equivalents to delete. + * @param indentInsideLineComments option whether to indent inside line comments starting at column 0 * @throws BadLocationException on concurrent document modification */ - private static void cutIndent(IDocument document, int line, int toDelete, int tabSize, boolean[] commentLines, int relative) throws BadLocationException { + private static void 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(); - // go behind line comments - while (from < endOffset - 2 && document.get(from, 2).equals(SLASHES)) - from += 2; - + if (indentInsideLineComments) { + // go behind line comments + while (from < endOffset - 2 && document.get(from, 2).equals(SLASHES)) + from += 2; + } + int to= from; while (toDelete > 0 && to < endOffset) { char ch= document.getChar(to); @@ -289,24 +324,26 @@ public final class IndentUtil { /** * Returns the indentation of the lineline
indocument
. * The returned string may contain pairs of leading slashes that are considered - * part of the indentation. The space before the asterix in a block - * comment is not considered part of the indentation. + * part of the indentation. * * @param document the document * @param line the line + * @param indentInsideLineComments option whether to indent inside line comments starting at column 0 * @return the indentation ofline
indocument
* @throws BadLocationException if the document is changed concurrently */ - private static String getCurrentIndent(IDocument document, int line) throws BadLocationException { + public static String getCurrentIndent(IDocument document, int line, boolean indentInsideLineComments) throws BadLocationException { IRegion region= document.getLineInformation(line); int from= region.getOffset(); int endOffset= region.getOffset() + region.getLength(); - // go behind line comments int to= from; - while (to < endOffset - 2 && document.get(to, 2).equals(SLASHES)) - to += 2; - + if (indentInsideLineComments) { + // go behind line comments + while (to < endOffset - 2 && document.get(to, 2).equals(SLASHES)) + to += 2; + } + while (to < endOffset) { char ch= document.getChar(to); if (!Character.isWhitespace(ch)) @@ -314,23 +351,16 @@ public final class IndentUtil { to++; } - // don't count the space before javadoc like, asterisk-style comment lines - if (to > from && to < endOffset - 1 && document.get(to - 1, 2).equals(" *")) { //$NON-NLS-1$ - String type= TextUtilities.getContentType(document, ICPartitions.C_PARTITIONING, to, true); - if (type.equals(ICPartitions.C_MULTI_LINE_COMMENT)) - to--; - } - return document.get(from, to - from); } - private static int getLeftMostLine(IDocument document, ILineRange lines, int tabSize) throws BadLocationException { + private static int getLeftMostLine(IDocument document, ILineRange lines, int tabSize, boolean indentInsideLineComments) throws BadLocationException { int numberOfLines= lines.getNumberOfLines(); int first= lines.getStartLine(); int minLine= -1; int minIndent= Integer.MAX_VALUE; for (int line= 0; line < numberOfLines; line++) { - int length= computeVisualLength(getCurrentIndent(document, line + first), tabSize); + int length= computeVisualLength(getCurrentIndent(document, line + first, indentInsideLineComments), tabSize); if (length < minIndent) { minIndent= length; minLine= line; @@ -362,11 +392,13 @@ public final class IndentUtil { * @param scanner the heuristic scanner * @param commentLines the indent token comment booleans * @param lineIndex the zero-based line index + * @param indentInsideLineComments option whether to indent inside line comments + * starting at column 0 * @returntrue
if the document was modified, *false
if not * @throws BadLocationException if the document got changed concurrently */ - private static boolean indentLine(IDocument document, int line, CIndenter indenter, CHeuristicScanner scanner, boolean[] commentLines, int lineIndex, int tabSize) throws BadLocationException { + private static boolean indentLine(IDocument document, int line, CIndenter indenter, CHeuristicScanner scanner, boolean[] commentLines, int lineIndex, int tabSize, boolean indentInsideLineComments) throws BadLocationException { IRegion currentLine= document.getLineInformation(line); final int offset= currentLine.getOffset(); int wsStart= offset; // where we start searching for non-WS; after the "//" in single line comments @@ -405,7 +437,8 @@ public final class IndentUtil { // memorize the fact that a line is a single line comment (but not at column 0) and should be treated like code // as opposed to commented out code, which should keep its slashes at column 0 - if (length > 0) { + // if 'indentInsideLineComments' is false, all comment lines are indented with the code + if (length > 0 || !indentInsideLineComments) { ITypedRegion partition= TextUtilities.getPartition(document, ICPartitions.C_PARTITIONING, end, false); if (partition.getOffset() == end && ICPartitions.C_SINGLE_LINE_COMMENT.equals(partition.getType())) { commentLines[lineIndex]= true; @@ -444,8 +477,6 @@ public final class IndentUtil { indent= computeCommentIndent(document, line, scanner, startingPartition); } else if (startingPartition.getType().equals(ICPartitions.C_PREPROCESSOR)) { indent= computePreprocessorIndent(document, line, startingPartition); - } else if (startingPartition.getOffset() == offset && startingPartition.getType().equals(ICPartitions.C_SINGLE_LINE_COMMENT)) { - indent= new String(); } } @@ -461,7 +492,7 @@ public final class IndentUtil { } /** - * Computes and returns the indentation for a comment line. + * Computes and returns the indentation for a block comment line. * * @param document the document * @param line the line in document diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CAutoIndentStrategy.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CAutoIndentStrategy.java index 1fcfa278b1e..95e571b954e 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CAutoIndentStrategy.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CAutoIndentStrategy.java @@ -570,6 +570,7 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy { int first= document.computeNumberOfLines(prefix) + firstLine; // don't format first line int lines= temp.getNumberOfLines(); boolean changed= false; + boolean indentInsideLineComments= IndentUtil.indentInsideLineComments(fProject); for (int l= first; l < lines; l++) { // we don't change the number of lines while adding indents IRegion r= temp.getLineInformation(l); @@ -581,7 +582,7 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy { if (!isIndentDetected) { // indent the first pasted line - String current= getCurrentIndent(temp, l); + String current= IndentUtil.getCurrentIndent(temp, l, indentInsideLineComments); StringBuffer correct= new StringBuffer(IndentUtil.computeIndent(temp, l, indenter, scanner)); if (correct == null) return; // bail out @@ -608,9 +609,9 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy { // relatively indent all pasted lines if (insertLength > 0) - addIndent(temp, l, addition); + addIndent(temp, l, addition, indentInsideLineComments); else if (insertLength < 0) - cutIndent(temp, l, -insertLength); + cutIndent(temp, l, -insertLength, indentInsideLineComments); } temp.stopRewriteSession(session); @@ -624,44 +625,6 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy { } } - /** - * Returns the indentation of the lineline
indocument
. - * The returned string may contain pairs of leading slashes that are considered - * part of the indentation. The space before the asterix in a javadoc-like - * comment is not considered part of the indentation. - * - * @param document the document - * @param line the line - * @return the indentation ofline
indocument
- * @throws BadLocationException if the document is changed concurrently - */ - private static String getCurrentIndent(Document document, int line) throws BadLocationException { - IRegion region= document.getLineInformation(line); - int from= region.getOffset(); - int endOffset= region.getOffset() + region.getLength(); - - // go behind line comments - int to= from; - while (to < endOffset - 2 && document.get(to, 2).equals(LINE_COMMENT)) - to += 2; - - while (to < endOffset) { - char ch= document.getChar(to); - if (!Character.isWhitespace(ch)) - break; - to++; - } - - // don't count the space before javadoc like, asterix-style comment lines - if (to > from && to < endOffset - 1 && document.get(to - 1, 2).equals(" *")) { //$NON-NLS-1$ - String type= TextUtilities.getContentType(document, ICPartitions.C_PARTITIONING, to, true); - if (type.equals(ICPartitions.C_MULTI_LINE_COMMENT)) - to--; - } - - return document.get(from, to - from); - } - /** * Computes the difference of two indentations and returns the difference in * length of current and correct. If the return value is positive,addition
@@ -697,16 +660,19 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy { * @param document the document * @param line the line * @param indent the indentation to insert + * @param indentInsideLineComments option whether to indent inside line comments starting at column 0 * @throws BadLocationException on concurrent document modification */ - private static void addIndent(Document document, int line, CharSequence indent) throws BadLocationException { + private static void addIndent(Document document, int line, CharSequence indent, boolean indentInsideLineComments) throws BadLocationException { IRegion region= document.getLineInformation(line); int insert= region.getOffset(); int endOffset= region.getOffset() + region.getLength(); - // go behind line comments - while (insert < endOffset - 2 && document.get(insert, 2).equals(LINE_COMMENT)) - insert += 2; + if (indentInsideLineComments) { + // go behind line comments + while (insert < endOffset - 2 && document.get(insert, 2).equals(LINE_COMMENT)) + insert += 2; + } // insert indent document.replace(insert, 0, indent.toString()); @@ -720,16 +686,19 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy { * @param document the document * @param line the line * @param toDelete the number of space equivalents to delete. + * @param indentInsideLineComments option whether to indent inside line comments starting at column 0 * @throws BadLocationException on concurrent document modification */ - private void cutIndent(Document document, int line, int toDelete) throws BadLocationException { + private void cutIndent(Document document, int line, int toDelete, boolean indentInsideLineComments) throws BadLocationException { IRegion region= document.getLineInformation(line); int from= region.getOffset(); int endOffset= region.getOffset() + region.getLength(); - // go behind line comments - while (from < endOffset - 2 && document.get(from, 2).equals(LINE_COMMENT)) - from += 2; + if (indentInsideLineComments) { + // go behind line comments + while (from < endOffset - 2 && document.get(from, 2).equals(LINE_COMMENT)) + from += 2; + } int to= from; while (toDelete > 0 && to < endOffset) {