Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[cdt-patch] FIXED 93281- [Open Declaration] the entire operator string shouldn't have to be selected for features to work


FIXED 93281- [Open Declaration] the entire operator string shouldn't have to be selected for features to work

Devin Steffler
IBM's Eclipse CDT
Ottawa (Palladium), Ontario, Canada


Index: ui/org/eclipse/cdt/ui/tests/AutomatedSuite.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt-core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/AutomatedSuite.java,v
retrieving revision 1.27
diff -u -r1.27 AutomatedSuite.java
--- ui/org/eclipse/cdt/ui/tests/AutomatedSuite.java	10 Feb 2005 15:33:59 -0000	1.27
+++ ui/org/eclipse/cdt/ui/tests/AutomatedSuite.java	29 Apr 2005 19:51:45 -0000
@@ -48,6 +48,7 @@
 import org.eclipse.cdt.ui.tests.text.contentassist.CompletionTest_VariableType_NoPrefix;
 import org.eclipse.cdt.ui.tests.text.contentassist.CompletionTest_VariableType_Prefix;
 import org.eclipse.cdt.ui.tests.text.contentassist.ContentAssistTests;
+import org.eclipse.cdt.ui.tests.text.selectiontests.SelectionTests;
 
 
 
@@ -113,6 +114,10 @@
 		
 		addTest( ContentAssistTests.suite() );
 		addTest( RegressionTestsUISuite.suite() );
+        
+        // selection tests
+        addTest( SelectionTests.suite() );      
+        
 		// Failed Tests
 		addTest(CompletionFailedTest_MemberReference_Arrow_Prefix2.suite());
 	}
