blob: 1eb60fc30c1d3b6cdda6cdc7a25f099ba5165955 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2012 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.index.tests;
import java.io.IOException;
import java.util.regex.Pattern;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ILinkage;
import org.eclipse.cdt.core.dom.IPDOMManager;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.index.IndexLocationFactory;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.testplugin.CProjectHelper;
import org.eclipse.cdt.core.testplugin.CTestPlugin;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import junit.framework.TestSuite;
public class IndexNamesTests extends BaseTestCase {
private ICProject fCProject;
protected IIndex fIndex;
public IndexNamesTests(String name) {
super(name);
}
public static TestSuite suite() {
return suite(IndexNamesTests.class);
}
@Override
protected void setUp() throws CoreException {
fCProject= CProjectHelper.createCCProject("__encNamesTest__", "bin", IPDOMManager.ID_FAST_INDEXER);
CCorePlugin.getIndexManager().reindex(fCProject);
fIndex= CCorePlugin.getIndexManager().getIndex(fCProject);
}
@Override
protected void tearDown() throws CoreException {
if (fCProject != null) {
CProjectHelper.delete(fCProject);
}
}
protected IProject getProject() {
return fCProject.getProject();
}
public String getComment() throws IOException {
CharSequence[] contents = TestSourceReader.getContentsForTest(
CTestPlugin.getDefault().getBundle(), "parser", getClass(), getName(), 1);
return contents[0].toString();
}
protected IFile createFile(IContainer container, String fileName, String contents) throws Exception {
return TestSourceReader.createFile(container, new Path(fileName), contents);
}
protected void waitForIndexer() throws InterruptedException {
waitForIndexer(fCProject);
}
protected Pattern[] getPattern(String qname) {
String[] parts= qname.split("::");
Pattern[] result= new Pattern[parts.length];
for (int i = 0; i < result.length; i++) {
result[i]= Pattern.compile(parts[i]);
}
return result;
}
private IIndexFile getIndexFile(int linkageID, IFile file) throws CoreException {
IIndexFile[] files = fIndex.getFiles(linkageID, IndexLocationFactory.getWorkspaceIFL(file));
assertTrue("Can't find " + file.getLocation(), files.length > 0);
assertEquals("Found " + files.length + " files for " + file.getLocation() + " instead of one", 1, files.length);
return files[0];
}
protected void waitUntilFileIsIndexed(IFile file, int time) throws Exception {
TestSourceReader.waitUntilFileIsIndexed(fIndex, file, time);
}
// void func();
// int var;
//
// void main() {
// func();
// var=1;
// };
public void testNestingWithFunction() throws Exception {
waitForIndexer();
String content= getComment();
IFile file= createFile(getProject().getProject(), "test.cpp", content);
waitUntilFileIsIndexed(file, 4000);
fIndex.acquireReadLock();
try {
IIndexBinding[] mainBS= fIndex.findBindings(getPattern("main"), true, IndexFilter.ALL, npm());
assertLength(1, mainBS);
IIndexBinding mainB= mainBS[0];
IIndexName[] names= fIndex.findDefinitions(mainB);
assertLength(1, names);
IIndexName main= names[0];
assertNull(main.getEnclosingDefinition());
IIndexName[] enclosed= main.getEnclosedNames();
assertLength(2, enclosed);
assertName("func", enclosed[0]);
assertName("var", enclosed[1]);
IIndexName enclosing= enclosed[0].getEnclosingDefinition();
assertNotNull(enclosing);
assertName("main", enclosing);
enclosing= enclosed[1].getEnclosingDefinition();
assertNotNull(enclosing);
assertName("main", enclosing);
} finally {
fIndex.releaseReadLock();
}
}
private void assertName(String name, IIndexName iname) {
assertEquals(name, new String(iname.toCharArray()));
}
private void assertLength(int length, Object[] array) {
assertNotNull(array);
assertEquals(length, array.length);
}
// class C {
// public:
// void func();
// int var;
// };
//
// void main() {
// C c;
// c.func();
// c.var=1;
// };
// void C::func() {
// func();
// var=1;
// };
public void testNestingWithMethod() throws Exception {
waitForIndexer();
String content= getComment();
IFile file= createFile(getProject().getProject(), "test.cpp", content);
waitUntilFileIsIndexed(file, 4000);
fIndex.acquireReadLock();
try {
IIndexBinding[] mainBS= fIndex.findBindings(getPattern("main"), true, IndexFilter.ALL, npm());
assertLength(1, mainBS);
IIndexBinding mainB= mainBS[0];
IIndexName[] names= fIndex.findDefinitions(mainB);
assertLength(1, names);
IIndexName main= names[0];
assertNull(main.getEnclosingDefinition());
IIndexName[] enclosed= main.getEnclosedNames();
assertLength(4, enclosed);
assertName("C", enclosed[0]); // Class reference
assertName("C", enclosed[1]); // Implicit ctor call
assertName("func", enclosed[2]);
assertName("var", enclosed[3]);
IIndexName enclosing= enclosed[0].getEnclosingDefinition();
assertNotNull(enclosing);
assertName("main", enclosing);
enclosing= enclosed[1].getEnclosingDefinition();
assertNotNull(enclosing);
assertName("main", enclosing);
enclosing= enclosed[2].getEnclosingDefinition();
assertNotNull(enclosing);
assertName("main", enclosing);
enclosing= enclosed[3].getEnclosingDefinition();
assertNotNull(enclosing);
assertName("main", enclosing);
IIndexBinding funcB= fIndex.findBinding(enclosed[2]);
assertNotNull(funcB);
names= fIndex.findDefinitions(funcB);
assertLength(1, names);
IIndexName funcdef= names[0];
assertNull(funcdef.getEnclosingDefinition());
enclosed= funcdef.getEnclosedNames();
assertLength(3, enclosed);
assertName("C", enclosed[0]);
assertName("func", enclosed[1]);
assertName("var", enclosed[2]);
enclosing= enclosed[0].getEnclosingDefinition();
assertNotNull(enclosing);
assertName("func", enclosing);
enclosing= enclosed[1].getEnclosingDefinition();
assertNotNull(enclosing);
assertName("func", enclosing);
enclosing= enclosed[2].getEnclosingDefinition();
assertNotNull(enclosing);
assertName("func", enclosing);
} finally {
fIndex.releaseReadLock();
}
}
// class X {
// public:
// virtual void vm() {
// }
// };
//
// class Y : public X {
// public:
// virtual void vm() {
// }
// void test();
// };
// void Y::test() {
// X* x= this;
// X& xr= *this;
// X xc= *this;
//
// vm(); // polymorphic
// X::vm(); // call to X::vm()
// x->vm(); // polymorphic
// x->X::vm(); // call to X::vm()
// xr.vm(); // polymorphic
// xr.X::vm(); // call to X::vm()
// xc.vm(); // call to X::vm()
// xc.X::vm(); // call to X::vm()
// }
public void testCouldBePolymorphicMethodCall_Bug156691() throws Exception {
waitForIndexer();
String content= getComment();
IFile file= createFile(getProject().getProject(), "test.cpp", content);
waitUntilFileIsIndexed(file, 4000);
boolean[] couldbepolymorphic= {true, false, true, false, true, false, false, false};
String[] container= {"Y", "X", "X", "X", "X", "X", "X", "X" };
fIndex.acquireReadLock();
try {
IIndexFile ifile= getIndexFile(ILinkage.CPP_LINKAGE_ID, file);
IIndexName[] names= ifile.findNames(0, content.length());
int j= 0;
for (IIndexName indexName : names) {
if (indexName.isReference() && indexName.toString().equals("vm")) {
assertEquals(couldbepolymorphic[j], indexName.couldBePolymorphicMethodCall());
assertEquals(container[j], CPPVisitor.getQualifiedName(fIndex.findBinding(indexName))[0]);
j++;
} else {
assertEquals(false, indexName.couldBePolymorphicMethodCall());
}
}
assertEquals(couldbepolymorphic.length, j);
} finally {
fIndex.releaseReadLock();
}
}
// class A {
// virtual void foo(){}
// template<typename C> void SetCallback(C callback){}
// void InitCallback() {
// SetCallback(&A::foo); // Can be A::foo or B::foo
// }
// };
// class B: public A {
// virtual void foo(){}
// };
public void testAddressOfPolymorphicMethod_Bug363731() throws Exception {
waitForIndexer();
String content= getComment();
IFile file= createFile(getProject().getProject(), "test.cpp", content);
waitUntilFileIsIndexed(file, 4000);
fIndex.acquireReadLock();
try {
IIndexFile ifile= getIndexFile(ILinkage.CPP_LINKAGE_ID, file);
IIndexName[] names= ifile.findNames(0, content.length());
int j= 0;
for (IIndexName indexName : names) {
if (indexName.isReference() && indexName.toString().equals("foo")) {
assertEquals(true, indexName.couldBePolymorphicMethodCall());
assertEquals("A", CPPVisitor.getQualifiedName(fIndex.findBinding(indexName))[0]);
j++;
} else {
assertEquals(false, indexName.couldBePolymorphicMethodCall());
}
}
assertEquals(1, j);
} finally {
fIndex.releaseReadLock();
}
}
// int _i, ri, wi, rwi;
// int* rp; int* wp; int* rwp;
// const int* cip= &ri;
// int* bla= &rwi;
// void fi(int);
// void fp(int*);
// void fcp(const int*);
// void fpp(int**);
// void fcpp(int const**);
// void fpcp(int *const*);
// void fcpcp(int const *const*);
//
// void test() {
// _i;
// wi= ri, _i, _i;
// rwi %= ri;
// ri ? _i : _i;
// (ri ? wi : wi)= ri;
// if (ri) _i;
// for(wi=1; ri>ri; rwi++) _i;
// do {_i;} while (ri);
// while(ri) {_i;};
// switch(ri) {case ri: _i;};
// fi(ri); fp(&rwi); fcp(&ri);
// fi(*rp); fp(rp); fcp(rp); fpp(&rwp); fcpp(&rwp); fpcp(&rp); fcpcp(&rp);
// return ri;
// }
public void testReadWriteFlagsC() throws Exception {
waitForIndexer();
String content= getComment();
IFile file= createFile(getProject().getProject(), "test.c", content);
waitUntilFileIsIndexed(file, 4000);
checkReadWriteFlags(file, ILinkage.C_LINKAGE_ID, 41);
}
private void checkReadWriteFlags(IFile file, int linkageID, int count) throws InterruptedException,
CoreException {
fIndex.acquireReadLock();
try {
IIndexFile ifile= getIndexFile(linkageID, file);
IIndexName[] names= ifile.findNames(0, Integer.MAX_VALUE);
int j= 0;
for (IIndexName indexName : names) {
final String name = indexName.toString();
final char c0= name.length() > 0 ? name.charAt(0) : 0;
if ((c0 == '_' || c0 == 'r' || c0 == 'w') && indexName.isReference()) {
boolean isRead= name.charAt(0) == 'r';
boolean isWrite= c0 == 'w' || (isRead && name.length() > 1 && name.charAt(1) == 'w');
String msg= name + "(j=" + j + "):";
assertEquals("Read access for " + msg, isRead, indexName.isReadAccess());
assertEquals("Write access for " + msg, isWrite, indexName.isWriteAccess());
j++;
} else {
assertEquals(false, indexName.couldBePolymorphicMethodCall());
}
}
assertEquals(count, j);
} finally {
fIndex.releaseReadLock();
}
}
// int _i, ri, wi, rwi;
// int* rp; int* wp; int* rwp;
// int* const rpc= 0;
// const int * const rcpc= 0;
// const int* rwcp= &ri;
// void fi(int);
// void fp(int*);
// void fr(int&);
// void fcp(const int*);
// void fcr(const int&);
// void fpp(int**);
// void fpr(int*&);
// void fcpp(int const**);
// void fcpr(int const*&);
// void fpcp(int *const*);
// void fpcr(int *const&);
// void fcpcp(int const *const*);
// void fcpcr(int const *const&);
// int test() {
// _i;
// wi= ri, _i, _i; // expr-list
// rwi %= ri; // assignment
// ri ? _i : _i; // conditional
// (ri ? wi : wi)= ri; // conditional
// if (ri) _i;
// for(wi=1; ri>ri; rwi++) _i;
// do {_i;} while (ri);
// while(ri) {_i;};
// switch(ri) {case ri: _i;};
// fi(ri); fp(&rwi); fcp(&ri);
// fi(*rp); fp(rp); fcp(rp); fpp(&rwp); fcpp(&rwcp); fpcp(&rpc); fcpcp(&rcpc);
// fr(rwi); fcr(ri);
// fpcr(&rwi); fcpcr(&ri);
// fpr(rwp); fcpr(rwcp); fpcr(rp); fcpcr(rp);
// return ri;
// }
public void testReadWriteFlagsCpp() throws Exception {
waitForIndexer();
String content= getComment();
IFile file= createFile(getProject().getProject(), "test.cpp", content);
waitUntilFileIsIndexed(file, 4000);
checkReadWriteFlags(file, ILinkage.CPP_LINKAGE_ID, 48);
}
// int _i, ri, wi, rwi;
// void f(int&, int);
// void g(int, int&);
// void test() {
// f(rwi, ri);
// g(ri, rwi);
// }
public void testRWInSecondArg() throws Exception {
waitForIndexer();
String content= getComment();
IFile file= createFile(getProject().getProject(), "testRWInSecondArg.cpp", content);
waitUntilFileIsIndexed(file, 4000);
checkReadWriteFlags(file, ILinkage.CPP_LINKAGE_ID, 4);
}
// struct A {
// A(int p) {}
// };
// int r;
// A a(r); // Should be read-access
// void test() {
// A b(r); // Should be read-access
// }
public void testRWInConstructorCall_328528() throws Exception {
waitForIndexer();
String content= getComment();
IFile file= createFile(getProject().getProject(), "testRWInConstructorCall.cpp", content);
waitUntilFileIsIndexed(file, 4000);
checkReadWriteFlags(file, ILinkage.CPP_LINKAGE_ID, 2);
}
// struct A {
// A(int p) {}
// };
// int r;
// int a[2] = {0, r}; // Should be read-access
// void test() {
// int b[2] = {0, r}; // Should be read-access
// }
public void testRWInArrayInitializer_328528() throws Exception {
waitForIndexer();
String content= getComment();
IFile file= createFile(getProject().getProject(), "testRWInArrayInitializer.cpp", content);
waitUntilFileIsIndexed(file, 4000);
checkReadWriteFlags(file, ILinkage.CPP_LINKAGE_ID, 2);
}
}