/* * Copyright (c) 2014, 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 */ package org.eclipse.cdt.qt.tests; import java.util.ArrayList; import java.util.List; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.parser.ParserLanguage; import org.eclipse.cdt.core.parser.tests.ast2.AST2TestBase; import org.eclipse.cdt.internal.qt.core.ASTUtil; public class ASTUtilTests extends AST2TestBase { // class Type { public: void function() { } }; // class T // { // void callee() { Type instance; instance.function(); } // void caller() { this->callee(); callee(); T::callee(); } // }; // void T::callee() { this->caller(); caller(); T::caller(); } public void testGetReceiverType() throws Exception { IASTTranslationUnit tu = parse(); assertNotNull(tu); // Find the callee function call. ArrayList<IASTFunctionCallExpression> fnCalls = new ArrayList<IASTFunctionCallExpression>(); collectChildren(fnCalls, tu, IASTFunctionCallExpression.class); assertEquals(7, fnCalls.size()); assertNotNull(fnCalls.get(0)); assertNotNull(fnCalls.get(1)); assertNotNull(fnCalls.get(2)); assertNotNull(fnCalls.get(3)); assertNotNull(fnCalls.get(4)); assertNotNull(fnCalls.get(5)); assertNotNull(fnCalls.get(6)); // explicit type IASTFunctionCallExpression call = fnCalls.get(0); ICPPClassType recvr0 = ASTUtil.getReceiverType(call); assertNotNull(recvr0); assertEquals("Type", recvr0.getName()); // implicit this ICPPClassType recvr1 = ASTUtil.getReceiverType(fnCalls.get(1)); ICPPClassType recvr2 = ASTUtil.getReceiverType(fnCalls.get(2)); ICPPClassType recvr3 = ASTUtil.getReceiverType(fnCalls.get(3)); ICPPClassType recvr4 = ASTUtil.getReceiverType(fnCalls.get(4)); ICPPClassType recvr5 = ASTUtil.getReceiverType(fnCalls.get(5)); ICPPClassType recvr6 = ASTUtil.getReceiverType(fnCalls.get(6)); assertNotNull(recvr1); assertNotNull(recvr2); assertNotNull(recvr3); assertNotNull(recvr4); assertNotNull(recvr5); assertNotNull(recvr6); assertSame(recvr1, recvr2); assertSame(recvr3, recvr4); assertSame(recvr4, recvr5); assertSame(recvr5, recvr6); } // class C1 // { // public: // void f( C1 * ) { } // C1 * g() { return this; } // }; // void h() { C1 c; c.f( c.g() ); } public void testBaseTypeOfFunctionCall() throws Exception { IASTTranslationUnit tu = parse(); assertNotNull(tu); // Find the C1 type. ArrayList<ICPPASTCompositeTypeSpecifier> specs = new ArrayList<ICPPASTCompositeTypeSpecifier>(); collectChildren(specs, tu, ICPPASTCompositeTypeSpecifier.class); assertEquals(1, specs.size()); ICPPASTCompositeTypeSpecifier spec = specs.get(0); assertNotNull(spec); IASTName specName = spec.getName(); assertNotNull(specName); assertEquals("C1", specName.getRawSignature()); // Find the function call expression "c.get()". ArrayList<IASTFunctionCallExpression> fnCalls = new ArrayList<IASTFunctionCallExpression>(); collectChildren(fnCalls, tu, IASTFunctionCallExpression.class); assertEquals(2, fnCalls.size()); IASTFunctionCallExpression c_f = fnCalls.get(0); IASTFunctionCallExpression c_g = fnCalls.get(1); assertNotNull(c_f); assertNotNull(c_g); IASTExpression nameExpr = c_f.getFunctionNameExpression(); assertNotNull(nameExpr); assertEquals("c.f", nameExpr.getRawSignature()); IType recvType = ASTUtil.getReceiverType(c_f); assertTrue(recvType instanceof ICPPClassType); nameExpr = c_g.getFunctionNameExpression(); assertNotNull(nameExpr); assertEquals("c.g", nameExpr.getRawSignature()); recvType = ASTUtil.getBaseType(c_g); assertTrue(recvType instanceof ICPPClassType); } private IASTTranslationUnit parse() throws Exception { String[] contents = BaseQtTestCase.getContentsForTest(getClass(), 1); return parse(contents[0], ParserLanguage.CPP); } private static <T> void collectChildren(List<T> list, IASTNode node, Class<T> cls) { if (cls.isAssignableFrom(node.getClass())) list.add(cls.cast(node)); for(IASTNode child : node.getChildren()) collectChildren(list, child, cls); } }