Index: ui/org/eclipse/cdt/ui/tests/text/selectiontests/SelectionTests.java
===================================================================
RCS file: ui/org/eclipse/cdt/ui/tests/text/selectiontests/SelectionTests.java
diff -N ui/org/eclipse/cdt/ui/tests/text/selectiontests/SelectionTests.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ui/org/eclipse/cdt/ui/tests/text/selectiontests/SelectionTests.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,205 @@
+package org.eclipse.cdt.ui.tests.text.selectiontests;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.eclipse.cdt.core.dom.ast.IASTName;
+import org.eclipse.cdt.core.dom.ast.IASTNode;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.core.search.DOMSearchUtil;
+import org.eclipse.cdt.core.testplugin.CProjectHelper;
+import org.eclipse.cdt.core.testplugin.FileManager;
+import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
+import org.eclipse.cdt.internal.core.index.sourceindexer.SourceIndexer;
+import org.eclipse.cdt.internal.ui.CHelpProviderManager;
+import org.eclipse.cdt.internal.ui.text.CHelpBookDescriptor;
+import org.eclipse.cdt.ui.tests.text.contentassist.ContentAssistTests;
+import org.eclipse.cdt.ui.text.ICHelpInvocationContext;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.texteditor.AbstractTextEditor;
+
+public class SelectionTests extends TestCase {
+    
+    static NullProgressMonitor      monitor;
+    static IWorkspace               workspace;
+    static IProject                 project;
+    static FileManager              fileManager;
+    static boolean                  disabledHelpContributions = false;
+    {
+        //(CCorePlugin.getDefault().getCoreModel().getIndexManager()).reset();
+        monitor = new NullProgressMonitor();
+        
+        workspace = ResourcesPlugin.getWorkspace();
+        
+        ICProject cPrj; 
+        try {
+            cPrj = CProjectHelper.createCCProject("SelectionTestProject", "bin"); //$NON-NLS-1$ //$NON-NLS-2$
+        
+            project = cPrj.getProject();
+            project.setSessionProperty(SourceIndexer.activationKey,new Boolean(false));
+        } catch ( CoreException e ) {
+            /*boo*/
+        }
+        if (project == null)
+            fail("Unable to create project"); //$NON-NLS-1$
+
+        //Create file manager
+        fileManager = new FileManager();
+    }
+    public SelectionTests()
+    {
+        super();
+    }
+    /**
+     * @param name
+     */
+    public SelectionTests(String name)
+    {
+        super(name);
+    }
+    
+    public static Test suite() {
+        TestSuite suite = new TestSuite( SelectionTests.class );
+        suite.addTest( new SelectionTests("cleanupProject") );    //$NON-NLS-1$
+        return suite;
+    }
+    
+    public void cleanupProject() throws Exception {
+        try{
+            project.delete( true, false, monitor );
+            project = null;
+        } catch( Throwable e ){
+            /*boo*/
+        }
+    }
+    
+    protected void tearDown() throws Exception {
+        if( project == null || !project.exists() ) 
+            return;
+        
+        IResource [] members = project.members();
+        for( int i = 0; i < members.length; i++ ){
+            if( members[i].getName().equals( ".project" ) || members[i].getName().equals( ".cdtproject" ) ) //$NON-NLS-1$ //$NON-NLS-2$
+                continue;
+            try{
+                members[i].delete( false, monitor );
+            } catch( Throwable e ){
+                /*boo*/
+            }
+        }
+    }
+    
+    protected IFile importFile(String fileName, String contents ) throws Exception{
+        //Obtain file handle
+        IFile file = project.getProject().getFile(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 );
+        
+        fileManager.addFile(file);
+        
+        return file;
+    }
+    
+    protected IASTNode testF3(IFile file, int offset) {
+        IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+        IEditorPart part = null;
+        try {
+            part = page.openEditor(new FileEditorInput(file), "org.eclipse.cdt.ui.editor.CEditor"); // TODO Devin testing
+        } catch (PartInitException e) {
+            assertFalse(true);
+        }
+        
+        if (part instanceof AbstractTextEditor) {
+            ((AbstractTextEditor)part).getSelectionProvider().setSelection(new TextSelection(offset,0));
+            
+            final IAction action = ((AbstractTextEditor)part).getAction("OpenDeclarations");
+            action.run();
+        
+            // the action above should highlight the declaration, so now retrieve it and use that selection to get the IASTName selected on the TU
+            ISelection sel = ((AbstractTextEditor)part).getSelectionProvider().getSelection();
+            
+            if (sel instanceof TextSelection) {
+                IASTName[] names = DOMSearchUtil.getSelectedNamesFrom(file, ((TextSelection)sel).getOffset(), ((TextSelection)sel).getLength());
+                
+                if (names.length == 0) {
+                    assertFalse(true);
+                } else {
+                    return names[0];
+                }
+            }
+        }
+        
+        return null;
+    }
+    
+    public void testBug93281() throws Exception {
+        StringBuffer buffer = new StringBuffer();
+        buffer.append("class Point{                         \n"); //$NON-NLS-1$
+        buffer.append("public:                              \n"); //$NON-NLS-1$
+        buffer.append("Point(): xCoord(0){}                 \n"); //$NON-NLS-1$
+        buffer.append("Point& operator=(const Point &rhs){return *this;}    // line A\n"); //$NON-NLS-1$
+        buffer.append("void* operator new [ ] (unsigned int);\n"); //$NON-NLS-1$
+        buffer.append("private:                             \n"); //$NON-NLS-1$
+        buffer.append("int xCoord;                          \n"); //$NON-NLS-1$
+        buffer.append("};                                   \n"); //$NON-NLS-1$
+        buffer.append("static const Point zero;\n"); //$NON-NLS-1$
+        buffer.append("int main(int argc, char **argv) {        \n"); //$NON-NLS-1$
+        buffer.append("Point *p2 = new Point();         \n"); //$NON-NLS-1$
+        buffer.append("p2->    operator // /* operator */ // F3 in the middle \n"); //$NON-NLS-1$
+        buffer.append("//of \"operator\" should work\n"); //$NON-NLS-1$
+        buffer.append("// \\n"); //$NON-NLS-1$
+        buffer.append("/* */\n"); //$NON-NLS-1$
+        buffer.append("=(zero);           // line B\n"); //$NON-NLS-1$
+        buffer.append("p2->operator /* oh yeah */ new // F3 in the middle of \"operator\"\n"); //$NON-NLS-1$
+        buffer.append("// should work\n"); //$NON-NLS-1$
+        buffer.append("//\n"); //$NON-NLS-1$
+        buffer.append("[ /* sweet */ ] //\n"); //$NON-NLS-1$
+        buffer.append("(2);\n"); //$NON-NLS-1$
+        buffer.append("return (0);                          \n"); //$NON-NLS-1$
+        buffer.append("}\n"); //$NON-NLS-1$
+        
+        String code = buffer.toString();
+        IFile file = importFile("test93281.cpp", code); //$NON-NLS-1$
+        
+        int offset = code.indexOf("p2->operator") + 6; //$NON-NLS-1$
+        IASTNode node = testF3(file, offset);
+        
+        assertTrue(node instanceof IASTName);
+        assertEquals(((IASTName)node).toString(), "operator new[]"); //$NON-NLS-1$
+        assertEquals(((ASTNode)node).getOffset(), 183);
+        assertEquals(((ASTNode)node).getLength(), 16);
+        
+        offset = code.indexOf("p2->    operator") + 11; //$NON-NLS-1$
+        node = testF3(file, offset);
+        
+        assertTrue(node instanceof IASTName);
+        assertEquals(((IASTName)node).toString(), "operator ="); //$NON-NLS-1$
+        assertEquals(((ASTNode)node).getOffset(), 121);
+        assertEquals(((ASTNode)node).getLength(), 9);
+        
+    }
+}
Index: src/org/eclipse/cdt/internal/ui/search/actions/SelectionParseAction.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt-core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/SelectionParseAction.java,v
retrieving revision 1.8
diff -u -r1.8 SelectionParseAction.java
--- src/org/eclipse/cdt/internal/ui/search/actions/SelectionParseAction.java	29 Apr 2005 00:56:11 -0000	1.8
+++ src/org/eclipse/cdt/internal/ui/search/actions/SelectionParseAction.java	29 Apr 2005 19:51:20 -0000
@@ -41,6 +41,7 @@
 import org.eclipse.jface.text.ITextSelection;
 import org.eclipse.jface.viewers.ISelection;
 import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IFileEditorInput;
 import org.eclipse.ui.IViewSite;
 import org.eclipse.ui.IWorkbenchSite;
 import org.eclipse.ui.texteditor.IDocumentProvider;
