mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-30 21:55:31 +02:00
Patch for Devin Steffler.
FIXED 93281- [Open Declaration] the entire operator string shouldn't have to be selected for features to work
This commit is contained in:
parent
d3314df607
commit
e95f21d2d8
4 changed files with 439 additions and 3 deletions
|
@ -48,6 +48,7 @@ import org.eclipse.cdt.ui.tests.text.contentassist.CompletionTest_VariableType_N
|
|||
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 @@ public class AutomatedSuite extends TestSuite {
|
|||
|
||||
addTest( ContentAssistTests.suite() );
|
||||
addTest( RegressionTestsUISuite.suite() );
|
||||
|
||||
// selection tests
|
||||
addTest( SelectionTests.suite() );
|
||||
|
||||
// Failed Tests
|
||||
addTest(CompletionFailedTest_MemberReference_Arrow_Prefix2.suite());
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ public class RefactoringRegressionTests extends SearchRegressionTests {
|
|||
suite.addTest( new FailingTest( new RefactoringRegressionTests("testDestructor_29_72612"), 72612) ); //$NON-NLS-1$
|
||||
suite.addTest( new RefactoringRegressionTests("testFunction_31") ); //$NON-NLS-1$
|
||||
suite.addTest( new FailingTest( new RefactoringRegressionTests("testMethod_32_72717"),72717) ); //$NON-NLS-1$
|
||||
suite.addTest( new FailingTest( new RefactoringRegressionTests("testMethod_33_72605"),72605) ); //$NON-NLS-1$
|
||||
suite.addTest( new RefactoringRegressionTests("testMethod_33_72605") ); //$NON-NLS-1$
|
||||
suite.addTest( new RefactoringRegressionTests("testMethod_34") ); //$NON-NLS-1$
|
||||
suite.addTest( new FailingTest( new RefactoringRegressionTests("testMethod_35_72726"),72726) ); //$NON-NLS-1$
|
||||
suite.addTest( new RefactoringRegressionTests("testMethod_39") ); //$NON-NLS-1$
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
|
@ -41,6 +41,7 @@ import org.eclipse.jface.text.IDocument;
|
|||
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 @@ import org.eclipse.ui.texteditor.IDocumentProvider;
|
|||
* 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 @@ public class SelectionParseAction extends Action {
|
|||
|
||||
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 @@ public class SelectionParseAction extends Action {
|
|||
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
|
||||
|
|
Loading…
Add table
Reference in a new issue