/*******************************************************************************
* Copyright (c) 2007, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.pdom.tests;
import java.util.Arrays;
import java.util.Comparator;
import java.util.regex.Pattern;
import junit.framework.Test;
import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.internal.core.CCoreInternals;
import org.eclipse.cdt.internal.core.pdom.PDOM;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
/**
* Test the correctness of C/C++ searches
*
* @author Vivian Kong
*
*/
public class PDOMSearchTest extends PDOMTestBase {
final Comparator<IBinding> BINDING_COMPARATOR = new Comparator<IBinding>() {
public int compare(IBinding o1, IBinding o2) {
return o1.getName().compareTo(o2.getName());
}};
protected ICProject project;
protected PDOM pdom;
protected IProgressMonitor NULL_MONITOR = new NullProgressMonitor();
protected IndexFilter INDEX_FILTER = IndexFilter.ALL_DECLARED;
public static Test suite() {
return suite(PDOMSearchTest.class);
}
@Override
protected void setUp() throws Exception {
if (pdom == null) {
ICProject project = createProject("searchTests", true);
pdom = (PDOM)CCoreInternals.getPDOMManager().getPDOM(project);
}
pdom.acquireReadLock();
}
@Override
protected void tearDown() throws Exception {
pdom.releaseReadLock();
}
/**
* Test the members inside namespaces
*/
public void testNamespaces() throws Exception {
/* Members in the namespace */
IBinding[] namespaces = pdom.findBindings(Pattern.compile("namespace1"), false, INDEX_FILTER, NULL_MONITOR);
assertEquals(1, namespaces.length);
assertTrue(namespaces[0] instanceof ICPPNamespace);
ICPPNamespace namespace1 = (ICPPNamespace) namespaces[0];
/* Consistent search results */
// Searching for "namespace1::namespace2"
Pattern[] patterns = { Pattern.compile("namespace1"), Pattern.compile("namespace2") };
namespaces = pdom.findBindings(patterns, true, INDEX_FILTER, NULL_MONITOR);
assertEquals(1, namespaces.length);
assertTrue(namespaces[0] instanceof ICPPNamespace);
ICPPNamespace namespace2 = (ICPPNamespace) namespaces[0];
// Searching for "namespace2"
namespaces = pdom.findBindings(Pattern.compile("namespace2"), false, INDEX_FILTER, NULL_MONITOR);
assertEquals(1, namespaces.length);
assertTrue(namespaces[0] instanceof ICPPNamespace);
assertEquals(namespace2, namespaces[0]);
/* Namespace references */
IName[] refs = pdom.findNames(namespace1,IIndex.FIND_REFERENCES);
assertEquals(3, refs.length);
IASTFileLocation loc = refs[0].getFileLocation();
assertEquals(offset("main.cpp","namespace1::Class1"), loc.getNodeOffset()); //character offset
loc = refs[1].getFileLocation();
assertEquals(offset("Class1.cpp","namespace1::Class1::~Class1()"), loc.getNodeOffset()); //character offset
loc = refs[2].getFileLocation();
assertEquals(offset("Class1.cpp","namespace1::Class1::Class1()"), loc.getNodeOffset()); //character offset
/* Namespace declaration */
IName[] decls = pdom.findNames(namespace1, IIndex.FIND_DECLARATIONS);
assertEquals(0, decls.length);
/* Namespace definition */
IName[] defs = pdom.findNames(namespace1, IIndex.FIND_DEFINITIONS);
assertEquals(1, defs.length);
loc = defs[0].getFileLocation();
assertEquals(offset("Class1.h","namespace namespace1") + 10, loc.getNodeOffset()); //character offset
}
public void testClasses() throws Exception {
// Bugzilla 160913
// classes and nested classes
/* Search for "Class1" */
IBinding[] class1s = pdom.findBindings(Pattern.compile("Class1"), false, INDEX_FILTER, NULL_MONITOR);
assertEquals(4, class1s.length);
assertTrue(class1s[0] instanceof ICPPClassType);
assertTrue(class1s[1] instanceof ICPPClassType);
assertTrue(class1s[2] instanceof ICPPClassType);
assertTrue(class1s[3] instanceof ICPPMethod);
/** result #1 * */
ICPPClassType class1 = (ICPPClassType) class1s[0];
assertEquals("Class1", getBindingQualifiedName(pdom.getLinkageImpls()[0].adaptBinding(class1)));
IBinding[] methods = class1.getDeclaredMethods();
assertEquals(0, methods.length);
/** result #2 * */
ICPPClassType class2 = (ICPPClassType) class1s[1];
assertEquals("namespace1::Class1", getBindingQualifiedName(pdom.getLinkageImpls()[0].adaptBinding(class2)));
/* Members in this class */
// methods
methods = class2.getDeclaredMethods();
assertEquals(2, methods.length);
if (methods[0].getName().equals("~Class1")) {
IBinding h= methods[1]; methods[1]= methods[0]; methods[0]=h;
}
assertEquals("Class1", methods[0].getName());
assertEquals("~Class1", methods[1].getName());
// nested class
IBinding[] nested = class2.getNestedClasses();
assertEquals(1, nested.length);
assertEquals("Class2", nested[0].getName());
// fields
IBinding[] fields = class2.getFields();
assertEquals(2, fields.length);
Arrays.sort(fields, BINDING_COMPARATOR);
assertEquals("class1x", fields[0].getName());
assertEquals("class1y", fields[1].getName());
/** result #3 * */
ICPPMethod method3 = (ICPPMethod) class1s[3];
assertEquals("namespace1::Class1::Class1", getBindingQualifiedName(pdom.getLinkageImpls()[0].adaptBinding(method3)));
assertEquals(method3, methods[0]);
/** result #4 * */
ICPPClassType class4 = (ICPPClassType) class1s[2];
assertEquals("namespace1::namespace2::Class1", getBindingQualifiedName(pdom.getLinkageImpls()[0].adaptBinding(class4)));
methods = class4.getDeclaredMethods();
assertEquals(0, methods.length);
/* Search for "Class2" */
IBinding[] class2s = pdom.findBindings(Pattern.compile("Class2"), false, INDEX_FILTER, NULL_MONITOR);
assertEquals(4, class2s.length);
assertTrue(class2s[0] instanceof ICPPClassType);
assertTrue(class2s[1] instanceof ICPPClassType);
assertTrue(class2s[2] instanceof ICPPClassType);
assertTrue(class2s[3] instanceof ICPPMethod);
/** result #1 * */
ICPPClassType cls1 = (ICPPClassType) class2s[0];
assertEquals("Class2", getBindingQualifiedName(pdom.getLinkageImpls()[0].adaptBinding(cls1)));
methods = cls1.getDeclaredMethods();
assertEquals(3, methods.length);
Arrays.sort(methods, BINDING_COMPARATOR);
assertEquals("Class2", methods[0].getName());
assertEquals("~Class2", methods[2].getName());
assertEquals("foo", methods[1].getName());
/** result #2 * */
ICPPMethod meth2 = (ICPPMethod) class2s[3];
assertEquals("Class2::Class2", getBindingQualifiedName(pdom.getLinkageImpls()[0].adaptBinding(meth2)));
assertEquals(meth2, methods[0]);
/** result #3 * */
ICPPClassType cls3 = (ICPPClassType) class2s[1];
assertEquals("namespace1::Class1::Class2", getBindingQualifiedName(pdom.getLinkageImpls()[0].adaptBinding(cls3)));
/** result #3 * */
ICPPClassType cls4 = (ICPPClassType) class2s[2];
assertEquals("namespace1::Class2", getBindingQualifiedName(pdom.getLinkageImpls()[0].adaptBinding(cls4)));
/* Nested class references - namespace1::Class1::Class2 */
IName[] refs = pdom.findNames(cls3, IIndex.FIND_REFERENCES);
assertEquals(0, refs.length);
/* Nested class declaration */
IName[] decls = pdom.findNames(cls3, IIndex.FIND_DECLARATIONS);
assertEquals(0, decls.length);
/* Nested class definition */
IName[] defs = pdom.findNames(cls3, IIndex.FIND_DEFINITIONS);
assertEquals(1, defs.length);
IASTFileLocation loc = defs[0].getFileLocation();
assertEquals(offset("Class1.h","class Class2 { //namespace1::Class1::Class2") + 6, loc.getNodeOffset()); //character offset
}
public void testFunction() throws Exception {
IBinding[] functions = pdom.findBindings(Pattern.compile("foo2"), false, INDEX_FILTER, NULL_MONITOR);
assertEquals(1, functions.length);
assertTrue(functions[0] instanceof ICPPFunction);
assertEquals("foo2", getBindingQualifiedName(pdom.getLinkageImpls()[0].adaptBinding(functions[0])));
functions = pdom.findBindings(Pattern.compile("main"), false, INDEX_FILTER, NULL_MONITOR);
assertEquals(1, functions.length);
assertTrue(functions[0] instanceof ICPPFunction);
assertEquals("main", getBindingQualifiedName(pdom.getLinkageImpls()[0].adaptBinding(functions[0])));
}
public void testMethods() throws Exception {
IBinding[] methods = pdom.findBindings(Pattern.compile("~Class2"), false, INDEX_FILTER, NULL_MONITOR);
assertEquals(1, methods.length);
assertTrue(methods[0] instanceof ICPPMethod);
assertEquals("Class2::~Class2", getBindingQualifiedName(pdom.getLinkageImpls()[0].adaptBinding(methods[0])));
}
public void testFields() throws Exception {
IBinding[] fields = pdom.findBindings(Pattern.compile("class1x"), false, INDEX_FILTER, NULL_MONITOR);
assertEquals(1, fields.length);
assertTrue(fields[0] instanceof ICPPField);
assertEquals("namespace1::Class1::class1x", getBindingQualifiedName(pdom.getLinkageImpls()[0].adaptBinding(fields[0])));
fields = pdom.findBindings(Pattern.compile("class1y"), false, INDEX_FILTER, NULL_MONITOR);
assertEquals(1, fields.length);
assertTrue(fields[0] instanceof ICPPField);
assertEquals("namespace1::Class1::class1y", getBindingQualifiedName(pdom.getLinkageImpls()[0].adaptBinding(fields[0])));
}
public void testVariables() throws Exception {
IBinding[] variables = pdom.findBindings(Pattern.compile("var"), false, INDEX_FILTER, NULL_MONITOR);
assertEquals(1, variables.length);
assertTrue(variables[0] instanceof ICPPVariable);
assertEquals("var", getBindingQualifiedName(pdom.getLinkageImpls()[0].adaptBinding(variables[0])));
/* Variable references */
IName[] refs = pdom.findNames(variables[0], IIndex.FIND_REFERENCES);
assertEquals(1, refs.length);
IASTFileLocation loc = refs[0].getFileLocation();
assertEquals(offset("main.cpp","var = 0;"), loc.getNodeOffset()); //character offset
/* Variable declaration */
IName[] decls = pdom.findNames(variables[0], IIndex.FIND_DECLARATIONS_DEFINITIONS);
assertEquals(1, decls.length);
loc = decls[0].getFileLocation();
assertEquals(offset("main.cpp","int var;") + 4, loc.getNodeOffset()); //character offset
/* Variable definition */
IName[] defs = pdom.findNames(variables[0], IIndex.FIND_DEFINITIONS);
assertEquals(1, defs.length);
loc = defs[0].getFileLocation();
assertEquals(offset("main.cpp","int var;") + 4, loc.getNodeOffset()); //character offset
}
/**
* Get the fully qualified name for a given PDOMBinding
*
* @param pdomBinding
* @return binding's fully qualified name
* @throws CoreException
*/
private String getBindingQualifiedName(PDOMBinding pdomBinding) throws CoreException {
StringBuffer buf = new StringBuffer(pdomBinding.getName());
PDOMNode parent = pdomBinding.getParentNode();
while (parent != null) {
if (parent instanceof PDOMBinding) {
buf.insert(0, ((PDOMBinding) parent).getName() + "::");
}
parent = parent.getParentNode();
}
return buf.toString();
}
}