From ef3dcbc65618a60b1662ac48dfffd694b71c304d Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Thu, 28 May 2009 09:13:11 +0000 Subject: [PATCH] Bugs 277624 and 277625. --- .../resources/indentation/sample/After.cpp | 9 +- .../resources/indentation/sample/Before.cpp | 1 - .../cdt/ui/tests/text/CAutoIndentTest.java | 22 +-- .../cdt/ui/tests/text/CIndenterTest.java | 122 +++++++++++++-- .../cdt/ui/tests/text/IndentActionTest.java | 3 +- .../cdt/internal/ui/editor/IndentUtil.java | 5 +- .../cdt/internal/ui/text/CIndenter.java | 147 +++++++++--------- 7 files changed, 207 insertions(+), 102 deletions(-) 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 6ecb3013f3c..b46d3e233f6 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 @@ -10,11 +10,10 @@ const SimpleStruct simpleStruct = #define SIZEOF( A, B ) sizeof( A.B ) #define FOREVER \ - for(;;)\ - {\ - \ - } -} + for(;;)\ + {\ + \ + } const OtherStruct array[] = { 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 c1f5449b7ac..0ce65ac1fc9 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 @@ -14,7 +14,6 @@ const SimpleStruct simpleStruct = {\ \ } - } const OtherStruct array[] = { 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 dc31dbc1b14..f853be4232c 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 @@ -177,24 +177,24 @@ public class CAutoIndentTest extends AbstractAutoEditTest { public void testDefaultAutoIndent() throws BadLocationException { AutoEditTester tester = createAutoEditTester(); //$NON-NLS-1$ - tester.type(" initial indent=3\n"); //$NON-NLS-1$ + tester.type(" initial indent=5\n"); //$NON-NLS-1$ assertEquals(1, tester.getCaretLine()); - assertEquals(3, tester.getCaretColumn()); - tester.type("indent=3\n"); //$NON-NLS-1$ + assertEquals(5, tester.getCaretColumn()); + tester.type("indent=5\n"); //$NON-NLS-1$ assertEquals(2, tester.getCaretLine()); - assertEquals(3, tester.getCaretColumn()); + assertEquals(5, tester.getCaretColumn()); + tester.backspace(); + tester.type("indent=4\n"); //$NON-NLS-1$ + assertEquals(3, tester.getCaretLine()); + assertEquals(4, tester.getCaretColumn()); + tester.backspace(); tester.backspace(); tester.type("indent=2\n"); //$NON-NLS-1$ - assertEquals(3, tester.getCaretLine()); - assertEquals(2, tester.getCaretColumn()); - tester.backspace(); - tester.backspace(); - tester.type("indent=0\n"); //$NON-NLS-1$ assertEquals(4, tester.getCaretLine()); - assertEquals(0, tester.getCaretColumn()); + assertEquals(2, tester.getCaretColumn()); tester.type("\n"); //$NON-NLS-1$ assertEquals(5, tester.getCaretLine()); - assertEquals(0, tester.getCaretColumn()); + assertEquals(2, tester.getCaretColumn()); } public void testCCommentAutoIndent() throws BadLocationException { diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CIndenterTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CIndenterTest.java index 00f0c57f25c..61818f9f92c 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CIndenterTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CIndenterTest.java @@ -27,8 +27,6 @@ import org.eclipse.cdt.internal.formatter.DefaultCodeFormatterOptions; import org.eclipse.cdt.internal.ui.editor.CDocumentSetupParticipant; import org.eclipse.cdt.internal.ui.editor.IndentUtil; -import org.eclipse.cdt.internal.ui.text.CHeuristicScanner; -import org.eclipse.cdt.internal.ui.text.CIndenter; /** * Tests for the CIndenter. @@ -61,8 +59,11 @@ public class CIndenterTest extends BaseUITestCase { IDocument document= new Document(before); String expected= contents[1].toString(); new CDocumentSetupParticipant().setup(document); - CIndenter indenter= new CIndenter(document, new CHeuristicScanner(document)); - IndentUtil.indentLines(document, new LineRange(0, document.getNumberOfLines()), null, null); + int numLines = document.getNumberOfLines(); + if (document.getLineLength(numLines - 1) == 0) { + numLines--; // Exclude an empty line at the end. + } + IndentUtil.indentLines(document, new LineRange(0, numLines), null, null); assertEquals(expected, document.get()); } @@ -300,7 +301,7 @@ public class CIndenterTest extends BaseUITestCase { DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED); assertIndenterResult(); } - + //// a comment //class MyClass : public Base //{ @@ -351,25 +352,124 @@ public class CIndenterTest extends BaseUITestCase { //x = // 0; - public void _testWrappedAssignment_277624_1() throws Exception { + public void testWrappedAssignment_277624_1() throws Exception { assertIndenterResult(); } + //{ + //a = 0; //x = 2 + + //2 + //2; - - //x = 2 + - // 2; - public void _testWrappedAssignment_277624_2() throws Exception { + + //{ + // a = 0; + // x = 2 + + // 2 + + // 2; + public void testWrappedAssignment_277624_2() throws Exception { assertIndenterResult(); } + //if (1 > 0) { + //double d = a * b / + //c; + + //if (1 > 0) { + // double d = a * b / + // c; + public void testWrappedAssignment_277624_3() throws Exception { + assertIndenterResult(); + } + //for (int i = 0; //i < 2; i++) //for (int i = 0; // i < 2; i++) - public void _testWrappedFor_277625() throws Exception { + public void testWrappedFor_277625_1() throws Exception { + assertIndenterResult(); + } + + //for (int i = 0; i < 2; + //i++) + + //for (int i = 0; i < 2; + // i++) + public void testWrappedFor_277625_2() throws Exception { + assertIndenterResult(); + } + + //for (int i = 0; + //i < 2; + //i++) + //{ + + //for (int i = 0; + // i < 2; + // i++) + //{ + public void testWrappedFor_277625_3() throws Exception { + assertIndenterResult(); + } + + //; + //for (hash_map::const_iterator it = container_.begin(); + //it != container_.end(); ++it) { + + //; + //for (hash_map::const_iterator it = container_.begin(); + // it != container_.end(); ++it) { + public void testWrappedFor_277625_4() throws Exception { + assertIndenterResult(); + } + + ///* comment */ + //#define MACRO(a, b) \ + //value + + ///* comment */ + //#define MACRO(a, b) \ + // value + public void testWrappedDefine() throws Exception { + assertIndenterResult(); + } + + //std::string + // func(); + + //std::string + //func(); + public void testFunctionDeclaration_1() throws Exception { + assertIndenterResult(); + } + + //; + //std::string + // func(); + + //; + //std::string + //func(); + public void testFunctionDeclaration_2() throws Exception { + assertIndenterResult(); + } + + //map::iterator + // func(); + + //map::iterator + //func(); + public void testFunctionDeclaration_3() throws Exception { + assertIndenterResult(); + } + + //template > + // class B { + + //template > + //class B { + public void testTemplateClass() throws Exception { assertIndenterResult(); } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/IndentActionTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/IndentActionTest.java index 35b64bf38dc..20373e654ab 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/IndentActionTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/IndentActionTest.java @@ -64,9 +64,8 @@ public class IndentActionTest extends TestCase { } } - private static final Class THIS= IndentActionTest.class; public static Test suite() { - return new IndentTestSetup(new TestSuite(THIS)); + return new IndentTestSetup(new TestSuite(IndentActionTest.class)); } private CEditor fEditor; 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 4179ab588f2..f58a72e759b 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 @@ -590,7 +590,8 @@ public final class IndentUtil { * @return the indent, or null if not computable * @throws BadLocationException */ - public static String computePreprocessorIndent(IDocument document, int line, ITypedRegion partition) 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$ @@ -598,7 +599,7 @@ public final class IndentUtil { CHeuristicScanner ppScanner= new CHeuristicScanner(document, ICPartitions.C_PARTITIONING, partition.getType()); CIndenter ppIndenter= new CIndenter(document, ppScanner); if (line == ppFirstLine + 1) { - return ppIndenter.createReusingIndent(new StringBuilder(), 1).toString(); + return ppIndenter.createReusingIndent(new StringBuilder(), ppIndenter.getContinuationLineIndent()).toString(); } StringBuilder computed= ppIndenter.computeIndentation(document.getLineOffset(line), false); if (computed != null) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CIndenter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CIndenter.java index 4858f1b97bc..6d32d16b2ad 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CIndenter.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CIndenter.java @@ -1,11 +1,11 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: + * Copyright (c) 2000, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: * IBM Corporation - initial API and implementation * Sergey Prigogin (Google) * Anton Leherbauer (Wind River Systems) @@ -67,7 +67,7 @@ public final class CIndenter { final boolean prefIndentBracesForMethods; final boolean prefIndentBracesForTypes; final int prefContinuationIndent; - final boolean prefHasGenerics; + final boolean prefHasTemplates; final String prefTabChar; private final ICProject fProject; @@ -115,7 +115,7 @@ public final class CIndenter { prefIndentBracesForArrays= prefIndentBracesForArrays(); prefIndentBracesForMethods= prefIndentBracesForMethods(); prefIndentBracesForTypes= prefIndentBracesForTypes(); - prefHasGenerics= hasGenerics(); + prefHasTemplates= hasTemplates(); prefTabChar= getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR); } @@ -197,7 +197,7 @@ public final class CIndenter { } private int prefAssignmentIndent() { - return prefBlockIndent(); + return prefContinuationIndent(); } private int prefSimpleIndent() { @@ -337,7 +337,7 @@ public final class CIndenter { return 2; // sensible default } - private boolean hasGenerics() { + private boolean hasTemplates() { return true; } } @@ -669,6 +669,14 @@ public final class CIndenter { return buffer; } + /** + * Returns relative indent of continuation lines. + * @return a number of indentation units. + */ + public int getContinuationLineIndent() { + return fPrefs.prefContinuationIndent; + } + /** * Returns the reference position regarding to indentation for offset, * or NOT_FOUND. This method calls @@ -731,8 +739,8 @@ public final class CIndenter { */ public int findReferencePosition(int offset, int nextToken) { boolean danglingElse= false; - boolean unindent= false; - boolean indent= false; + boolean cancelIndent= false; // If set to true, fIndent is ignored. + int extraIndent= 0; // Can be either positive or negative. boolean matchBrace= false; boolean matchParen= false; boolean matchCase= false; @@ -770,16 +778,18 @@ public final class CIndenter { break; case Symbols.TokenLBRACE: // for opening-brace-on-new-line style - if (bracelessBlockStart) - unindent= !fPrefs.prefIndentBracesForBlocks; - else if (prevToken == Symbols.TokenCOLON && !fPrefs.prefIndentBracesForBlocks) - unindent= true; - else if ((prevToken == Symbols.TokenEQUAL || prevToken == Symbols.TokenRBRACKET) && !fPrefs.prefIndentBracesForArrays) - unindent= true; - else if (prevToken == Symbols.TokenRPAREN && fPrefs.prefIndentBracesForMethods) - indent= true; - else if (prevToken == Symbols.TokenIDENT && fPrefs.prefIndentBracesForTypes) - indent= true; + if (bracelessBlockStart) { + extraIndent= fPrefs.prefIndentBracesForBlocks ? 0 : -1; + } else if (prevToken == Symbols.TokenCOLON && !fPrefs.prefIndentBracesForBlocks) { + extraIndent= -1; + } else if ((prevToken == Symbols.TokenEQUAL || prevToken == Symbols.TokenRBRACKET) && + !fPrefs.prefIndentBracesForArrays) { + cancelIndent= true; + } else if (prevToken == Symbols.TokenRPAREN && fPrefs.prefIndentBracesForMethods) { + extraIndent= 1; + } else if (prevToken == Symbols.TokenIDENT && fPrefs.prefIndentBracesForTypes) { + extraIndent= 1; + } break; case Symbols.TokenRBRACE: // closing braces get unindented @@ -799,12 +809,15 @@ public final class CIndenter { danglingElse= false; } - int ref= findReferencePosition(offset, danglingElse, matchBrace, matchParen, matchCase, matchAccessSpecifier); - if (unindent) - fIndent--; - if (indent) { + int ref= findReferencePosition(offset, danglingElse, matchBrace, matchParen, matchCase, + matchAccessSpecifier); + if (cancelIndent) { + fIndent = 0; + } else if (extraIndent > 0) { fAlign= CHeuristicScanner.NOT_FOUND; - fIndent++; + fIndent += extraIndent; + } else { + fIndent += extraIndent; } return ref; } @@ -1138,6 +1151,7 @@ public final class CIndenter { final int READ_IDENT= 2; int mayBeMethodBody= NOTHING; boolean isTypeBody= false; + int startLine = fLine; while (true) { int prevToken= fToken; nextToken(); @@ -1167,11 +1181,23 @@ public final class CIndenter { } } + if (fToken == Symbols.TokenSEMICOLON && fLine == startLine) { + // Skip semicolons on the same line. Otherwise we may never reach beginning of a 'for' + // statement. + continue; + } + switch (fToken) { // scope introduction through: LPAREN, LBRACE, LBRACKET // search stop on SEMICOLON, RBRACE, COLON, EOF // -> the next token is the start of the statement (i.e. previousPos when backward scanning) case Symbols.TokenLPAREN: + if (peekToken() == Symbols.TokenFOR) { + nextToken(); // Consume 'for' + fIndent = fPrefs.prefContinuationIndent; + return fPosition; + } + //$FALL-THROUGH$ case Symbols.TokenLBRACE: case Symbols.TokenLBRACKET: case Symbols.TokenSEMICOLON: @@ -1215,7 +1241,6 @@ public final class CIndenter { else return pos; case Symbols.TokenRBRACKET: - case Symbols.TokenGREATERTHAN: pos= fPreviousPos; if (skipScope()) break; @@ -1352,7 +1377,6 @@ public final class CIndenter { case Symbols.TokenRPAREN: case Symbols.TokenRBRACKET: case Symbols.TokenRBRACE: - case Symbols.TokenGREATERTHAN: skipScope(); break; @@ -1403,7 +1427,6 @@ public final class CIndenter { case Symbols.TokenRPAREN: case Symbols.TokenRBRACKET: case Symbols.TokenRBRACE: - case Symbols.TokenGREATERTHAN: skipScope(); break; @@ -1427,6 +1450,7 @@ public final class CIndenter { private int skipToPreviousListItemOrListStart() { int startLine= fLine; int startPosition= fPosition; + boolean seenEqual = fToken == Symbols.TokenEQUAL; while (true) { nextToken(); @@ -1435,7 +1459,12 @@ public final class CIndenter { try { int lineOffset= fDocument.getLineOffset(startLine); int bound= Math.min(fDocument.getLength(), startPosition + 1); - fAlign= fScanner.findNonWhitespaceForwardInAnyPartition(lineOffset, bound); + if ((fToken == Symbols.TokenSEMICOLON || fToken == Symbols.TokenRBRACE || + fToken == Symbols.TokenLBRACE) && seenEqual) { + fIndent = fPrefs.prefContinuationIndent; + } else { + fAlign= fScanner.findNonWhitespaceForwardInAnyPartition(lineOffset, bound); + } } catch (BadLocationException e) { // ignore and return just the position } @@ -1447,7 +1476,6 @@ public final class CIndenter { case Symbols.TokenRPAREN: case Symbols.TokenRBRACKET: case Symbols.TokenRBRACE: - case Symbols.TokenGREATERTHAN: skipScope(); break; @@ -1468,7 +1496,14 @@ public final class CIndenter { } return fPosition; + case Symbols.TokenEQUAL: + seenEqual = true; + break; + case Symbols.TokenEOF: + if (seenEqual) { + fIndent = fPrefs.prefContinuationIndent; + } return 0; } } @@ -1492,16 +1527,13 @@ public final class CIndenter { case Symbols.TokenRBRACE: return skipScope(Symbols.TokenLBRACE, Symbols.TokenRBRACE); case Symbols.TokenGREATERTHAN: - if (!fPrefs.prefHasGenerics) + if (!fPrefs.prefHasTemplates) return false; int storedPosition= fPosition; int storedToken= fToken; nextToken(); switch (fToken) { case Symbols.TokenIDENT: - if (!isGenericStarter(getTokenContent())) - break; - // fall thru if (skipScope(Symbols.TokenLESSTHAN, Symbols.TokenGREATERTHAN)) return true; break; @@ -1532,36 +1564,6 @@ public final class CIndenter { return new DocumentCharacterIterator(fDocument, fPosition, fPreviousPos); } - /** - * Returns true if identifier is probably a - * type variable or type name, false if it is rather not. - * This is a heuristic. - * - * @param identifier the identifier to check - * @return true if identifier is probably a - * type variable or type name, false if not - */ - private boolean isGenericStarter(CharSequence identifier) { - /* This heuristic allows any identifiers if they start with an upper - * case. This will fail when a comparison is made with constants: - * - * if (MAX > foo) - * - * will try to find the matching '<' which will never come - * - * Also, it will fail on lower case types and type variables - */ - int length= identifier.length(); - if (length > 0 && Character.isUpperCase(identifier.charAt(0))) { - for (int i= 0; i < length; i++) { - if (identifier.charAt(i) == '_') - return false; - } - return true; - } - return false; - } - /** * Handles the introduction of a new scope. The current token must be one out * of Symbols.TokenLPAREN, Symbols.TokenLBRACE, @@ -1738,7 +1740,6 @@ public final class CIndenter { case Symbols.TokenRPAREN: case Symbols.TokenRBRACKET: case Symbols.TokenRBRACE: - case Symbols.TokenGREATERTHAN: skipScope(); break; @@ -1863,6 +1864,14 @@ public final class CIndenter { } } + /** + * Reads the next token in backward direction from the heuristic scanner + * and returns that token without changing the current position. + */ + private int peekToken() { + return fScanner.previousToken(fPosition - 1, CHeuristicScanner.UNBOUND); + } + /** * Returns true if the current tokens look like a method * declaration header (i.e. only the return type and method name). The @@ -1905,8 +1914,6 @@ public final class CIndenter { return true; } break; - case Symbols.TokenGREATERTHAN: - return skipScope(); case Symbols.TokenCOLON: nextToken(); switch (fToken) {