/******************************************************************************* * Copyright (c) 2006, 2015 IBM Corporation. * 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 *******************************************************************************/ package org.eclipse.cdt.internal.pdom.tests; 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.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceAlias; 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.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; /** * Tests for verifying whether the PDOM correctly stores information about C++ namespaces. * * @author Vivian Kong */ public class NamespaceTests extends PDOMTestBase { protected ICProject project; protected PDOM pdom; protected IProgressMonitor NULL_MONITOR = new NullProgressMonitor(); protected IndexFilter INDEX_FILTER = IndexFilter.ALL; public static Test suite() { return suite(NamespaceTests.class); } @Override protected void setUp() throws Exception { if (pdom == null) { project = createProject("namespaceTests", true); pdom = (PDOM) CCoreInternals.getPDOMManager().getPDOM(project); } pdom.acquireReadLock(); } @Override protected void tearDown() throws Exception { pdom.releaseReadLock(); if (project != null) { project.getProject().delete(IResource.FORCE | IResource.ALWAYS_DELETE_PROJECT_CONTENT, new NullProgressMonitor()); } } public void testAlias() throws Exception { // Find all 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]; IBinding[] members = namespace1.getMemberBindings(); assertEquals(1, members.length); assertTrue(members[0] instanceof ICPPNamespace); assertEquals("namespace2", ((ICPPNamespace) members[0]).getName()); //nested namespace ICPPNamespace namespace2 = (ICPPNamespace) members[0]; namespaces = pdom.findBindings(Pattern.compile("namespaceNew"), false, INDEX_FILTER, NULL_MONITOR); assertEquals(1, namespaces.length); assertTrue(namespaces[0] instanceof ICPPNamespace); assertTrue(namespaces[0] instanceof ICPPNamespaceAlias); ICPPNamespaceAlias namespaceAlias = (ICPPNamespaceAlias) namespaces[0]; // TODO PDOM has no alias information // namespace2 and namespaceAlias should be referencing the same namespace assertEquals(namespace2, namespaceAlias.getBinding()); } public void testNested() throws Exception { // Find deeply nested namespace Pattern[] patterns = {Pattern.compile("namespace1"), Pattern.compile("namespace2"), Pattern.compile("namespace3")}; IBinding[] namespaces = pdom.findBindings(patterns, false, INDEX_FILTER, NULL_MONITOR); assertEquals(1, namespaces.length); assertTrue(namespaces[0] instanceof ICPPNamespace); } public void testMemberDefinition() throws Exception { // Find the definition of a member declared in a namespace Pattern[] patterns = {Pattern.compile("namespace1"), Pattern.compile("namespace2"), Pattern.compile("foo")}; IBinding[] members = pdom.findBindings(patterns, false, INDEX_FILTER, NULL_MONITOR); assertEquals(1, members.length); assertTrue(members[0] instanceof ICPPFunction); IName[] decls = pdom.findNames(members[0], IIndex.FIND_DECLARATIONS); assertEquals(1, decls.length); IASTFileLocation loc = decls[0].getFileLocation(); assertEquals(offset("namespace.cpp", "void foo()") + 5, loc.getNodeOffset()); // character offset IName[] defs = pdom.findNames(members[0], IIndex.FIND_DEFINITIONS); assertEquals(1, defs.length); loc = defs[0].getFileLocation(); assertEquals(offset("namespace.cpp", "::foo()") + 2, loc.getNodeOffset()); // character offset } public void testExtend() throws Exception { // Extending a namespace IBinding[] namespaces = pdom.findBindings(Pattern.compile("ns1"), false, INDEX_FILTER, NULL_MONITOR); assertEquals(1, namespaces.length); assertTrue(namespaces[0] instanceof ICPPNamespace); ICPPNamespace namespace1 = (ICPPNamespace) namespaces[0]; Pattern[] patterns = {Pattern.compile("ns1"), Pattern.compile("c")}; IBinding[] members = pdom.findBindings(patterns, false, INDEX_FILTER, NULL_MONITOR); assertEquals(1, members.length); // c was added by extending the namespace } public void testOverload() throws Exception { // Function overloading in namespace Pattern[] patterns = {Pattern.compile("ns3"), Pattern.compile("blah")}; IBinding[] functions = pdom.findBindings(patterns, false, INDEX_FILTER, NULL_MONITOR); assertEquals(1, functions.length); assertTrue(functions[0] instanceof ICPPFunction); ICPPFunction function = (ICPPFunction) functions[0]; IName[] defs = pdom.findNames(function, IIndex.FIND_DEFINITIONS); assertEquals(1, defs.length); IASTFileLocation loc = defs[0].getFileLocation(); assertEquals(offset("overload.cpp", "void blah(char)") + 5, loc.getNodeOffset()); // character offset IName[] decls = pdom.findNames(function, IIndex.FIND_DECLARATIONS_DEFINITIONS); assertEquals(1, decls.length); loc = decls[0].getFileLocation(); assertEquals(offset("overload.cpp", "void blah(char)") + 5, loc.getNodeOffset()); // character offset IName[] refs = pdom.findNames(function, IIndex.FIND_REFERENCES); assertEquals(1, refs.length); loc = refs[0].getFileLocation(); assertEquals(offset("overload.cpp", "blah('a')"), loc.getNodeOffset()); // character offset } public void testUnnamed_162226() throws Exception { // Unnamed Namespace IBinding[] functions = pdom.findBindings(Pattern.compile("function1"), true, INDEX_FILTER, NULL_MONITOR); assertEquals(1, functions.length); assertTrue(functions[0] instanceof ICPPFunction); ICPPFunction function = (ICPPFunction) functions[0]; IName[] defs = pdom.findNames(function, IIndex.FIND_DEFINITIONS); assertEquals(1, defs.length); IASTFileLocation loc = defs[0].getFileLocation(); assertEquals(offset("unnamed.cpp", "void function1()") + 5, loc.getNodeOffset()); // character offset IName[] decls = pdom.findNames(function, IIndex.FIND_DECLARATIONS_DEFINITIONS); assertEquals(1, decls.length); loc = decls[0].getFileLocation(); assertEquals(offset("unnamed.cpp", "void function1()") + 5, loc.getNodeOffset()); // character offset IName[] refs = pdom.findNames(function, IIndex.FIND_REFERENCES); assertEquals(1, refs.length); loc = refs[0].getFileLocation(); assertEquals(offset("unnamed.cpp", "function1();"), loc.getNodeOffset()); // character offset } public void testFriend_162011() throws Exception { // Friend in namespace - function2 is not in Class1 IBinding[] functions = pdom.findBindings(Pattern.compile("function2"), false, INDEX_FILTER, NULL_MONITOR); assertEquals(1, functions.length); assertTrue(functions[0] instanceof ICPPFunction); ICPPFunction function = (ICPPFunction) functions[0]; IName[] defs = pdom.findNames(function, IIndex.FIND_DEFINITIONS); assertEquals(1, defs.length); IASTFileLocation loc = defs[0].getFileLocation(); assertEquals(offset("friend.cpp", "void function2(Class1){};") + 5, loc.getNodeOffset()); // character offset IName[] decls = pdom.findNames(function, IIndex.FIND_DECLARATIONS); assertEquals(1, decls.length); loc = decls[0].getFileLocation(); assertEquals(offset("friend.cpp", "friend void function2(Class1);") + 12, loc.getNodeOffset()); // character offset IName[] refs = pdom.findNames(function, IIndex.FIND_REFERENCES); assertEquals(1, refs.length); loc = refs[0].getFileLocation(); assertEquals(offset("friend.cpp", "ns4::function2(element)") + 5, loc.getNodeOffset()); // character offset } public void testUsingDirective() throws Exception { // TODO need to test for PDOM? or is it more for compiler? Pattern[] patterns = {Pattern.compile("ns4"), Pattern.compile("element")}; IBinding[] variables = pdom.findBindings(patterns, false, INDEX_FILTER, NULL_MONITOR); assertEquals(1, variables.length); assertTrue(variables[0] instanceof ICPPVariable); ICPPVariable variable1 = (ICPPVariable) variables[0]; IName[] defs = pdom.findNames(variable1, IIndex.FIND_DEFINITIONS); assertEquals(1, defs.length); IASTFileLocation loc = defs[0].getFileLocation(); assertEquals(offset("friend.cpp", "Class1 element;") + 7, loc.getNodeOffset()); // character offset IName[] decls = pdom.findNames(variable1, IIndex.FIND_DECLARATIONS); assertEquals(0, decls.length); IName[] refs = pdom.findNames(variable1, IIndex.FIND_REFERENCES); assertEquals(3, refs.length); } }