From 826a0b2c0effc6a8d1479ddbff8d5b4bbd31a6b6 Mon Sep 17 00:00:00 2001 From: Marco Stornelli Date: Sat, 16 Mar 2019 09:12:21 +0100 Subject: [PATCH] Bug 405409 - Formatting namespaces with inactive sections Local scanner was peeking tokens from inactive regions confusing the formatter. Change-Id: I5975ec1042474be84b897e047a1e59cfc8bfa083 Signed-off-by: Marco Stornelli --- .../formatter/CodeFormatterVisitor.java | 30 +++++++++++++++++-- .../cdt/ui/tests/text/CodeFormatterTest.java | 29 ++++++++++++++++++ 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java index 6fcac39eb33..ec20bed2b7f 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.EmptyStackException; +import java.util.Iterator; import java.util.List; import java.util.Stack; @@ -401,6 +402,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, } private final Scanner localScanner; + private List fInactivePreprocessorPositions; final DefaultCodeFormatterOptions preferences; private final Scribe scribe; @@ -424,6 +426,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, }; this.preferences = preferences; scribe = new Scribe(this, offset, length); + fInactivePreprocessorPositions = Collections.emptyList(); } /** @@ -439,8 +442,9 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, localScanner.setSource(compilationUnitSource); scribe.initializeScanner(compilationUnitSource); - List inactive = collectInactiveCodePositions(unit); - inactive.addAll(collectNoFormatCodePositions(unit)); + fInactivePreprocessorPositions = collectInactiveCodePositions(unit); + List inactive = collectNoFormatCodePositions(unit); + inactive.addAll(fInactivePreprocessorPositions); scribe.setSkipInactivePositions(inactive); fStatus = new MultiStatus(CCorePlugin.PLUGIN_ID, 0, "Formatting problem(s) in '" + unit.getFilePath() + "'", //$NON-NLS-1$//$NON-NLS-2$ @@ -4502,14 +4506,34 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, return peekNextToken(false); } + /** + * It returns a position range if offset is included into an inactive + * preprocessor region. + * @param offset The offset to be checked + * @return The region if found, null otherwise + */ + private Position getInactivePosAt(int offset) { + for (Iterator iter = fInactivePreprocessorPositions.iterator(); iter.hasNext();) { + Position pos = iter.next(); + if (pos.includes(offset)) { + return pos; + } + } + return null; + } + private int peekNextToken(boolean ignoreSkip) { if (!ignoreSkip && scribe.shouldSkip(getCurrentPosition())) { return Token.tBADCHAR; } localScanner.resetTo(getCurrentPosition(), scribe.scannerEndPosition); int token = localScanner.getNextToken(); - while (token == Token.tBLOCKCOMMENT || token == Token.tLINECOMMENT) { + int currentStart = localScanner.getCurrentTokenStartPosition(); + Position p = getInactivePosAt(currentStart); + while ((token == Token.tBLOCKCOMMENT || token == Token.tLINECOMMENT) || p != null) { token = localScanner.getNextToken(); + currentStart = localScanner.getCurrentTokenStartPosition(); + p = getInactivePosAt(currentStart); } return token; } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java index 0bcab92ea21..37a33867ae8 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java @@ -4123,4 +4123,33 @@ public class CodeFormatterTest extends BaseUITestCase { public void testCastFuncDeclarator2_Bug390324() throws Exception { assertFormatterResult(); } + + //#define ONE + //namespace n1 { + //namespace n2 { + //#ifdef ONE + //int v1; + //#elif defined(TWO) + //int v2; + //#endif + //} + //} + //int main(){return 0;} + + //#define ONE + //namespace n1 { + //namespace n2 { + //#ifdef ONE + //int v1; + //#elif defined(TWO) + //int v2; + //#endif + //} + //} + //int main() { + // return 0; + //} + public void testNamespacesWithInactiveSections_Bug405049() throws Exception { + assertFormatterResult(); + } }