From 07031919f127bf3e176717fc8bd2396f8c7afcbe Mon Sep 17 00:00:00 2001 From: Anton Leherbauer Date: Wed, 4 Oct 2006 10:44:31 +0000 Subject: [PATCH] Add smart edit and indenter tests --- .../resources/indentation/complex/After.cpp | 25 + .../resources/indentation/complex/Before.cpp | 25 + .../resources/indentation/sample/After.cpp | 48 + .../resources/indentation/sample/Before.cpp | 48 + .../resources/indentation/unchanged/After.cpp | 80 ++ .../indentation/unchanged/Before.cpp | 80 ++ .../ui/tests/text/BracketInserterTest.java | 428 +++++++++ .../ui/tests/text/CHeuristicScannerTest.java | 881 ++++++++++++++++++ .../cdt/ui/tests/text/EditorTestHelper.java | 14 + .../cdt/ui/tests/text/IndentActionTest.java | 127 +++ .../cdt/ui/tests/text/TextTestSuite.java | 14 +- .../cdt/internal/ui/actions/IndentAction.java | 36 +- .../cdt/internal/ui/editor/CEditor.java | 3 +- .../internal/ui/text/CHeuristicScanner.java | 39 +- .../cdt/internal/ui/text/CIndenter.java | 31 +- .../eclipse/cdt/internal/ui/text/Symbols.java | 11 +- 16 files changed, 1844 insertions(+), 46 deletions(-) create mode 100644 core/org.eclipse.cdt.ui.tests/resources/indentation/complex/After.cpp create mode 100644 core/org.eclipse.cdt.ui.tests/resources/indentation/complex/Before.cpp create mode 100644 core/org.eclipse.cdt.ui.tests/resources/indentation/sample/After.cpp create mode 100644 core/org.eclipse.cdt.ui.tests/resources/indentation/sample/Before.cpp create mode 100644 core/org.eclipse.cdt.ui.tests/resources/indentation/unchanged/After.cpp create mode 100644 core/org.eclipse.cdt.ui.tests/resources/indentation/unchanged/Before.cpp create mode 100644 core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/BracketInserterTest.java create mode 100644 core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CHeuristicScannerTest.java create mode 100644 core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/IndentActionTest.java diff --git a/core/org.eclipse.cdt.ui.tests/resources/indentation/complex/After.cpp b/core/org.eclipse.cdt.ui.tests/resources/indentation/complex/After.cpp new file mode 100644 index 00000000000..c18516e1537 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/indentation/complex/After.cpp @@ -0,0 +1,25 @@ + + +/* This is sample code to test the indenter */ + + + +class Complex { +private: + float re; + float im; +public: + Complex(float re, float im) : + re(re), im(im) {} + float GetRe() + { + return re; + } + float GetIm() { + return im; + } + void Set(float r, float i); + void SetRe(float r); + void SetIm(float i); + void Print(); +}; diff --git a/core/org.eclipse.cdt.ui.tests/resources/indentation/complex/Before.cpp b/core/org.eclipse.cdt.ui.tests/resources/indentation/complex/Before.cpp new file mode 100644 index 00000000000..41beaba01d1 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/indentation/complex/Before.cpp @@ -0,0 +1,25 @@ + + + /* This is sample code to test the indenter */ + + + + class Complex { + private: + float re; + float im; + public: + Complex(float re, float im) : + re(re), im(im) {} + float GetRe() + { + return re; + } + float GetIm() { + return im; + } + void Set(float r, float i); + void SetRe(float r); + void SetIm(float i); + void Print(); + }; 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 new file mode 100644 index 00000000000..bb1040abe7d --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/indentation/sample/After.cpp @@ -0,0 +1,48 @@ +#include + +const SimpleStruct simpleStruct = +{ + 1 + , "mySimple" + , 0.1232 +}; + +#define SIZEOF( A, B ) sizeof( A.B ) + +const OtherStruct array[] = +{ + { +#if FOO + "foo" +#else + "bar" +#endif + , SIZEOF( simpleStruct, num ) + , &t_int + , 0 + } + , { + "name" + , SIZEOF( simpleStruct, floatnum ) + , &t_float + , 1 + } +}; + + +void SimpleStruct_construct( + struct SimpleStruct * const this ) +{ +// single line + this->num = 1; + this->name = "boo"; + this->floatNum = 1.5; +} + +int ConnectParams_doSomething( const struct SimpleStruct * const this ) +{ + /* + * multiline + */ + return 1; +} 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 new file mode 100644 index 00000000000..a0b3297f10d --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/indentation/sample/Before.cpp @@ -0,0 +1,48 @@ +#include + +const SimpleStruct simpleStruct = +{ + 1 + , "mySimple" + , 0.1232 +}; + +#define SIZEOF( A, B ) sizeof( A.B ) + +const OtherStruct array[] = +{ + { +#if FOO + "foo" + #else + "bar" +#endif + , SIZEOF( simpleStruct, num ) + , &t_int + , 0 + } + , { + "name" + , SIZEOF( simpleStruct, floatnum ) + , &t_float + , 1 + } +}; + + +void SimpleStruct_construct( +struct SimpleStruct * const this ) + { +// single line +this->num = 1; +this->name = "boo"; +this->floatNum = 1.5; + } + +int ConnectParams_doSomething( const struct SimpleStruct * const this ) + { +/* + * multiline + */ + return 1; + } diff --git a/core/org.eclipse.cdt.ui.tests/resources/indentation/unchanged/After.cpp b/core/org.eclipse.cdt.ui.tests/resources/indentation/unchanged/After.cpp new file mode 100644 index 00000000000..b60e3ef8488 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/indentation/unchanged/After.cpp @@ -0,0 +1,80 @@ +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +std::string +StringTools::toString( int value ) +{ + OStringStream stream; + stream << value; + return stream.str(); +} + + +std::string +StringTools::toString( double value ) +{ + OStringStream stream; + stream << value; + return stream.str(); +} + + +StringTools::Strings +StringTools::split( const std::string &text, + char separator ) +{ + Strings splittedText; + + std::string::const_iterator itStart = text.begin(); + while ( !text.empty() ) + { + std::string::const_iterator itSeparator = std::find( itStart, + text.end(), + separator ); + splittedText.push_back( text.substr( itStart - text.begin(), + itSeparator - itStart ) ); + if ( itSeparator == text.end() ) + break; + itStart = itSeparator +1; + } + + return splittedText; +} + + +std::string +StringTools::wrap( const std::string &text, + int wrapColumn ) +{ + const char lineBreak = '\n'; + Strings lines = split( text, lineBreak ); + + std::string wrapped; + for ( Strings::const_iterator it = lines.begin(); it != lines.end(); ++it ) + { + if ( it != lines.begin() ) + wrapped += lineBreak; + + const std::string &line = *it; + unsigned int index =0; + while ( index < line.length() ) + { + std::string lineSlice( line.substr( index, wrapColumn ) ); + wrapped += lineSlice; + index += wrapColumn; + if ( index < line.length() ) + wrapped += lineBreak; + } + } + + return wrapped; +} + + +CPPUNIT_NS_END + diff --git a/core/org.eclipse.cdt.ui.tests/resources/indentation/unchanged/Before.cpp b/core/org.eclipse.cdt.ui.tests/resources/indentation/unchanged/Before.cpp new file mode 100644 index 00000000000..b60e3ef8488 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/resources/indentation/unchanged/Before.cpp @@ -0,0 +1,80 @@ +#include +#include +#include + + +CPPUNIT_NS_BEGIN + + +std::string +StringTools::toString( int value ) +{ + OStringStream stream; + stream << value; + return stream.str(); +} + + +std::string +StringTools::toString( double value ) +{ + OStringStream stream; + stream << value; + return stream.str(); +} + + +StringTools::Strings +StringTools::split( const std::string &text, + char separator ) +{ + Strings splittedText; + + std::string::const_iterator itStart = text.begin(); + while ( !text.empty() ) + { + std::string::const_iterator itSeparator = std::find( itStart, + text.end(), + separator ); + splittedText.push_back( text.substr( itStart - text.begin(), + itSeparator - itStart ) ); + if ( itSeparator == text.end() ) + break; + itStart = itSeparator +1; + } + + return splittedText; +} + + +std::string +StringTools::wrap( const std::string &text, + int wrapColumn ) +{ + const char lineBreak = '\n'; + Strings lines = split( text, lineBreak ); + + std::string wrapped; + for ( Strings::const_iterator it = lines.begin(); it != lines.end(); ++it ) + { + if ( it != lines.begin() ) + wrapped += lineBreak; + + const std::string &line = *it; + unsigned int index =0; + while ( index < line.length() ) + { + std::string lineSlice( line.substr( index, wrapColumn ) ); + wrapped += lineSlice; + index += wrapColumn; + if ( index < line.length() ) + wrapped += lineBreak; + } + } + + return wrapped; +} + + +CPPUNIT_NS_END + diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/BracketInserterTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/BracketInserterTest.java new file mode 100644 index 00000000000..fe73ad53cbc --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/BracketInserterTest.java @@ -0,0 +1,428 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 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 + * Anton Leherbauer (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.ui.tests.text; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.text.link.ILinkedModeListener; +import org.eclipse.jface.text.link.LinkedModeModel; +import org.eclipse.jface.text.link.LinkedPosition; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.widgets.Event; +import org.eclipse.ui.PartInitException; + +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.ICContainer; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.testplugin.CProjectHelper; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.PreferenceConstants; + +import org.eclipse.cdt.internal.ui.editor.CEditor; + + +/** + * Tests the automatic bracket insertion feature of the CEditor. Also tests + * linked mode along the way. + */ +public class BracketInserterTest extends TestCase { + + private static final String SRC= "src"; + private static final String SEP= "/"; + private static final String TU_NAME= "smartedit.cpp"; + private static final String TU_CONTENTS= + "#include \n" + + "class Application {\n" + + " char* string;\n" + + " int integer;\n" + + "\n" + + "public:\n" + + " static void main(int argc, char** args);\n" + + "protected:\n" + + " void foo(char** args);\n" + + "};\n" + + "\n" + + "void Application::main(int argc, char** args) {\n" + + " \n" + + "}\n" + + "void Application::foo(char** args) {\n" + + " char[] t= args[0];" + + "}\n"; + + // document offsets + private static final int INCLUDE_OFFSET= 9; + private static final int BODY_OFFSET= 212; + private static final int ARGS_OFFSET= 184; + private static final int BRACKETS_OFFSET= 262; + + public static Test suite() { + TestSuite suite= new TestSuite(BracketInserterTest.class); + return suite; + } + + private CEditor fEditor; + private StyledText fTextWidget; + private IDocument fDocument; + private Accessor fAccessor; + private ICProject fProject; + + protected void setUp() throws Exception { + IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore(); + store.setValue(PreferenceConstants.EDITOR_CLOSE_BRACKETS, true); + setUpProject(); + setUpEditor(); + } + + private void setUpProject() throws CoreException { + fProject= CProjectHelper.createCProject(getName(), "bin"); + ICContainer cContainer= CProjectHelper.addCContainer(fProject, SRC); + IFile file= EditorTestHelper.createFile((IContainer)cContainer.getResource(), TU_NAME, TU_CONTENTS, new NullProgressMonitor()); + assertNotNull(file); + assertTrue(file.exists()); + } + + private void setUpEditor() { + fEditor= openCEditor(new Path(SEP + getName() + SEP + SRC + SEP + TU_NAME)); + assertNotNull(fEditor); + fTextWidget= fEditor.getViewer().getTextWidget(); + assertNotNull(fTextWidget); + fAccessor= new Accessor(fTextWidget, StyledText.class); + fDocument= fEditor.getDocumentProvider().getDocument(fEditor.getEditorInput()); + assertNotNull(fDocument); + assertEquals(TU_CONTENTS, fDocument.get()); + } + + private CEditor openCEditor(IPath path) { + IFile file= ResourcesPlugin.getWorkspace().getRoot().getFile(path); + assertTrue(file != null && file.exists()); + try { + return (CEditor)EditorTestHelper.openInEditor(file, true); + } catch (PartInitException e) { + fail(); + return null; + } + } + + protected void tearDown() throws Exception { + EditorTestHelper.closeEditor(fEditor); + fEditor= null; + if (fProject != null) { + CProjectHelper.delete(fProject); + fProject= null; + } + + // reset to defaults + IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore(); + store.setToDefault(PreferenceConstants.EDITOR_CLOSE_BRACKETS); + } + + public void testInsertClosingParenthesis() throws BadLocationException, CModelException, CoreException, CModelException, CoreException { + setCaret(BODY_OFFSET); + type('('); + + assertEquals("()", fDocument.get(BODY_OFFSET, 2)); + assertSingleLinkedPosition(BODY_OFFSET + 1); + } + + public void testDeletingParenthesis() throws CModelException, CoreException { + setCaret(BODY_OFFSET); + type('('); + type(SWT.BS); + + assertEquals(TU_CONTENTS, fDocument.get()); + assertFalse(LinkedModeModel.hasInstalledModel(fDocument)); + } + + public void testMultipleParenthesisInsertion() throws BadLocationException, CModelException, CoreException { + setCaret(BODY_OFFSET); + type("(((("); + + assertEquals("(((())))", fDocument.get(BODY_OFFSET, 8)); + assertEquals(BODY_OFFSET + 4, getCaret()); + + assertModel(true); + } + + public void testDeletingMultipleParenthesisInertion() throws BadLocationException, CModelException, CoreException { + setCaret(BODY_OFFSET); + type("(((("); + + // delete two levels + linkedType(SWT.BS, true, ILinkedModeListener.EXTERNAL_MODIFICATION); + linkedType(SWT.BS, true, ILinkedModeListener.EXTERNAL_MODIFICATION); + + assertEquals("(())", fDocument.get(BODY_OFFSET, 4)); + assertEquals(BODY_OFFSET + 2, getCaret()); + + // delete the second-last level + linkedType(SWT.BS, true, ILinkedModeListener.EXTERNAL_MODIFICATION); + assertEquals("()", fDocument.get(BODY_OFFSET, 2)); + assertEquals(BODY_OFFSET + 1, getCaret()); + + // delete last level + linkedType(SWT.BS, false, ILinkedModeListener.EXTERNAL_MODIFICATION); + assertEquals(TU_CONTENTS, fDocument.get()); + assertEquals(BODY_OFFSET, getCaret()); + + assertEquals(TU_CONTENTS, fDocument.get()); + assertFalse(LinkedModeModel.hasInstalledModel(fDocument)); + } + + public void testNoInsertInsideText() throws BadLocationException, CModelException, CoreException { + setCaret(ARGS_OFFSET); + type('('); + + assertEquals("(in", fDocument.get(ARGS_OFFSET, 3)); + assertEquals(ARGS_OFFSET + 1, getCaret()); + assertFalse(LinkedModeModel.hasInstalledModel(fDocument)); + } + + public void testInsertInsideBrackets() throws BadLocationException, CModelException, CoreException { + setCaret(BRACKETS_OFFSET); + type('('); + + assertEquals("()", fDocument.get(BRACKETS_OFFSET, 2)); + assertSingleLinkedPosition(BRACKETS_OFFSET + 1); + } + + public void testPeerEntry() throws BadLocationException, CModelException, CoreException { + setCaret(BODY_OFFSET); + type("()"); + + assertEquals("()", fDocument.get(BODY_OFFSET, 2)); + assertEquals(BODY_OFFSET + 2, getCaret()); + + assertFalse(LinkedModeModel.hasInstalledModel(fDocument)); + } + + public void testMultiplePeerEntry() throws BadLocationException, CModelException, CoreException { + setCaret(BODY_OFFSET); + type("(((("); + + linkedType(')', true, ILinkedModeListener.UPDATE_CARET); + linkedType(')', true, ILinkedModeListener.UPDATE_CARET); + linkedType(')', true, ILinkedModeListener.UPDATE_CARET); + + assertEquals("(((())))", fDocument.get(BODY_OFFSET, 8)); + assertEquals(BODY_OFFSET + 7, getCaret()); + + LinkedPosition position= assertModel(false).findPosition(new LinkedPosition(fDocument, BODY_OFFSET + 1, 0)); + assertNotNull(position); + assertEquals(BODY_OFFSET + 1, position.getOffset()); + assertEquals(6, position.getLength()); + + linkedType(')', false, ILinkedModeListener.UPDATE_CARET); + + assertEquals("(((())))", fDocument.get(BODY_OFFSET, 8)); + assertEquals(BODY_OFFSET + 8, getCaret()); + assertFalse(LinkedModeModel.hasInstalledModel(fDocument)); + } + + public void testExitOnTab() throws BadLocationException, CModelException, CoreException { + setCaret(BODY_OFFSET); + type("(((("); + linkedType('\t', true, ILinkedModeListener.NONE); + + assertEquals("(((())))", fDocument.get(BODY_OFFSET, 8)); + assertEquals(BODY_OFFSET + 5, getCaret()); + + linkedType('\t', true, ILinkedModeListener.NONE); + linkedType('\t', true, ILinkedModeListener.NONE); + + assertEquals("(((())))", fDocument.get(BODY_OFFSET, 8)); + assertEquals(BODY_OFFSET + 7, getCaret()); + + linkedType('\t', false, ILinkedModeListener.NONE); + + assertEquals("(((())))", fDocument.get(BODY_OFFSET, 8)); + assertEquals(BODY_OFFSET + 8, getCaret()); + + assertFalse(LinkedModeModel.hasInstalledModel(fDocument)); + } + + public void testExitOnReturn() throws BadLocationException, CModelException, CoreException { + setCaret(BODY_OFFSET); + type("(((("); + linkedType(SWT.CR, true, ILinkedModeListener.UPDATE_CARET | ILinkedModeListener.EXIT_ALL); + + assertEquals("(((())))", fDocument.get(BODY_OFFSET, 8)); + assertEquals(BODY_OFFSET + 8, getCaret()); + + assertFalse(LinkedModeModel.hasInstalledModel(fDocument)); + } + + public void testExitOnEsc() throws BadLocationException, CModelException, CoreException { + setCaret(BODY_OFFSET); + type("(((("); + linkedType(SWT.ESC, true, ILinkedModeListener.EXIT_ALL); + + assertEquals("(((())))", fDocument.get(BODY_OFFSET, 8)); + assertEquals(BODY_OFFSET + 4, getCaret()); + + assertFalse(LinkedModeModel.hasInstalledModel(fDocument)); + } + + public void testInsertClosingQuote() throws BadLocationException, CModelException, CoreException { + setCaret(BODY_OFFSET); + type('"'); + + assertEquals("\"\"", fDocument.get(BODY_OFFSET, 2)); + + assertSingleLinkedPosition(BODY_OFFSET + 1); + } + + public void testPreferences() throws BadLocationException, CModelException, CoreException { + IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore(); + store.setValue(PreferenceConstants.EDITOR_CLOSE_BRACKETS, false); + + setCaret(BODY_OFFSET); + type('('); + + assertEquals("(", fDocument.get(BODY_OFFSET, 1)); + assertEquals(BODY_OFFSET + 1, getCaret()); + + assertFalse(LinkedModeModel.hasInstalledModel(fDocument)); + } + + public void testAngleBracketsAsOperator() throws Exception { + setCaret(BODY_OFFSET); + type("test<"); + + assertEquals("test<", fDocument.get(BODY_OFFSET, 5)); + assertFalse(">".equals(fDocument.get(BODY_OFFSET + 5, 1))); + assertEquals(BODY_OFFSET + 5, getCaret()); + + assertFalse(LinkedModeModel.hasInstalledModel(fDocument)); + } + + public void testAngleBrackets() throws Exception { + setCaret(BODY_OFFSET); + type("Test<"); + + assertEquals("Test<>", fDocument.get(BODY_OFFSET, 6)); + assertSingleLinkedPosition(BODY_OFFSET + 5); + } + + public void testAngleBracketsInInclude() throws Exception { + setCaret(INCLUDE_OFFSET); + type('<'); + + assertEquals("#include <>", fDocument.get(INCLUDE_OFFSET - 9, 11)); + assertSingleLinkedPosition(INCLUDE_OFFSET + 1); + } + + /* utilities */ + + private void assertSingleLinkedPosition(int offset) { + assertEquals(offset, getCaret()); + + LinkedPosition position= assertModel(false).findPosition(new LinkedPosition(fDocument, offset, 0)); + assertNotNull(position); + assertEquals(offset, position.getOffset()); + assertEquals(0, position.getLength()); + } + + /** + * Type characters into the styled text. + * + * @param characters the characters to type + */ + private void type(CharSequence characters) { + for (int i= 0; i < characters.length(); i++) + type(characters.charAt(i), 0, 0); + } + + /** + * Type a character into the styled text. + * + * @param character the character to type + */ + private void type(char character) { + type(character, 0, 0); + } + + /** + * Ensure there is a linked mode and type a character into the styled text. + * + * @param character the character to type + * @param nested whether the linked mode is expected to be nested or not + * @param expectedExitFlags the expected exit flags for the current linked mode after typing the character, -1 for no exit + */ + private void linkedType(char character, boolean nested, int expectedExitFlags) { + final int[] exitFlags= { -1 }; + assertModel(nested).addLinkingListener(new ILinkedModeListener() { + public void left(LinkedModeModel model, int flags) { + exitFlags[0]= flags; + } + public void resume(LinkedModeModel model, int flags) { + } + public void suspend(LinkedModeModel model) { + } + }); + type(character, 0, 0); + assertEquals(expectedExitFlags, exitFlags[0]); + } + + private LinkedModeModel assertModel(boolean nested) { + LinkedModeModel model= LinkedModeModel.getModel(fDocument, 0); // offset does not matter + assertNotNull(model); + assertEquals(nested, model.isNested()); + return model; + } + + /** + * Type a character into the styled text. + * + * @param character the character to type + * @param keyCode the key code + * @param stateMask the state mask + */ + private void type(char character, int keyCode, int stateMask) { + Event event= new Event(); + event.character= character; + event.keyCode= keyCode; + event.stateMask= stateMask; + fAccessor.invoke("handleKeyDown", new Object[] {event}); + + new DisplayHelper() { + protected boolean condition() { + return false; + } + }.waitForCondition(EditorTestHelper.getActiveDisplay(), 200); + + } + + private int getCaret() { + return ((ITextSelection) fEditor.getSelectionProvider().getSelection()).getOffset(); + } + + private void setCaret(int offset) { + fEditor.getSelectionProvider().setSelection(new TextSelection(offset, 0)); + int newOffset= ((ITextSelection)fEditor.getSelectionProvider().getSelection()).getOffset(); + assertEquals(offset, newOffset); + } +} diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CHeuristicScannerTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CHeuristicScannerTest.java new file mode 100644 index 00000000000..245b8e35d87 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CHeuristicScannerTest.java @@ -0,0 +1,881 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 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 + * Anton Leherbauer (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.ui.tests.text; + +import java.util.HashMap; + +import junit.framework.Assert; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.rules.FastPartitioner; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants; +import org.eclipse.cdt.ui.text.ICPartitions; + +import org.eclipse.cdt.internal.ui.text.CHeuristicScanner; +import org.eclipse.cdt.internal.ui.text.CIndenter; +import org.eclipse.cdt.internal.ui.text.FastCPartitionScanner; + +/** + * CHeuristicScannerTest. + * Derived from JDT. + */ +public class CHeuristicScannerTest extends TestCase { + + private FastPartitioner fPartitioner; + private Document fDocument; + private CIndenter fScanner; + private CHeuristicScanner fHeuristicScanner; + + public static Test suite() { + return new TestSuite(CHeuristicScannerTest.class); + } + + /* + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() { + if (CCorePlugin.getDefault() != null) { + HashMap options= CCorePlugin.getDefaultOptions(); + options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.TAB); + options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, "4"); + + final String indentOnColumn= DefaultCodeFormatterConstants.createAlignmentValue(false, DefaultCodeFormatterConstants.WRAP_NO_SPLIT, DefaultCodeFormatterConstants.INDENT_ON_COLUMN); + options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_PARAMETERS_IN_METHOD_DECLARATION, indentOnColumn); + options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_EXPRESSIONS_IN_ARRAY_INITIALIZER, indentOnColumn); + options.put(DefaultCodeFormatterConstants.FORMATTER_CONTINUATION_INDENTATION, "1"); + CCorePlugin.setOptions(options); + } + + fDocument= new Document(); + String[] types= new String[] { + ICPartitions.C_MULTI_LINE_COMMENT, + ICPartitions.C_SINGLE_LINE_COMMENT, + ICPartitions.C_STRING, + ICPartitions.C_CHARACTER, + ICPartitions.C_PREPROCESSOR, + IDocument.DEFAULT_CONTENT_TYPE + }; + fPartitioner= new FastPartitioner(new FastCPartitionScanner(), types); + fPartitioner.connect(fDocument); + fDocument.setDocumentPartitioner(ICPartitions.C_PARTITIONING, fPartitioner); + + fHeuristicScanner= new CHeuristicScanner(fDocument); + fScanner= new CIndenter(fDocument, fHeuristicScanner); + } + + /* + * @see junit.framework.TestCase#tearDown() + */ + protected void tearDown() throws Exception { + fDocument.setDocumentPartitioner(ICPartitions.C_PARTITIONING, null); + fPartitioner.disconnect(); + fPartitioner= null; + fDocument= null; + + if (CCorePlugin.getDefault() != null) { + CCorePlugin.setOptions(CCorePlugin.getDefaultOptions()); + } +} + + public void testPrevIndentationUnit1() { + fDocument.set("\tint a;\n" + + "\tif (true)\n" + + ""); + + int pos= fScanner.findReferencePosition(18); + Assert.assertEquals(9, pos); + } + + public void testPrevIndentationUnit2() { + fDocument.set("\tint a;\n" + + "\tif (true)\n" + + "\t\treturn a"); + + int pos= fScanner.findReferencePosition(28); + Assert.assertEquals(21, pos); + } + + public void testPrevIndentationUnit4() { + fDocument.set("\tint a;\n" + + "\tif (true)\n" + + "\t\treturn a\n" + + ""); + + int pos= fScanner.findReferencePosition(29); + Assert.assertEquals(28, pos); + } + + public void testPrevIndentationUnit5() { + fDocument.set("\tint a;\n" + + "\tif (true)\n" + + "\t\treturn a;\n" + + ""); + + int pos= fScanner.findReferencePosition(30); + Assert.assertEquals(9, pos); + } + + public void testPrevIndentationUnit6() { + // method definition + fDocument.set("\tvoid proc (int par1, int par2\n"); + + int pos= fScanner.findReferencePosition(30); + Assert.assertEquals(12, pos); + } + + public void testPrevIndentationUnit7() { + // for with semis + fDocument.set("\tvoid proc (int par1, int par2) {\n" + + "\t\t\n" + + "\t\tfor (int i= 4; i < 33; i++) \n" + + ""); + + int pos= fScanner.findReferencePosition(fDocument.getLength()); + Assert.assertEquals(39, pos); + } + + public void testPrevIndentationUnit8() { + // TODO this is mean - comment at indentation spot + fDocument.set("\t/* comment */ void proc (int par1, int par2) {\n"); + + int pos= fScanner.findReferencePosition(fDocument.getLength()); +// Assert.assertEquals(1, pos); + Assert.assertEquals(15, pos); + } + + public void testPrevIndentationUnit9() { + // block + fDocument.set("\tvoid proc (int par1, int par2) {\n" + + "\t\t\n" + + "\t\tfor (int i= 4; i < 33; i++) {\n" + + "\t\t}\n" + + "\t\t\n" + + "\t\tint i;\n"); + + int pos= fScanner.findReferencePosition(fDocument.getLength()); + Assert.assertEquals(fDocument.getLength() - 7, pos); + } + + public void testPrevIndentationUnit10() { + // if else + fDocument.set("\tvoid proc (int par1, int par2) {\n" + + "\t\t\n" + + "\t\tif (condition()) {\n" + + "\t\t\tcode();\n" + + "\t\t} else {\n" + + "\t\t\totherCode();\n" + + "\t\t}\n" + + ""); + + int pos= fScanner.findReferencePosition(fDocument.getLength()); + Assert.assertEquals(39, pos); + } + + public void testPrevIndentationUnit11() { + // inside else block + fDocument.set("\tvoid proc (int par1, int par2) {\n" + + "\t\t\n" + + "\t\tif (condition()) {\n" + + "\t\t\tcode();\n" + + "\t\t} else {\n" + + "\t\t\totherCode();\n" + + "\t\t" + + ""); + + int pos= fScanner.findReferencePosition(fDocument.getLength()); + Assert.assertEquals(83, pos); + } + + public void testPrevIndentation1() { + fDocument.set("\tint a;\n" + + "\tif (true)\n" + + ""); + + String indent= fScanner.getReferenceIndentation(18).toString(); + Assert.assertEquals("\t", indent); + } + + public void testPrevIndentation2() { + fDocument.set("\tint a;\n" + + "\tif (true)\n" + + "\t\treturn a"); + + String indent= fScanner.getReferenceIndentation(28).toString(); + Assert.assertEquals("\t\t", indent); + } + + public void testPrevIndentation3() { + fDocument.set("\tint a;\n" + + "\tif (true)\n" + + "\t\treturn a;"); + + String indent= fScanner.getReferenceIndentation(29).toString(); + Assert.assertEquals("\t\t", indent); + } + + public void testPrevIndentation4() { + fDocument.set("\tint a;\n" + + "\tif (true)\n" + + "\t\treturn a\n" + + ""); + + String indent= fScanner.getReferenceIndentation(29).toString(); + Assert.assertEquals("\t\t", indent); + } + + public void testPrevIndentation5() { + fDocument.set("\tint a;\n" + + "\tif (true)\n" + + "\t\treturn a;\n" + + ""); + + String indent= fScanner.getReferenceIndentation(30).toString(); + Assert.assertEquals("\t", indent); + } + + public void testPrevIndentation6() { + fDocument.set("\tvoid proc (int par1, int par2\n"); + + String indent= fScanner.getReferenceIndentation(30).toString(); + Assert.assertEquals("\t", indent); + } + + public void testPrevIndentation7() { + // for with semis + fDocument.set("\tvoid proc (int par1, int par2) {\n" + + "\t\t\n" + + "\t\tfor (int i= 4; i < 33; i++) \n" + + ""); + + String indent= fScanner.getReferenceIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t\t", indent); + } + + public void testPrevIndentation8() { + fDocument.set("\t/* comment */ void proc (int par1, int par2) {\n"); + + String indent= fScanner.getReferenceIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t", indent); + } + + public void testPrevIndentation9() { + // block + fDocument.set("\tvoid proc (int par1, int par2) {\n" + + "\t\t\n" + + "\t\tfor (int i= 4; i < 33; i++) {\n" + + "\t\t}\n" + + "\t\t\n" + + "\t\tint i;\n"); + + String indent= fScanner.getReferenceIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t\t", indent); + } + + public void testPrevIndentation10() { + // else + fDocument.set("\tvoid proc (int par1, int par2) {\n" + + "\t\t\n" + + "\t\tif (condition()) {\n" + + "\t\t\tcode();\n" + + "\t\t} else {\n" + + "\t\t\totherCode();\n" + + "\t\t}\n" + + ""); + + String indent= fScanner.getReferenceIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t\t", indent); + } + + public void testPrevIndentation11() { + // else + fDocument.set("\tvoid proc (int par1, int par2) {\n" + + "\t\t\n" + + "\t\tif (condition()) {\n" + + "\t\t\tcode();\n" + + "\t\t} else {\n" + + "\t\t\totherCode();\n" + + "\t\t" + + ""); + + String indent= fScanner.getReferenceIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t\t\t", indent); + } + + public void testIndentation1() { + fDocument.set("\tint a;\n" + + "\tif (true)\n" + + ""); + + String indent= fScanner.computeIndentation(18).toString(); + Assert.assertEquals("\t\t", indent); + } + + public void testIndentation2() { + fDocument.set("\tint a;\n" + + "\tif (true)\n" + + "\t\treturn a"); + + String indent= fScanner.computeIndentation(28).toString(); + Assert.assertEquals("\t\t", indent); + } + + public void testIndentation3() { + fDocument.set("\tint a;\n" + + "\tif (true)\n" + + "\t\treturn a;"); + + String indent= fScanner.computeIndentation(29).toString(); + Assert.assertEquals("\t\t", indent); + } + + public void testIndentation4() { + fDocument.set("\tint a;\n" + + "\tif (true)\n" + + "\t\treturn a\n" + + ""); + + String indent= fScanner.computeIndentation(29).toString(); + Assert.assertEquals("\t\t", indent); + } + + public void testIndentation5() { + fDocument.set("\tint a;\n" + + "\tif (true)\n" + + "\t\treturn a;\n" + + ""); + + String indent= fScanner.computeIndentation(30).toString(); + Assert.assertEquals("\t", indent); + } + + public void testIndentation6() { + // parameter declaration - alignment with parenthesis + fDocument.set("\tvoid proc (int par1, int par2\n"); + + String indent= fScanner.computeIndentation(30).toString(); + Assert.assertEquals("\t ", indent); + } + + public void testIndentation6a() { + // parameter declaration - alignment with parenthesis + fDocument.set("\tvoid proc ( int par1, int par2\n"); + + String indent= fScanner.computeIndentation(30).toString(); + Assert.assertEquals("\t ", indent); + } + + public void testIndentation7() { + // for with semis + fDocument.set("\tvoid proc (int par1, int par2) {\n" + + "\t\t\n" + + "\t\tfor (int i= 4; i < 33; i++) \n" + + ""); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t\t\t", indent); + } + + public void testIndentation8() { + // method definition + fDocument.set("\t/* package */ void proc (int par1, int par2) {\n"); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t\t", indent); + } + + public void testIndentation9() { + // block + fDocument.set("\tvoid proc (int par1, int par2) {\n" + + "\t\t\n" + + "\t\tfor (int i= 4; i < 33; i++) {\n" + + "\t\t}\n" + + "\t\t\n" + + "\t\tint i;\n"); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t\t", indent); + } + + public void testIndentation10() { + // else + fDocument.set("\tvoid proc (int par1, int par2) {\n" + + "\t\t\n" + + "\t\tif (condition()) {\n" + + "\t\t\tcode();\n" + + "\t\t} else {\n" + + "\t\t\totherCode();\n" + + "\t\t}\n" + + ""); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t\t", indent); + } + + public void testIndentation11() { + // else + fDocument.set("\tvoid proc (int par1, int par2) {\n" + + "\t\t\n" + + "\t\tif (condition()) {\n" + + "\t\t\tcode();\n" + + "\t\t} else {\n" + + "\t\t\totherCode();\n" + + "\t\t" + + ""); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t\t\t", indent); + } + + public void testIndentation12() { + // multi-line condition + fDocument.set("\tvoid proc (int par1, int par2) {\n" + + "\t\t\n" + + "\t\tif (condition1()\n" + + ""); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t\t\t", indent); + } + + public void testIndentation13() { + // multi-line call + fDocument.set("\tvoid proc (int par1, int par2) {\n" + + "\t\t\n" + + "\t\tthis->doStuff(param1, param2,\n" + + ""); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t\t\t", indent); + } + + public void testIndentation14() { + // multi-line array initializer + fDocument.set("\tvoid proc (int par1, int par2) {\n" + + "\t\t\n" + + "\t\tString[] arr= new String[] { a1, a2,\n" + + ""); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals(" ", indent); + } + + public void testIndentation15() { + // for + fDocument.set("\tfor (int i= 0; i < 10; i++) {\n" + + "\t\tbar(); bar(); // foo\n" + + "\t}\n"); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t", indent); + } + + public void testIndentation16() { + // if + fDocument.set("\tif (true)\n" + + "\t\t;"); + + String indent= fScanner.computeIndentation(fDocument.getLength() - 1).toString(); + Assert.assertEquals("\t\t", indent); + } + + public void testIndentation17() { + // if + fDocument.set("\tif (true)\n" + + ";"); + + String indent= fScanner.computeIndentation(fDocument.getLength() - 1).toString(); + Assert.assertEquals("\t\t", indent); + } + + public void testIndentation18() { + // if + fDocument.set("\tif (true)\n" + + ""); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t\t", indent); + } + + public void testIndentation19() { + // if w/ brace right after } + fDocument.set("\tif (true) {\n" + + "\t\t}"); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t", indent); + } + + public void testIndentation20() { + // if w/ brace right before } + fDocument.set("\tif (true) {\n" + + "\t\t}"); + + String indent= fScanner.computeIndentation(fDocument.getLength() - 1).toString(); + Assert.assertEquals("\t", indent); + } + + public void testIndentation21() { + // double if w/ brace + fDocument.set("\tif (true)\n" + + "\t\tif (true) {\n" + + ""); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t\t\t", indent); + } + + public void testIndentation22() { + // after double if w/ brace + fDocument.set("\tif (true)\n" + + "\t\tif (true) {\n" + + "\t\t\tstuff();" + + "\t\t}\n" + + ""); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t", indent); // because of possible dangling else + } + + public void testIndentation22a() { + // after double if w/ brace + fDocument.set("\tif (true)\n" + + "\t\tif (true) {\n" + + "\t\t\tstuff();\n" + + "\t\t}\n" + + ""); + + String indent= fScanner.computeIndentation(fDocument.getLength() - 2).toString(); + Assert.assertEquals("\t\t", indent); + } + + public void testIndentation22b() { + // after double if w/ brace + fDocument.set("\tif (true)\n" + + "\t\tif (true) {\n" + + "\t\t\tstuff();" + + "\t\t}\n" + + "a"); + + String indent= fScanner.computeIndentation(fDocument.getLength() - 1).toString(); + Assert.assertEquals("\t", indent); // no dangling else possible + } + + public void testIndentation23() { + // do + fDocument.set("\tdo\n" + + ""); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t\t", indent); + } + + public void testIndentation24() { + // braceless else + fDocument.set("\tif (true) {\n" + + "\t\tstuff();\n" + + "\t} else\n" + + "\t\tnoStuff"); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t\t", indent); + } + + public void testIndentation25() { + // braceless else + fDocument.set("\tif (true) {\r\n" + + "\t\tstuff();\r\n" + + "\t} else\r\n" + + "\t\tnoStuff;\r\n"); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t", indent); + } + + public void testIndentation26() { + // do while + fDocument.set("\tdo\n" + + "\t\t\n" + + "\twhile (true);" + + ""); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t", indent); + } + + public void testIndentation27() { + // do while + fDocument.set("\tdo\n" + + "\t\t;\n" + + "\twhile (true);" + + ""); + + int i= fScanner.findReferencePosition(8); + Assert.assertEquals(1, i); + String indent= fScanner.computeIndentation(8).toString(); + Assert.assertEquals("\t", indent); + } + + public void testIndentation28() { + // TODO do while - how to we distinguish from while {} loop? + fDocument.set("\tdo\n" + + "\t\t;\n" + + "\twhile (true);" + + ""); + + int i= fScanner.findReferencePosition(fDocument.getLength()); + Assert.assertEquals(1, i); + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t", indent); + } + + public void testIndentation29() { + fDocument.set("\t\twhile (condition)\n" + + "\t\t\twhile (condition)\n" + + "\t\t\t\tfoo();\n"); + + int i= fScanner.findReferencePosition(fDocument.getLength()); + Assert.assertEquals(2, i); + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t\t", indent); + } + + public void testIndentation30() { + // braceless else + fDocument.set("\tif (true)\n" + + "\t{"); + + String indent= fScanner.computeIndentation(fDocument.getLength() - 1).toString(); + Assert.assertEquals("\t", indent); + } + + public void testIndentation31() { + // braceless else + fDocument.set("\tif (true)\n" + + "{\t\n" + + "\t\tstuff();\n" + + "\t} else\n" + + "\t\tnoStuff"); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t\t", indent); + } + + public void testIndentation32() { + // braceless else + fDocument.set("\tswitch(ch) {\n" + + "\t\tcase one:\n"); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals(" ", indent); + } + + public void testAnonymousIndentation1() { + fDocument.set( " MenuItem mi= new MenuItem(\"About...\");\n" + + " mi->addActionListener(\n" + + " new ActionListener() {\n" + ); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals(" ", indent); + } + + public void testAnonymousIndentation2() { + fDocument.set( " MenuItem mi= new MenuItem(\"About...\");\n" + + " mi->addActionListener(\n" + + " new ActionListener() {\n" + + " public void actionPerformed(ActionEvent event) {\n" + + " about();\n" + + " }\n" + + " }\n" + + ");" + ); + + // this is bogus, since this is really just an unfinished call argument list - how could we know + String indent= fScanner.computeIndentation(fDocument.getLength() - 2).toString(); + Assert.assertEquals(" ", indent); + } + + public void testExceptionIndentation1() { + fDocument.set("public void processChildren(CompositeExpression result, IConfigurationElement element) throws CoreException {\n" + + " IConfigurationElement[] children= element.getChildren();\n" + + " if (children != null) {\n" + + " for (int i= 0; i < children.length; i++) {\n" + + " Expression child= parse(children[i]);\n" + + " if (child == null)\n" + + " new Bla(new CoreExeption(new Status(IStatus.ERROR, JavaPlugin.getPluginId()"); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals(" ", indent); + } + + public void testExceptionIndentation2() { + fDocument.set("public void processChildren(CompositeExpression result, IConfigurationElement element) throws CoreException {\n" + + " IConfigurationElement[] children= element.getChildren();\n" + + " if (children != null) {\n" + + " for (int i= 0; i < children.length; i++) {\n" + + " Expression child= parse(children[i]);\n" + + " if (child == null)\n" + + " new Bla(new CoreExeption(new Status(IStatus.ERROR, JavaPlugin.getPluginId(),"); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals(" ", indent); + } + + public void testExceptionIndentation3() { + fDocument.set("public void processChildren(CompositeExpression result, IConfigurationElement element) throws CoreException {\n" + + " IConfigurationElement[] children= element.getChildren();\n" + + " if (children != null) {\n" + + " for (int i= 0; i < children.length; i++) {\n" + + " Expression child= parse(children[i]);\n" + + " if (child == null)\n" + + " new char[] { new CoreExeption(new Status(IStatus.ERROR, JavaPlugin.getPluginId(),"); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals(" ", indent); + } + + public void testListAlignmentMethodDeclaration() { + // parameter declaration - alignment with parenthesis + fDocument.set( "\tvoid proc ( int par1, int par2,\n" + + " int par3, int par4,\n"); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals(" ", indent); + } + + public void testListAlignmentMethodCall() { + // parameter declaration - alignment with parenthesis + fDocument.set( "\this->proc (par1, par2,\n" + + " par3, par4,\n"); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals(" ", indent); + } + + public void testListAlignmentArray() { + // parameter declaration - alignment with parenthesis + fDocument.set( "\tint[]= new int[] { 1, two,\n" + + " three, four,\n"); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals(" ", indent); + } + + public void testListAlignmentArray2() { + // no prior art - probe system settings. + fDocument.set( "\tint[]= new int[] { 1, two,\n"); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t ", indent); + + } + + public void testBraceAlignmentOfMultilineDeclaration() { + fDocument.set( " int foobar(int one, int two,\n" + + " int three, int four,\n" + + " int five) {\n" + + " \n" + + " return 0;\n" + + " }"); + + String indent= fScanner.computeIndentation(fDocument.getLength() - 1).toString(); + Assert.assertEquals(" ", indent); + } + + public void testBlocksInCaseStatements() { + fDocument.set( + " switch (i) {\n" + + " case 1:\n" + + " new Runnable() {\n" + + ""); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals(" ", indent); + } + + public void testAnonymousTypeBraceNextLine() throws Exception { + fDocument.set( + " MenuItem mi= new MenuItem(\"About...\");\n" + + " mi->addActionListener(new ActionListener() " + + " {\n" + ); + + String indent= fScanner.computeIndentation(fDocument.getLength() - 2).toString(); + Assert.assertEquals(" ", indent); + + } + + public void testClassInstanceCreationHeuristic() throws Exception { + fDocument.set(" method(new std::vector(10), foo, new int[])"); + + for (int offset= 0; offset < 15; offset++) + assertFalse(fHeuristicScanner.looksLikeClassInstanceCreationBackward(offset, CHeuristicScanner.UNBOUND)); + for (int offset= 15; offset < 18; offset++) + assertTrue(fHeuristicScanner.looksLikeClassInstanceCreationBackward(offset, CHeuristicScanner.UNBOUND)); + for (int offset= 18; offset < 20; offset++) + assertFalse(fHeuristicScanner.looksLikeClassInstanceCreationBackward(offset, CHeuristicScanner.UNBOUND)); + for (int offset= 20; offset < 26; offset++) + assertTrue(fHeuristicScanner.looksLikeClassInstanceCreationBackward(offset, CHeuristicScanner.UNBOUND)); + for (int offset= 26; offset < 48; offset++) + assertFalse(fHeuristicScanner.looksLikeClassInstanceCreationBackward(offset, CHeuristicScanner.UNBOUND)); + for (int offset= 48; offset < 54; offset++) + assertFalse(fHeuristicScanner.looksLikeClassInstanceCreationBackward(offset, CHeuristicScanner.UNBOUND)); + for (int offset= 54; offset < 57; offset++) + assertTrue(fHeuristicScanner.looksLikeClassInstanceCreationBackward(offset, CHeuristicScanner.UNBOUND)); + for (int offset= 57; offset < 59; offset++) + assertFalse(fHeuristicScanner.looksLikeClassInstanceCreationBackward(offset, CHeuristicScanner.UNBOUND)); + } + + public void testShiftOperator() throws Exception { + fDocument.set( + " for (int j = 0; j == 0; j ++) {\n" + + " j = 3 >> 1;\n" + ); + + String indent= fScanner.computeIndentation(fDocument.getLength()).toString(); + Assert.assertEquals("\t\t\t", indent); + } + + public void testConditional1() throws Exception { + if (true) // XXX enable when https://bugs.eclipse.org/bugs/show_bug.cgi?id=65463 is fixed + return; + fDocument.set( + " boolean isPrime() {\n" + + " return fPrime == true ? true\n" + + " : false;" + ); + + String indent= fScanner.computeIndentation(fDocument.getLength() - 8).toString(); + Assert.assertEquals(" ", indent); + } + + public void testConditional2() throws Exception { + if (true) // XXX enable when https://bugs.eclipse.org/bugs/show_bug.cgi?id=65463 is fixed + return; + fDocument.set( + " boolean isPrime() {\n" + + " return fPrime == true" + + " ? true\n" + + " : false;" + ); + + String indent= fScanner.computeIndentation(fDocument.getLength() - 8).toString(); + Assert.assertEquals(" ", indent); + + } +} diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/EditorTestHelper.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/EditorTestHelper.java index 996da0ff02a..fb55493aaeb 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/EditorTestHelper.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/EditorTestHelper.java @@ -12,8 +12,10 @@ package org.eclipse.cdt.ui.tests.text; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -446,6 +448,18 @@ public class EditorTestHelper { return cProject; } + public static IFile createFile(IContainer container, String fileName, String contents, IProgressMonitor monitor) throws CoreException { + //Obtain file handle + IFile file = container.getFile(new Path(fileName)); + InputStream stream = new ByteArrayInputStream(contents.getBytes()); + //Create file input stream + if(file.exists()) + file.setContents(stream, false, false, monitor); + else + file.create(stream, false, monitor); + return file; + } + public static IFile[] findFiles(IResource resource) throws CoreException { List files= new ArrayList(); findFiles(resource, files); 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 new file mode 100644 index 00000000000..35b64bf38dc --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/IndentActionTest.java @@ -0,0 +1,127 @@ +/******************************************************************************* + * Copyright (c) 2005, 2006 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 + * Anton Leherbauer (Wind River Systems) + *******************************************************************************/ +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; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.testplugin.CProjectHelper; + +import org.eclipse.cdt.internal.ui.actions.IndentAction; +import org.eclipse.cdt.internal.ui.editor.CEditor; + +/** + * Test the IndentAction. + */ +public class IndentActionTest extends TestCase { + private static final String PROJECT= "IndentTests"; + + private static final class EmptyBundle extends ListResourceBundle { + protected Object[][] getContents() { + return new Object[0][]; + } + } + + protected static class IndentTestSetup extends TestSetup { + + private ICProject fCProject; + + public IndentTestSetup(Test test) { + super(test); + } + + protected void setUp() throws Exception { + super.setUp(); + + fCProject= EditorTestHelper.createCProject(PROJECT, "resources/indentation"); + fCProject.setOption(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.TAB); + } + + protected void tearDown () throws Exception { + if (fCProject != null) + CProjectHelper.delete(fCProject); + + super.tearDown(); + } + } + + private static final Class THIS= IndentActionTest.class; + public static Test suite() { + return new IndentTestSetup(new TestSuite(THIS)); + } + + private CEditor fEditor; + private SourceViewer fSourceViewer; + private IDocument fDocument; + + /* + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception { + String filename= createFileName("Before"); + fEditor= (CEditor) EditorTestHelper.openInEditor(ResourceTestHelper.findFile(filename), true); + fSourceViewer= EditorTestHelper.getSourceViewer(fEditor); + fDocument= fSourceViewer.getDocument(); + } + + /* + * @see junit.framework.TestCase#tearDown() + */ + protected void tearDown() throws Exception { + EditorTestHelper.closeEditor(fEditor); + } + + private void assertIndentResult() throws Exception { + String afterFile= createFileName("After"); + String expected= ResourceTestHelper.read(afterFile).toString(); + + new IndentAction(new EmptyBundle(), "prefix", fEditor, false).run(); + + assertEquals(expected, fDocument.get()); + } + + private String createFileName(String qualifier) { + String name= getName(); + 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(); + } + + public void testSample() throws Exception { + selectAll(); + assertIndentResult(); + } + + public void testComplex() throws Exception { + selectAll(); + assertIndentResult(); + } + +} diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/TextTestSuite.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/TextTestSuite.java index 0e74416f9a5..ea307d0e0f8 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/TextTestSuite.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/TextTestSuite.java @@ -21,12 +21,16 @@ public class TextTestSuite extends TestSuite { public TextTestSuite() { super("Tests in package org.eclipse.cdt.ui.tests.text"); - + + // partitioning tests addTest(PartitionTokenScannerTest.suite()); - addTest(NumberRuleTest.suite()); - addTest(CAutoIndentTest.suite()); addTest(CPartitionerTest.suite()); - addTest(PairMatcherTest.suite()); + + // smart edit tests + addTest(CAutoIndentTest.suite()); + addTest(CHeuristicScannerTest.suite()); + addTest(BracketInserterTest.suite()); + addTest(IndentActionTest.suite()); // Break iterator tests. addTest(CBreakIteratorTest.suite()); @@ -36,6 +40,8 @@ public class TextTestSuite extends TestSuite { addTest(SemanticHighlightingTest.suite()); addTest(InactiveCodeHighlightingTest.suite()); addTest(CHeaderRuleTest.suite()); + addTest(NumberRuleTest.suite()); + addTest(PairMatcherTest.suite()); // folding tests addTest(FoldingTest.suite()); 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 7fcac3839cd..30dda96853c 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 @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Sergey Prigogin, Google + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.actions; @@ -188,13 +189,13 @@ public class IndentAction extends TextEditorAction { } /** - * Indents a single line using the java heuristic scanner. Cdoc and multiline comments are + * Indents a single line using the heuristic scanner. Cdoc and multiline comments are * indented as specified by the CDocAutoIndentStrategy. * * @param document the document * @param line the line to be indented * @param caret the caret position - * @param indenter the java indenter + * @param indenter the indenter * @param scanner the heuristic scanner * @param multiLine true if more than one line is being indented * @return true if document was modified, false otherwise @@ -211,7 +212,9 @@ public class IndentAction extends TextEditorAction { ITypedRegion startingPartition= TextUtilities.getPartition(document, ICPartitions.C_PARTITIONING, offset, false); String type= partition.getType(); if (type.equals(ICPartitions.C_MULTI_LINE_COMMENT)) { - indent= computeDocIndent(document, line, scanner, startingPartition); + indent= computeCommentIndent(document, line, scanner, startingPartition); + } else if (startingPartition.getType().equals(ICPartitions.C_PREPROCESSOR)) { + indent= computePreprocessorIndent(document, line, scanner, startingPartition); } else if (!fIsTabAction && startingPartition.getOffset() == offset && startingPartition.getType().equals(ICPartitions.C_SINGLE_LINE_COMMENT)) { // line comment starting at position 0 -> indent inside int max= document.getLength() - offset; @@ -245,7 +248,7 @@ public class IndentAction extends TextEditorAction { } } - // standard java indentation + // standard C indentation if (indent == null) { StringBuffer computed= indenter.computeIndentation(offset); if (computed != null) @@ -292,18 +295,17 @@ public class IndentAction extends TextEditorAction { } /** - * Computes and returns the indentation for a javadoc line. The line - * must be inside a javadoc comment. + * Computes and returns the indentation for a comment line. * * @param document the document * @param line the line in document * @param scanner the scanner - * @param partition the javadoc partition + * @param partition the comment partition * @return the indent, or null if not computable * @throws BadLocationException */ - private String computeDocIndent(IDocument document, int line, CHeuristicScanner scanner, ITypedRegion partition) throws BadLocationException { - if (line == 0) // impossible - the first line is never inside a javadoc comment + 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 null; // don't make any assumptions if the line does not start with \s*\* - it might be @@ -347,6 +349,20 @@ public class IndentAction extends TextEditorAction { return buf.toString(); } + /** + * Computes and returns the indentation for a preprocessor line. + * + * @param document the document + * @param line the line in document + * @param scanner the scanner + * @param partition the comment partition + * @return the indent, or null if not computable + * @throws BadLocationException + */ + private String computePreprocessorIndent(IDocument document, int line, CHeuristicScanner scanner, ITypedRegion partition) throws BadLocationException { + return ""; //$NON-NLS-1$ + } + /** * Returns the size in characters of a string. All characters count one, tabs count the editor's * preference for the tab display @@ -390,7 +406,7 @@ public class IndentAction extends TextEditorAction { } /** - * Returns the tab size used by the java editor, which is deduced from the + * Returns the tab size used by the editor, which is deduced from the * formatter preferences. * * @return the tab size as defined in the current formatter preferences diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java index 00c2ee23bbb..91807ba234a 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java @@ -692,7 +692,8 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IR } ITypedRegion partition = TextUtilities.getPartition(document, ICPartitions.C_PARTITIONING, offset, true); - if (!IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType())) + if (!IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType()) + && !ICPartitions.C_PREPROCESSOR.equals(partition.getType())) return; if (!validateEditorInputState()) 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 b1aaae0736a..7bec92ae7ca 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 @@ -7,6 +7,8 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Sergey Prigogin, Google + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.text; @@ -88,7 +90,7 @@ public final class CHeuristicScanner implements Symbols { */ private static class NonWhitespace extends StopCondition { /* - * @see org.eclipse.jdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char) + * @see org.eclipse.cdt.internal.ui.text.CHeuristicScanner.StopCondition#stop(char) */ public boolean stop(char ch, int position, boolean forward) { return !Character.isWhitespace(ch); @@ -102,14 +104,14 @@ public final class CHeuristicScanner implements Symbols { */ private final class NonWhitespaceDefaultPartition extends NonWhitespace { /* - * @see org.eclipse.jdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char) + * @see org.eclipse.cdt.internal.ui.text.CHeuristicScanner.StopCondition#stop(char) */ public boolean stop(char ch, int position, boolean forward) { return super.stop(ch, position, true) && isDefaultPartition(position); } /* - * @see org.eclipse.jdt.internal.ui.text.JavaHeuristicScanner.StopCondition#nextPosition(int, boolean) + * @see org.eclipse.cdt.internal.ui.text.CHeuristicScanner.StopCondition#nextPosition(int, boolean) */ public int nextPosition(int position, boolean forward) { ITypedRegion partition= getPartition(position); @@ -134,7 +136,7 @@ public final class CHeuristicScanner implements Symbols { */ private static class NonJavaIdentifierPart extends StopCondition { /* - * @see org.eclipse.jdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char) + * @see org.eclipse.cdt.internal.ui.text.CHeuristicScanner.StopCondition#stop(char) */ public boolean stop(char ch, int position, boolean forward) { return !Character.isJavaIdentifierPart(ch); @@ -148,14 +150,14 @@ public final class CHeuristicScanner implements Symbols { */ private final class NonJavaIdentifierPartDefaultPartition extends NonJavaIdentifierPart { /* - * @see org.eclipse.jdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char) + * @see org.eclipse.cdt.internal.ui.text.CHeuristicScanner.StopCondition#stop(char) */ public boolean stop(char ch, int position, boolean forward) { return super.stop(ch, position, true) || !isDefaultPartition(position); } /* - * @see org.eclipse.jdt.internal.ui.text.JavaHeuristicScanner.StopCondition#nextPosition(int, boolean) + * @see org.eclipse.cdt.internal.ui.text.CHeuristicScanner.StopCondition#nextPosition(int, boolean) */ public int nextPosition(int position, boolean forward) { ITypedRegion partition= getPartition(position); @@ -201,14 +203,14 @@ public final class CHeuristicScanner implements Symbols { } /* - * @see org.eclipse.jdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char, int) + * @see org.eclipse.cdt.internal.ui.text.CHeuristicScanner.StopCondition#stop(char, int) */ public boolean stop(char ch, int position, boolean forward) { return Arrays.binarySearch(fChars, ch) >= 0 && isDefaultPartition(position); } /* - * @see org.eclipse.jdt.internal.ui.text.JavaHeuristicScanner.StopCondition#nextPosition(int, boolean) + * @see org.eclipse.cdt.internal.ui.text.CHeuristicScanner.StopCondition#nextPosition(int, boolean) */ public int nextPosition(int position, boolean forward) { ITypedRegion partition= getPartition(position); @@ -268,7 +270,7 @@ public final class CHeuristicScanner implements Symbols { } /** - * Calls this(document, ICPartitions.JAVA_PARTITIONING, IDocument.DEFAULT_CONTENT_TYPE). + * Calls this(document, ICPartitions.C_PARTITIONING, IDocument.DEFAULT_CONTENT_TYPE). * * @param document the document to scan. */ @@ -841,18 +843,18 @@ public final class CHeuristicScanner implements Symbols { * true if start is at the following positions (|): * *
-	 *  new java.util. ArrayList|<String>(10)
-	 *  new ArrayList |(10)
-	 *  new  / * comment  * / ArrayList |(10)
+	 *  new new std::vector<std::string>|(10)
+	 *  new new str_vector |(10)
+	 *  new new / * comment * / str_vector |(10)
 	 * 
