diff --git a/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/ctagsindexer/CTagsIndexer.java b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/ctagsindexer/CTagsIndexer.java index 7b3e535cd20..8782841fcb8 100644 --- a/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/ctagsindexer/CTagsIndexer.java +++ b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/ctagsindexer/CTagsIndexer.java @@ -11,16 +11,23 @@ package org.eclipse.cdt.internal.core.index.ctagsindexer; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; import java.util.HashSet; +import java.util.List; import org.eclipse.cdt.core.AbstractCExtension; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.ICLogConstants; import org.eclipse.cdt.core.index.ICDTIndexer; +import org.eclipse.cdt.core.index.IIndexChangeListener; import org.eclipse.cdt.core.index.IIndexStorage; +import org.eclipse.cdt.core.index.IndexChangeEvent; import org.eclipse.cdt.core.model.ICModelMarker; +import org.eclipse.cdt.internal.core.Util; import org.eclipse.cdt.internal.core.index.IIndex; import org.eclipse.cdt.internal.core.index.IIndexerOutput; +import org.eclipse.cdt.internal.core.index.impl.IndexDelta; import org.eclipse.cdt.internal.core.index.sourceindexer.CIndexStorage; import org.eclipse.cdt.internal.core.search.indexing.IndexManager; import org.eclipse.cdt.internal.core.search.indexing.ReadWriteMonitor; @@ -32,16 +39,26 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.ISafeRunnable; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; /** * @author Bogdan Gheorghe */ public class CTagsIndexer extends AbstractCExtension implements ICDTIndexer { + public static boolean VERBOSE = false; + public final static String CTAGS_INTERNAL = "ctags_internal"; //$NON-NLS-1$ public final static String CTAGS_EXTERNAL = "ctags_external"; //$NON-NLS-1$ public final static String CTAGS_LOCATION = "ctags_location"; //$NON-NLS-1$ + protected List indexChangeListeners = Collections.synchronizedList(new ArrayList()); + public static final String INDEX_NOTIFICATION_NAME = Util.bind( "indexNotificationJob" ); //$NON-NLS-1$ private CIndexStorage indexStorage = null; public ReadWriteMonitor storageMonitor = null; private IndexManager indexManager = null; @@ -374,5 +391,61 @@ public class CTagsIndexer extends AbstractCExtension implements ICDTIndexer { indexManager.removeIndexerProblems(project); } + public void addIndexChangeListener(IIndexChangeListener listener) { + synchronized(indexChangeListeners) { + if (!indexChangeListeners.contains(listener)) { + indexChangeListeners.add(listener); + } + } + } + + public void removeIndexChangeListener(IIndexChangeListener listener) { + synchronized(indexChangeListeners) { + int i = indexChangeListeners.indexOf(listener); + if (i != -1) { + indexChangeListeners.remove(i); + } + } + } + /** + * @param indexDelta + */ + public void notifyListeners(IndexDelta indexDelta) { + final IndexChangeEvent indexEvent = new IndexChangeEvent(indexDelta); + for (int i= 0; i < indexChangeListeners.size(); i++) { + IIndexChangeListener tempListener = null; + synchronized(indexChangeListeners){ + tempListener = (IIndexChangeListener) indexChangeListeners.get(i); + } + final IIndexChangeListener listener = tempListener; + long start = -1; + if (VERBOSE) { + System.out.print("Listener #" + (i+1) + "=" + listener.toString());//$NON-NLS-1$//$NON-NLS-2$ + start = System.currentTimeMillis(); + } + + // wrap callbacks with Safe runnable for subsequent listeners to be called when some are causing grief + Job job = new Job(INDEX_NOTIFICATION_NAME){ + protected IStatus run(IProgressMonitor monitor) { + Platform.run(new ISafeRunnable() { + public void handleException(Throwable exception) { + CCorePlugin.log(exception); + } + public void run() throws Exception { + listener.indexChanged(indexEvent); + } + }); + + return Status.OK_STATUS; + } + }; + + job.schedule(); + if (VERBOSE) { + System.out.println(" -> " + (System.currentTimeMillis()-start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + } } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModel.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModel.java index 598e8941f9b..d238669eef0 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModel.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModel.java @@ -1098,7 +1098,7 @@ public class CoreModel { public static boolean isScannerInformationEmpty(IResource resource) { final int PATH_ENTRY_MASK = IPathEntry.CDT_INCLUDE | IPathEntry.CDT_MACRO | - IPathEntry.CDT_INCLUDE_FILE | IPathEntry.CDT_MACRO_FILE; + IPathEntry.CDT_INCLUDE_FILE | IPathEntry.CDT_MACRO_FILE | IPathEntry.CDT_SOURCE; boolean rc = true; IPath resPath = resource.getFullPath(); IProject project = resource.getProject(); diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/AutomatedSuite.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/AutomatedSuite.java index 2d181dafbdd..618ff238273 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/AutomatedSuite.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/AutomatedSuite.java @@ -48,7 +48,11 @@ 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.CPPSelectionTestsCTagsIndexer; +import org.eclipse.cdt.ui.tests.text.selectiontests.CPPSelectionTestsDOMIndexer; import org.eclipse.cdt.ui.tests.text.selectiontests.CPPSelectionTestsNoIndexer; +import org.eclipse.cdt.ui.tests.text.selectiontests.CSelectionTestsCTagsIndexer; +import org.eclipse.cdt.ui.tests.text.selectiontests.CSelectionTestsDOMIndexer; import org.eclipse.cdt.ui.tests.text.selectiontests.CSelectionTestsNoIndexer; @@ -119,9 +123,13 @@ public class AutomatedSuite extends TestSuite { // Failed Tests addTest(CompletionFailedTest_MemberReference_Arrow_Prefix2.suite()); - // selection tests with no indexer + // selection tests addTest( CPPSelectionTestsNoIndexer.suite() ); addTest( CSelectionTestsNoIndexer.suite() ); + addTest( CPPSelectionTestsDOMIndexer.suite() ); + addTest( CSelectionTestsDOMIndexer.suite() ); + addTest( CPPSelectionTestsCTagsIndexer.suite() ); + addTest( CSelectionTestsCTagsIndexer.suite() ); } } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selectiontests/BaseSelectionTestsIndexer.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selectiontests/BaseSelectionTestsIndexer.java new file mode 100644 index 00000000000..72642da407d --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selectiontests/BaseSelectionTestsIndexer.java @@ -0,0 +1,310 @@ +/********************************************************************** + * Copyright (c) 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.ui.tests.text.selectiontests; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.ICDescriptor; +import org.eclipse.cdt.core.ICDescriptorOperation; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.index.IIndexDelta; +import org.eclipse.cdt.core.index.IndexChangeEvent; +import org.eclipse.cdt.core.search.DOMSearchUtil; +import org.eclipse.cdt.core.testplugin.FileManager; +import org.eclipse.cdt.internal.core.parser.ParserException; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +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.IEditorInput; +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; + +import junit.framework.TestCase; + +/** + * Base test class for testing F2/F3 with the indexers. + * + * @author dsteffle + */ +public class BaseSelectionTestsIndexer extends TestCase { + public static final int TIMEOUT = 50; + protected boolean fileIndexed; + protected IProject project; + static FileManager fileManager = new FileManager(); + IProgressMonitor monitor = new NullProgressMonitor(); + + public BaseSelectionTestsIndexer(String name) { + super(name); + } + + public void waitForIndex(int maxSec) throws Exception { + int delay = 0; + while (fileIndexed != true && delay < (maxSec * 1000)) + { + Thread.sleep(TIMEOUT); + delay += TIMEOUT; + } + } + + public void indexChanged(IndexChangeEvent event) { + IIndexDelta delta = event.getDelta(); + if (delta.getDeltaType() == IIndexDelta.MERGE_DELTA){ + fileIndexed = true; + } + } + + protected String getMessage(IStatus status) { + StringBuffer message = new StringBuffer("["); //$NON-NLS-1$ + message.append(status.getMessage()); + if (status.isMultiStatus()) { + IStatus children[] = status.getChildren(); + for (int i = 0; i < children.length; i++) { + message.append(getMessage(children[i])); + } + } + message.append("]"); //$NON-NLS-1$ + return message.toString(); + } + + protected IFile importFile(String fileName, String contents ) throws Exception{ + resetIndexState(); + + //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); + + waitForIndex(20); // only wait 20 seconds max. + + return file; + } + + protected IFolder importFolder(String folderName) throws Exception { + IFolder folder = project.getProject().getFolder(folderName); + + //Create file input stream + if( !folder.exists() ) + folder.create( false, false, monitor ); + + return folder; + } + + public void resetIndexState() { + fileIndexed = false; + } + + protected IASTNode testF3(IFile file, int offset) throws ParserException { + return testF3(file, offset, 0); + } + + protected IASTNode testF3(IFile file, int offset, int length) throws ParserException { + if (offset < 0) + throw new ParserException("offset can not be less than 0 and was " + offset); //$NON-NLS-1$ + + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + IEditorPart part = null; + try { + part = page.openEditor(new FileEditorInput(file), "org.eclipse.cdt.ui.editor.CEditor"); //$NON-NLS-1$ + } catch (PartInitException e) { + assertFalse(true); + } + + if (part instanceof AbstractTextEditor) { + ((AbstractTextEditor)part).getSelectionProvider().setSelection(new TextSelection(offset,length)); + + final IAction action = ((AbstractTextEditor)part).getAction("OpenDeclarations"); //$NON-NLS-1$ + action.run(); + + // update the file/part to point to the newly opened IFile/IEditorPart + part = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + IEditorInput input = part.getEditorInput(); + if (input instanceof FileEditorInput) { + file = ((FileEditorInput)input).getFile(); + } else { + assertFalse(true); // bail! + } + + // 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 == null || names.length == 0) + return null; + + return names[0]; + } + } + + return null; + } + + protected ISelection testF3Selection(IFile file, int offset) throws ParserException { + return testF3Selection(file, offset, 0); + } + + protected ISelection testF3Selection(IFile file, int offset, int length) throws ParserException { + if (offset < 0) + throw new ParserException("offset can not be less than 0 and was " + offset); //$NON-NLS-1$ + + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + IEditorPart part = null; + try { + part = page.openEditor(new FileEditorInput(file), "org.eclipse.cdt.ui.editor.CEditor"); //$NON-NLS-1$ + } catch (PartInitException e) { + assertFalse(true); + } + + if (part instanceof AbstractTextEditor) { + ((AbstractTextEditor)part).getSelectionProvider().setSelection(new TextSelection(offset,length)); + + final IAction action = ((AbstractTextEditor)part).getAction("OpenDeclarations"); //$NON-NLS-1$ + action.run(); + + // update the file/part to point to the newly opened IFile/IEditorPart + part = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + IEditorInput input = part.getEditorInput(); + if (input instanceof FileEditorInput) { + file = ((FileEditorInput)input).getFile(); + } else { + assertFalse(true); // bail! + } + + // the action above should highlight the declaration, so now retrieve it and use that selection to get the IASTName selected on the TU + return ((AbstractTextEditor)part).getSelectionProvider().getSelection(); + } + + return null; + } + + protected IASTNode testF2(IFile file, int offset) throws ParserException { + return testF2(file, offset, 0); + } + + protected IASTNode testF2(IFile file, int offset, int length) throws ParserException { + if (offset < 0) + throw new ParserException("offset can not be less than 0 and was " + offset); //$NON-NLS-1$ + + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + IEditorPart part = null; + try { + part = page.openEditor(new FileEditorInput(file), "org.eclipse.cdt.ui.editor.CEditor"); //$NON-NLS-1$ + } catch (PartInitException e) { + assertFalse(true); + } + + if (part instanceof AbstractTextEditor) { + ((AbstractTextEditor)part).getSelectionProvider().setSelection(new TextSelection(offset,length)); + + final IAction action = ((AbstractTextEditor)part).getAction("OpenDefinition"); //$NON-NLS-1$ + action.run(); + + // update the file/part to point to the newly opened IFile/IEditorPart + part = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + IEditorInput input = part.getEditorInput(); + if (input instanceof FileEditorInput) { + file = ((FileEditorInput)input).getFile(); + } else { + assertFalse(true); // bail! + } + + // 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 == null || names.length == 0) + return null; + + return names[0]; + } + } + + return null; + } + + protected ISelection testF2Selection(IFile file, int offset) throws ParserException { + return testF2Selection(file, offset, 0); + } + + protected ISelection testF2Selection(IFile file, int offset, int length) throws ParserException { + if (offset < 0) + throw new ParserException("offset can not be less than 0 and was " + offset); //$NON-NLS-1$ + + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + IEditorPart part = null; + try { + part = page.openEditor(new FileEditorInput(file), "org.eclipse.cdt.ui.editor.CEditor"); //$NON-NLS-1$ + } catch (PartInitException e) { + assertFalse(true); + } + + if (part instanceof AbstractTextEditor) { + ((AbstractTextEditor)part).getSelectionProvider().setSelection(new TextSelection(offset,length)); + + final IAction action = ((AbstractTextEditor)part).getAction("OpenDefinition"); //$NON-NLS-1$ + action.run(); + + // update the file/part to point to the newly opened IFile/IEditorPart + part = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + IEditorInput input = part.getEditorInput(); + if (input instanceof FileEditorInput) { + file = ((FileEditorInput)input).getFile(); + } else { + assertFalse(true); // bail! + } + + // the action above should highlight the declaration, so now retrieve it and use that selection to get the IASTName selected on the TU + return ((AbstractTextEditor)part).getSelectionProvider().getSelection(); + } + + return null; + } + + public void resetIndexer(final String indexerId){ + if ( project != null) { + ICDescriptorOperation op = new ICDescriptorOperation() { + + public void execute(ICDescriptor descriptor, IProgressMonitor monitor) throws CoreException { + descriptor.remove(CCorePlugin.INDEXER_UNIQ_ID); + descriptor.create(CCorePlugin.INDEXER_UNIQ_ID,indexerId); + } + }; + try { + CCorePlugin.getDefault().getCDescriptorManager().runDescriptorOperation(project, op, new NullProgressMonitor()); + CCorePlugin.getDefault().getCoreModel().getIndexManager().indexerChangeNotification(project); + } catch (CoreException e) {} + } + } +} diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selectiontests/CPPSelectionTestsCTagsIndexer.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selectiontests/CPPSelectionTestsCTagsIndexer.java new file mode 100644 index 00000000000..8e5d3fceb7a --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selectiontests/CPPSelectionTestsCTagsIndexer.java @@ -0,0 +1,631 @@ +/********************************************************************** + * Copyright (c) 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.ui.tests.text.selectiontests; + +import java.io.File; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.index.IIndexChangeListener; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.testplugin.CProjectHelper; +import org.eclipse.cdt.internal.core.dom.parser.ASTNode; +import org.eclipse.cdt.internal.core.index.ctagsindexer.CTagsIndexer; +import org.eclipse.cdt.internal.core.index.sourceindexer.SourceIndexer; +import org.eclipse.cdt.internal.core.search.indexing.IndexManager; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.NullProgressMonitor; + +/** + * Test F2/F3 with the CTags Indexer for a CPP project. + * + * @author dsteffle + */ +public class CPPSelectionTestsCTagsIndexer extends BaseSelectionTestsIndexer + implements IIndexChangeListener { + + private static final String INDEX_TAG = "3931153591.index"; //$NON-NLS-1$ + IFile file; + NullProgressMonitor monitor; + IndexManager indexManager; + CTagsIndexer sourceIndexer; + + static final String sourceIndexerID = "org.eclipse.cdt.core.ctagsindexer"; //$NON-NLS-1$ + + public CPPSelectionTestsCTagsIndexer(String name) { + super(name); + } + + protected void setUp() throws Exception { + super.setUp(); + + //Create temp project + project = createProject("CPPSelectionTestsCTagsIndexerProject"); //$NON-NLS-1$ + IPath pathLoc = CCorePlugin.getDefault().getStateLocation(); + + File indexFile = new File(pathLoc.append(INDEX_TAG).toOSString()); + if (indexFile.exists()) + indexFile.delete(); + + //Set the id of the source indexer extension point as a session property to allow + //index manager to instantiate it + project.setSessionProperty(IndexManager.indexerIDKey, sourceIndexerID); + + //Enable indexing on test project + project.setSessionProperty(SourceIndexer.activationKey,new Boolean(true)); + + if (project==null) + fail("Unable to create project"); //$NON-NLS-1$ + + indexManager = CCorePlugin.getDefault().getCoreModel().getIndexManager(); + + resetIndexer(sourceIndexerID); // set indexer + + //indexManager.reset(); + //Get the indexer used for the test project + sourceIndexer = (CTagsIndexer) indexManager.getIndexerForProject(project); + sourceIndexer.addIndexChangeListener(this); + } + + protected void tearDown() { + try { + super.tearDown(); + sourceIndexer.removeIndexChangeListener(this); + } catch (Exception e1) { + } + //Delete project + if (project.exists()) { + try { + System.gc(); + System.runFinalization(); + project.delete(true, monitor); + } catch (CoreException e) { + fail(getMessage(e.getStatus())); + } + } + } + + public static Test suite() { + TestSuite suite = new TestSuite(CPPSelectionTestsCTagsIndexer.class.getName()); + + suite.addTest(new CPPSelectionTestsCTagsIndexer("testSimpleOpenDeclaration")); //$NON-NLS-1$ + suite.addTest(new CPPSelectionTestsCTagsIndexer("testSimpleOpenDeclaration2")); //$NON-NLS-1$ + suite.addTest(new CPPSelectionTestsCTagsIndexer("testBasicDefinition")); //$NON-NLS-1$ + suite.addTest(new CPPSelectionTestsCTagsIndexer("testCPPSpecDeclsDefs")); //$NON-NLS-1$ + suite.addTest(new CPPSelectionTestsCTagsIndexer("testNoDefinitions")); //$NON-NLS-1$ + suite.addTest(new CPPSelectionTestsCTagsIndexer("testOpenFileDiffDir")); //$NON-NLS-1$ + + return suite; + } + + private IProject createProject(String projectName) throws CoreException { + ICProject cPrj = CProjectHelper.createCCProject(projectName, "bin"); //$NON-NLS-1$ + return cPrj.getProject(); + } + + public void testSimpleOpenDeclaration() throws Exception { + String header = "char c; /* comment */ \n // comment \nint x;\n"; //$NON-NLS-1$ + importFile("test.h", header); //$NON-NLS-1$ + String code = "#include \"test.h\"\nint foo() { \n return x;\n}\n"; //$NON-NLS-1$ + IFile file = importFile("test.cpp", code); //$NON-NLS-1$ + + int offset = code.indexOf("x;\n}\n"); //$NON-NLS-1$ + IASTNode def = testF2(file, offset); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + assertTrue(def instanceof IASTName); + assertEquals(((ASTNode)def).getOffset(), header.indexOf("x;\n")); + assertEquals(((ASTNode)def).getLength(), "x".length()); + IASTNode decl = testF3(file, offset); + if (decl instanceof IASTName); + assertEquals(((ASTNode)decl).getOffset(), header.indexOf("x;\n")); + assertEquals(((ASTNode)decl).getLength(), "x".length()); + } + + public void testSimpleOpenDeclaration2() throws Exception { + String header = "int x;\r\n // comment \r\nint y;\r\n /* comment */ \r\n int z;\r\n"; //$NON-NLS-1$ + importFile("test.h", header); //$NON-NLS-1$ + String code = "#include \"test.h\"\r\nint foo() { \r\n return y;\r\n}\r\n"; //$NON-NLS-1$ + IFile file = importFile("test.cpp", code); //$NON-NLS-1$ + + int offset = code.indexOf("y;"); //$NON-NLS-1$ + IASTNode def = testF2(file, offset); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + assertTrue(def instanceof IASTName); + assertEquals(((ASTNode)def).getOffset(), header.indexOf("y;")); + assertEquals(((ASTNode)def).getLength(), "y".length()); + IASTNode decl = testF3(file, offset); + assertTrue(decl instanceof IASTName); + assertEquals(((ASTNode)decl).getOffset(), header.indexOf("y;")); + assertEquals(((ASTNode)decl).getLength(), "y".length()); + } + + // perform the tests from CSelectionTestsNoIndexer and make sure they work with an indexer as well: + public void testBasicDefinition() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("extern int MyInt; // MyInt is in another file\n"); //$NON-NLS-1$ + buffer.append("extern const int MyConst; // MyConst is in another file\n"); //$NON-NLS-1$ + buffer.append("void MyFunc(int); // often used in header files\n"); //$NON-NLS-1$ + buffer.append("struct MyStruct; // often used in header files\n"); //$NON-NLS-1$ + buffer.append("typedef int NewInt; // a normal typedef statement\n"); //$NON-NLS-1$ + buffer.append("int MyInt;\n"); //$NON-NLS-1$ + buffer.append("extern const int MyConst = 42;\n"); //$NON-NLS-1$ + buffer.append("void MyFunc(int a) { cout << a << endl; }\n"); //$NON-NLS-1$ + buffer.append("struct MyStruct { int Member1; int Member2; };\n"); //$NON-NLS-1$ + + String code = buffer.toString(); + IFile file = importFile("testBasicDefinition.c", code); //$NON-NLS-1$ + + int offset = code.indexOf("MyInt;\n") + 2; //$NON-NLS-1$ + IASTNode def = testF2(file, offset); + IASTNode decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "MyInt"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 11); + assertEquals(((ASTNode)decl).getLength(), 5); + assertEquals(((IASTName)def).toString(), "MyInt"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 276); + assertEquals(((ASTNode)def).getLength(), 5); + + offset = code.indexOf("MyConst = 42") + 2; //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "MyConst"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 69); + assertEquals(((ASTNode)decl).getLength(), 7); + assertEquals(((IASTName)def).toString(), "MyConst"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 300); + assertEquals(((ASTNode)def).getLength(), 7); + + offset = code.indexOf("MyFunc(int a)") + 2; //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "MyFunc"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 115); + assertEquals(((ASTNode)decl).getLength(), 6); + assertEquals(((IASTName)def).toString(), "MyFunc"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 319); + assertEquals(((ASTNode)def).getLength(), 6); + + offset = code.indexOf("MyStruct {") + 2; //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "MyStruct"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 171); + assertEquals(((ASTNode)decl).getLength(), 8); + assertEquals(((IASTName)def).toString(), "MyStruct"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 363); + assertEquals(((ASTNode)def).getLength(), 8); + } + + // taken from C++ spec 3.1-3: + /* + // all but one of the following are definitions: + int a; // defines a + extern const int c = 1; // defines c + int f(int x) { return x+a; } // defines f and defines x + struct S { int a; int b; }; // defines S, S::a, and S::b + struct X { // defines X + int x; // defines nonstatic data member x + }; + enum { up, down }; // defines up and down + struct X anX; // defines anX + // whereas these are just declarations: + extern int a; // declares a + extern const int c; // declares c + int f(int); // declares f + struct S; // declares S + typedef int Int; // declares Int + extern struct X anotherX; // declares anotherX + */ + public void testCPPSpecDeclsDefs() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("int a; // defines a\n"); //$NON-NLS-1$ + buffer.append("extern const int c = 1; // defines c\n"); //$NON-NLS-1$ + buffer.append("int f(int x) { return x+a; } // defines f and defines x\n"); //$NON-NLS-1$ + buffer.append("struct S { int a; int b; }; // defines S, S::a, and S::b\n"); //$NON-NLS-1$ + buffer.append("struct X { // defines X\n"); //$NON-NLS-1$ + buffer.append("int x; // defines nonstatic data member x\n"); //$NON-NLS-1$ + buffer.append("};\n"); //$NON-NLS-1$ + buffer.append("enum { up, down }; // defines up and down\n"); //$NON-NLS-1$ + buffer.append("struct X anX; // defines anX\n"); //$NON-NLS-1$ + buffer.append("extern int a; // declares a\n"); //$NON-NLS-1$ + buffer.append("extern const int c; // declares c\n"); //$NON-NLS-1$ + buffer.append("int f(int); // declares f\n"); //$NON-NLS-1$ + buffer.append("struct S; // declares S\n"); //$NON-NLS-1$ + buffer.append("typedef int Int; // declares Int\n"); //$NON-NLS-1$ + buffer.append("extern struct X anotherX; // declares anotherX\n"); //$NON-NLS-1$ + + String code = buffer.toString(); + IFile file = importFile("testCPPSpecDeclsDefs.c", code); //$NON-NLS-1$ + + int offset = code.indexOf("a; // defines a"); //$NON-NLS-1$ + IASTNode def = testF2(file, offset); + IASTNode decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 4); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 4); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("c = 1; // defines c"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "c"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 37); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "c"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 37); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("f(int x) { return x+a; } // defines f and defines x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "f"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 61); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "f"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 61); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("x) { return x+a; } // defines f and defines x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 67); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 67); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("x+a; } // defines f and defines x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 67); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 67); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("x+a; } // defines f and defines x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 67); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 67); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("a; } // defines f and defines x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 4); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 4); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("S { int a; int b; }; // defines S, S::a, and S::b"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "S"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 120); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "S"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 120); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("a; int b; }; // defines S, S::a, and S::b"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 128); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 128); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("b; }; // defines S, S::a, and S::b"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "b"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 135); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "b"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 135); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("X { // defines X"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 177); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 177); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("x; // defines nonstatic data member x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 198); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 198); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("up, down }; // defines up and down"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "up"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 246); + assertEquals(((ASTNode)decl).getLength(), 2); + assertEquals(((IASTName)def).toString(), "up"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 246); + assertEquals(((ASTNode)def).getLength(), 2); + + offset = code.indexOf("down }; // defines up and down"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "down"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 250); + assertEquals(((ASTNode)decl).getLength(), 4); + assertEquals(((IASTName)def).toString(), "down"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 250); + assertEquals(((ASTNode)def).getLength(), 4); + + offset = code.indexOf("X anX; // defines anX"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 177); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 177); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("anX; // defines anX"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "anX"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 290); + assertEquals(((ASTNode)decl).getLength(), 3); + assertEquals(((IASTName)def).toString(), "anX"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 290); + assertEquals(((ASTNode)def).getLength(), 3); + + offset = code.indexOf("a; // declares a"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 4); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 4); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("c; // declares c"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "c"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 37); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "c"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 37); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("f(int); // declares f"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "f"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 61); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "f"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 61); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("S; // declares S"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "S"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 120); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "S"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 120); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("Int; // declares Int"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "Int"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 434); + assertEquals(((ASTNode)decl).getLength(), 3); + assertEquals(((IASTName)def).toString(), "Int"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 434); + assertEquals(((ASTNode)def).getLength(), 3); + + offset = code.indexOf("X anotherX; // declares anotherX"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 177); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 177); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("anotherX; // declares anotherX"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + try { + assertNull(def); // TODO raised bug 96689 + assertTrue(false); // try/catch/assertTrue(false) added to alert the tester when this test passes! + } catch (AssertionFailedError e) {} + + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "anotherX"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 471); + assertEquals(((ASTNode)decl).getLength(), 8); + } + + public void testNoDefinitions() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("extern int a1; // declares a\n"); //$NON-NLS-1$ + buffer.append("extern const int c1; // declares c\n"); //$NON-NLS-1$ + buffer.append("int f1(int); // declares f\n"); //$NON-NLS-1$ + buffer.append("struct S1; // declares S\n"); //$NON-NLS-1$ + buffer.append("typedef int Int; // declares Int\n"); //$NON-NLS-1$ + + String code = buffer.toString(); + IFile file = importFile("testNoDefinitions.c", code); //$NON-NLS-1$ + + int offset = code.indexOf("a1; // declares a"); //$NON-NLS-1$ + IASTNode def = testF2(file, offset); + IASTNode decl = testF3(file, offset); + try { + assertNull(def); // TODO raised bug 96689 + assertTrue(false); // try/catch/assertTrue(false) added to alert the tester when this test passes! + } catch (AssertionFailedError e) {} + + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "a1"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 11); + assertEquals(((ASTNode)decl).getLength(), 2); + + offset = code.indexOf("c1; // declares c"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + try { + assertNull(def); // TODO raised bug 96689 + assertTrue(false); // try/catch/assertTrue(false) added to alert the tester when this test passes! + } catch (AssertionFailedError e) {} + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "c1"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 46); + assertEquals(((ASTNode)decl).getLength(), 2); + + offset = code.indexOf("f1(int); // declares f"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertNull(def); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "f1"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 68); + assertEquals(((ASTNode)decl).getLength(), 2); + + offset = code.indexOf("S1; // declares S"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + try { + assertNull(def); // TODO raised bug 96690 + assertTrue(false); // try/catch/assertTrue(false) added to alert the tester when this test passes! + } catch (AssertionFailedError e) {} + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "S1"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 98); + assertEquals(((ASTNode)decl).getLength(), 2); + + offset = code.indexOf("Int; // declares Int"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "Int"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 128); + assertEquals(((ASTNode)decl).getLength(), 3); + assertEquals(((IASTName)def).toString(), "Int"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 128); + assertEquals(((ASTNode)def).getLength(), 3); + } + + public void testOpenFileDiffDir() throws Exception { + importFolder("test"); //$NON-NLS-1$ + String header = "int x;\r\n // comment \r\n int y; /* comment */ \r\n int z; \r\n"; //$NON-NLS-1$ + importFile("test/test.h", header); //$NON-NLS-1$ + String code = "#include \"test\\test.h\"\r\nint foo() { \r\n return y;\r\n}\n"; //$NON-NLS-1$ + IFile file = importFile("test.cpp", code); + + int offset = code.indexOf("y;"); //$NON-NLS-1$ + IASTNode def = testF2(file, offset); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + assertTrue(def instanceof IASTName); + assertEquals(((ASTNode)def).getOffset(), header.indexOf("y;")); + assertEquals(((ASTNode)def).getLength(), "y".length()); + IASTNode decl = testF3(file, offset); + if (decl instanceof IASTName); + assertEquals(((ASTNode)decl).getOffset(), header.indexOf("y;")); + assertEquals(((ASTNode)decl).getLength(), "y".length()); + + } + + // REMINDER: see CSelectionTestsCTagsIndexer#suite() when appending new tests to this suite + +} diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selectiontests/CPPSelectionTestsDOMIndexer.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selectiontests/CPPSelectionTestsDOMIndexer.java new file mode 100644 index 00000000000..ab217903bb9 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selectiontests/CPPSelectionTestsDOMIndexer.java @@ -0,0 +1,987 @@ +/********************************************************************** + * Copyright (c) 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.ui.tests.text.selectiontests; + +import java.io.File; +import java.io.StringWriter; +import java.io.Writer; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.index.IIndexChangeListener; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.testplugin.CProjectHelper; +import org.eclipse.cdt.internal.core.dom.parser.ASTNode; +import org.eclipse.cdt.internal.core.index.sourceindexer.SourceIndexer; +import org.eclipse.cdt.internal.core.search.indexing.IndexManager; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.NullProgressMonitor; + +/** + * Test F2/F3 with the DOM Indexer for a C++ project. + * + * @author dsteffle + */ +public class CPPSelectionTestsDOMIndexer extends BaseSelectionTestsIndexer implements IIndexChangeListener { + private static final String INDEX_TAG = "1196338025.index"; //$NON-NLS-1$ + IFile file; + NullProgressMonitor monitor; + IndexManager indexManager; + SourceIndexer sourceIndexer; + + static final String sourceIndexerID = "org.eclipse.cdt.core.domsourceindexer"; //$NON-NLS-1$ + + public CPPSelectionTestsDOMIndexer(String name) { + super(name); + } + + protected void setUp() throws Exception { + super.setUp(); + + //Create temp project + project = createProject("CPPSelectionTestsDOMIndexerProject"); //$NON-NLS-1$ + IPath pathLoc = CCorePlugin.getDefault().getStateLocation(); + + File indexFile = new File(pathLoc.append(INDEX_TAG).toOSString()); + if (indexFile.exists()) + indexFile.delete(); + + //Set the id of the source indexer extension point as a session property to allow + //index manager to instantiate it + project.setSessionProperty(IndexManager.indexerIDKey, sourceIndexerID); + + //Enable indexing on test project + project.setSessionProperty(SourceIndexer.activationKey,new Boolean(true)); + + if (project==null) + fail("Unable to create project"); //$NON-NLS-1$ + + indexManager = CCorePlugin.getDefault().getCoreModel().getIndexManager(); + + resetIndexer(sourceIndexerID); // set indexer + + //indexManager.reset(); + //Get the indexer used for the test project + sourceIndexer = (SourceIndexer) indexManager.getIndexerForProject(project); + sourceIndexer.addIndexChangeListener(this); + } + + protected void tearDown() { + try { + super.tearDown(); + sourceIndexer.removeIndexChangeListener(this); + } catch (Exception e1) { + } + //Delete project + if (project.exists()) { + try { + System.gc(); + System.runFinalization(); + project.delete(true, monitor); + } catch (CoreException e) { + fail(getMessage(e.getStatus())); + } + } + } + + public static Test suite() { + TestSuite suite = new TestSuite(CPPSelectionTestsDOMIndexer.class.getName()); + + suite.addTest(new CPPSelectionTestsDOMIndexer("testBug93281")); //$NON-NLS-1$ + suite.addTest(new CPPSelectionTestsDOMIndexer("testBasicDefinition")); //$NON-NLS-1$ + suite.addTest(new CPPSelectionTestsDOMIndexer("testBug95224")); //$NON-NLS-1$ + suite.addTest(new CPPSelectionTestsDOMIndexer("testBasicTemplateInstance")); //$NON-NLS-1$ + suite.addTest(new CPPSelectionTestsDOMIndexer("testBug86829A")); //$NON-NLS-1$ + suite.addTest(new CPPSelectionTestsDOMIndexer("testBug86829B")); //$NON-NLS-1$ + suite.addTest(new CPPSelectionTestsDOMIndexer("testCPPSpecDeclsDefs")); //$NON-NLS-1$ + suite.addTest(new CPPSelectionTestsDOMIndexer("testBug95225")); //$NON-NLS-1$ + suite.addTest(new CPPSelectionTestsDOMIndexer("testNoDefinitions")); //$NON-NLS-1$ + suite.addTest(new CPPSelectionTestsDOMIndexer("testBug95202")); //$NON-NLS-1$ + suite.addTest(new CPPSelectionTestsDOMIndexer("testBug95229")); //$NON-NLS-1$ + + return suite; + } + + private IProject createProject(String projectName) throws CoreException { + ICProject cPrj = CProjectHelper.createCCProject(projectName, "bin"); //$NON-NLS-1$ + return cPrj.getProject(); + } + + 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); + + } + + public void testBasicDefinition() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("extern int MyInt; // MyInt is in another file\n"); //$NON-NLS-1$ + buffer.append("extern const int MyConst; // MyConst is in another file\n"); //$NON-NLS-1$ + buffer.append("void MyFunc(int); // often used in header files\n"); //$NON-NLS-1$ + buffer.append("struct MyStruct; // often used in header files\n"); //$NON-NLS-1$ + buffer.append("typedef int NewInt; // a normal typedef statement\n"); //$NON-NLS-1$ + buffer.append("class MyClass; // often used in header files\n"); //$NON-NLS-1$ + buffer.append("int MyInt;\n"); //$NON-NLS-1$ + buffer.append("extern const int MyConst = 42;\n"); //$NON-NLS-1$ + buffer.append("void MyFunc(int a) { cout << a << endl; }\n"); //$NON-NLS-1$ + buffer.append("struct MyStruct { int Member1; int Member2; };\n"); //$NON-NLS-1$ + buffer.append("class MyClass { int MemberVar; };\n"); //$NON-NLS-1$ + + String code = buffer.toString(); + IFile file = importFile("testBasicDefinition.cpp", code); //$NON-NLS-1$ + + int offset = code.indexOf("MyInt;\n") + 2; //$NON-NLS-1$ + IASTNode def = testF2(file, offset); + IASTNode decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "MyInt"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 11); + assertEquals(((ASTNode)decl).getLength(), 5); + assertEquals(((IASTName)def).toString(), "MyInt"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 330); + assertEquals(((ASTNode)def).getLength(), 5); + + offset = code.indexOf("MyConst = 42") + 2; //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "MyConst"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 69); + assertEquals(((ASTNode)decl).getLength(), 7); + assertEquals(((IASTName)def).toString(), "MyConst"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 354); + assertEquals(((ASTNode)def).getLength(), 7); + + offset = code.indexOf("MyFunc(int a)") + 2; //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "MyFunc"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 115); + assertEquals(((ASTNode)decl).getLength(), 6); + assertEquals(((IASTName)def).toString(), "MyFunc"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 373); + assertEquals(((ASTNode)def).getLength(), 6); + + offset = code.indexOf("MyStruct {") + 2; //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "MyStruct"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 171); + assertEquals(((ASTNode)decl).getLength(), 8); + assertEquals(((IASTName)def).toString(), "MyStruct"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 417); + assertEquals(((ASTNode)def).getLength(), 8); + + offset = code.indexOf("MyClass {") + 2; //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "MyClass"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 278); + assertEquals(((ASTNode)decl).getLength(), 7); + assertEquals(((IASTName)def).toString(), "MyClass"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 463); + assertEquals(((ASTNode)def).getLength(), 7); + } + + public void testBug95224() throws Exception{ + Writer writer = new StringWriter(); + writer.write( "class A{\n"); //$NON-NLS-1$ + writer.write( "A();\n"); //$NON-NLS-1$ + writer.write( "A(const A&); // open definition on A finds class A\n"); //$NON-NLS-1$ + writer.write( "~A(); // open definition on A finds nothing\n"); //$NON-NLS-1$ + writer.write( "};\n"); //$NON-NLS-1$ + + String code = writer.toString(); + IFile file = importFile("testBug95224.cpp", code); //$NON-NLS-1$ + + int offset = code.indexOf("A(); // open definition "); //$NON-NLS-1$ + IASTNode def = testF2(file, offset); + IASTNode decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "~A"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 65); + assertEquals(((ASTNode)decl).getLength(), 2); + assertEquals(((IASTName)def).toString(), "A"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 6); + assertEquals(((ASTNode)def).getLength(), 1); + } + + public void testBasicTemplateInstance() throws Exception{ + Writer writer = new StringWriter(); + writer.write( "namespace N{ \n"); //$NON-NLS-1$ + writer.write( " template < class T > class AAA { T _t; };\n"); //$NON-NLS-1$ + writer.write( "}; \n"); //$NON-NLS-1$ + writer.write( "N::AAA a; \n"); //$NON-NLS-1$ + + String code = writer.toString(); + IFile file = importFile("testBasicTemplateInstance.cpp", code); //$NON-NLS-1$ + + int offset = code.indexOf("AAA"); //$NON-NLS-1$ + IASTNode def1 = testF2(file, offset, 3); + IASTNode decl1 = testF3(file, offset, 3); + assertTrue(def1 instanceof IASTName); + assertTrue(decl1 instanceof IASTName); + assertEquals(((IASTName)decl1).toString(), "AAA"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl1).getOffset(), 74); + assertEquals(((ASTNode)decl1).getLength(), 3); + assertEquals(((IASTName)def1).toString(), "AAA"); //$NON-NLS-1$ + assertEquals(((ASTNode)def1).getOffset(), 74); + assertEquals(((ASTNode)def1).getLength(), 3); + + IASTNode def2 = testF2(file, offset, 8); + IASTNode decl2 = testF3(file, offset, 8); + assertTrue(def2 instanceof IASTName); + assertTrue(decl2 instanceof IASTName); + assertEquals(((IASTName)decl2).toString(), "AAA"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl2).getOffset(), 74); + assertEquals(((ASTNode)decl2).getLength(), 3); + assertEquals(((IASTName)def2).toString(), "AAA"); //$NON-NLS-1$ + assertEquals(((ASTNode)def2).getOffset(), 74); + assertEquals(((ASTNode)def2).getLength(), 3); + } + + public void testBug86829A() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("class X {\n"); //$NON-NLS-1$ + buffer.append("public:\n"); //$NON-NLS-1$ + buffer.append("X(int); // openReferences fails to find the constructor in g()\n"); //$NON-NLS-1$ + buffer.append("};\n"); //$NON-NLS-1$ + buffer.append("X f(X);\n"); //$NON-NLS-1$ + buffer.append("void g()\n"); //$NON-NLS-1$ + buffer.append("{\n"); //$NON-NLS-1$ + buffer.append("X b = f(X(2)); // openDeclarations on X(int) finds the class and not \n"); //$NON-NLS-1$ + buffer.append("}\n"); //$NON-NLS-1$ + + String code = buffer.toString(); + IFile file = importFile("testBug86829A.cpp", code); //$NON-NLS-1$ + + int offset = code.indexOf("X(2)"); //$NON-NLS-1$ + IASTNode decl = testF3(file, offset); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 18); + assertEquals(((ASTNode)decl).getLength(), 1); + } + + public void testBug86829B() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("class X {\n"); //$NON-NLS-1$ + buffer.append("public:\n"); //$NON-NLS-1$ + buffer.append("operator int();\n"); //$NON-NLS-1$ + buffer.append("};\n"); //$NON-NLS-1$ + buffer.append("class Y {\n"); //$NON-NLS-1$ + buffer.append("public:\n"); //$NON-NLS-1$ + buffer.append("operator X();\n"); //$NON-NLS-1$ + buffer.append("};\n"); //$NON-NLS-1$ + buffer.append("Y a;\n"); //$NON-NLS-1$ + buffer.append("int c = X(a); // OK: a.operator X().operator int()\n"); //$NON-NLS-1$ + + String code = buffer.toString(); + IFile file = importFile("testBug86829B.cpp", code); //$NON-NLS-1$ + + int offset = code.indexOf("X(a);"); //$NON-NLS-1$ + IASTNode def = testF2(file, offset); + IASTNode decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 6); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 6); + assertEquals(((ASTNode)def).getLength(), 1); + } + + // taken from C++ spec 3.1-3: + /* + // all but one of the following are definitions: + int a; // defines a + extern const int c = 1; // defines c + int f(int x) { return x+a; } // defines f and defines x + struct S { int a; int b; }; // defines S, S::a, and S::b + struct X { // defines X + int x; // defines nonstatic data member x + static int y; // declares static data member y + X(): x(0) { } // defines a constructor of X + }; + int X::y = 1; // defines X::y + enum { up, down }; // defines up and down + namespace N { int d; } // defines N and N::d + namespace N1 = N; // defines N1 + X anX; // defines anX + // whereas these are just declarations: + extern int a; // declares a + extern const int c; // declares c + int f(int); // declares f + struct S; // declares S + typedef int Int; // declares Int + extern X anotherX; // declares anotherX + using N::d; // declares N::d + */ + public void testCPPSpecDeclsDefs() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("int a; // defines a\n"); //$NON-NLS-1$ + buffer.append("extern const int c = 1; // defines c\n"); //$NON-NLS-1$ + buffer.append("int f(int x) { return x+a; } // defines f and defines x\n"); //$NON-NLS-1$ + buffer.append("struct S { int a; int b; }; // defines S, S::a, and S::b\n"); //$NON-NLS-1$ + buffer.append("struct X { // defines X\n"); //$NON-NLS-1$ + buffer.append("int x; // defines nonstatic data member x\n"); //$NON-NLS-1$ + buffer.append("static int y; // declares static data member y\n"); //$NON-NLS-1$ + buffer.append("X(): x(0) { } // defines a constructor of X\n"); //$NON-NLS-1$ + buffer.append("};\n"); //$NON-NLS-1$ + buffer.append("int X::y = 1; // defines X::y\n"); //$NON-NLS-1$ + buffer.append("enum { up, down }; // defines up and down\n"); //$NON-NLS-1$ + buffer.append("namespace N { int d; } // defines N and N::d\n"); //$NON-NLS-1$ + buffer.append("namespace N1 = N; // defines N1\n"); //$NON-NLS-1$ + buffer.append("X anX; // defines anX\n"); //$NON-NLS-1$ + buffer.append("extern int a; // declares a\n"); //$NON-NLS-1$ + buffer.append("extern const int c; // declares c\n"); //$NON-NLS-1$ + buffer.append("int f(int); // declares f\n"); //$NON-NLS-1$ + buffer.append("struct S; // declares S\n"); //$NON-NLS-1$ + buffer.append("typedef int Int; // declares Int\n"); //$NON-NLS-1$ + buffer.append("extern X anotherX; // declares anotherX\n"); //$NON-NLS-1$ + buffer.append("using N::d; // declares N::d\n"); //$NON-NLS-1$ + + String code = buffer.toString(); + IFile file = importFile("testCPPSpecDeclsDefs.cpp", code); //$NON-NLS-1$ + + int offset = code.indexOf("a; // defines a"); //$NON-NLS-1$ + IASTNode def = testF2(file, offset); + IASTNode decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 4); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 4); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("c = 1; // defines c"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "c"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 37); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "c"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 37); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("f(int x) { return x+a; } // defines f and defines x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "f"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 61); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "f"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 61); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("x) { return x+a; } // defines f and defines x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 67); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 67); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("x+a; } // defines f and defines x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 67); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 67); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("x+a; } // defines f and defines x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 67); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 67); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("a; } // defines f and defines x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 4); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 4); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("S { int a; int b; }; // defines S, S::a, and S::b"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "S"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 120); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "S"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 120); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("a; int b; }; // defines S, S::a, and S::b"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 128); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 128); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("b; }; // defines S, S::a, and S::b"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "b"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 135); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "b"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 135); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("X { // defines X"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 177); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 177); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("x; // defines nonstatic data member x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 198); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 198); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("y; // declares static data member y"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "y"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 247); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "y"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 337); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("X(): x(0) { } // defines a constructor of X"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 283); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 283); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("x(0) { } // defines a constructor of X"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 198); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 198); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("X::y = 1; // defines X::y"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 177); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 177); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("y = 1; // defines X::y"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "y"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 247); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "y"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 337); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("up, down }; // defines up and down"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "up"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 367); + assertEquals(((ASTNode)decl).getLength(), 2); + assertEquals(((IASTName)def).toString(), "up"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 367); + assertEquals(((ASTNode)def).getLength(), 2); + + offset = code.indexOf("down }; // defines up and down"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "down"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 371); + assertEquals(((ASTNode)decl).getLength(), 4); + assertEquals(((IASTName)def).toString(), "down"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 371); + assertEquals(((ASTNode)def).getLength(), 4); + + offset = code.indexOf("N { int d; } // defines N and N::d"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "N"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 412); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "N"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 412); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("d; } // defines N and N::d"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "d"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 420); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "d"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 420); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("N1 = N; // defines N1"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "N1"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 457); + assertEquals(((ASTNode)decl).getLength(), 2); + assertEquals(((IASTName)def).toString(), "N1"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 457); + assertEquals(((ASTNode)def).getLength(), 2); + + offset = code.indexOf("N; // defines N1"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "N"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 412); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "N"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 412); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("X anX; // defines anX"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 177); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 177); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("anX; // defines anX"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "anX"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 481); + assertEquals(((ASTNode)decl).getLength(), 3); + assertEquals(((IASTName)def).toString(), "anX"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 481); + assertEquals(((ASTNode)def).getLength(), 3); + + offset = code.indexOf("a; // declares a"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 4); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 4); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("c; // declares c"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "c"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 37); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "c"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 37); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("f(int); // declares f"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "f"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 61); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "f"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 61); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("S; // declares S"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "S"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 120); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "S"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 120); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("Int; // declares Int"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + try { + assertNull(def); // TODO raised bug 96689 + assertTrue(false); // try/catch/assertTrue(false) added to alert the tester when this test passes! + } catch (AssertionFailedError e) {} + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "Int"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 625); + assertEquals(((ASTNode)decl).getLength(), 3); + + offset = code.indexOf("X anotherX; // declares anotherX"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 177); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 177); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("anotherX; // declares anotherX"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + try { + assertNull(def); // TODO raised bug 96689 + assertTrue(false); // try/catch/assertTrue(false) added to alert the tester when this test passes! + } catch (AssertionFailedError e) {} + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "anotherX"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 655); + assertEquals(((ASTNode)decl).getLength(), 8); + + offset = code.indexOf("N::d; // declares N::d"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "N"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 412); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "N"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 412); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("d; // declares N::d"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "d"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 420); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "d"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 420); + assertEquals(((ASTNode)def).getLength(), 1); + } + + public void testBug95225() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("class Overflow {\n"); //$NON-NLS-1$ + buffer.append("public:\n"); //$NON-NLS-1$ + buffer.append("Overflow(char,double,double);\n"); //$NON-NLS-1$ + buffer.append("};\n"); //$NON-NLS-1$ + buffer.append("void f(double x)\n"); //$NON-NLS-1$ + buffer.append("{\n"); //$NON-NLS-1$ + buffer.append("throw Overflow('+',x,3.45e107);\n"); //$NON-NLS-1$ + buffer.append("}\n"); //$NON-NLS-1$ + buffer.append("int foo() {\n"); //$NON-NLS-1$ + buffer.append("try {\n"); //$NON-NLS-1$ + buffer.append("f(1.2);\n"); //$NON-NLS-1$ + buffer.append("}\n"); //$NON-NLS-1$ + buffer.append("catch(Overflow& oo) {\n"); //$NON-NLS-1$ + buffer.append(" // handle exceptions of type Overflow here\n"); //$NON-NLS-1$ + buffer.append("}\n"); //$NON-NLS-1$ + buffer.append("}\n"); //$NON-NLS-1$ + + String code = buffer.toString(); + IFile file = importFile("testBug95225.cpp", code); //$NON-NLS-1$ + + int offset = code.indexOf("rflow('+',x,3.45e107);"); //$NON-NLS-1$ + IASTNode def = testF2(file, offset); + IASTNode decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "Overflow"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 25); + assertEquals(((ASTNode)decl).getLength(), 8); + assertEquals(((IASTName)def).toString(), "Overflow"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 6); + assertEquals(((ASTNode)def).getLength(), 8); + + offset = code.indexOf("x,3.45e107);"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 72); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 72); + assertEquals(((ASTNode)def).getLength(), 1); + } + + public void testNoDefinitions() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("extern int a1; // declares a\n"); //$NON-NLS-1$ + buffer.append("extern const int c1; // declares c\n"); //$NON-NLS-1$ + buffer.append("int f1(int); // declares f\n"); //$NON-NLS-1$ + buffer.append("struct S1; // declares S\n"); //$NON-NLS-1$ + buffer.append("typedef int Int; // declares Int\n"); //$NON-NLS-1$ + + String code = buffer.toString(); + IFile file = importFile("testNoDefinitions.cpp", code); //$NON-NLS-1$ + + int offset = code.indexOf("a1; // declares a"); //$NON-NLS-1$ + IASTNode def = testF2(file, offset); + IASTNode decl = testF3(file, offset); + try { + assertNull(def); // TODO raised bug 96689 + assertTrue(false); // try/catch/assertTrue(false) added to alert the tester when this test passes! + } catch (AssertionFailedError e) {} + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "a1"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 11); + assertEquals(((ASTNode)decl).getLength(), 2); + + offset = code.indexOf("c1; // declares c"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + try { + assertNull(def); // TODO raised bug 96694 + assertTrue(false); // try/catch/assertTrue(false) added to alert the tester when this test passes! + } catch (AssertionFailedError e) {} + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "c1"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 46); + assertEquals(((ASTNode)decl).getLength(), 2); + + offset = code.indexOf("f1(int); // declares f"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertNull(def); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "f1"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 68); + assertEquals(((ASTNode)decl).getLength(), 2); + + offset = code.indexOf("S1; // declares S"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertNull(def); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "S1"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 98); + assertEquals(((ASTNode)decl).getLength(), 2); + + offset = code.indexOf("Int; // declares Int"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + try { + assertNull(def); // TODO raised bug 96689 + assertTrue(false); // try/catch/assertTrue(false) added to alert the tester when this test passes! + } catch (AssertionFailedError e) {} + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "Int"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 128); + assertEquals(((ASTNode)decl).getLength(), 3); + } + + public void testBug95202() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("struct A { }; // implicitlydeclared A::operator=\n"); //$NON-NLS-1$ + buffer.append("struct B : A {\n"); //$NON-NLS-1$ + buffer.append("B& operator=(const B &);\n"); //$NON-NLS-1$ + buffer.append("};\n"); //$NON-NLS-1$ + buffer.append("B& B::operator=(const B& s) {\n"); //$NON-NLS-1$ + buffer.append("this->B::operator=(s); // wellformed\n"); //$NON-NLS-1$ + buffer.append("return *this;\n"); //$NON-NLS-1$ + buffer.append("}\n"); //$NON-NLS-1$ + + String code = buffer.toString(); + IFile file = importFile("testBug95202.cpp", code); //$NON-NLS-1$ + + int offset = code.indexOf("s); // wellformed"); //$NON-NLS-1$ + IASTNode def = testF2(file, offset); + IASTNode decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "s"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 117); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "s"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 117); + assertEquals(((ASTNode)def).getLength(), 1); + + } + + public void testBug95229() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("struct A {\n"); //$NON-NLS-1$ + buffer.append("operator short(); // F3 on operator causes an infinite loop\n"); //$NON-NLS-1$ + buffer.append("} a;\n"); //$NON-NLS-1$ + buffer.append("int f(int);\n"); //$NON-NLS-1$ + buffer.append("int f(float);\n"); //$NON-NLS-1$ + buffer.append("int i = f(a); // Calls f(int), because short -> int is\n"); //$NON-NLS-1$ + + String code = buffer.toString(); + IFile file = importFile("testBug95229.cpp", code); //$NON-NLS-1$ + + int offset = code.indexOf("rator short(); // F3"); //$NON-NLS-1$ + IASTNode def = testF2(file, offset); + IASTNode decl = testF3(file, offset); + assertNull(def); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "operator short"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 11); + assertEquals(((ASTNode)decl).getLength(), 14); + } + + // REMINDER: see CPPSelectionTestsDomIndexer#suite() when appending new tests to this suite +} diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selectiontests/CSelectionTestsCTagsIndexer.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selectiontests/CSelectionTestsCTagsIndexer.java new file mode 100644 index 00000000000..3d5e3e68552 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selectiontests/CSelectionTestsCTagsIndexer.java @@ -0,0 +1,650 @@ +/********************************************************************** + * Copyright (c) 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.ui.tests.text.selectiontests; + +import java.io.File; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.index.IIndexChangeListener; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.testplugin.CProjectHelper; +import org.eclipse.cdt.internal.core.dom.parser.ASTNode; +import org.eclipse.cdt.internal.core.index.ctagsindexer.CTagsIndexer; +import org.eclipse.cdt.internal.core.index.sourceindexer.SourceIndexer; +import org.eclipse.cdt.internal.core.search.indexing.IndexManager; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.viewers.ISelection; + +/** + * Test F2/F3 with the CTags Indexer for a C project. + * + * @author dsteffle + */ +public class CSelectionTestsCTagsIndexer extends BaseSelectionTestsIndexer + implements IIndexChangeListener { + + private static final String INDEX_TAG = "3931153591.index"; //$NON-NLS-1$ + IFile file; + NullProgressMonitor monitor; + IndexManager indexManager; + CTagsIndexer sourceIndexer; + + static final String sourceIndexerID = "org.eclipse.cdt.core.ctagsindexer"; //$NON-NLS-1$ + + public CSelectionTestsCTagsIndexer(String name) { + super(name); + } + + protected void setUp() throws Exception { + super.setUp(); + + //Create temp project + project = createProject("CSelectionTestsCTagsIndexerProject"); //$NON-NLS-1$ + IPath pathLoc = CCorePlugin.getDefault().getStateLocation(); + + File indexFile = new File(pathLoc.append(INDEX_TAG).toOSString()); + if (indexFile.exists()) + indexFile.delete(); + + //Set the id of the source indexer extension point as a session property to allow + //index manager to instantiate it + project.setSessionProperty(IndexManager.indexerIDKey, sourceIndexerID); + + //Enable indexing on test project + project.setSessionProperty(SourceIndexer.activationKey,new Boolean(true)); + + if (project==null) + fail("Unable to create project"); //$NON-NLS-1$ + + indexManager = CCorePlugin.getDefault().getCoreModel().getIndexManager(); + + resetIndexer(sourceIndexerID); // set indexer + + //indexManager.reset(); + //Get the indexer used for the test project + sourceIndexer = (CTagsIndexer) indexManager.getIndexerForProject(project); + sourceIndexer.addIndexChangeListener(this); + } + + protected void tearDown() { + try { + super.tearDown(); + sourceIndexer.removeIndexChangeListener(this); + } catch (Exception e1) { + } + //Delete project + if (project.exists()) { + try { + System.gc(); + System.runFinalization(); + project.delete(true, monitor); + } catch (CoreException e) { + fail(getMessage(e.getStatus())); + } + } + } + + public static Test suite() { + TestSuite suite = new TestSuite(CSelectionTestsCTagsIndexer.class.getName()); + + suite.addTest(new CSelectionTestsCTagsIndexer("testSimpleOpenDeclaration")); //$NON-NLS-1$ + suite.addTest(new CSelectionTestsCTagsIndexer("testSimpleOpenDeclaration2")); //$NON-NLS-1$ + suite.addTest(new CSelectionTestsCTagsIndexer("testBasicDefinition")); //$NON-NLS-1$ + suite.addTest(new CSelectionTestsCTagsIndexer("testCPPSpecDeclsDefs")); //$NON-NLS-1$ + suite.addTest(new CSelectionTestsCTagsIndexer("testNoDefinitions")); //$NON-NLS-1$ + suite.addTest(new CSelectionTestsCTagsIndexer("testOpenFileDiffDir")); //$NON-NLS-1$ + + return suite; + } + + private IProject createProject(String projectName) throws CoreException { + ICProject cPrj = CProjectHelper.createCCProject(projectName, "bin"); //$NON-NLS-1$ + return cPrj.getProject(); + } + + public void testSimpleOpenDeclaration() throws Exception { + String header = "char c; /* comment */ \n // comment \nint x() { return 1; }\n"; //$NON-NLS-1$ + importFile("test.h", header); //$NON-NLS-1$ + String code = "int foo() { \n return x();\n}\n"; //$NON-NLS-1$ + IFile file = importFile("test.c", code); //$NON-NLS-1$ + + int offset = code.indexOf("x();\n}\n"); //$NON-NLS-1$ + ISelection def = testF2Selection(file, offset); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + if (def instanceof TextSelection) { + assertEquals(((TextSelection)def).getOffset(), header.indexOf("int x() { return 1; }\n")); + assertEquals(((TextSelection)def).getLength(), "int x() { return 1; }\n".length()); + } + try { + // TODO raised bug 97079 + ISelection decl = testF3Selection(file, offset); + if (decl instanceof TextSelection) { + assertEquals(((TextSelection)decl).getOffset(), header.indexOf("int x() { return 1; }\n")); + assertEquals(((TextSelection)decl).getLength(), "int x() { return 1; }\n".length()); + } + assertFalse(true); // when this fails then the test is passing correctly + } catch (AssertionFailedError afe) {} + } + + public void testSimpleOpenDeclaration2() throws Exception { + String header = "int x;\r\n // comment \r\nint y() { return 1; }\r\n /* comment */ \r\n int z;\r\n"; //$NON-NLS-1$ + importFile("test.h", header); //$NON-NLS-1$ + String code = "int foo() { \n return y();\n}\n"; //$NON-NLS-1$ + IFile file = importFile("test.c", code); //$NON-NLS-1$ + + int offset = code.indexOf("y();\n}\n"); //$NON-NLS-1$ + ISelection def = testF2Selection(file, offset); + if (def instanceof TextSelection) { + assertEquals(((TextSelection)def).getOffset(), header.indexOf("int y() { return 1; }\r\n")); + assertEquals(((TextSelection)def).getLength(), "int y() { return 1; }\r\n".length()); + } + try { + // TODO raised bug 97079 + ISelection decl = testF3Selection(file, offset); + if (decl instanceof TextSelection) { + assertEquals(((TextSelection)decl).getOffset(), header.indexOf("int y() { return 1; }\r\n")); + assertEquals(((TextSelection)decl).getLength(), "int y() { return 1; }\r\n".length()); + } + assertFalse(true); // when this fails then the test is passing correctly + } catch (AssertionFailedError afe) {} + } + + // perform the tests from CSelectionTestsNoIndexer and make sure they work with an indexer as well: + public void testBasicDefinition() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("extern int MyInt; // MyInt is in another file\n"); //$NON-NLS-1$ + buffer.append("extern const int MyConst; // MyConst is in another file\n"); //$NON-NLS-1$ + buffer.append("void MyFunc(int); // often used in header files\n"); //$NON-NLS-1$ + buffer.append("struct MyStruct; // often used in header files\n"); //$NON-NLS-1$ + buffer.append("typedef int NewInt; // a normal typedef statement\n"); //$NON-NLS-1$ + buffer.append("int MyInt;\n"); //$NON-NLS-1$ + buffer.append("extern const int MyConst = 42;\n"); //$NON-NLS-1$ + buffer.append("void MyFunc(int a) { cout << a << endl; }\n"); //$NON-NLS-1$ + buffer.append("struct MyStruct { int Member1; int Member2; };\n"); //$NON-NLS-1$ + + String code = buffer.toString(); + IFile file = importFile("testBasicDefinition.c", code); //$NON-NLS-1$ + + int offset = code.indexOf("MyInt;\n") + 2; //$NON-NLS-1$ + IASTNode def = testF2(file, offset); + IASTNode decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "MyInt"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 11); + assertEquals(((ASTNode)decl).getLength(), 5); + assertEquals(((IASTName)def).toString(), "MyInt"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 276); + assertEquals(((ASTNode)def).getLength(), 5); + + offset = code.indexOf("MyConst = 42") + 2; //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "MyConst"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 69); + assertEquals(((ASTNode)decl).getLength(), 7); + assertEquals(((IASTName)def).toString(), "MyConst"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 300); + assertEquals(((ASTNode)def).getLength(), 7); + + offset = code.indexOf("MyFunc(int a)") + 2; //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "MyFunc"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 115); + assertEquals(((ASTNode)decl).getLength(), 6); + assertEquals(((IASTName)def).toString(), "MyFunc"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 319); + assertEquals(((ASTNode)def).getLength(), 6); + + offset = code.indexOf("MyStruct {") + 2; //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "MyStruct"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 171); + assertEquals(((ASTNode)decl).getLength(), 8); + assertEquals(((IASTName)def).toString(), "MyStruct"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 363); + assertEquals(((ASTNode)def).getLength(), 8); + } + + // taken from C++ spec 3.1-3: + /* + // all but one of the following are definitions: + int a; // defines a + extern const int c = 1; // defines c + int f(int x) { return x+a; } // defines f and defines x + struct S { int a; int b; }; // defines S, S::a, and S::b + struct X { // defines X + int x; // defines nonstatic data member x + }; + enum { up, down }; // defines up and down + struct X anX; // defines anX + // whereas these are just declarations: + extern int a; // declares a + extern const int c; // declares c + int f(int); // declares f + struct S; // declares S + typedef int Int; // declares Int + extern struct X anotherX; // declares anotherX + */ + public void testCPPSpecDeclsDefs() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("int a; // defines a\n"); //$NON-NLS-1$ + buffer.append("extern const int c = 1; // defines c\n"); //$NON-NLS-1$ + buffer.append("int f(int x) { return x+a; } // defines f and defines x\n"); //$NON-NLS-1$ + buffer.append("struct S { int a; int b; }; // defines S, S::a, and S::b\n"); //$NON-NLS-1$ + buffer.append("struct X { // defines X\n"); //$NON-NLS-1$ + buffer.append("int x; // defines nonstatic data member x\n"); //$NON-NLS-1$ + buffer.append("};\n"); //$NON-NLS-1$ + buffer.append("enum { up, down }; // defines up and down\n"); //$NON-NLS-1$ + buffer.append("struct X anX; // defines anX\n"); //$NON-NLS-1$ + buffer.append("extern int a; // declares a\n"); //$NON-NLS-1$ + buffer.append("extern const int c; // declares c\n"); //$NON-NLS-1$ + buffer.append("int f(int); // declares f\n"); //$NON-NLS-1$ + buffer.append("struct S; // declares S\n"); //$NON-NLS-1$ + buffer.append("typedef int Int; // declares Int\n"); //$NON-NLS-1$ + buffer.append("extern struct X anotherX; // declares anotherX\n"); //$NON-NLS-1$ + + String code = buffer.toString(); + IFile file = importFile("testCPPSpecDeclsDefs.c", code); //$NON-NLS-1$ + + int offset = code.indexOf("a; // defines a"); //$NON-NLS-1$ + IASTNode def = testF2(file, offset); + IASTNode decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 4); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 4); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("c = 1; // defines c"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "c"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 37); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "c"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 37); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("f(int x) { return x+a; } // defines f and defines x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "f"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 61); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "f"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 61); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("x) { return x+a; } // defines f and defines x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 67); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 67); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("x+a; } // defines f and defines x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 67); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 67); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("x+a; } // defines f and defines x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 67); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 67); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("a; } // defines f and defines x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 4); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 4); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("S { int a; int b; }; // defines S, S::a, and S::b"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "S"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 120); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "S"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 120); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("a; int b; }; // defines S, S::a, and S::b"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 128); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 128); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("b; }; // defines S, S::a, and S::b"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "b"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 135); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "b"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 135); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("X { // defines X"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 177); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 177); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("x; // defines nonstatic data member x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 198); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 198); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("up, down }; // defines up and down"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "up"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 246); + assertEquals(((ASTNode)decl).getLength(), 2); + assertEquals(((IASTName)def).toString(), "up"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 246); + assertEquals(((ASTNode)def).getLength(), 2); + + offset = code.indexOf("down }; // defines up and down"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "down"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 250); + assertEquals(((ASTNode)decl).getLength(), 4); + assertEquals(((IASTName)def).toString(), "down"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 250); + assertEquals(((ASTNode)def).getLength(), 4); + + offset = code.indexOf("X anX; // defines anX"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 177); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 177); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("anX; // defines anX"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "anX"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 290); + assertEquals(((ASTNode)decl).getLength(), 3); + assertEquals(((IASTName)def).toString(), "anX"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 290); + assertEquals(((ASTNode)def).getLength(), 3); + + offset = code.indexOf("a; // declares a"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 4); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 4); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("c; // declares c"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "c"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 37); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "c"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 37); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("f(int); // declares f"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "f"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 61); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "f"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 61); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("S; // declares S"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "S"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 120); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "S"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 120); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("Int; // declares Int"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "Int"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 434); + assertEquals(((ASTNode)decl).getLength(), 3); + assertEquals(((IASTName)def).toString(), "Int"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 434); + assertEquals(((ASTNode)def).getLength(), 3); + + offset = code.indexOf("X anotherX; // declares anotherX"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 177); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 177); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("anotherX; // declares anotherX"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + try { + assertNull(def); // TODO raised bug 96689 + assertTrue(false); // try/catch/assertTrue(false) added to alert the tester when this test passes! + } catch (AssertionFailedError e) {} + + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "anotherX"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 471); + assertEquals(((ASTNode)decl).getLength(), 8); + } + + public void testNoDefinitions() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("extern int a1; // declares a\n"); //$NON-NLS-1$ + buffer.append("extern const int c1; // declares c\n"); //$NON-NLS-1$ + buffer.append("int f1(int); // declares f\n"); //$NON-NLS-1$ + buffer.append("struct S1; // declares S\n"); //$NON-NLS-1$ + buffer.append("typedef int Int; // declares Int\n"); //$NON-NLS-1$ + + String code = buffer.toString(); + IFile file = importFile("testNoDefinitions.c", code); //$NON-NLS-1$ + + int offset = code.indexOf("a1; // declares a"); //$NON-NLS-1$ + IASTNode def = testF2(file, offset); + IASTNode decl = testF3(file, offset); + try { + assertNull(def); // TODO raised bug 96689 + assertTrue(false); // try/catch/assertTrue(false) added to alert the tester when this test passes! + } catch (AssertionFailedError e) {} + + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "a1"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 11); + assertEquals(((ASTNode)decl).getLength(), 2); + + offset = code.indexOf("c1; // declares c"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + try { + assertNull(def); // TODO raised bug 96689 + assertTrue(false); // try/catch/assertTrue(false) added to alert the tester when this test passes! + } catch (AssertionFailedError e) {} + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "c1"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 46); + assertEquals(((ASTNode)decl).getLength(), 2); + + offset = code.indexOf("f1(int); // declares f"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertNull(def); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "f1"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 68); + assertEquals(((ASTNode)decl).getLength(), 2); + + offset = code.indexOf("S1; // declares S"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + try { + assertNull(def); // TODO raised bug 96690 + assertTrue(false); // try/catch/assertTrue(false) added to alert the tester when this test passes! + } catch (AssertionFailedError e) {} + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "S1"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 98); + assertEquals(((ASTNode)decl).getLength(), 2); + + offset = code.indexOf("Int; // declares Int"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "Int"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 128); + assertEquals(((ASTNode)decl).getLength(), 3); + assertEquals(((IASTName)def).toString(), "Int"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 128); + assertEquals(((ASTNode)def).getLength(), 3); + } + + public void testOpenFileDiffDir() throws Exception { + importFolder("test"); //$NON-NLS-1$ + String header = "int x;\r\n // comment \r\n int y() { return 1; } /* comment */ \r\n int z; \r\n"; //$NON-NLS-1$ + importFile("test/test.h", header); //$NON-NLS-1$ + String code = "int foo() { \n return y();\n}\n"; //$NON-NLS-1$ + IFile file = importFile("test.c", code); + + int offset = code.indexOf("y();\n}\n"); //$NON-NLS-1$ + ISelection def = testF2Selection(file, offset); + if (def instanceof TextSelection) { + assertEquals(((TextSelection)def).getOffset(), header.indexOf(" int y() { return 1; } /* comment */ \r\n")); //$NON-NLS-1$ + assertEquals(((TextSelection)def).getLength(), " int y() { return 1; } /* comment */ \r\n".length()); //$NON-NLS-1$ + } + try { + // TODO raised bug 97079 + ISelection decl = testF3Selection(file, offset); + if (decl instanceof TextSelection) { + assertEquals(((TextSelection)decl).getOffset(), header.indexOf(" int y() { return 1; } /* comment */ \r\n")); + assertEquals(((TextSelection)decl).getLength(), " int y() { return 1; } /* comment */ \r\n".length()); + } + assertFalse(true); // when this fails then the test is passing correctly + } catch (AssertionFailedError afe) {} + } + + // REMINDER: see CSelectionTestsCTagsIndexer#suite() when appending new tests to this suite + +} diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selectiontests/CSelectionTestsDOMIndexer.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selectiontests/CSelectionTestsDOMIndexer.java new file mode 100644 index 00000000000..369a559d2f7 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selectiontests/CSelectionTestsDOMIndexer.java @@ -0,0 +1,641 @@ +/********************************************************************** + * Copyright (c) 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.ui.tests.text.selectiontests; + +import java.io.File; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.index.IIndexChangeListener; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.testplugin.CProjectHelper; +import org.eclipse.cdt.internal.core.dom.parser.ASTNode; +import org.eclipse.cdt.internal.core.index.sourceindexer.SourceIndexer; +import org.eclipse.cdt.internal.core.search.indexing.IndexManager; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.NullProgressMonitor; + +/** + * Test F2/F3 with the DOM Indexer for a C project. + * + * @author dsteffle + */ +public class CSelectionTestsDOMIndexer extends BaseSelectionTestsIndexer implements IIndexChangeListener { + private static final String INDEX_TAG = "1161844423.index"; //$NON-NLS-1$ + IFile file; + NullProgressMonitor monitor; + IndexManager indexManager; + SourceIndexer sourceIndexer; + + static final String sourceIndexerID = "org.eclipse.cdt.core.domsourceindexer"; //$NON-NLS-1$ + + public CSelectionTestsDOMIndexer(String name) { + super(name); + } + + protected void setUp() throws Exception { + super.setUp(); + + //Create temp project + project = createProject("CSelectionTestsDOMIndexerProject"); //$NON-NLS-1$ + IPath pathLoc = CCorePlugin.getDefault().getStateLocation(); + + File indexFile = new File(pathLoc.append(INDEX_TAG).toOSString()); + if (indexFile.exists()) + indexFile.delete(); + + //Set the id of the source indexer extension point as a session property to allow + //index manager to instantiate it + project.setSessionProperty(IndexManager.indexerIDKey, sourceIndexerID); + + //Enable indexing on test project + project.setSessionProperty(SourceIndexer.activationKey,new Boolean(true)); + + if (project==null) + fail("Unable to create project"); //$NON-NLS-1$ + + indexManager = CCorePlugin.getDefault().getCoreModel().getIndexManager(); + + resetIndexer(sourceIndexerID); // set indexer + + //indexManager.reset(); + //Get the indexer used for the test project + sourceIndexer = (SourceIndexer) indexManager.getIndexerForProject(project); + sourceIndexer.addIndexChangeListener(this); + } + + protected void tearDown() { + try { + super.tearDown(); + sourceIndexer.removeIndexChangeListener(this); + } catch (Exception e1) { + } + //Delete project + if (project.exists()) { + try { + System.gc(); + System.runFinalization(); + project.delete(true, monitor); + } catch (CoreException e) { + fail(getMessage(e.getStatus())); + } + } + } + + public static Test suite() { + TestSuite suite = new TestSuite(CSelectionTestsDOMIndexer.class.getName()); + + suite.addTest(new CSelectionTestsDOMIndexer("testSimpleOpenDeclaration")); //$NON-NLS-1$ + suite.addTest(new CSelectionTestsDOMIndexer("testSimpleOpenDeclaration2")); //$NON-NLS-1$ + suite.addTest(new CSelectionTestsDOMIndexer("testBasicDefinition")); //$NON-NLS-1$ + suite.addTest(new CSelectionTestsDOMIndexer("testCPPSpecDeclsDefs")); //$NON-NLS-1$ + suite.addTest(new CSelectionTestsDOMIndexer("testNoDefinitions")); //$NON-NLS-1$ + suite.addTest(new CSelectionTestsDOMIndexer("testOpenFileDiffDir")); //$NON-NLS-1$ + + return suite; + } + + private IProject createProject(String projectName) throws CoreException { + ICProject cPrj = CProjectHelper.createCCProject(projectName, "bin"); //$NON-NLS-1$ + return cPrj.getProject(); + } + + public void testSimpleOpenDeclaration() throws Exception { + String header = "int x() { return 1; }"; //$NON-NLS-1$ + importFile("test.h", header); //$NON-NLS-1$ + String code = "int foo() { \n return x();\n}\n"; //$NON-NLS-1$ + IFile file = importFile("test.c", code); + + int offset = code.indexOf("x();\n}\n"); + IASTNode def = testF2(file, offset); + try { + // TODO raised bug 97079 + assertTrue(def instanceof IASTName); + assertEquals(((ASTNode)def).getOffset(), header.indexOf("x")); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getLength(), "x".length()); //$NON-NLS-1$ + assertTrue(false); // when this fails then the test is passing correctly + } catch (AssertionFailedError afe) {} + IASTNode decl = testF3(file, offset); + assertTrue(decl instanceof IASTName); + assertEquals(((ASTNode)decl).getOffset(), header.indexOf("x")); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getLength(), "x".length()); //$NON-NLS-1$ + + } + + public void testSimpleOpenDeclaration2() throws Exception { + String header = "int x;\r\n // comment \r\n int y() { return 1; } /* comment */ \r\n int z; \r\n"; //$NON-NLS-1$ + importFile("test.h", header); //$NON-NLS-1$ + String code = "int foo() { \n return y();\n}\n"; //$NON-NLS-1$ + IFile file = importFile("test.c", code); + + int offset = code.indexOf("y();\n}\n"); + IASTNode def = testF2(file, offset); + try { + // TODO raised bug 97079 + assertTrue(def instanceof IASTName); + assertEquals(((ASTNode)def).getOffset(), header.indexOf("y")); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getLength(), "y".length()); //$NON-NLS-1$ + assertTrue(false); // when this fails then the test is passing correctly + } catch (AssertionFailedError afe) {} + IASTNode decl = testF3(file, offset); + assertTrue(decl instanceof IASTName); + assertEquals(((ASTNode)decl).getOffset(), header.indexOf("y")); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getLength(), "y".length()); //$NON-NLS-1$ + + } + + // perform the tests from CSelectionTestsNoIndexer and make sure they work with an indexer as well: + public void testBasicDefinition() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("extern int MyInt; // MyInt is in another file\n"); //$NON-NLS-1$ + buffer.append("extern const int MyConst; // MyConst is in another file\n"); //$NON-NLS-1$ + buffer.append("void MyFunc(int); // often used in header files\n"); //$NON-NLS-1$ + buffer.append("struct MyStruct; // often used in header files\n"); //$NON-NLS-1$ + buffer.append("typedef int NewInt; // a normal typedef statement\n"); //$NON-NLS-1$ + buffer.append("int MyInt;\n"); //$NON-NLS-1$ + buffer.append("extern const int MyConst = 42;\n"); //$NON-NLS-1$ + buffer.append("void MyFunc(int a) { cout << a << endl; }\n"); //$NON-NLS-1$ + buffer.append("struct MyStruct { int Member1; int Member2; };\n"); //$NON-NLS-1$ + + String code = buffer.toString(); + IFile file = importFile("testBasicDefinition.c", code); //$NON-NLS-1$ + + int offset = code.indexOf("MyInt;\n") + 2; //$NON-NLS-1$ + IASTNode def = testF2(file, offset); + IASTNode decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "MyInt"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 11); + assertEquals(((ASTNode)decl).getLength(), 5); + assertEquals(((IASTName)def).toString(), "MyInt"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 276); + assertEquals(((ASTNode)def).getLength(), 5); + + offset = code.indexOf("MyConst = 42") + 2; //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "MyConst"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 69); + assertEquals(((ASTNode)decl).getLength(), 7); + assertEquals(((IASTName)def).toString(), "MyConst"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 300); + assertEquals(((ASTNode)def).getLength(), 7); + + offset = code.indexOf("MyFunc(int a)") + 2; //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "MyFunc"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 115); + assertEquals(((ASTNode)decl).getLength(), 6); + assertEquals(((IASTName)def).toString(), "MyFunc"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 319); + assertEquals(((ASTNode)def).getLength(), 6); + + offset = code.indexOf("MyStruct {") + 2; //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "MyStruct"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 171); + assertEquals(((ASTNode)decl).getLength(), 8); + assertEquals(((IASTName)def).toString(), "MyStruct"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 363); + assertEquals(((ASTNode)def).getLength(), 8); + } + + // taken from C++ spec 3.1-3: + /* + // all but one of the following are definitions: + int a; // defines a + extern const int c = 1; // defines c + int f(int x) { return x+a; } // defines f and defines x + struct S { int a; int b; }; // defines S, S::a, and S::b + struct X { // defines X + int x; // defines nonstatic data member x + }; + enum { up, down }; // defines up and down + struct X anX; // defines anX + // whereas these are just declarations: + extern int a; // declares a + extern const int c; // declares c + int f(int); // declares f + struct S; // declares S + typedef int Int; // declares Int + extern struct X anotherX; // declares anotherX + */ + public void testCPPSpecDeclsDefs() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("int a; // defines a\n"); //$NON-NLS-1$ + buffer.append("extern const int c = 1; // defines c\n"); //$NON-NLS-1$ + buffer.append("int f(int x) { return x+a; } // defines f and defines x\n"); //$NON-NLS-1$ + buffer.append("struct S { int a; int b; }; // defines S, S::a, and S::b\n"); //$NON-NLS-1$ + buffer.append("struct X { // defines X\n"); //$NON-NLS-1$ + buffer.append("int x; // defines nonstatic data member x\n"); //$NON-NLS-1$ + buffer.append("};\n"); //$NON-NLS-1$ + buffer.append("enum { up, down }; // defines up and down\n"); //$NON-NLS-1$ + buffer.append("struct X anX; // defines anX\n"); //$NON-NLS-1$ + buffer.append("extern int a; // declares a\n"); //$NON-NLS-1$ + buffer.append("extern const int c; // declares c\n"); //$NON-NLS-1$ + buffer.append("int f(int); // declares f\n"); //$NON-NLS-1$ + buffer.append("struct S; // declares S\n"); //$NON-NLS-1$ + buffer.append("typedef int Int; // declares Int\n"); //$NON-NLS-1$ + buffer.append("extern struct X anotherX; // declares anotherX\n"); //$NON-NLS-1$ + + String code = buffer.toString(); + IFile file = importFile("testCPPSpecDeclsDefs.c", code); //$NON-NLS-1$ + + int offset = code.indexOf("a; // defines a"); //$NON-NLS-1$ + IASTNode def = testF2(file, offset); + IASTNode decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 4); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 4); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("c = 1; // defines c"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "c"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 37); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "c"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 37); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("f(int x) { return x+a; } // defines f and defines x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "f"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 61); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "f"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 61); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("x) { return x+a; } // defines f and defines x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 67); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 67); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("x+a; } // defines f and defines x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 67); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 67); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("x+a; } // defines f and defines x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 67); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 67); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("a; } // defines f and defines x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 4); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 4); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("S { int a; int b; }; // defines S, S::a, and S::b"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "S"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 120); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "S"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 120); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("a; int b; }; // defines S, S::a, and S::b"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 128); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 128); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("b; }; // defines S, S::a, and S::b"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "b"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 135); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "b"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 135); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("X { // defines X"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 177); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 177); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("x; // defines nonstatic data member x"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 198); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "x"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 198); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("up, down }; // defines up and down"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "up"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 246); + assertEquals(((ASTNode)decl).getLength(), 2); + assertEquals(((IASTName)def).toString(), "up"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 246); + assertEquals(((ASTNode)def).getLength(), 2); + + offset = code.indexOf("down }; // defines up and down"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "down"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 250); + assertEquals(((ASTNode)decl).getLength(), 4); + assertEquals(((IASTName)def).toString(), "down"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 250); + assertEquals(((ASTNode)def).getLength(), 4); + + offset = code.indexOf("X anX; // defines anX"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 177); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 177); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("anX; // defines anX"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "anX"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 290); + assertEquals(((ASTNode)decl).getLength(), 3); + assertEquals(((IASTName)def).toString(), "anX"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 290); + assertEquals(((ASTNode)def).getLength(), 3); + + offset = code.indexOf("a; // declares a"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 4); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "a"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 4); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("c; // declares c"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "c"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 37); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "c"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 37); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("f(int); // declares f"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "f"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 61); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "f"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 61); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("S; // declares S"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "S"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 120); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "S"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 120); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("Int; // declares Int"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "Int"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 434); + assertEquals(((ASTNode)decl).getLength(), 3); + assertEquals(((IASTName)def).toString(), "Int"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 434); + assertEquals(((ASTNode)def).getLength(), 3); + + offset = code.indexOf("X anotherX; // declares anotherX"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 177); + assertEquals(((ASTNode)decl).getLength(), 1); + assertEquals(((IASTName)def).toString(), "X"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 177); + assertEquals(((ASTNode)def).getLength(), 1); + + offset = code.indexOf("anotherX; // declares anotherX"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + try { + assertNull(def); // TODO raised bug 96689 + assertTrue(false); // try/catch/assertTrue(false) added to alert the tester when this test passes! + } catch (AssertionFailedError e) {} + + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "anotherX"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 471); + assertEquals(((ASTNode)decl).getLength(), 8); + } + + public void testNoDefinitions() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("extern int a1; // declares a\n"); //$NON-NLS-1$ + buffer.append("extern const int c1; // declares c\n"); //$NON-NLS-1$ + buffer.append("int f1(int); // declares f\n"); //$NON-NLS-1$ + buffer.append("struct S1; // declares S\n"); //$NON-NLS-1$ + buffer.append("typedef int Int; // declares Int\n"); //$NON-NLS-1$ + + String code = buffer.toString(); + IFile file = importFile("testNoDefinitions.c", code); //$NON-NLS-1$ + + int offset = code.indexOf("a1; // declares a"); //$NON-NLS-1$ + IASTNode def = testF2(file, offset); + IASTNode decl = testF3(file, offset); + try { + assertNull(def); // TODO raised bug 96689 + assertTrue(false); // try/catch/assertTrue(false) added to alert the tester when this test passes! + } catch (AssertionFailedError e) {} + + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "a1"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 11); + assertEquals(((ASTNode)decl).getLength(), 2); + + offset = code.indexOf("c1; // declares c"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + try { + assertNull(def); // TODO raised bug 96689 + assertTrue(false); // try/catch/assertTrue(false) added to alert the tester when this test passes! + } catch (AssertionFailedError e) {} + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "c1"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 46); + assertEquals(((ASTNode)decl).getLength(), 2); + + offset = code.indexOf("f1(int); // declares f"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertNull(def); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "f1"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 68); + assertEquals(((ASTNode)decl).getLength(), 2); + + offset = code.indexOf("S1; // declares S"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + try { + assertNull(def); // TODO raised bug 96690 + assertTrue(false); // try/catch/assertTrue(false) added to alert the tester when this test passes! + } catch (AssertionFailedError e) {} + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "S1"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 98); + assertEquals(((ASTNode)decl).getLength(), 2); + + offset = code.indexOf("Int; // declares Int"); //$NON-NLS-1$ + def = testF2(file, offset); + decl = testF3(file, offset); + assertTrue(def instanceof IASTName); + assertTrue(decl instanceof IASTName); + assertEquals(((IASTName)decl).toString(), "Int"); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getOffset(), 128); + assertEquals(((ASTNode)decl).getLength(), 3); + assertEquals(((IASTName)def).toString(), "Int"); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getOffset(), 128); + assertEquals(((ASTNode)def).getLength(), 3); + } + + public void testOpenFileDiffDir() throws Exception { + importFolder("test"); //$NON-NLS-1$ + String header = "int x;\r\n // comment \r\n int y(){ return 1; } /* comment */ \r\n int z; \r\n"; //$NON-NLS-1$ + importFile("test/test.h", header); //$NON-NLS-1$ + String code = "int foo() { \n return y();\n}\n"; //$NON-NLS-1$ + IFile file = importFile("test.c", code); + + int offset = code.indexOf("y();\n}\n"); + IASTNode def = testF2(file, offset); + try { + // TODO raised bug 97079 + assertTrue(def instanceof IASTName); + assertEquals(((ASTNode)def).getOffset(), header.indexOf("y")); //$NON-NLS-1$ + assertEquals(((ASTNode)def).getLength(), "y".length()); //$NON-NLS-1$ + assertTrue(false); // when this fails then the test is passing correctly + } catch (AssertionFailedError afe) {} + IASTNode decl = testF3(file, offset); + assertTrue(decl instanceof IASTName); + assertEquals(((ASTNode)decl).getOffset(), header.indexOf("y")); //$NON-NLS-1$ + assertEquals(((ASTNode)decl).getLength(), "y".length()); //$NON-NLS-1$ + + } + + // REMINDER: see CSelectionTestsDomIndexer#suite() when appending new tests to this suite +} \ No newline at end of file