1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Fix preprocessor auto-indentation

This commit is contained in:
Anton Leherbauer 2006-10-18 09:37:07 +00:00
parent 39fd51b72a
commit a696db918b
6 changed files with 195 additions and 138 deletions

View file

@ -9,12 +9,19 @@ const SimpleStruct simpleStruct =
#define SIZEOF( A, B ) sizeof( A.B ) #define SIZEOF( A, B ) sizeof( A.B )
#define FOREVER \
for(;;)\
{\
\
}
}
const OtherStruct array[] = const OtherStruct array[] =
{ {
{ {
#if FOO #if FOO
"foo" "foo"
#else # else
"bar" "bar"
#endif #endif
, SIZEOF( simpleStruct, num ) , SIZEOF( simpleStruct, num )

View file

@ -9,12 +9,19 @@ const SimpleStruct simpleStruct =
#define SIZEOF( A, B ) sizeof( A.B ) #define SIZEOF( A, B ) sizeof( A.B )
#define FOREVER \
for(;;)\
{\
\
}
}
const OtherStruct array[] = const OtherStruct array[] =
{ {
{ {
#if FOO #if FOO
"foo" "foo"
#else # else
"bar" "bar"
#endif #endif
, SIZEOF( simpleStruct, num ) , SIZEOF( simpleStruct, num )

View file

@ -12,7 +12,6 @@
package org.eclipse.cdt.ui.tests.text; package org.eclipse.cdt.ui.tests.text;
import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -20,7 +19,6 @@ import junit.framework.Test;
import junit.framework.TestCase; import junit.framework.TestCase;
import junit.framework.TestSuite; import junit.framework.TestSuite;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document; import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.DocumentCommand; import org.eclipse.jface.text.DocumentCommand;
@ -245,10 +243,12 @@ public class CAutoIndentTest extends TestCase {
tester.setAutoEditStrategy(IDocument.DEFAULT_CONTENT_TYPE, tester.setAutoEditStrategy(IDocument.DEFAULT_CONTENT_TYPE,
new CAutoIndentStrategy(textTools.getDocumentPartitioning(), null)); new CAutoIndentStrategy(textTools.getDocumentPartitioning(), null));
tester.setAutoEditStrategy(ICPartitions.C_MULTI_LINE_COMMENT, new CCommentAutoIndentStrategy()); tester.setAutoEditStrategy(ICPartitions.C_MULTI_LINE_COMMENT, new CCommentAutoIndentStrategy());
tester.setAutoEditStrategy(ICPartitions.C_PREPROCESSOR,
new CAutoIndentStrategy(textTools.getDocumentPartitioning(), null));
return tester; return tester;
} }
public void testCAutoIndent() throws IOException, CoreException, BadLocationException { public void testCAutoIndent() throws BadLocationException {
AutoEditTester tester = createAutoEditTester(); //$NON-NLS-1$ AutoEditTester tester = createAutoEditTester(); //$NON-NLS-1$
tester.type("void main() {\n"); //$NON-NLS-1$ tester.type("void main() {\n"); //$NON-NLS-1$
assertEquals(1, tester.getCaretLine()); assertEquals(1, tester.getCaretLine());
@ -286,7 +286,7 @@ public class CAutoIndentTest extends TestCase {
assertEquals("\t\tint x = 5;", tester.getLine(1)); //$NON-NLS-1$ assertEquals("\t\tint x = 5;", tester.getLine(1)); //$NON-NLS-1$
} }
public void testPasteAutoIndent() throws IOException, CoreException, BadLocationException { public void testPasteAutoIndent() throws BadLocationException {
AutoEditTester tester = createAutoEditTester(); //$NON-NLS-1$ AutoEditTester tester = createAutoEditTester(); //$NON-NLS-1$
tester.type("class A {\n"); //$NON-NLS-1$ tester.type("class A {\n"); //$NON-NLS-1$
tester.goTo(1, 0); tester.goTo(1, 0);
@ -313,7 +313,7 @@ public class CAutoIndentTest extends TestCase {
assertEquals("\t};", tester.getLine(9)); //$NON-NLS-1$ assertEquals("\t};", tester.getLine(9)); //$NON-NLS-1$
} }
public void testDefaultAutoIndent() throws IOException, CoreException, BadLocationException { public void testDefaultAutoIndent() throws BadLocationException {
AutoEditTester tester = createAutoEditTester(); //$NON-NLS-1$ AutoEditTester tester = createAutoEditTester(); //$NON-NLS-1$
tester.type(" initial indent=3\n"); //$NON-NLS-1$ tester.type(" initial indent=3\n"); //$NON-NLS-1$
assertEquals(1, tester.getCaretLine()); assertEquals(1, tester.getCaretLine());
@ -335,7 +335,7 @@ public class CAutoIndentTest extends TestCase {
assertEquals(0, tester.getCaretColumn()); assertEquals(0, tester.getCaretColumn());
} }
public void testCCommentAutoIndent() throws IOException, CoreException, BadLocationException { public void testCCommentAutoIndent() throws BadLocationException {
AutoEditTester tester = createAutoEditTester(); //$NON-NLS-1$ AutoEditTester tester = createAutoEditTester(); //$NON-NLS-1$
tester.type("/*\n"); //$NON-NLS-1$ tester.type("/*\n"); //$NON-NLS-1$
assertEquals(ICPartitions.C_MULTI_LINE_COMMENT, tester.getContentType(-1)); assertEquals(ICPartitions.C_MULTI_LINE_COMMENT, tester.getContentType(-1));
@ -352,4 +352,26 @@ public class CAutoIndentTest extends TestCase {
assertEquals(0, tester.getCaretColumn()); assertEquals(0, tester.getCaretColumn());
} }
public void testPreprocessorAutoIndent() throws BadLocationException {
AutoEditTester tester = createAutoEditTester(); //$NON-NLS-1$
tester.type("void main() {\n"); //$NON-NLS-1$
assertEquals(1, tester.getCaretLine());
// Nested statement is indented by one.
assertEquals(1, tester.getCaretColumn());
// The brace was closed automatically.
assertEquals("}", tester.getLine(1)); //$NON-NLS-1$
tester.type("#define"); //$NON-NLS-1$
assertEquals("#define", tester.getLine()); //$NON-NLS-1$
tester.type(" FOREVER \\\n");
assertEquals(1, tester.getCaretColumn());
tester.type("for(;;) \\\n");
assertEquals(1, tester.getCaretColumn());
tester.type("\t{");
assertEquals(2, tester.getCaretColumn());
assertEquals("\t{", tester.getLine());
tester.type("\\\n");
assertEquals(2, tester.getCaretColumn());
assertEquals("\t}", tester.getLine(1));
}
} }

View file

@ -16,13 +16,6 @@ import java.util.ResourceBundle;
import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.Status;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.widgets.Display;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.text.Assert; import org.eclipse.jface.text.Assert;
import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocument;
@ -34,7 +27,10 @@ import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.TextSelection; import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.text.TextUtilities; import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.ui.texteditor.ITextEditor;
@ -45,11 +41,11 @@ import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants; import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.ICPartitions; import org.eclipse.cdt.ui.text.ICPartitions;
import org.eclipse.cdt.internal.ui.editor.CEditor; import org.eclipse.cdt.internal.ui.editor.CEditor;
import org.eclipse.cdt.internal.ui.editor.IndentUtil;
import org.eclipse.cdt.internal.ui.text.CHeuristicScanner; import org.eclipse.cdt.internal.ui.text.CHeuristicScanner;
import org.eclipse.cdt.internal.ui.text.CIndenter; import org.eclipse.cdt.internal.ui.text.CIndenter;
@ -189,8 +185,8 @@ public class IndentAction extends TextEditorAction {
} }
/** /**
* Indents a single line using the heuristic scanner. Cdoc and multiline comments are * Indents a single line using the heuristic scanner. Multiline comments are
* indented as specified by the <code>CDocAutoIndentStrategy</code>. * indented as specified by the <code>CCommentAutoIndentStrategy</code>.
* *
* @param document the document * @param document the document
* @param line the line to be indented * @param line the line to be indented
@ -214,7 +210,7 @@ public class IndentAction extends TextEditorAction {
if (type.equals(ICPartitions.C_MULTI_LINE_COMMENT)) { if (type.equals(ICPartitions.C_MULTI_LINE_COMMENT)) {
indent= computeCommentIndent(document, line, scanner, startingPartition); indent= computeCommentIndent(document, line, scanner, startingPartition);
} else if (startingPartition.getType().equals(ICPartitions.C_PREPROCESSOR)) { } else if (startingPartition.getType().equals(ICPartitions.C_PREPROCESSOR)) {
indent= computePreprocessorIndent(document, line, scanner, startingPartition); indent= computePreprocessorIndent(document, line, startingPartition);
} else if (!fIsTabAction && startingPartition.getOffset() == offset && startingPartition.getType().equals(ICPartitions.C_SINGLE_LINE_COMMENT)) { } else if (!fIsTabAction && startingPartition.getOffset() == offset && startingPartition.getType().equals(ICPartitions.C_SINGLE_LINE_COMMENT)) {
// line comment starting at position 0 -> indent inside // line comment starting at position 0 -> indent inside
int max= document.getLength() - offset; int max= document.getLength() - offset;
@ -248,7 +244,7 @@ public class IndentAction extends TextEditorAction {
} }
} }
// standard C indentation // standard C code indentation
if (indent == null) { if (indent == null) {
StringBuffer computed= indenter.computeIndentation(offset); StringBuffer computed= indenter.computeIndentation(offset);
if (computed != null) if (computed != null)
@ -305,48 +301,7 @@ public class IndentAction extends TextEditorAction {
* @throws BadLocationException * @throws BadLocationException
*/ */
private String computeCommentIndent(IDocument document, int line, CHeuristicScanner scanner, ITypedRegion partition) throws BadLocationException { private String computeCommentIndent(IDocument document, int line, CHeuristicScanner scanner, ITypedRegion partition) throws BadLocationException {
if (line == 0) // impossible - the first line is never inside a comment comment return IndentUtil.computeCommentIndent(document, line, scanner, partition);
return null;
// don't make any assumptions if the line does not start with \s*\* - it might be
// commented out code, for which we don't want to change the indent
final IRegion lineInfo= document.getLineInformation(line);
final int lineStart= lineInfo.getOffset();
final int lineLength= lineInfo.getLength();
final int lineEnd= lineStart + lineLength;
int nonWS= scanner.findNonWhitespaceForwardInAnyPartition(lineStart, lineEnd);
if (nonWS == CHeuristicScanner.NOT_FOUND || document.getChar(nonWS) != '*') {
if (nonWS == CHeuristicScanner.NOT_FOUND)
return document.get(lineStart, lineLength);
return document.get(lineStart, nonWS - lineStart);
}
// take the indent from the previous line and reuse
IRegion previousLine= document.getLineInformation(line - 1);
int previousLineStart= previousLine.getOffset();
int previousLineLength= previousLine.getLength();
int previousLineEnd= previousLineStart + previousLineLength;
StringBuffer buf= new StringBuffer();
int previousLineNonWS= scanner.findNonWhitespaceForwardInAnyPartition(previousLineStart, previousLineEnd);
if (previousLineNonWS == CHeuristicScanner.NOT_FOUND || document.getChar(previousLineNonWS) != '*') {
// align with the comment start if the previous line is not an asterisked line
previousLine= document.getLineInformationOfOffset(partition.getOffset());
previousLineStart= previousLine.getOffset();
previousLineLength= previousLine.getLength();
previousLineEnd= previousLineStart + previousLineLength;
previousLineNonWS= scanner.findNonWhitespaceForwardInAnyPartition(previousLineStart, previousLineEnd);
if (previousLineNonWS == CHeuristicScanner.NOT_FOUND)
previousLineNonWS= previousLineEnd;
// add the initial space
// TODO this may be controlled by a formatter preference in the future
buf.append(' ');
}
String indentation= document.get(previousLineStart, previousLineNonWS - previousLineStart);
buf.insert(0, indentation);
return buf.toString();
} }
/** /**
@ -354,13 +309,12 @@ public class IndentAction extends TextEditorAction {
* *
* @param document the document * @param document the document
* @param line the line in document * @param line the line in document
* @param scanner the scanner
* @param partition the comment partition * @param partition the comment partition
* @return the indent, or <code>null</code> if not computable * @return the indent, or <code>null</code> if not computable
* @throws BadLocationException * @throws BadLocationException
*/ */
private String computePreprocessorIndent(IDocument document, int line, CHeuristicScanner scanner, ITypedRegion partition) throws BadLocationException { private String computePreprocessorIndent(IDocument document, int line, ITypedRegion partition) throws BadLocationException {
return ""; //$NON-NLS-1$ return IndentUtil.computePreprocessorIndent(document, line, partition);
} }
/** /**

View file

@ -134,7 +134,7 @@ public final class IndentUtil {
CIndenter indenter= new CIndenter(document, scanner, project); CIndenter indenter= new CIndenter(document, scanner, project);
String current= getCurrentIndent(document, lines.getStartLine()); String current= getCurrentIndent(document, lines.getStartLine());
StringBuffer correct= indenter.computeIndentation(document.getLineOffset(lines.getStartLine())); StringBuffer correct= new StringBuffer(computeIndent(document, lines.getStartLine(), indenter, scanner));
if (correct == null) if (correct == null)
return result; // bail out return result; // bail out
@ -289,7 +289,7 @@ public final class IndentUtil {
/** /**
* Returns the indentation of the line <code>line</code> in <code>document</code>. * Returns the indentation of the line <code>line</code> in <code>document</code>.
* The returned string may contain pairs of leading slashes that are considered * 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 * part of the indentation. The space before the asterix in a block
* comment is not considered part of the indentation. * comment is not considered part of the indentation.
* *
* @param document the document * @param document the document
@ -314,7 +314,7 @@ public final class IndentUtil {
to++; to++;
} }
// don't count the space before javadoc like, asterix-style comment lines // 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$ 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); String type= TextUtilities.getContentType(document, ICPartitions.C_PARTITIONING, to, true);
if (type.equals(ICPartitions.C_MULTI_LINE_COMMENT)) if (type.equals(ICPartitions.C_MULTI_LINE_COMMENT))
@ -353,12 +353,12 @@ public final class IndentUtil {
} }
/** /**
* Indents a single line using the java heuristic scanner. Multi line comments * Indents a single line using the heuristic scanner. Multiline comments are
* are indented as specified by the <code>CDocAutoIndentStrategy</code>. * indented as specified by the <code>CCommentAutoIndentStrategy</code>.
* *
* @param document the document * @param document the document
* @param line the line to be indented * @param line the line to be indented
* @param indenter the java indenter * @param indenter the C indenter
* @param scanner the heuristic scanner * @param scanner the heuristic scanner
* @param commentLines the indent token comment booleans * @param commentLines the indent token comment booleans
* @param lineIndex the zero-based line index * @param lineIndex the zero-based line index
@ -377,13 +377,15 @@ public final class IndentUtil {
ITypedRegion startingPartition= TextUtilities.getPartition(document, ICPartitions.C_PARTITIONING, offset, false); ITypedRegion startingPartition= TextUtilities.getPartition(document, ICPartitions.C_PARTITIONING, offset, false);
String type= partition.getType(); String type= partition.getType();
if (type.equals(ICPartitions.C_MULTI_LINE_COMMENT)) { if (type.equals(ICPartitions.C_MULTI_LINE_COMMENT)) {
indent= computeCdocIndent(document, line, scanner, startingPartition); indent= computeCommentIndent(document, line, scanner, startingPartition);
} else if (startingPartition.getType().equals(ICPartitions.C_PREPROCESSOR)) {
indent= computePreprocessorIndent(document, line, startingPartition);
} else if (!commentLines[lineIndex] && startingPartition.getOffset() == offset && startingPartition.getType().equals(ICPartitions.C_SINGLE_LINE_COMMENT)) { } else if (!commentLines[lineIndex] && startingPartition.getOffset() == offset && startingPartition.getType().equals(ICPartitions.C_SINGLE_LINE_COMMENT)) {
return false; return false;
} }
} }
// standard java indentation // standard C code indentation
if (indent == null) { if (indent == null) {
StringBuffer computed= indenter.computeIndentation(offset); StringBuffer computed= indenter.computeIndentation(offset);
if (computed != null) if (computed != null)
@ -418,10 +420,48 @@ public final class IndentUtil {
return false; return false;
} }
/**
* Computes and returns the indentation for a source line.
*
* @param document the document
* @param line the line in document
* @param indenter the C indenter
* @param scanner the scanner
* @return the indent, never <code>null</code>
* @throws BadLocationException
*/
public static String computeIndent(IDocument document, int line, CIndenter indenter, CHeuristicScanner scanner) throws BadLocationException {
IRegion currentLine= document.getLineInformation(line);
final int offset= currentLine.getOffset();
String indent= null;
if (offset < document.getLength()) {
ITypedRegion partition= TextUtilities.getPartition(document, ICPartitions.C_PARTITIONING, offset, true);
ITypedRegion startingPartition= TextUtilities.getPartition(document, ICPartitions.C_PARTITIONING, offset, false);
String type= partition.getType();
if (type.equals(ICPartitions.C_MULTI_LINE_COMMENT)) {
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();
}
}
// standard C code indentation
if (indent == null) {
StringBuffer computed= indenter.computeIndentation(offset);
if (computed != null)
indent= computed.toString();
else
indent= new String();
}
return indent;
}
/** /**
* Computes and returns the indentation for a javadoc line. The line * Computes and returns the indentation for a comment line.
* must be inside a javadoc comment.
* *
* @param document the document * @param document the document
* @param line the line in document * @param line the line in document
@ -430,8 +470,8 @@ public final class IndentUtil {
* @return the indent, or <code>null</code> if not computable * @return the indent, or <code>null</code> if not computable
* @throws BadLocationException * @throws BadLocationException
*/ */
private static String computeCdocIndent(IDocument document, int line, CHeuristicScanner scanner, ITypedRegion partition) throws BadLocationException { public static String computeCommentIndent(IDocument document, int line, CHeuristicScanner scanner, ITypedRegion partition) throws BadLocationException {
if (line == 0) // impossible - the first line is never inside a javadoc comment if (line == 0) // impossible - the first line is never inside a comment
return null; return null;
// don't make any assumptions if the line does not start with \s*\* - it might be // don't make any assumptions if the line does not start with \s*\* - it might be
@ -474,4 +514,40 @@ public final class IndentUtil {
buf.insert(0, indentation); buf.insert(0, indentation);
return buf.toString(); return buf.toString();
} }
/**
* Computes and returns the indentation for a preprocessor line.
*
* @param document the document
* @param line the line in document
* @param partition the comment partition
* @return the indent, or <code>null</code> if not computable
* @throws BadLocationException
*/
public static String computePreprocessorIndent(IDocument document, int line, ITypedRegion partition) throws BadLocationException {
int ppFirstLine= document.getLineOfOffset(partition.getOffset());
if (line == ppFirstLine) {
return ""; //$NON-NLS-1$
}
CHeuristicScanner ppScanner= new CHeuristicScanner(document, ICPartitions.C_PARTITIONING, partition.getType());
CIndenter ppIndenter= new CIndenter(document, ppScanner);
if (line == ppFirstLine + 1) {
return ppIndenter.createReusingIndent(new StringBuffer(), 1).toString();
}
StringBuffer computed= ppIndenter.computeIndentation(document.getLineOffset(line), false);
if (computed != null) {
return computed.toString();
}
// take the indent from the previous line and reuse
IRegion previousLine= document.getLineInformation(line - 1);
int previousLineStart= previousLine.getOffset();
int previousLineLength= previousLine.getLength();
int previousLineEnd= previousLineStart + previousLineLength;
int previousLineNonWS= ppScanner.findNonWhitespaceForwardInAnyPartition(previousLineStart, previousLineEnd);
String previousIndent= document.get(previousLineStart, previousLineNonWS - previousLineStart);
computed= new StringBuffer(previousIndent);
return computed.toString();
}
} }

View file

@ -8,7 +8,7 @@
* Contributors: * Contributors:
* IBM Corporation - initial API and implementation * IBM Corporation - initial API and implementation
* QNX Software System * QNX Software System
* Anton Leherbauer (Wind River Systems) - Fixed bug 48339 * Anton Leherbauer (Wind River Systems)
* Sergey Prigogin, Google * Sergey Prigogin, Google
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.ui.text; package org.eclipse.cdt.internal.ui.text;
@ -23,6 +23,7 @@ import org.eclipse.jface.text.DocumentRewriteSession;
import org.eclipse.jface.text.DocumentRewriteSessionType; import org.eclipse.jface.text.DocumentRewriteSessionType;
import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.TextUtilities; import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.rules.FastPartitioner; import org.eclipse.jface.text.rules.FastPartitioner;
import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IEditorPart;
@ -36,6 +37,8 @@ import org.eclipse.cdt.ui.text.ICPartitions;
import org.eclipse.cdt.internal.corext.util.CodeFormatterUtil; import org.eclipse.cdt.internal.corext.util.CodeFormatterUtil;
import org.eclipse.cdt.internal.ui.editor.IndentUtil;
/** /**
* Auto indent strategy sensitive to brackets. * Auto indent strategy sensitive to brackets.
*/ */
@ -72,25 +75,6 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
fProject = project; fProject = project;
} }
// evaluate the line with the opening bracket that matches the closing bracket on the given line
protected int findMatchingOpenBracket(IDocument d, int line, int end, int closingBracketIncrease) throws BadLocationException {
int start = d.getLineOffset(line);
int brackcount = getBracketCount(d, start, end, false) - closingBracketIncrease;
// sum up the brackets counts of each line (closing brackets count negative,
// opening positive) until we find a line the brings the count to zero
while (brackcount < 0) {
line--;
if (line < 0) {
return -1;
}
start = d.getLineOffset(line);
end = start + d.getLineLength(line) - 1;
brackcount += getBracketCount(d, start, end, false);
}
return line;
}
private int getBracketCount(IDocument d, int start, int end, boolean ignoreCloseBrackets) throws BadLocationException { private int getBracketCount(IDocument d, int start, int end, boolean ignoreCloseBrackets) throws BadLocationException {
int bracketcount = 0; int bracketcount = 0;
while (start < end) { while (start < end) {
@ -153,7 +137,7 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
return end; return end;
} }
protected String getIndentOfLine(IDocument d, int line) throws BadLocationException { private String getIndentOfLine(IDocument d, int line) throws BadLocationException {
if (line > -1) { if (line > -1) {
int start = d.getLineOffset(line); int start = d.getLineOffset(line);
int end = start + d.getLineLength(line) - 1; int end = start + d.getLineLength(line) - 1;
@ -177,37 +161,6 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
return end; return end;
} }
protected void smartInsertAfterBracket(IDocument d, DocumentCommand c) {
if (c.offset == -1 || d.getLength() == 0)
return;
try {
int p = (c.offset == d.getLength() ? c.offset - 1 : c.offset);
int line = d.getLineOfOffset(p);
int start = d.getLineOffset(line);
int whiteend = findEndOfWhiteSpace(d, start, c.offset);
// shift only when line does not contain any text up to the closing bracket
if (whiteend == c.offset) {
// evaluate the line with the opening bracket that matches out closing bracket
int indLine = findMatchingOpenBracket(d, line, c.offset, 1);
if (indLine != -1 && indLine != line) {
// take the indent of the found line
StringBuffer replaceText = new StringBuffer(getIndentOfLine(d, indLine));
// add the rest of the current line including the just added close bracket
replaceText.append(d.get(whiteend, c.offset - whiteend));
replaceText.append(c.text);
// modify document command
c.length = c.offset - start;
c.offset = start;
c.text = replaceText.toString();
}
}
} catch (BadLocationException excp) {
CUIPlugin.getDefault().log(excp);
}
}
private void smartIndentAfterClosingBracket(IDocument d, DocumentCommand c) { private void smartIndentAfterClosingBracket(IDocument d, DocumentCommand c) {
if (c.offset == -1 || d.getLength() == 0) if (c.offset == -1 || d.getLength() == 0)
return; return;
@ -218,7 +171,11 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
int start = d.getLineOffset(line); int start = d.getLineOffset(line);
int whiteend = findEndOfWhiteSpace(d, start, c.offset); int whiteend = findEndOfWhiteSpace(d, start, c.offset);
CHeuristicScanner scanner = new CHeuristicScanner(d); CHeuristicScanner scanner= new CHeuristicScanner(d);
ITypedRegion partition= TextUtilities.getPartition(d, fPartitioning, p, false);
if (ICPartitions.C_PREPROCESSOR.equals(partition.getType())) {
scanner = new CHeuristicScanner(d, fPartitioning, ICPartitions.C_PREPROCESSOR);
}
CIndenter indenter = new CIndenter(d, scanner, fProject); CIndenter indenter = new CIndenter(d, scanner, fProject);
// shift only when line does not contain any text up to the closing bracket // shift only when line does not contain any text up to the closing bracket
@ -247,11 +204,14 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
if (c.offset < 1 || d.getLength() == 0) if (c.offset < 1 || d.getLength() == 0)
return; return;
CHeuristicScanner scanner = new CHeuristicScanner(d);
int p = (c.offset == d.getLength() ? c.offset - 1 : c.offset); int p = (c.offset == d.getLength() ? c.offset - 1 : c.offset);
try { try {
CHeuristicScanner scanner= new CHeuristicScanner(d);
ITypedRegion partition= TextUtilities.getPartition(d, fPartitioning, p, false);
if (ICPartitions.C_PREPROCESSOR.equals(partition.getType())) {
scanner = new CHeuristicScanner(d, fPartitioning, ICPartitions.C_PREPROCESSOR);
}
// current line // current line
int line = d.getLineOfOffset(p); int line = d.getLineOfOffset(p);
int lineOffset = d.getLineOffset(line); int lineOffset = d.getLineOffset(line);
@ -284,12 +244,23 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
} }
private void smartIndentAfterNewLine(IDocument d, DocumentCommand c) { private void smartIndentAfterNewLine(IDocument d, DocumentCommand c) {
CHeuristicScanner scanner = new CHeuristicScanner(d); int addIndent= 0;
CHeuristicScanner scanner= new CHeuristicScanner(d);
try {
ITypedRegion partition= TextUtilities.getPartition(d, fPartitioning, c.offset, false);
if (ICPartitions.C_PREPROCESSOR.equals(partition.getType()) && d.get(c.offset-1, 1).charAt(0) == '\\') {
scanner = new CHeuristicScanner(d, fPartitioning, ICPartitions.C_PREPROCESSOR);
addIndent= 1;
}
} catch (BadLocationException exc) {
}
CIndenter indenter = new CIndenter(d, scanner, fProject); CIndenter indenter = new CIndenter(d, scanner, fProject);
StringBuffer indent = indenter.computeIndentation(c.offset); StringBuffer indent = indenter.computeIndentation(c.offset);
if (indent == null) if (indent == null)
indent = new StringBuffer(); indent = new StringBuffer();
if (addIndent > 0 && indent.length() == 0) {
indent= indenter.createReusingIndent(indent, addIndent);
}
int docLength = d.getLength(); int docLength = d.getLength();
if (c.offset == -1 || docLength == 0) if (c.offset == -1 || docLength == 0)
return; return;
@ -533,6 +504,7 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
ICPartitions.C_SINGLE_LINE_COMMENT, ICPartitions.C_SINGLE_LINE_COMMENT,
ICPartitions.C_STRING, ICPartitions.C_STRING,
ICPartitions.C_CHARACTER, ICPartitions.C_CHARACTER,
ICPartitions.C_PREPROCESSOR,
IDocument.DEFAULT_CONTENT_TYPE IDocument.DEFAULT_CONTENT_TYPE
}; };
FastPartitioner partitioner= new FastPartitioner(new FastCPartitionScanner(), types); FastPartitioner partitioner= new FastPartitioner(new FastCPartitionScanner(), types);
@ -610,7 +582,7 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
if (!isIndentDetected) { if (!isIndentDetected) {
// indent the first pasted line // indent the first pasted line
String current= getCurrentIndent(temp, l); String current= getCurrentIndent(temp, l);
StringBuffer correct= indenter.computeIndentation(lineOffset); StringBuffer correct= new StringBuffer(IndentUtil.computeIndent(temp, l, indenter, scanner));
if (correct == null) if (correct == null)
return; // bail out return; // bail out
@ -978,6 +950,9 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
case ':': case ':':
smartIndentAfterColumn(document, command); smartIndentAfterColumn(document, command);
break; break;
case '#':
smartIndentAfterHash(document, command);
break;
} }
} }
@ -1136,6 +1111,22 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
} }
} }
private void smartIndentAfterHash(IDocument doc, DocumentCommand c) {
try {
ITypedRegion partition= TextUtilities.getPartition(doc, fPartitioning, c.offset, false);
if (IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType())) {
IRegion startLine= doc.getLineInformationOfOffset(c.offset);
String indent= (doc.get(startLine.getOffset(), c.offset - startLine.getOffset()));
if (indent.trim().length() == 0) {
c.offset -= indent.length();
c.length += indent.length();
}
}
} catch (BadLocationException e) {
CUIPlugin.getDefault().log(e);
}
}
/* /*
* @see org.eclipse.jface.text.IAutoEditStrategy#customizeDocumentCommand(IDocument, DocumentCommand) * @see org.eclipse.jface.text.IAutoEditStrategy#customizeDocumentCommand(IDocument, DocumentCommand)
*/ */
@ -1175,7 +1166,7 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
private boolean isAppendToOpenMultilineComment(IDocument d, DocumentCommand c) { private boolean isAppendToOpenMultilineComment(IDocument d, DocumentCommand c) {
if (d.getLength() >= 2 && c.offset == d.getLength()) { if (d.getLength() >= 2 && c.offset == d.getLength()) {
try { try {
String contentType = org.eclipse.jface.text.TextUtilities.getContentType(d, fPartitioning, c.offset - 1, false); String contentType = TextUtilities.getContentType(d, fPartitioning, c.offset - 1, false);
if (ICPartitions.C_MULTI_LINE_COMMENT.equals(contentType)) { if (ICPartitions.C_MULTI_LINE_COMMENT.equals(contentType)) {
return !d.get(c.offset - 2, 2).equals(MULTILINE_COMMENT_CLOSE); return !d.get(c.offset - 2, 2).equals(MULTILINE_COMMENT_CLOSE);
} }