@@ -50,7 +51,8 @@
  * Created on Jun 2, 2004
  */
 public class SelectionParseAction extends Action {
-	protected static final String CSEARCH_OPERATION_TOO_MANY_NAMES_MESSAGE = "CSearchOperation.tooManyNames.message"; //$NON-NLS-1$
+	private static final String OPERATOR = "operator"; //$NON-NLS-1$
+    protected static final String CSEARCH_OPERATION_TOO_MANY_NAMES_MESSAGE = "CSearchOperation.tooManyNames.message"; //$NON-NLS-1$
 	protected static final String CSEARCH_OPERATION_NO_NAMES_SELECTED_MESSAGE = "CSearchOperation.noNamesSelected.message"; //$NON-NLS-1$
 	protected static final String CSEARCH_OPERATION_OPERATION_UNAVAILABLE_MESSAGE = "CSearchOperation.operationUnavailable.message"; //$NON-NLS-1$
 	
@@ -218,8 +220,27 @@
         
         SelSearchNode sel = new SelSearchNode();
 
+        boolean selectedOperator=false;
+        if (selectedWord != null && selectedWord.indexOf(OPERATOR) >= 0 && fPos >= fStartPos + selectedWord.indexOf(OPERATOR) && fPos < fStartPos + selectedWord.indexOf(OPERATOR) + OPERATOR.length()) {
+            selectedOperator=true;
+        }
+    
+        // if the operator was selected, get its proper bounds
+        if (selectedOperator && fEditor.getEditorInput() instanceof IFileEditorInput &&  
+                CoreModel.hasCCNature(((IFileEditorInput)fEditor.getEditorInput()).getFile().getProject())) {
+            int actualStart=fStartPos + selectedWord.indexOf(OPERATOR);
+            int actualEnd=getOperatorActualEnd(doc, fStartPos + selectedWord.indexOf(OPERATOR) + OPERATOR.length());
+            
+            actualEnd=(actualEnd>0?actualEnd:fEndPos);
+            
+            try {
+                sel.selText = doc.get(actualStart, actualEnd - actualStart);
+            } catch (BadLocationException e) {}
+            sel.selStart = actualStart;
+            sel.selEnd = actualEnd;
+        // TODO Devin this only works for definitions of destructors right now
         // if there is a destructor and the cursor is in the destructor name's segment then get the entire destructor
-        if (selectedWord != null && selectedWord.indexOf('~') >= 0 && fPos - 2 >= fStartPos + selectedWord.lastIndexOf(new String(Keywords.cpCOLONCOLON))) {
+        } else if (selectedWord != null && selectedWord.indexOf('~') >= 0 && fPos - 2 >= fStartPos + selectedWord.lastIndexOf(new String(Keywords.cpCOLONCOLON))) {
             int tildePos = selectedWord.indexOf('~');
             int actualStart=fStartPos + tildePos;
             int length=0;
@@ -259,6 +280,211 @@
         return sel;     
 	}
     
+    private int getOperatorActualEnd(IDocument doc, int index) {
+        char c1, c2;
+        int actualEnd=-1;
+        boolean multiComment=false;
+        boolean singleComment=false;
+        int possibleEnd=-1;
+        while (actualEnd==-1) {
+            try {
+                c1=doc.getChar(index);
+                c2=doc.getChar(index+1);
+                
+                // skip anything within a single-line comment
+                if (singleComment) {
+                    char c3=doc.getChar(index-1);
+                    if (c3 != '\\' && (c1 == '\n' || c1 == '\r' && c2 == '\n' )) {
+                        singleComment=false;
+                    }
+                    index++;
+                    continue;
+                }
+                // skip anything within a multi-line comment
+                if (multiComment) {
+                    if (c1 == '*' && c2 == '/') {
+                        multiComment=false;
+                        index+=2;
+                        continue;
+                    }
+                    index++;
+                    continue;
+                }
+                
+                switch(c1) {
+                case '+': {
+                    switch(c2) {
+                    case '=':
+                    case '+':
+                        actualEnd=index+2;
+                        break;
+                    default:
+                        actualEnd=index+1;
+                        break;
+                    }
+                    break;
+                }
+                case '-': {
+                    switch(c2) {
+                    case '=':
+                        actualEnd=index+2;
+                        break;
+                    case '-':
+                        switch(doc.getChar(index+2)) {
+                        case '>': {
+                            switch(doc.getChar(index+3)) {
+                            case '*':
+                                actualEnd=index+4;
+                                break;
+                            default:
+                                actualEnd=index+3;
+                                break;
+                            }
+                            break;
+                        }
+                        default:
+                            actualEnd=index+2;
+                            break;                                
+                        }
+                        break;
+                    default:
+                        
+                        break;
+                    }
+                    break;
+                }
+                case '|': {
+                    switch(c2) {
+                    case '=':
+                    case '|':
+                        actualEnd=index+2;
+                        break;
+                    default:
+                        actualEnd=index+1;
+                        break;
+                    }
+                    break;                  
+                }
+                case '&': {
+                    switch(c2) {
+                    case '=':
+                    case '&':
+                        actualEnd=index+2;
+                        break;
+                    default:
+                        actualEnd=index+1;
+                        break;
+                    }
+                    break;
+                }
+                case '/': {
+                    switch(c2) {
+                    case '/':
+                        singleComment=true;
+                        index+=2;
+                        break;
+                    case '*':
+                        multiComment=true;
+                        index+=2;
+                        break;
+                    case '=':
+                        actualEnd=index+2;
+                        break;
+                    default:
+                        actualEnd=index+1;
+                        break;
+                    }
+                    break;
+                }
+                case '*':
+                case '%': 
+                case '^': 
+                case '!': 
+                case '=': {
+                    switch(c2) {
+                    case '=':
+                        actualEnd=index+2;
+                        break;
+                    default:
+                        actualEnd=index+1;
+                        break;
+                    }
+                    break;
+                }
+                case '(': {
+                    if (possibleEnd > 0)
+                        actualEnd = possibleEnd;
+                    break;
+                }   
+                case ']':
+                case ')':
+                case ',':
+                case '~': {
+                    actualEnd=index+1;
+                    break;
+                }
+                case '<': {
+                    switch(c2) {
+                    case '=':
+                    case '<':
+                        switch(doc.getChar(index+2)) {
+                        case '=':
+                            actualEnd=index+3;
+                            break;
+                        default:
+                            actualEnd=index+2;
+                            break;
+                        }
+                        break;
+                    default:
+                        actualEnd=index;
+                        break;
+                    }
+                    break;                  
+                }
+                case '>': {
+                    switch(c2) {
+                    case '=':
+                    case '>':
+                        switch(doc.getChar(index+2)) {
+                        case '=':
+                            actualEnd=index+3;
+                            break;
+                        default:
+                            actualEnd=index+2;
+                            break;
+                        }
+                        break;
+                    default:
+                        actualEnd=index;
+                        break;
+                    }
+                    break;  
+                }
+                case 'n': { // start of "new"
+                    while (doc.getChar(++index) != 'w');
+                    possibleEnd=++index;
+                    break;
+                }
+                case 'd': { // start of "delete"
+                    while (doc.getChar(++index) != 't' && doc.getChar(index+1) != 'e');
+                    index+=2;
+                    possibleEnd=index;
+                    break;
+                }
+                default:
+                    index++;
+                    break;
+                }
+            } catch (BadLocationException e) {
+                // something went wrong
+                return -1;
+            }
+        }
+        
+        return actualEnd;
+    }
+    
 	/**
 	  * Return the selected string from the editor
 	  * @return The string currently selected, or null if there is no valid selection

Back to the top