* * but not the following: * *
-	 *  new java.util. ArrayList<String>(10)|
-	 *  new java.util. ArrayList<String>|(10)
-	 *  new ArrayList (10)|
-	 *  ArrayList |(10)
+	 *  new new std::vector<std::string>(10)|
+	 *  new new std::vector<std::string>|(10)
+	 *  new new vector (10)|
+	 *  vector |(10)
 	 * 
* * @param start the position where the type name of the class instance creation supposedly ends @@ -865,7 +867,10 @@ public final class CHeuristicScanner implements Symbols { int token= previousToken(start - 1, bound); if (token == Symbols.TokenIDENT) { // type name token= previousToken(getPosition(), bound); - while (token == Symbols.TokenOTHER) { // dot of qualification + while (token == Symbols.TokenCOLON) { // colon of qualification + token= previousToken(getPosition(), bound); + if (token != Symbols.TokenCOLON) // second colon of qualification + return false; token= previousToken(getPosition(), bound); if (token != Symbols.TokenIDENT) // qualification name return false; 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 713e17ea178..e4c12ac62b3 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 @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Sergey Prigogin, Google + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.text; @@ -1582,6 +1583,25 @@ public final class CIndenter { return false; } + /** + * Skips scope qualifiers of identifiers. + * + * @return true if a qualifier was encountered, the last token + * will be an IDENT. + */ + private boolean skipQualifiers() { + if (fToken == Symbols.TokenCOLON) { + nextToken(); + if (fToken == Symbols.TokenCOLON) { + nextToken(); + if (fToken == Symbols.TokenIDENT) { + return true; + } + } + } + return false; + } + /** * Reads the next token in backward direction from the heuristic scanner * and sets the fields fToken, fPreviousPosition and fPosition @@ -1621,17 +1641,10 @@ public final class CIndenter { * declaration header. */ private boolean looksLikeMethodDecl() { - /* - * TODO This heuristic does not recognize package private constructors - * since those do have neither type nor visibility keywords. - * One option would be to go over the parameter list, but that might - * be empty as well, or not typed in yet - hard to do without an AST... - */ - nextToken(); if (fToken == Symbols.TokenIDENT) { // method name do nextToken(); - while (skipBrackets()); // optional brackets for array valued return types + while (skipBrackets() || skipQualifiers()); // optional brackets for array valued return types return fToken == Symbols.TokenIDENT; // return type name @@ -1674,7 +1687,7 @@ public final class CIndenter { * header. */ private boolean looksLikeMethodCall() { - // TODO add awareness for constructor calls with generic types: new ArrayList() + // TODO add awareness for constructor calls with templates: new complex() nextToken(); return fToken == Symbols.TokenIDENT; // method name } 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 7d7bc13e903..1d0f899aee0 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. + * Copyright (c) 2000, 2006 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 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Sergey Prigogin, Google *******************************************************************************/ package org.eclipse.cdt.internal.ui.text; @@ -43,11 +44,11 @@ public interface Symbols { int TokenSWITCH= 1020; int TokenGOTO= 1021; int TokenDEFAULT= 1022; - int TokenPRIVATE= 1023; - int TokenPROTECTED= 1024; - int TokenPUBLIC= 1025; + int TokenPRIVATE= 1023; + int TokenPROTECTED= 1024; + int TokenPUBLIC= 1025; int TokenNEW= 1026; - int TokenDELETE= 1027; + int TokenDELETE= 1027; int TokenCLASS= 1028; int TokenSTRUCT= 1029; int TokenENUM= 1030;