From 74af047e4a55cc924514a42cf2c022db97d9c256 Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Sun, 30 May 2010 05:34:06 +0000 Subject: [PATCH] Auto indentation in calls to template functions. Bug 314995. --- .../cdt/ui/tests/text/CIndenterTest.java | 15 +++++ .../internal/ui/text/CHeuristicScanner.java | 26 ++++---- .../cdt/internal/ui/text/CIndenter.java | 63 ++++++++++--------- .../cdt/internal/ui/text/CPairMatcher.java | 2 +- .../eclipse/cdt/internal/ui/text/Symbols.java | 4 ++ 5 files changed, 70 insertions(+), 40 deletions(-) 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 b4d177bbe28..e6bd5f2a8ba 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 @@ -255,6 +255,21 @@ public class CIndenterTest extends BaseUITestCase { assertIndenterResult(); } + //new pair(a, + //b); + + //new pair(a, + // b); + public void testCallOfTemplateFunction() throws Exception { + fOptions.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.SPACE); + fOptions.put(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, "2"); + fOptions.put(DefaultCodeFormatterConstants.FORMATTER_INDENTATION_SIZE, "2"); + fOptions.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_METHOD_INVOCATION, + DefaultCodeFormatterConstants.createAlignmentValue(false, DefaultCodeFormatterConstants.WRAP_COMPACT, + DefaultCodeFormatterConstants.INDENT_ON_COLUMN)); + assertIndenterResult(); + } + //struct x { // int f1 : 1; // int f2 : 1; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CHeuristicScanner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CHeuristicScanner.java index e6d4d18cc92..bdb6e249a2f 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CHeuristicScanner.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CHeuristicScanner.java @@ -513,12 +513,9 @@ public final class CHeuristicScanner implements Symbols { } return getToken(identOrKeyword); - - } // operators, number literals etc return TokenOTHER; - } /** @@ -541,7 +538,7 @@ public final class CHeuristicScanner implements Symbols { if (fPos >= 0) { try { return fDocument.getChar(fPos); - } catch (BadLocationException exc) { + } catch (BadLocationException e) { } } return (char)-1; @@ -588,14 +585,16 @@ public final class CHeuristicScanner implements Symbols { return TokenCATCH; if ("class".equals(s)) //$NON-NLS-1$ return TokenCLASS; + if ("const".equals(s)) //$NON-NLS-1$ + return TokenCONST; if ("while".equals(s)) //$NON-NLS-1$ return TokenWHILE; if ("union".equals(s)) //$NON-NLS-1$ return TokenUNION; + if ("using".equals(s)) //$NON-NLS-1$ + return TokenUSING; if ("throw".equals(s)) //$NON-NLS-1$ return TokenTHROW; - if ("const".equals(s)) //$NON-NLS-1$ - return TokenCONST; break; case 6: if ("delete".equals(s)) //$NON-NLS-1$ @@ -618,12 +617,18 @@ public final class CHeuristicScanner implements Symbols { return TokenDEFAULT; if ("private".equals(s)) //$NON-NLS-1$ return TokenPRIVATE; + if ("typedef".equals(s)) //$NON-NLS-1$ + return TokenTYPEDEF; if ("virtual".equals(s)) //$NON-NLS-1$ return TokenVIRTUAL; break; case 8: if ("operator".equals(s)) //$NON-NLS-1$ return TokenOPERATOR; + if ("template".equals(s)) //$NON-NLS-1$ + return TokenTEMPLATE; + if ("typename".equals(s)) //$NON-NLS-1$ + return TokenTYPENAME; break; case 9: if ("namespace".equals(s)) //$NON-NLS-1$ @@ -635,8 +640,8 @@ public final class CHeuristicScanner implements Symbols { } /** - * Returns the position of the closing peer character (forward search). Any scopes introduced by opening peers - * are skipped. All peers accounted for must reside in the default partition. + * Returns the position of the closing peer character (forward search). Any scopes introduced + * by opening peers are skipped. All peers accounted for must reside in the default partition. * *

