/******************************************************************************* * Copyright (c) 2007, 2015 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.util.Arrays; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.IPDOMManager; import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.ICompositeType; import org.eclipse.cdt.core.dom.ast.IEnumeration; import org.eclipse.cdt.core.dom.ast.IEnumerator; import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.IParameter; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; 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.ICPPEnumeration; 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.ICPPMember; 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.ICPPNamespaceAlias; import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.index.IndexFilter; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.testplugin.CProjectHelper; import org.eclipse.cdt.core.testplugin.util.TestSourceReader; import org.eclipse.cdt.internal.core.pdom.CModelListener; import org.eclipse.cdt.internal.core.pdom.dom.PDOMFile; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import junit.framework.TestSuite; public class IndexUpdateTests extends IndexTestBase { private static final String EXPLICIT = "explicit"; private static final String VIRTUAL = "virtual"; private static final String PURE_VIRTUAL= "pure-virtual"; private static final String PROTECTED = "protected"; private static final String PUBLIC = "public"; private static final String PRIVATE = "private"; private static final String CHAR = "char"; private static final String INLINE = "inline"; private static final String MUTABLE = "mutable"; private static final String STATIC = "static"; private static final String REGISTER = "register"; private static final String AUTO = "auto"; private static final String SHORT = "short int"; private static final String INT = "int"; private static final String IMPLICIT= "implicit"; public static TestSuite suite() { TestSuite suite= suite(IndexUpdateTests.class, "_"); suite.addTest(new IndexUpdateTests("deleteProject")); return suite; } private ICProject fCppProject; private ICProject fCProject; private IIndex fIndex; private CharSequence[] fContents; private IFile fFile; private IFile fHeader; private int fContentUsed; public IndexUpdateTests(String name) { super(name); } @Override public void setUp() throws Exception { super.setUp(); if (fCppProject == null) { fCppProject= CProjectHelper.createCCProject("indexUpdateTestsCpp", null, IPDOMManager.ID_FAST_INDEXER); } if (fCProject == null) { fCProject= CProjectHelper.createCProject("indexUpdateTestsC", null, IPDOMManager.ID_FAST_INDEXER); } waitForIndexer(fCppProject); waitForIndexer(fCProject); fIndex= CCorePlugin.getIndexManager().getIndex(new ICProject[] {fCProject, fCppProject}); } private void setupHeader(int totalFileVersions, boolean cpp) throws Exception { if (fContents == null) { fContents= getContentsForTest(totalFileVersions); fContentUsed= -1; } IProject project= cpp ? fCppProject.getProject() : fCProject.getProject(); fHeader= TestSourceReader.createFile(project, "header.h", fContents[++fContentUsed].toString()); waitForIndexer(fCppProject); waitForIndexer(fCProject); } private void updateHeader() throws Exception { // Append variable comment to the end of the file to change its contents. // Indexer would not reindex the file if its contents remain the same. IProject project= fHeader.getProject(); fHeader= TestSourceReader.createFile(project, "header.h", fContents[++fContentUsed].toString() + "\n// " + fContentUsed); waitUntilFileIsIndexed(fIndex, fHeader); } private void setupFile(int totalFileVersions, boolean cpp) throws Exception { if (fContents == null) { fContents= getContentsForTest(totalFileVersions); fContentUsed= -1; } ICProject cproject= cpp ? fCppProject : fCProject; fFile= TestSourceReader.createFile(cproject.getProject(), "file" + (cpp ? ".cpp" : ".c"), fContents[++fContentUsed].toString()); TestSourceReader.waitUntilFileIsIndexed(fIndex, fFile, INDEXER_TIMEOUT_MILLISEC); waitForIndexer(cproject); } private void updateFile() throws Exception { // Append variable comment to the end of the file to change its contents. // Indexer would not reindex the file if its contents remain the same. fFile= TestSourceReader.createFile(fFile.getParent(), fFile.getName(), fContents[++fContentUsed].toString() + "\n// " + fContentUsed); waitUntilFileIsIndexed(fIndex, fFile); } @Override public void tearDown() throws Exception { fIndex= null; if (fFile != null) { fFile.delete(true, npm()); } if (fHeader != null) { fHeader.delete(true, npm()); } super.tearDown(); } public void deleteProject() { if (fCProject != null) { CProjectHelper.delete(fCProject); fCProject= null; } if (fCppProject != null) { CProjectHelper.delete(fCppProject); fCppProject= null; } } // int globalVar; // short globalVar; // auto int globalVar; // register int globalVar; public void testGlobalCVariable() throws Exception { setupFile(4, false); checkVariable("globalVar", INT, new String[] {}); updateFile(); checkVariable("globalVar", SHORT, new String[] {}); updateFile(); checkVariable("globalVar", INT, new String[] {AUTO}); updateFile(); checkVariable("globalVar", INT, new String[] {REGISTER}); } private void checkVariable(String name, String type, String[] modifiers) throws Exception { fIndex.acquireReadLock(); try { IVariable var = (IVariable) findBinding(name); checkVariable(var, type, modifiers); } finally { fIndex.releaseReadLock(); } } private void checkValue(String name, Long value) throws Exception { fIndex.acquireReadLock(); try { IBinding b = findBinding(name); IValue v= null; if (b instanceof IVariable) v= ((IVariable) b).getInitialValue(); else if (b instanceof IEnumerator) v= ((IEnumerator) b).getValue(); else fail(); if (value == null) assertNull(v); else assertEquals(value, v.numberValue()); } finally { fIndex.releaseReadLock(); } } private void checkVariable(IVariable var, String type, String[] modifiers) throws DOMException { assertEquals(msg(), type, ASTTypeUtil.getType(var.getType())); checkModifier(modifiers, AUTO, var.isAuto()); checkModifier(modifiers, REGISTER, var.isRegister()); checkModifier(modifiers, STATIC, var.isStatic()); } private void checkModifier(String[] modifiers, String modifier, boolean actual) throws DOMException { assertEquals(msg(modifier), hasMod(modifiers, modifier), actual); } private boolean hasMod(String[] modifiers, String mod) { return Arrays.asList(modifiers).contains(mod); } private IIndexBinding findBinding(String name) throws CoreException { String[] names= name.split("::"); char[][] nchars= new char[names.length][]; for (int i = 0; i < nchars.length; i++) { nchars[i]= names[i].toCharArray(); } IIndexBinding[] bindings = fIndex.findBindings(nchars, IndexFilter.ALL_DECLARED, npm()); return bindings.length > 0 ? bindings[0] : null; } private String msg() { return "Update #" + fContentUsed; } private String msg(String modifier) { return msg() + "; " + modifier + ":"; } // int globalVar; // short globalVar; // register int globalVar; public void testGlobalCppVariable() throws Exception { setupFile(3, true); checkCppVariable("globalVar", INT, new String[]{}); updateFile(); checkCppVariable("globalVar", SHORT, new String[]{}); updateFile(); checkCppVariable("globalVar", INT, new String[]{}); } private void checkCppVariable(String name, String type, String[] modifiers) throws Exception { fIndex.acquireReadLock(); try { ICPPVariable var = (ICPPVariable) findBinding(name); checkCppVariable(var, type, modifiers); } finally { fIndex.releaseReadLock(); } } private void checkCppVariable(ICPPVariable var, String type, String[] modifiers) throws Exception { checkVariable(var, type, modifiers); checkModifier(modifiers, MUTABLE, var.isMutable()); } // int globalFunction(int a, int b){}; // short globalFunction(int a, int b){}; // int globalFunction(char a){}; // inline int globalFunction(char a){}; public void testCFunction() throws Exception { setupFile(4, false); checkFunction("globalFunction", new String[] {INT, INT, INT}, new String[]{}); updateFile(); checkFunction("globalFunction", new String[] {SHORT, INT, INT}, new String[]{}); updateFile(); checkFunction("globalFunction", new String[] {INT, CHAR}, new String[]{}); updateFile(); checkFunction("globalFunction", new String[] {INT, CHAR}, new String[]{INLINE}); } private void checkFunction(String name, String[] types, String[] modifiers) throws Exception { fIndex.acquireReadLock(); try { IFunction func = (IFunction) findBinding(name); checkFunction(func, types, modifiers); } finally { fIndex.releaseReadLock(); } } private void checkFunction(IFunction func, String[] types, String[] modifiers) throws DOMException { assertEquals(msg(), types[0], ASTTypeUtil.getType(func.getType().getReturnType())); IParameter[] params= func.getParameters(); assertEquals(msg(), types.length - 1, params.length); for (int i = 0; i < params.length; i++) { IParameter parameter = params[i]; assertEquals(msg(), types[i + 1], ASTTypeUtil.getType(parameter.getType())); } checkModifier(modifiers, INLINE, func.isInline()); checkModifier(modifiers, STATIC, func.isStatic()); } // int globalFunction(int a, int b){}; // short globalFunction(int a, int b){}; // int globalFunction(char a){}; // inline int globalFunction(char a){}; public void testCppFunction() throws Exception { setupFile(4, true); checkFunction("globalFunction", new String[] {INT, INT, INT}, new String[]{}); updateFile(); checkFunction("globalFunction", new String[] {SHORT, INT, INT}, new String[]{}); updateFile(); checkFunction("globalFunction", new String[] {INT, CHAR}, new String[]{}); updateFile(); checkFunction("globalFunction", new String[] {INT, CHAR}, new String[]{INLINE}); } // struct my_struct {int fField;}; // struct my_struct {short fField;}; public void testCField() throws Exception { setupFile(2, false); checkVariable("my_struct::fField", INT, new String[]{}); updateFile(); checkVariable("my_struct::fField", SHORT, new String[]{}); } // class MyClass {int fField;}; // class MyClass {short fField;}; // class MyClass {mutable int fField;}; // class MyClass {public: int fField;}; // class MyClass {protected: int fField;}; // class MyClass {private: int fField;}; // class MyClass {private: static int fField;}; public void testCppField() throws Exception { setupFile(7, true); checkCppField("MyClass::fField", INT, new String[]{PRIVATE}); updateFile(); checkCppField("MyClass::fField", SHORT, new String[]{PRIVATE}); updateFile(); checkCppField("MyClass::fField", INT, new String[]{PRIVATE, MUTABLE}); updateFile(); checkCppField("MyClass::fField", INT, new String[]{PUBLIC}); updateFile(); checkCppField("MyClass::fField", INT, new String[]{PROTECTED}); updateFile(); checkCppField("MyClass::fField", INT, new String[]{PRIVATE}); updateFile(); checkCppField("MyClass::fField", INT, new String[]{PRIVATE, STATIC}); } private void checkCppField(String name, String type, String[] modifiers) throws Exception { fIndex.acquireReadLock(); try { ICPPField field = (ICPPField) findBinding(name); checkCppVariable(field, type, modifiers); checkCppMember(field, modifiers); } finally { fIndex.releaseReadLock(); } } private void checkCppMember(ICPPMember member, String[] modifiers) throws Exception { int visibility= member.getVisibility(); checkModifier(modifiers, PUBLIC, visibility == ICPPMember.v_public); checkModifier(modifiers, PROTECTED, visibility == ICPPMember.v_protected); checkModifier(modifiers, PRIVATE, visibility == ICPPMember.v_private); } // class MyClass {int method(int a, int b);}; // class MyClass {short method(int a, int b);}; // class MyClass {int method(char a);}; // class MyClass {inline int method(char a);}; // class MyClass {virtual int method(char a);}; // class MyClass {public: int method(char a);}; // class MyClass {protected: int method(char a);}; // class MyClass {private: int method(char a);}; // class MyClass {int method(char a){};}; // class MyClass {virtual int method(char a) = 0;}; public void testCppMethod() throws Exception { setupFile(10, true); checkCppMethod("MyClass::method", new String[] {INT, INT, INT}, new String[]{PRIVATE}); updateFile(); checkCppMethod("MyClass::method", new String[] {SHORT, INT, INT}, new String[]{PRIVATE}); updateFile(); checkCppMethod("MyClass::method", new String[] {INT, CHAR}, new String[]{PRIVATE}); updateFile(); checkCppMethod("MyClass::method", new String[] {INT, CHAR}, new String[]{PRIVATE, INLINE}); updateFile(); checkCppMethod("MyClass::method", new String[] {INT, CHAR}, new String[]{PRIVATE, VIRTUAL}); updateFile(); checkCppMethod("MyClass::method", new String[] {INT, CHAR}, new String[]{PUBLIC}); updateFile(); checkCppMethod("MyClass::method", new String[] {INT, CHAR}, new String[]{PROTECTED}); updateFile(); checkCppMethod("MyClass::method", new String[] {INT, CHAR}, new String[]{PRIVATE}); updateFile(); checkCppMethod("MyClass::method", new String[] {INT, CHAR}, new String[]{PRIVATE, INLINE}); updateFile(); checkCppMethod("MyClass::method", new String[] {INT, CHAR}, new String[]{PRIVATE, VIRTUAL, PURE_VIRTUAL}); } // class MyClass {protected: int method(int a, int b);}; // #include "header.h" // int MyClass::method(int a, int b); // #include "header.h" // char MyClass::method(int a, int b); public void testFixedCppMethod() throws Exception { setupHeader(3, true); checkCppMethod("MyClass::method", new String[] {INT, INT, INT}, new String[]{PROTECTED}); setupFile(0, true); checkCppMethod("MyClass::method", new String[] {INT, INT, INT}, new String[]{PROTECTED}); updateFile(); checkCppMethod("MyClass::method", new String[] {INT, INT, INT}, new String[]{PROTECTED}); } private void checkCppMethod(String name, String[] types, String[] modifiers) throws Exception { fIndex.acquireReadLock(); try { ICPPMethod method = (ICPPMethod) findBinding(name); checkCppMethod(method, types, modifiers); } finally { fIndex.releaseReadLock(); } } private void checkCppMethod(ICPPMethod method, String[] types, String[] modifiers) throws DOMException, Exception { checkFunction(method, types, modifiers); checkCppMember(method, modifiers); checkModifier(modifiers, VIRTUAL, method.isVirtual()); checkModifier(modifiers, PURE_VIRTUAL, method.isPureVirtual()); checkModifier(modifiers, IMPLICIT, method.isImplicit()); } // class MyClass {MyClass(int a, int b);}; // class MyClass {MyClass(char a, int b);}; // class MyClass {explicit MyClass(char a, int b);}; // class MyClass {public: MyClass(char a, int b);}; // class MyClass {protected: MyClass(char a, int b);}; // class MyClass {private: MyClass(char a, int b);}; public void testCppConstructor() throws Exception { setupFile(6, true); checkCppConstructor("MyClass::MyClass", new String[] {"", INT, INT}, new String[]{PRIVATE}); updateFile(); checkCppConstructor("MyClass::MyClass", new String[] {"", CHAR, INT}, new String[]{PRIVATE}); updateFile(); checkCppConstructor("MyClass::MyClass", new String[] {"", CHAR, INT}, new String[]{PRIVATE,EXPLICIT}); updateFile(); checkCppConstructor("MyClass::MyClass", new String[] {"", CHAR, INT}, new String[]{PUBLIC}); updateFile(); checkCppConstructor("MyClass::MyClass", new String[] {"", CHAR, INT}, new String[]{PROTECTED}); updateFile(); checkCppConstructor("MyClass::MyClass", new String[] {"", CHAR, INT}, new String[]{PRIVATE}); } private void checkCppConstructor(String name, String[] types, String[] modifiers) throws Exception { fIndex.acquireReadLock(); try { ICPPConstructor ctor = (ICPPConstructor) findBinding(name); checkCppConstructor(ctor, types, modifiers); } finally { fIndex.releaseReadLock(); } } private void checkCppConstructor(ICPPConstructor ctor, String[] types, String[] modifiers) throws Exception { checkFunction(ctor, types, modifiers); checkCppMember(ctor, modifiers); checkModifier(modifiers, EXPLICIT, ctor.isExplicit()); } // class MyClass {}; // class MyClass {protected: MyClass(void);}; // class MyClass {explicit MyClass(const MyClass& rhs);}; // class MyClass {public: MyClass& operator=(const MyClass& rhs) {}}; // class MyClass {}; public void testImplicitMethods() throws Exception { setupFile(5, true); checkImplicitMethods("MyClass", new String[] {IMPLICIT, PUBLIC}, new String[] {IMPLICIT, PUBLIC}, new String[] {IMPLICIT, PUBLIC}); updateFile(); checkImplicitMethods("MyClass", new String[] {PROTECTED}, new String[] {IMPLICIT, PUBLIC}, new String[] {IMPLICIT, PUBLIC}); updateFile(); checkImplicitMethods("MyClass", null, // no default constructor, because we declared the copy constructor. new String[] {EXPLICIT, PRIVATE}, new String[] {IMPLICIT, PUBLIC}); updateFile(); checkImplicitMethods("MyClass", new String[] {IMPLICIT, PUBLIC}, new String[] {IMPLICIT, PUBLIC}, new String[] {INLINE, PUBLIC}); updateFile(); checkImplicitMethods("MyClass", new String[] {IMPLICIT, PUBLIC}, new String[] {IMPLICIT, PUBLIC}, new String[] {IMPLICIT, PUBLIC}); } private void checkImplicitMethods(String name, String[] m1, String[] m2, String[] m3) throws Exception { fIndex.acquireReadLock(); try { final char[] nchars = name.toCharArray(); final String refType = name + " &"; final String constRefType = "const " + refType; IIndexBinding[] ctors= fIndex.findBindings(new char[][] {nchars, nchars}, IndexFilter.ALL_DECLARED_OR_IMPLICIT, npm()); int count= 0; for (int i = 0; i < ctors.length; i++) { IIndexBinding ctor= ctors[i]; if (ctor.isFileLocal()) { ctors[count++]= ctor; } } assertEquals(m1 == null ? 1 : 2, count); final IType[] parameterTypes = ((ICPPConstructor) ctors[0]).getType().getParameterTypes(); if (parameterTypes.length != 1 || !(parameterTypes[0] instanceof ICPPReferenceType)) { IIndexBinding h= ctors[0]; ctors[0]= ctors[1]; ctors[1]= h; } if (m1 != null) { checkCppConstructor((ICPPConstructor) ctors[1], new String[] {""}, m1); } checkCppConstructor((ICPPConstructor) ctors[0], new String[] {"", constRefType}, m2); IIndexBinding[] assignmentOps= fIndex.findBindings( new char[][] {nchars, "operator =".toCharArray() }, IndexFilter.ALL_DECLARED_OR_IMPLICIT, npm()); count= 0; for (int i = 0; i < assignmentOps.length; i++) { IIndexBinding assignmentOp= assignmentOps[i]; if (assignmentOp.isFileLocal()) { assignmentOps[count++]= assignmentOp; } } assertEquals(1, count); checkCppMethod((ICPPMethod) assignmentOps[0], new String[]{refType, constRefType}, m3); } finally { fIndex.releaseReadLock(); } } // typedef int myType; // typedef short myType; public void testCTypedef() throws Exception { setupFile(2, false); checkTypedef("myType", INT); updateFile(); checkTypedef("myType", SHORT); } private void checkTypedef(String name, String type) throws Exception { fIndex.acquireReadLock(); try { ITypedef var = (ITypedef) findBinding(name); checkTypedef(var, type); } finally { fIndex.releaseReadLock(); } } private void checkTypedef(ITypedef var, String type) throws DOMException { assertEquals(msg(), type, ASTTypeUtil.getType(var.getType())); } // typedef int myType; // typedef short myType; public void testCppTypedef() throws Exception { setupFile(2, true); checkTypedef("myType", INT); updateFile(); checkTypedef("myType", SHORT); } // namespace aNs { // } // namespace nsAlias= aNs; // namespace bNs { // } // namespace nsAlias= bNs; public void testNamespaceAlias() throws Exception { setupFile(2, true); checkNamespaceAlias("nsAlias", "aNs"); updateFile(); checkNamespaceAlias("nsAlias", "bNs"); } private void checkNamespaceAlias(String name, String target) throws Exception { fIndex.acquireReadLock(); try { ICPPNamespaceAlias nsalias = (ICPPNamespaceAlias) findBinding(name); assertEquals(msg(), target, nsalias.getBinding().getName()); } finally { fIndex.releaseReadLock(); } } // struct myType { // int a; // }; // union myType { // int a; // }; // typedef int myType; // enum myType {}; public void testChangingTypePlainC() throws Exception { setupFile(4, false); IBinding binding; ICompositeType ct; fIndex.acquireReadLock(); try { binding = findBinding("myType"); assertTrue(binding instanceof ICompositeType); ct = (ICompositeType) binding; assertTrue(ct.getKey() == ICompositeType.k_struct); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { binding = findBinding("myType"); assertTrue(binding instanceof ICompositeType); ct = (ICompositeType) binding; assertTrue(ct.getKey() == ICompositeType.k_union); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { binding = findBinding("myType"); assertTrue(binding instanceof ITypedef); ITypedef td = (ITypedef) binding; assertEquals(INT, ASTTypeUtil.getType(td.getType())); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { binding = findBinding("myType"); assertTrue(binding instanceof IEnumeration); } finally { fIndex.releaseReadLock(); } } // class myType { // int a; // }; // struct myType { // int a; // }; // union myType { // int a; // }; // typedef int myType; // enum myType {}; public void testChangingTypeCPP() throws Exception { setupFile(4, true); IBinding binding; ICompositeType ct; fIndex.acquireReadLock(); try { binding = findBinding("myType"); assertTrue(binding instanceof ICompositeType); ct = (ICompositeType) binding; assertTrue(ct.getKey() == ICompositeType.k_struct); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { binding = findBinding("myType"); assertTrue(binding instanceof ICompositeType); ct = (ICompositeType) binding; assertTrue(ct.getKey() == ICompositeType.k_union); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { binding = findBinding("myType"); assertTrue(binding instanceof ITypedef); ITypedef td = (ITypedef) binding; assertEquals(INT, ASTTypeUtil.getType(td.getType())); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { binding = findBinding("myType"); assertTrue(binding instanceof IEnumeration); } finally { fIndex.releaseReadLock(); } } // template<typename T> class CT {}; // template<typename T=int> class CT {}; // template<typename T=char> class CT {}; // template<int U, typename T> struct CT {}; // template<template<typename T> class V> class CT {}; // template<template<template<typename I> class T> class V> class CT {}; // template<typename U> class CT {}; public void testClassTemplates() throws Exception { setupFile(7, true); ICPPClassTemplate binding; ICompositeType ct; fIndex.acquireReadLock(); long pdomid; try { binding = (ICPPClassTemplate) findBinding("CT"); assertEquals(ICPPClassType.k_class , binding.getKey()); ICPPTemplateParameter[] tpars = binding.getTemplateParameters(); assertEquals(1, tpars.length); assertTrue(tpars[0] instanceof ICPPTemplateTypeParameter); assertEquals(0, tpars[0].getParameterID()); assertEquals("T", tpars[0].getName()); assertNull(tpars[0].getDefaultValue()); pdomid= ((IAdaptable) tpars[0]).getAdapter(PDOMNode.class).getRecord(); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { binding = (ICPPClassTemplate) findBinding("CT"); assertEquals(ICPPClassType.k_class , binding.getKey()); ICPPTemplateParameter[] tpars = binding.getTemplateParameters(); assertEquals(1, tpars.length); assertTrue(tpars[0] instanceof ICPPTemplateTypeParameter); assertEquals(0, tpars[0].getParameterID()); assertEquals("T", tpars[0].getName()); assertEquals("int", ASTTypeUtil.getType(tpars[0].getDefaultValue().getTypeValue())); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { binding = (ICPPClassTemplate) findBinding("CT"); assertEquals(ICPPClassType.k_class , binding.getKey()); ICPPTemplateParameter[] tpars = binding.getTemplateParameters(); assertEquals(1, tpars.length); assertTrue(tpars[0] instanceof ICPPTemplateTypeParameter); assertEquals(0, tpars[0].getParameterID()); assertEquals("T", tpars[0].getName()); assertEquals("char", ASTTypeUtil.getType(tpars[0].getDefaultValue().getTypeValue())); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { binding = (ICPPClassTemplate) findBinding("CT"); assertEquals(ICompositeType.k_struct , binding.getKey()); ICPPTemplateParameter[] tpars = binding.getTemplateParameters(); assertEquals(2, tpars.length); assertTrue(tpars[0] instanceof ICPPTemplateNonTypeParameter); assertEquals("U", tpars[0].getName()); assertEquals(0, tpars[0].getParameterID()); assertTrue(tpars[1] instanceof ICPPTemplateTypeParameter); assertEquals("T", tpars[1].getName()); assertEquals(1, tpars[1].getParameterID()); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { binding = (ICPPClassTemplate) findBinding("CT"); assertEquals(ICPPClassType.k_class , binding.getKey()); ICPPTemplateParameter[] tpars = binding.getTemplateParameters(); assertEquals(1, tpars.length); assertTrue(tpars[0] instanceof ICPPTemplateTemplateParameter); assertEquals("V", tpars[0].getName()); assertEquals(0, tpars[0].getParameterID()); tpars= ((ICPPTemplateTemplateParameter) tpars[0]).getTemplateParameters(); assertEquals(1, tpars.length); assertTrue(tpars[0] instanceof ICPPTemplateTypeParameter); assertEquals(0x10000, tpars[0].getParameterID()); assertEquals("T", tpars[0].getName()); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { binding = (ICPPClassTemplate) findBinding("CT"); assertEquals(ICPPClassType.k_class , binding.getKey()); ICPPTemplateParameter[] tpars = binding.getTemplateParameters(); assertEquals(1, tpars.length); assertTrue(tpars[0] instanceof ICPPTemplateTemplateParameter); assertEquals("V", tpars[0].getName()); assertEquals(0, tpars[0].getParameterID()); tpars= ((ICPPTemplateTemplateParameter) tpars[0]).getTemplateParameters(); assertEquals(1, tpars.length); assertTrue(tpars[0] instanceof ICPPTemplateTemplateParameter); assertEquals(0x10000, tpars[0].getParameterID()); assertEquals("T", tpars[0].getName()); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { binding = (ICPPClassTemplate) findBinding("CT"); assertEquals(ICPPClassType.k_class , binding.getKey()); ICPPTemplateParameter[] tpars = binding.getTemplateParameters(); assertEquals(1, tpars.length); assertTrue(tpars[0] instanceof ICPPTemplateTypeParameter); assertEquals(0, tpars[0].getParameterID()); assertEquals("U", tpars[0].getName()); assertEquals(pdomid, ((IAdaptable) tpars[0]).getAdapter(PDOMNode.class).getBindingID()); } finally { fIndex.releaseReadLock(); } } // int globalVar; // #include "header.h" // void test() { // globalVar= 1; // } public void testChangingSourceBeforeHeader_Bug171834() throws Exception { CModelListener.sSuppressUpdateOfLastRecentlyUsed= false; setupHeader(2, true); setupFile(0, true); IBinding binding; ICompositeType ct; fIndex.acquireReadLock(); try { binding = findBinding("globalVar"); assertTrue(binding instanceof IVariable); assertEquals(2, fIndex.findNames(binding, IIndex.FIND_ALL_OCCURRENCES).length); } finally { fIndex.releaseReadLock(); } fFile= TestSourceReader.createFile(fFile.getParent(), fFile.getName(), fContents[1].toString().replaceAll("globalVar", "newVar")); TestSourceReader.waitUntilFileIsIndexed(fIndex, fFile, INDEXER_TIMEOUT_MILLISEC); fIndex.acquireReadLock(); try { binding = findBinding("globalVar"); assertTrue(binding instanceof IVariable); assertEquals(1, fIndex.findNames(binding, IIndex.FIND_ALL_OCCURRENCES).length); } finally { fIndex.releaseReadLock(); } fHeader= TestSourceReader.createFile(fHeader.getParent(), fHeader.getName(), fContents[0].toString().replaceAll("globalVar", "newVar")); waitUntilFileIsIndexed(fIndex, fHeader); fIndex.acquireReadLock(); try { binding = findBinding("newVar"); assertTrue(binding instanceof IVariable); assertEquals(2, fIndex.findNames(binding, IIndex.FIND_ALL_OCCURRENCES).length); } finally { fIndex.releaseReadLock(); } } // int globalVar; // void func(); // extern "C" { // int globalVar; // void func(); // } // int globalVar; // void func(); // extern "C" int globalVar; // extern "C" void func(); // int globalVar; // void func(); public void testExternC() throws Exception { setupFile(5, true); checkExternC(false); updateFile(); checkExternC(true); updateFile(); checkExternC(false); updateFile(); checkExternC(true); updateFile(); checkExternC(false); } private void checkExternC(boolean value) throws Exception { fIndex.acquireReadLock(); try { ICPPVariable var = (ICPPVariable) findBinding("globalVar"); assertEquals(value, var.isExternC()); ICPPFunction func = (ICPPFunction) findBinding("func"); assertEquals(value, func.isExternC()); } finally { fIndex.releaseReadLock(); } } // int global; // struct C {int mem;}; // enum E {e0}; // int global=1; // struct C {int mem=1;}; // enum E {e0=1}; // int global; // struct C {int mem;}; // enum E {e0}; public void testValuesC() throws Exception { setupFile(3, false); checkValue("global", null); checkValue("C::mem", null); checkValue("e0", 0L); updateFile(); checkValue("global", 1L); checkValue("C::mem", 1L); checkValue("e0", 1L); updateFile(); checkValue("global", null); checkValue("C::mem", null); checkValue("e0", 0L); } // class A { // public: void foo(); // }; // class A { // public: void foo() throw(); // }; // class A { // public: void foo() throw(int, double); // }; // class A { // public: void foo() throw(); // }; // class A { // public: void foo(); // }; public void testExceptionSpecification() throws Exception { ICPPMethod method; IType[] exceptionSpec; setupFile(5, true); fIndex.acquireReadLock(); try { method = (ICPPMethod) findBinding("A::foo"); exceptionSpec = method.getExceptionSpecification(); assertNull(exceptionSpec); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { method = (ICPPMethod) findBinding("A::foo"); exceptionSpec = method.getExceptionSpecification(); assertEquals(0, exceptionSpec.length); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { method = (ICPPMethod) findBinding("A::foo"); exceptionSpec = method.getExceptionSpecification(); assertNotNull(exceptionSpec); assertEquals(2, exceptionSpec.length); assertEquals("int", ASTTypeUtil.getType(exceptionSpec[0])); assertEquals("double", ASTTypeUtil.getType(exceptionSpec[1])); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { method = (ICPPMethod) findBinding("A::foo"); exceptionSpec = method.getExceptionSpecification(); assertEquals(0, exceptionSpec.length); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { method = (ICPPMethod) findBinding("A::foo"); exceptionSpec = method.getExceptionSpecification(); assertNull(exceptionSpec); } finally { fIndex.releaseReadLock(); } } // int global; // struct C {int mem;}; // enum E {e0}; // int global=1; // struct C {int mem=1;}; // enum E {e0=1}; // int global; // struct C {int mem;}; // enum E {e0}; public void testValuesCPP() throws Exception { setupFile(3, true); checkValue("global", null); checkValue("C::mem", null); checkValue("e0", 0L); updateFile(); checkValue("global", 1L); checkValue("C::mem", 1L); checkValue("e0", 1L); updateFile(); checkValue("global", null); checkValue("C::mem", null); checkValue("e0", 0L); } //class A {}; //class B {friend class A;}; //class B {}; public void testFriendClass() throws Exception { setupFile(2, true); assertFriendRemoval("B", "A"); } // class X {public: char* foo(int);}; // class Y {friend char* X::foo(int);}; // class Y {}; public void testFriendMethod() throws Exception { setupFile(2, true); assertFriendRemoval("Y", "X::foo"); } // class X {friend void friend_set(X*, int);}; // void friend_set(X* p, int i) {} // class X {}; public void testFriendFunction() throws Exception { setupFile(2, true); assertFriendRemoval("X", "friend_set"); } private void assertFriendRemoval(String clientClassBinding, String supplierBinding) throws Exception { fIndex.acquireReadLock(); try { IBinding client = findBinding(clientClassBinding); IBinding supplier = findBinding(supplierBinding); assertNotNull("Unable to find binding with name \""+clientClassBinding+"\"", client); assertTrue("Unable to find binding with name \""+clientClassBinding+"\"", client instanceof ICPPClassType); assertNotNull("Unable to find binding with name \""+supplierBinding+"\"", supplier); assertTrue(((ICPPClassType)client).getFriends().length == 1); assertTrue(((ICPPClassType)client).getFriends()[0].equals(supplier)); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { IBinding client = findBinding(clientClassBinding); assertNotNull("Unable to find binding with name \""+clientClassBinding+"\"", client); assertTrue("Unable to find binding with name \""+clientClassBinding+"\"", client instanceof ICPPClassType); assertTrue(((ICPPClassType)client).getFriends().length == 0); } finally { fIndex.releaseReadLock(); } } // void funcTypeDeletion(int); // #include "header.h" // typeof(funcTypeDeletion) storeRef; // char funcTypeDeletion(int); // delete type // typeof(storeRef) useRef; // use reference public void testTypedeletion_Bug294306() throws Exception { setupHeader(2, true); setupFile(2, true); checkFunction("useRef", new String[]{"void", "int"}, new String[]{}); fContentUsed--; updateFile(); checkFunction("useRef", new String[]{"char", "int"}, new String[]{}); } // void f(int a, int b=0); // #include "header.h" // void f(int a, int b) {} // void ref() { // f(1); // } // #include "header.h" // void f(int a, int b) {} // void ref() { // f(1); // } public void testDefaultParam_Bug297438() throws Exception { setupHeader(3, true); setupFile(3, true); checkReferenceCount("f", 1); updateFile(); checkReferenceCount("f", 1); } private void checkReferenceCount(String name, int count) throws InterruptedException, CoreException { fIndex.acquireReadLock(); try { IBinding func = findBinding(name); assertEquals(count, fIndex.findReferences(func).length); } finally { fIndex.releaseReadLock(); } } // enum E {e0}; // enum class E; // enum E : short {e1}; // enum class E {e2}; // enum class E : short {e1}; // enum E : int; public void testEnumCPP() throws Exception { setupFile(6, true); checkEnum(false, null, "e0"); updateFile(); checkEnum(true, "int", null); updateFile(); checkEnum(false, "short int", "e1"); updateFile(); checkEnum(true, "int", "e2"); updateFile(); checkEnum(true, "short int", "e1"); updateFile(); checkEnum(false, "int", null); } private void checkEnum(boolean scoped, String fixedType, String enumItem) throws Exception { fIndex.acquireReadLock(); try { ICPPEnumeration enumType = (ICPPEnumeration) findBinding("E"); assertEquals(scoped, enumType.isScoped()); if (fixedType == null) { assertNull(enumType.getFixedType()); } else { assertEquals(fixedType, ASTTypeUtil.getType(enumType.getFixedType())); } final IEnumerator[] enumItems = enumType.getEnumerators(); if (enumItem == null) { assertEquals(0, enumItems.length); } else { assertEquals(1, enumItems.length); assertEquals(enumItem, enumItems[0].getName()); } } finally { fIndex.releaseReadLock(); } } // class X {}; // class X {}; public void testFileLocalBinding() throws Exception { setupFile(2, true); long id1, id2; fIndex.acquireReadLock(); try { final IIndexBinding binding = findBinding("X"); id1= ((PDOMFile) binding.getLocalToFile()).getRecord(); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { final IIndexBinding binding = findBinding("X"); id2= ((PDOMFile) binding.getLocalToFile()).getRecord(); } finally { fIndex.releaseReadLock(); } assertEquals(id1, id2); } // namespace ns { // namespace m {} // } // inline namespace ns { // inline namespace m {} // } // namespace ns { // namespace m {} // } public void testInlineNamespaces_305980() throws Exception { setupFile(3, true); fIndex.acquireReadLock(); try { final ICPPNamespace ns = (ICPPNamespace) findBinding("ns"); assertFalse(ns.isInline()); final ICPPNamespace m = (ICPPNamespace) findBinding("ns::m"); assertFalse(ns.isInline()); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { final ICPPNamespace ns = (ICPPNamespace) findBinding("ns"); assertTrue(ns.isInline()); final ICPPNamespace m = (ICPPNamespace) findBinding("ns::m"); assertTrue(ns.isInline()); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { final ICPPNamespace ns = (ICPPNamespace) findBinding("ns"); assertFalse(ns.isInline()); final ICPPNamespace m = (ICPPNamespace) findBinding("ns::m"); assertFalse(ns.isInline()); } finally { fIndex.releaseReadLock(); } } // typedef enum { // AE_ON = 0 // } Adaptiv_T; // struct mystruct { // Adaptiv_T eAdapt; // }; // int main() { // mystruct ms; // ms.eAdapt = AE_ON; // } // // insert line // typedef enum { // AE_ON = 0 // } Adaptiv_T; // struct mystruct { // Adaptiv_T eAdapt; // }; public void testAnonymousEnum_Bug356057cpp() throws Exception { setupHeader(3, true); setupFile(3, true); String name1; fIndex.acquireReadLock(); try { final IEnumerator e = (IEnumerator) findBinding("AE_ON"); assertNotNull(e); name1= e.getOwner().getName(); } finally { fIndex.releaseReadLock(); } updateHeader(); fIndex.acquireReadLock(); try { final IEnumerator e = (IEnumerator) findBinding("AE_ON"); assertNotNull(e); assertFalse(name1.equals(e.getOwner().getName())); } finally { fIndex.releaseReadLock(); } } // typedef enum { // AE_ON = 0 // } Adaptiv_T; // struct mystruct { // Adaptiv_T eAdapt; // }; // int main() { // mystruct ms; // ms.eAdapt = AE_ON; // } // // insert line // typedef enum { // AE_ON = 0 // } Adaptiv_T; // struct mystruct { // Adaptiv_T eAdapt; // }; public void testAnonymousEnum_Bug356057c() throws Exception { setupHeader(3, false); setupFile(3, false); String name1; fIndex.acquireReadLock(); try { final IEnumerator e = (IEnumerator) findBinding("AE_ON"); assertNotNull(e); name1= e.getOwner().getName(); } finally { fIndex.releaseReadLock(); } updateHeader(); fIndex.acquireReadLock(); try { final IEnumerator e = (IEnumerator) findBinding("AE_ON"); assertNotNull(e); assertFalse(name1.equals(e.getOwner().getName())); } finally { fIndex.releaseReadLock(); } } // struct S {}; // struct S {S(int){}}; public void testImplicitDefaultCtor_Bug359376() throws Exception { setupFile(2, true); fIndex.acquireReadLock(); try { final ICPPClassType s = (ICPPClassType) findBinding("S"); assertNotNull(s); final ICPPConstructor[] ctors = s.getConstructors(); assertEquals(2, ctors.length); // 2 implicit ctors assertTrue(ctors[0].isImplicit()); assertTrue(ctors[1].isImplicit()); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { final ICPPClassType s = (ICPPClassType) findBinding("S"); assertNotNull(s); final ICPPConstructor[] ctors = s.getConstructors(); assertEquals(2, ctors.length); // 1 explicit and one implicit ctor assertTrue(ctors[0].isImplicit() != ctors[1].isImplicit()); } finally { fIndex.releaseReadLock(); } } // struct Base { // void foo() {} // }; // struct Derived: Base { // Derived(); // }; // struct Base { // void foo() {} // }; // struct Derived: Base { // Derived(); // }; public void testBaseClass_Bug391284() throws Exception { setupFile(2, true); fIndex.acquireReadLock(); try { final ICPPClassType s = (ICPPClassType) findBinding("Derived"); assertNotNull(s); final ICPPBase[] bases = s.getBases(); assertEquals(1, bases.length); assertEquals("Base", bases[0].getBaseClass().getName()); } finally { fIndex.releaseReadLock(); } updateFile(); fIndex.acquireReadLock(); try { final ICPPClassType s = (ICPPClassType) findBinding("Derived"); assertNotNull(s); final ICPPBase[] bases = s.getBases(); assertEquals(1, bases.length); assertEquals("Base", bases[0].getBaseClass().getName()); } finally { fIndex.releaseReadLock(); } } }