From 1d6cf481985826cf0f1a04b0c86ab59af173dc88 Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Fri, 20 Jan 2017 19:24:59 -0800 Subject: [PATCH] Bug 510794 - Tab character is ignored at the beginning of line inside a raw string literal Change-Id: Idc8dfba8900495933f681f809dc96c4d92a6db8a --- .../resources/indentation/rawString/After.cpp | 3 ++ .../indentation/rawString/Before.cpp | 3 ++ .../cdt/ui/tests/text/IndentActionTest.java | 51 +++++++++++-------- .../cdt/internal/ui/actions/IndentAction.java | 25 +++++++-- 4 files changed, 57 insertions(+), 25 deletions(-) create mode 100644 core/org.eclipse.cdt.ui.tests/resources/indentation/rawString/After.cpp create mode 100644 core/org.eclipse.cdt.ui.tests/resources/indentation/rawString/Before.cpp diff --git a/core/org.eclipse.cdt.ui.tests/resources/indentation/rawString/After.cpp b/core/org.eclipse.cdt.ui.tests/resources/indentation/rawString/After.cpp new file mode 100644 index 00000000000..2a0289da016 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/indentation/rawString/After.cpp @@ -0,0 +1,3 @@ +const char* s = R"( + Some text +)"; diff --git a/core/org.eclipse.cdt.ui.tests/resources/indentation/rawString/Before.cpp b/core/org.eclipse.cdt.ui.tests/resources/indentation/rawString/Before.cpp new file mode 100644 index 00000000000..347f6c7ddca --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/indentation/rawString/Before.cpp @@ -0,0 +1,3 @@ +const char* s = R"( + Some text +)"; 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 41323ef8906..c1ae02ef376 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 @@ -8,16 +8,12 @@ * Contributors: * IBM Corporation - initial API and implementation * Anton Leherbauer (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.ui.tests.text; import java.util.ListResourceBundle; -import junit.extensions.TestSetup; -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; - import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.source.SourceViewer; @@ -31,6 +27,11 @@ import org.eclipse.cdt.ui.testplugin.ResourceTestHelper; import org.eclipse.cdt.internal.ui.actions.IndentAction; import org.eclipse.cdt.internal.ui.editor.CEditor; +import junit.extensions.TestSetup; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + /** * Test the IndentAction. */ @@ -46,15 +47,15 @@ public class IndentActionTest extends TestCase { protected static class IndentTestSetup extends TestSetup { private ICProject fCProject; - + public IndentTestSetup(Test test) { super(test); } - + @Override protected void setUp() throws Exception { super.setUp(); - + fCProject= EditorTestHelper.createCProject(PROJECT, "resources/indentation"); fCProject.setOption(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.TAB); } @@ -63,11 +64,11 @@ public class IndentActionTest extends TestCase { protected void tearDown () throws Exception { if (fCProject != null) CProjectHelper.delete(fCProject); - + super.tearDown(); } } - + public static Test suite() { return new IndentTestSetup(new TestSuite(IndentActionTest.class)); } @@ -83,18 +84,18 @@ public class IndentActionTest extends TestCase { fSourceViewer= EditorTestHelper.getSourceViewer(fEditor); fDocument= fSourceViewer.getDocument(); } - + @Override protected void tearDown() throws Exception { EditorTestHelper.closeEditor(fEditor); } - - private void assertIndentResult() throws Exception { + + private void assertIndentResult(boolean isTabAction) throws Exception { String afterFile= createFileName("After"); String expected= ResourceTestHelper.read(afterFile).toString(); - - new IndentAction(new EmptyBundle(), "prefix", fEditor, false).run(); - + + new IndentAction(new EmptyBundle(), "prefix", fEditor, isTabAction).run(); + assertEquals(expected, fDocument.get()); } @@ -103,23 +104,29 @@ public class IndentActionTest extends TestCase { name= name.substring(4, 5).toLowerCase() + name.substring(5); return "/" + PROJECT + "/src/" + name + "/" + qualifier + ".cpp"; } - + private void selectAll() { fSourceViewer.setSelectedRange(0, fDocument.getLength()); } - + public void testUnchanged() throws Exception { selectAll(); - assertIndentResult(); + assertIndentResult(false); } - + public void testSample() throws Exception { selectAll(); - assertIndentResult(); + assertIndentResult(false); } public void testComplex() throws Exception { selectAll(); - assertIndentResult(); + assertIndentResult(false); + } + + // See http://bugs.eclipse.org/510794 + public void testRawString() throws Exception { + fSourceViewer.setSelectedRange(fDocument.getLineOffset(1) + 1, 0); + assertIndentResult(true); } } 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 9bbcf8eae07..ba116133af7 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 @@ -7,7 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation - * Sergey Prigogin, Google + * Sergey Prigogin (Google) * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.actions; @@ -212,8 +212,27 @@ public class IndentAction extends TextEditorAction { } else if (startingPartition.getType().equals(ICPartitions.C_PREPROCESSOR)) { indent= computePreprocessorIndent(document, line, startingPartition); } else if (startingPartition.getType().equals(ICPartitions.C_STRING) && offset > startingPartition.getOffset()) { - // don't indent inside (raw-)string - return false; + // Don't indent inside (raw-)string, but if the indent action was triggered by a Tab key, + // insert a '\t' character or spaces at the caret position. + if (!fIsTabAction) + return false; + + String text = "\t"; //$NON-NLS-1$ + if (useSpaces()) { + int tabSize = getTabSize(); + if (tabSize == 0) + return false; + + int numSpaces = tabSize - (caret - offset) % tabSize; + StringBuilder buf = new StringBuilder(numSpaces); + for (int i = 0; i < numSpaces; i++) { + buf.append(' '); + } + text = buf.toString(); + } + document.replace(caret, 0, text); + fCaretOffset= caret + text.length(); + return true; } else if (!fIsTabAction && startingPartition.getOffset() == offset && startingPartition.getType().equals(ICPartitions.C_SINGLE_LINE_COMMENT)) { // line comment starting at position 0 -> indent inside if (indentInsideLineComments()) {