/*******************************************************************************
* 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
* IBM Corporation
* Andrew Ferguson (Symbian)
* Anton Leherbauer (Wind River Systems)
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.browser;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.EScopeKind;
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.IMacroBinding;
import org.eclipse.cdt.core.dom.ast.IParameter;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceAlias;
import org.eclipse.cdt.core.index.IIndexMacroContainer;
import org.eclipse.cdt.core.model.ICElement;
/**
* Convenience class for bridging the model gap between binding types and CModel types
*
* This is internal in case some IBinding's do not have ICElement constants in future
*/
public class IndexModelUtil {
private static final String[] EMPTY_STRING_ARRAY= {};
/**
* Returns whether the binding is of any of the specified CElement type constants
*
* @param binding
* @param kinds
* @return whether the binding is of any of the specified CElement type constants
*/
public static boolean bindingHasCElementType(IBinding binding, int[] kinds) {
for (int kind : kinds) {
switch (kind) {
case ICElement.C_STRUCT:
if (binding instanceof ICompositeType
&& ((ICompositeType) binding).getKey() == ICompositeType.k_struct)
return true;
break;
case ICElement.C_UNION:
if (binding instanceof ICompositeType
&& ((ICompositeType) binding).getKey() == ICompositeType.k_union)
return true;
break;
case ICElement.C_CLASS:
if (binding instanceof ICompositeType
&& ((ICompositeType) binding).getKey() == ICPPClassType.k_class)
return true;
break;
case ICElement.C_NAMESPACE:
if (binding instanceof ICPPNamespace || binding instanceof ICPPNamespaceAlias)
return true;
break;
case ICElement.C_ENUMERATION:
if (binding instanceof IEnumeration)
return true;
break;
case ICElement.C_TYPEDEF:
if(binding instanceof ITypedef)
return true;
break;
case ICElement.C_FUNCTION:
if(binding instanceof IFunction)
return true;
break;
case ICElement.C_VARIABLE:
if(binding instanceof IVariable)
return true;
break;
case ICElement.C_ENUMERATOR:
if (binding instanceof IEnumerator)
return true;
break;
}
}
return false;
}
/**
* Returns the CElement type constant for the specified binding
* @param binding
* @return the CElement type constant for the specified binding
*/
public static int getElementType(IBinding binding) {
int elementType = Integer.MIN_VALUE;
if (binding instanceof ICompositeType) {
ICompositeType classType = (ICompositeType) binding;
switch(classType.getKey()) {
case ICPPClassType.k_class:
elementType = ICElement.C_CLASS;
break;
case ICompositeType.k_struct:
elementType = ICElement.C_STRUCT;
break;
case ICompositeType.k_union:
elementType = ICElement.C_UNION;
break;
}
}
if (binding instanceof ICPPNamespace || binding instanceof ICPPNamespaceAlias) {
elementType = ICElement.C_NAMESPACE;
}
if (binding instanceof IEnumeration) {
elementType = ICElement.C_ENUMERATION;
}
if (binding instanceof ITypedef) {
elementType = ICElement.C_TYPEDEF;
}
if (binding instanceof IFunction) {
elementType = ICElement.C_FUNCTION;
}
if (binding instanceof IVariable) {
IScope scope= null;
try {
scope = binding.getScope();
} catch (DOMException e) {
}
if (scope != null && scope.getKind() == EScopeKind.eLocal) {
elementType= ICElement.C_VARIABLE_LOCAL;
} else {
elementType = ICElement.C_VARIABLE;
}
}
if (binding instanceof IEnumerator) {
elementType = ICElement.C_ENUMERATOR;
}
if (binding instanceof IMacroBinding || binding instanceof IIndexMacroContainer) {
elementType= ICElement.C_MACRO;
}
if (binding instanceof IParameter) {
elementType= ICElement.C_VARIABLE_LOCAL;
}
return elementType;
}
/**
* Extract the parameter types of the given function as array of strings.
* @param function
* @return the parameter types of the function
* @throws DOMException
*/
public static String[] extractParameterTypes(IFunction function) throws DOMException {
IParameter[] params= function.getParameters();
boolean vararg = function.takesVarArgs();
int paramCount = params.length + (vararg ? 1 : 0);
String[] parameterTypes= new String[paramCount];
for (int i = 0; i < params.length; i++) {
IParameter param = params[i];
parameterTypes[i]= ASTTypeUtil.getType(param.getType(), false);
}
if (vararg) {
parameterTypes[paramCount - 1] = "..."; //$NON-NLS-1$
}
if (parameterTypes.length == 1 && parameterTypes[0].equals("void")) { //$NON-NLS-1$
return EMPTY_STRING_ARRAY;
}
return parameterTypes;
}
/**
* Extract the return type of the given function as string.
* @param function
* @return the return type of the function
* @throws DOMException
*/
public static String extractReturnType(IFunction function) throws DOMException {
return ASTTypeUtil.getType(function.getType().getReturnType(), false);
}
}