Note that start must not point to the opening peer, but to the first * character being searched.

@@ -1089,7 +1094,6 @@ public final class CHeuristicScanner implements Symbols { * bound < start, or UNBOUND * @return true if the current position looks like a composite type definition */ - @SuppressWarnings("fallthrough") public boolean looksLikeCompositeTypeDefinitionBackward(int start, int bound) { int token= previousToken(start - 1, bound); switch (token) { @@ -1140,7 +1144,7 @@ public final class CHeuristicScanner implements Symbols { switch (token) { case Symbols.TokenVIRTUAL: token= previousToken(getPosition(), bound); - /* fallthrough */ + //$FALL-THROUGH$ case Symbols.TokenPUBLIC: case Symbols.TokenPROTECTED: case Symbols.TokenPRIVATE: @@ -1162,7 +1166,7 @@ public final class CHeuristicScanner implements Symbols { } if (token != Symbols.TokenCOLON) // colon after class def identifier return false; - /* fallthrough */ + //$FALL-THROUGH$ case Symbols.TokenCOLON: token= previousToken(getPosition(), bound); break outerWhile; 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 45bd501d775..89053f73250 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 @@ -984,6 +984,7 @@ public final class CIndenter { if (!skipScope()) fPosition= pos; return skipToStatementStart(danglingElse, false); + case Symbols.TokenSEMICOLON: // this is the 90% case: after a statement block // the end of the previous statement / block previous.end @@ -1049,6 +1050,12 @@ public final class CIndenter { case Symbols.TokenTRY: return skipToStatementStart(danglingElse, false); + case Symbols.TokenRETURN: + case Symbols.TokenTYPEDEF: + case Symbols.TokenUSING: + fIndent = fPrefs.prefContinuationIndent; + return fPosition; + case Symbols.TokenCONST: nextToken(); if (fToken != Symbols.TokenRPAREN) { @@ -1086,18 +1093,14 @@ public final class CIndenter { return skipToPreviousListItemOrListStart(); case Symbols.TokenCOMMA: - // inside a list of some type - // easy if there is already a list item before with its own indentation - we just align - // if not: take the start of the list ( LPAREN, LBRACE, LBRACKET ) and either align or - // indent by list-indent + // Inside a list of some type. + // Easy if there is already a list item before with its own indentation - we just align. + // If not: take the start of the list (LPAREN, LBRACE, LBRACKET) and either align or + // indent by list-indent. return skipToPreviousListItemOrListStart(); - case Symbols.TokenRETURN: - fIndent = fPrefs.prefContinuationIndent; - return fPosition; - default: - // inside whatever we don't know about: similar to the list case: + // Inside whatever we don't know about: similar to the list case: // if we are inside a continued expression, then either align with a previous line that // has indentation or indent from the expression start line (either a scope introducer // or the start of the expression). @@ -1361,7 +1364,6 @@ public final class CIndenter { case Symbols.TokenEOF: if (isInBlock) fIndent= getBlockIndent(mayBeMethodBody == READ_IDENT, isTypeBody); - // else: fIndent set by previous calls return fPreviousPos; case Symbols.TokenCOLON: @@ -1611,9 +1613,9 @@ public final class CIndenter { private int skipToPreviousListItemOrListStart() { int startLine= fLine; int startPosition= fPosition; - boolean seenEqual = fToken == Symbols.TokenEQUAL; - boolean seenShiftLeft = fToken == Symbols.TokenSHIFTLEFT; - boolean seenRightParen = fToken == Symbols.TokenRPAREN; + boolean continuationLineCandidate = + fToken == Symbols.TokenEQUAL || fToken == Symbols.TokenSHIFTLEFT || + fToken == Symbols.TokenRPAREN; while (true) { nextToken(); @@ -1624,7 +1626,7 @@ public final class CIndenter { int bound= Math.min(fDocument.getLength(), startPosition + 1); if ((fToken == Symbols.TokenSEMICOLON || fToken == Symbols.TokenRBRACE || fToken == Symbols.TokenLBRACE && !looksLikeArrayInitializerIntro() && !looksLikeEnumDeclaration()) && - (seenEqual || seenShiftLeft || seenRightParen)) { + continuationLineCandidate) { fIndent = fPrefs.prefContinuationIndent; } else { fAlign= fScanner.findNonWhitespaceForwardInAnyPartition(lineOffset, bound); @@ -1642,7 +1644,7 @@ public final class CIndenter { switch (fToken) { // scopes: skip them case Symbols.TokenRPAREN: - seenRightParen = true; + continuationLineCandidate = true; //$FALL-THROUGH$ case Symbols.TokenRBRACKET: case Symbols.TokenRBRACE: @@ -1667,22 +1669,21 @@ public final class CIndenter { return fPosition; case Symbols.TokenEQUAL: - seenEqual = true; + case Symbols.TokenSHIFTLEFT: + continuationLineCandidate = true; break; - case Symbols.TokenSHIFTLEFT: - seenShiftLeft = true; - break; + case Symbols.TokenRETURN: + case Symbols.TokenTYPEDEF: + case Symbols.TokenUSING: + fIndent = fPrefs.prefContinuationIndent; + return fPosition; case Symbols.TokenEOF: - if (seenEqual || seenShiftLeft || seenRightParen) { + if (continuationLineCandidate) { fIndent = fPrefs.prefContinuationIndent; } return 0; - - case Symbols.TokenRETURN: - fIndent = fPrefs.prefContinuationIndent; - return fPosition; } } } @@ -1712,11 +1713,13 @@ public final class CIndenter { nextToken(); switch (fToken) { case Symbols.TokenIDENT: + fPosition = storedPosition; if (skipScope(Symbols.TokenLESSTHAN, Symbols.TokenGREATERTHAN)) return true; break; case Symbols.TokenQUESTIONMARK: case Symbols.TokenGREATERTHAN: + fPosition = storedPosition; if (skipScope(Symbols.TokenLESSTHAN, Symbols.TokenGREATERTHAN)) return true; break; @@ -2233,9 +2236,9 @@ public final class CIndenter { } /** - * Returns true if the current tokens look like a method - * call header (i.e. an identifier as opposed to a keyword taking parenthesized - * parameters such as if). + * Returns true if the current tokens look like beginning of a method + * call (i.e. an identifier as opposed to a keyword taking parenthesized parameters + * such as if). *

The heuristic calls nextToken and expects an identifier * (method name). * @@ -2243,8 +2246,12 @@ public final class CIndenter { * header. */ private boolean looksLikeMethodCall() { - // TODO add awareness for constructor calls with templates: new complex() nextToken(); + if (fToken == Symbols.TokenGREATERTHAN) { + if (!skipScope()) + return false; + nextToken(); + } return fToken == Symbols.TokenIDENT; // method name } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPairMatcher.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPairMatcher.java index 6652b1e02aa..edccdf624c7 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPairMatcher.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPairMatcher.java @@ -182,7 +182,7 @@ public class CPairMatcher extends DefaultCharacterPairMatcher { */ private boolean isTemplateParameterOpenBracket(int offset, IDocument document, CHeuristicScanner scanner) { int prevToken= scanner.previousToken(offset - 1, Math.max(0, offset - ANGLE_BRACKETS_SEARCH_BOUND)); - if (prevToken == Symbols.TokenIDENT) { + if (prevToken == Symbols.TokenIDENT || prevToken == Symbols.TokenTEMPLATE) { return true; } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/Symbols.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/Symbols.java index 786d737992f..a9e05f6813a 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/Symbols.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/Symbols.java @@ -68,5 +68,9 @@ public interface Symbols { int TokenTHROW= 1035; int TokenCONST= 1036; int TokenEXTERN= 1037; + int TokenTYPEDEF= 1038; + int TokenUSING= 1039; + int TokenTEMPLATE= 1040; + int TokenTYPENAME= 1041; int TokenIDENT= 2000; }