/*******************************************************************************
* Copyright (c) 2006, 2015 QNX Software Systems 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:
* QNX - Initial API and implementation
* Markus Schorn (Wind River Systems)
* IBM Corporation
* Thomas Corbat (IFS)
*******************************************************************************/
package org.eclipse.cdt.internal.pdom.tests;
import java.util.regex.Pattern;
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.IField;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
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.ICPPNamespaceScope;
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.PDOMName;
import junit.framework.Test;
/**
* @author Doug Schaefer
*/
public class ClassTests extends PDOMTestBase {
protected PDOM pdom;
public static Test suite() {
return suite(ClassTests.class, "_");
}
@Override
protected void setUp() throws Exception {
if (pdom == null) {
ICProject project = createProject("classTests");
pdom = (PDOM)CCoreInternals.getPDOMManager().getPDOM(project);
}
pdom.acquireReadLock();
}
@Override
protected void tearDown() throws Exception {
pdom.releaseReadLock();
}
public void test1() throws Exception {
IBinding[] Bs = pdom.findBindings(Pattern.compile("B"), true, IndexFilter.ALL, npm());
assertEquals(1, Bs.length);
ICPPClassType B = (ICPPClassType) Bs[0];
ICPPMethod[] Bmethods = B.getAllDeclaredMethods();
assertEquals(4, Bmethods.length);
assertNotNull(findMethod(Bmethods, "B"));
assertNotNull(findMethod(Bmethods, "A"));
assertNotNull(findMethod(Bmethods, "bf"));
ICPPMethod Bf = findMethod(Bmethods, "f");
assertNotNull(Bf);
IName [] Bf_refs = pdom.findNames(Bf, IIndex.FIND_REFERENCES);
assertEquals(1, Bf_refs.length);
IASTFileLocation loc = Bf_refs[0].getFileLocation();
assertEquals(offset("class.cpp", "b.f()") + 2, loc.getNodeOffset());
}
private ICPPMethod findMethod(ICPPMethod[] bmethods, String name) {
for (ICPPMethod method : bmethods) {
if (method.getName().equals(name)) {
return method;
}
}
return null;
}
public void testNested() throws Exception {
IBinding[] bindings = pdom.findBindings(Pattern.compile("NestedA"), false, IndexFilter.ALL_DECLARED, npm());
assertEquals(1, bindings.length);
ICPPClassType NestedA = (ICPPClassType)bindings[0];
ICPPClassType[] nested = NestedA.getNestedClasses();
assertEquals(1, nested.length);
ICPPClassType NestedB = nested[0];
assertEquals("NestedB", NestedB.getName());
IField[] fields = NestedB.getFields();
assertEquals(1, fields.length);
IField NestedB_x = fields[0];
IName[] refs = pdom.findNames(NestedB, IIndex.FIND_REFERENCES);
assertEquals(1, refs.length);
IASTFileLocation loc = refs[0].getFileLocation();
assertEquals(offset("nested.cpp", "::NestedB") + 2, loc.getNodeOffset());
refs = pdom.findNames(NestedB_x, IIndex.FIND_REFERENCES);
assertEquals(1, refs.length);
loc = refs[0].getFileLocation();
assertEquals(offset("nested.cpp", "x.x") + 2, loc.getNodeOffset());
}
public void test147903() throws Exception {
IBinding[] bindings = pdom.findBindings(Pattern.compile("pr147903"), false, IndexFilter.ALL, npm());
assertEquals(1, bindings.length);
ICPPNamespaceScope ns = ((ICPPNamespace) bindings[0]).getNamespaceScope();
bindings = ns.find("testRef", null);
assertEquals(1, bindings.length);
IName[] refs = pdom.findNames(bindings[0], IIndex.FIND_REFERENCES);
// for (int i = 0; i < refs.length; ++i)
// System.out.println(refs[i].getFileLocation().getNodeOffset());
assertEquals(5, refs.length);
}
/* Test friend relationships between classes */
public void testFriend() throws Exception {
IBinding[] bindings = pdom.findBindings(Pattern.compile("ClassA"), true, IndexFilter.ALL_DECLARED, npm());
assertEquals(1, bindings.length);
ICPPClassType classA = (ICPPClassType) bindings[0];
bindings = pdom.findBindings(Pattern.compile("ClassC"), true, IndexFilter.ALL_DECLARED, npm());
assertEquals(1, bindings.length);
ICPPClassType classC = (ICPPClassType) bindings[0];
bindings = pdom.findBindings(Pattern.compile("functionB"), false, IndexFilter.ALL_DECLARED, npm());
assertEquals(1, bindings.length);
ICPPFunction funcB = (ICPPFunction) bindings[0];
IBinding[] friends = classA.getFriends();
assertEquals(1, friends.length);
assertEquals(classC, friends[0]); //ClassC is a friend class of ClassA
friends = classC.getFriends();
assertEquals(1, friends.length);
assertEquals(funcB, friends[0]); //functionB is a friend of ClassC
}
public void noTest_testConstructor() throws Exception {
// the source does not define Class1, so it is no surprise that the test is failing.
// TODO PDOM doesn't have information on constructor
IBinding[] bindings = pdom.findBindings(Pattern.compile("Class1"), false, IndexFilter.ALL, npm());
assertEquals(2, bindings.length);
assertTrue(bindings[0] instanceof ICPPClassType);
assertTrue(bindings[1] instanceof ICPPMethod);
IName[] decls = pdom.findNames(bindings[1], IIndex.FIND_DECLARATIONS_DEFINITIONS);
assertEquals(2, decls.length);
IASTFileLocation loc = decls[0].getFileLocation();
assertEquals(offset("constructor.cpp","Class1(int num);"), loc.getNodeOffset()); //character offset
loc = decls[1].getFileLocation();
assertEquals(offset("constructor.cpp","Class1::Class1") + 8, loc.getNodeOffset()); //character offset
/* Member initialization */
bindings = pdom.findBindings(Pattern.compile("number"), false, IndexFilter.ALL, npm());
assertEquals(1, bindings.length);
IName[] refs = pdom.findNames(bindings[0], IIndex.FIND_REFERENCES);
assertEquals(1, refs.length);
loc = refs[0].getFileLocation();
assertEquals(offset("constructor.cpp", "number(num)"), loc.getNodeOffset()); //character offset
assertEquals(bindings[0], ((PDOMName)refs[0]).getBinding());
}
public void testAbsenceOfDefaultConstructorWhenExplicitNonDefaultPresentA() throws Exception {
IndexFilter JUST_CONSTRUCTORS= new IndexFilter() {
@Override
public boolean acceptBinding(IBinding binding) {
return binding instanceof ICPPConstructor;
}
};
IBinding[] bindings = pdom.findBindings(Pattern.compile("C"), false, JUST_CONSTRUCTORS, npm());
// expecting C(int) and C(const C &)
assertEquals(2, bindings.length);
}
public void testAbsenceOfDefaultConstructorWhenExplicitNonDefaultPresentB() throws Exception {
IndexFilter JUST_CONSTRUCTORS= new IndexFilter() {
@Override
public boolean acceptBinding(IBinding binding) {
return binding instanceof ICPPConstructor;
}
};
IBinding[] bindings = pdom.findBindings(Pattern.compile("D"), false, JUST_CONSTRUCTORS, npm());
// expecting just D(D &)
assertEquals(1, bindings.length);
}
public void testClassScope_bug185408() throws Exception {
char[][] name= {"B".toCharArray(), "bf".toCharArray()};
IBinding[] bindings= pdom.findBindings(name, IndexFilter.ALL, npm());
assertEquals(1, bindings.length);
IScope classScope= bindings[0].getScope();
assertTrue(classScope instanceof ICPPClassScope);
bindings= classScope.find("bf", null);
ICPPMethod method= extractSingleMethod(bindings);
assertEquals("B", method.getQualifiedName()[0]);
bindings= classScope.find("f", null);
method= extractSingleMethod(bindings);
assertEquals("A", method.getQualifiedName()[0]);
bindings= classScope.find("B", null);
ICPPClassType classType= extractSingleClass(bindings);
assertEquals("B", classType.getQualifiedName()[0]);
bindings= classScope.find("A", null);
classType= extractSingleClass(bindings);
assertEquals("A", classType.getQualifiedName()[0]);
}
private ICPPMethod extractSingleMethod(IBinding[] bindings) {
assertEquals(1, bindings.length);
assertInstance(bindings[0], ICPPMethod.class);
return (ICPPMethod) bindings[0];
}
private ICPPClassType extractSingleClass(IBinding[] bindings) {
assertEquals(1, bindings.length);
assertInstance(bindings[0], ICPPClassType.class);
return (ICPPClassType) bindings[0];
}
public void testFinalClass() throws Exception {
char[][] name = {"E".toCharArray()};
IBinding[] bindings = pdom.findBindings(name, IndexFilter.ALL, npm());
assertEquals(1, bindings.length);
assertInstance(bindings[0], ICPPClassType.class);
ICPPClassType classBinding = (ICPPClassType) bindings[0];
assertTrue(classBinding.isFinal());
}
}