/******************************************************************************* * Copyright (c) 2006, 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: * Anton Leherbauer (Wind River Systems) - initial API and implementation * Markus Schorn (Wind River Systems) * Sergey Prigogin (Google) * Marc-Andre Laperle (Ericsson) *******************************************************************************/ package org.eclipse.cdt.internal.core.model; import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator; import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression; import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; import org.eclipse.cdt.core.dom.ast.IASTCastExpression; import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTConditionalExpression; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier; import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTExpressionList; import org.eclipse.cdt.core.dom.ast.IASTFieldDeclarator; import org.eclipse.cdt.core.dom.ast.IASTFieldReference; import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTIdExpression; import org.eclipse.cdt.core.dom.ast.IASTInitializer; import org.eclipse.cdt.core.dom.ast.IASTInitializerClause; import org.eclipse.cdt.core.dom.ast.IASTInitializerList; import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.IASTPointer; import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression; import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; import org.eclipse.cdt.core.dom.ast.c.ICASTDesignatedInitializer; import org.eclipse.cdt.core.dom.ast.c.ICASTSimpleDeclSpecifier; import org.eclipse.cdt.core.dom.ast.c.ICASTTypeIdInitializerExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCastExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDecltypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignatedInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator.RefQualifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNameSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTPackExpansionExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTPointerToMember; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTReferenceOperator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeConstructorExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplatedTypeTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeIdExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression; import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression; import org.eclipse.cdt.core.dom.ast.gnu.c.ICASTKnRFunctionDeclarator; import org.eclipse.cdt.core.parser.GCCKeywords; import org.eclipse.cdt.core.parser.Keywords; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; /** * This is a utility class to help convert AST elements to strings. * * @see org.eclipse.cdt.core.dom.ast.ASTTypeUtil */ public class ASTStringUtil { private static final String SPACE= " "; //$NON-NLS-1$ private static final String COMMA_SPACE= ", "; //$NON-NLS-1$ private static final String[] EMPTY_STRING_ARRAY= {}; /** * Return the qualified name if the given <code>IASTName</code> * is an <code>ICPPASTQualifiedName</code>, otherwise a simple name is returned. * * @param name * @return a (possibly) qualified name */ public static String getQualifiedName(IASTName name) { return appendQualifiedNameString(new StringBuilder(), name).toString(); } /** * Return the non-qualified name. * * @param name * @return a non-qualified name */ public static String getSimpleName(IASTName name) { return appendSimpleNameString(new StringBuilder(), name).toString(); } /** * Compute a signature string with parameters, without initializers. */ public static String getSignatureString(IASTDeclarator declarator) { return trimRight(appendSignatureString(new StringBuilder(), declarator)).toString(); } /** * Compute a signature string including parameters, but without initializers. * * @param declSpecifier * @param declarator * @return the signature string */ public static String getSignatureString(IASTDeclSpecifier declSpecifier, IASTDeclarator declarator) { final StringBuilder buffer= new StringBuilder(); appendDeclarationString(buffer, declSpecifier, declarator, null); return trimRight(buffer).toString(); } /** * Compute the return-type string for a function declarator. * * @param declSpecifier * @param fdecl * @return the return type string */ public static String getReturnTypeString(IASTDeclSpecifier declSpecifier, IASTFunctionDeclarator fdecl) { final StringBuilder buffer= new StringBuilder(); final IASTDeclarator declarator= ASTQueries.findOutermostDeclarator(fdecl); appendDeclarationString(buffer, declSpecifier, declarator, fdecl); return trimRight(buffer).toString(); } /** * Get the signatures of the function parameter declarations. * * @param functionDeclarator * @return the parameter signature array */ public static String[] getParameterSignatureArray(IASTFunctionDeclarator functionDeclarator) { if (functionDeclarator instanceof IASTStandardFunctionDeclarator) { final IASTStandardFunctionDeclarator standardFunctionDecl= (IASTStandardFunctionDeclarator) functionDeclarator; final IASTParameterDeclaration[] parameters= standardFunctionDecl.getParameters(); final boolean takesVarArgs= standardFunctionDecl.takesVarArgs(); final String[] parameterStrings= new String[parameters.length + (takesVarArgs ? 1 : 0)]; int i; for (i = 0; i < parameters.length; ++i) { parameterStrings[i]= getParameterSignatureString(parameters[i]); } if (takesVarArgs) { parameterStrings[i]= new String(Keywords.cpELLIPSIS); } return parameterStrings; } else if (functionDeclarator instanceof ICASTKnRFunctionDeclarator) { final ICASTKnRFunctionDeclarator knrDeclarator= (ICASTKnRFunctionDeclarator) functionDeclarator; final IASTName[] names= knrDeclarator.getParameterNames(); final String[] result= new String[names.length]; for (int i = 0; i < names.length; i++) { if (names[i] != null) { final IASTDeclarator declaratorForParameterName= knrDeclarator.getDeclaratorForParameterName(names[i]); if (declaratorForParameterName != null) { result[i]= getSignatureString(declaratorForParameterName); } else { result[i]= "?"; //$NON-NLS-1$ } } } return result; } return EMPTY_STRING_ARRAY; } /** * Convert the given template parameters into a string array. * * @param templateParams * @return a string array of template parameters */ public static String[] getTemplateParameterArray(ICPPASTTemplateParameter[] templateParams) { final String[] parameterTypes= new String[templateParams.length]; for (int i = 0; i < templateParams.length; i++) { final StringBuilder paramType= new StringBuilder(); final ICPPASTTemplateParameter parameter= templateParams[i]; appendTemplateParameterString(paramType, parameter); parameterTypes[i]= trimRight(paramType).toString(); } return parameterTypes; } /** * Returns a string representation for the given expression */ public static String getExpressionString(IASTExpression expression) { StringBuilder buf= new StringBuilder(); return appendExpressionString(buf, expression).toString(); } public static String getInitializerString(IASTInitializer init) { StringBuilder buf= new StringBuilder(); return appendInitializerString(buf, init).toString(); } /** * Joins strings together using a given delimiter. * @param strings the strings to join. * @param delimiter the delimiter that is put between the strings when joining them. * @return the joined string. */ public static String join(String[] strings, CharSequence delimiter) { if (strings.length == 0) { return ""; //$NON-NLS-1$ } else if (strings.length == 1) { return strings[0]; } else { StringBuilder buf = new StringBuilder(strings[0]); for (int i = 1; i < strings.length; i++) { buf.append(delimiter); buf.append(strings[i]); } return buf.toString(); } } private static String getParameterSignatureString(IASTParameterDeclaration parameterDeclaration) { return trimRight(appendParameterDeclarationString(new StringBuilder(), parameterDeclaration)).toString(); } private static StringBuilder appendSignatureString(StringBuilder buffer, IASTDeclarator declarator) { // get the declaration node IASTNode node= declarator.getParent(); while (node instanceof IASTDeclarator) { declarator= (IASTDeclarator) node; node= node.getParent(); } // get the declSpec final IASTDeclSpecifier declSpec; if (node instanceof IASTParameterDeclaration) { declSpec= ((IASTParameterDeclaration) node).getDeclSpecifier(); } else if (node instanceof IASTSimpleDeclaration) { declSpec= ((IASTSimpleDeclaration) node).getDeclSpecifier(); } else if (node instanceof IASTFunctionDefinition) { declSpec= ((IASTFunctionDefinition) node).getDeclSpecifier(); } else if (node instanceof IASTTypeId) { declSpec= ((IASTTypeId) node).getDeclSpecifier(); } else { declSpec= null; } return appendDeclarationString(buffer, declSpec, declarator, null); } private static StringBuilder appendDeclarationString(StringBuilder buffer, IASTDeclSpecifier declSpecifier, IASTDeclarator declarator, IASTFunctionDeclarator returnTypeOf) { if (declSpecifier != null) { appendDeclSpecifierString(buffer, declSpecifier); trimRight(buffer); } appendDeclaratorString(buffer, declarator, false, returnTypeOf); return buffer; } private static StringBuilder appendDeclaratorString(StringBuilder buffer, IASTDeclarator declarator, boolean protectPointers, IASTFunctionDeclarator returnTypeOf) { if (declarator == null) { return buffer; } final IASTPointerOperator[] ptrs = declarator.getPointerOperators(); final boolean useParenthesis= protectPointers && ptrs.length > 0; if (useParenthesis) { buffer.append(Keywords.cpLPAREN); protectPointers= false; } appendPointerOperatorsString(buffer, ptrs); if (declarator != returnTypeOf) { final IASTDeclarator nestedDeclarator= declarator.getNestedDeclarator(); if (nestedDeclarator != null) { protectPointers= protectPointers || declarator instanceof IASTArrayDeclarator || declarator instanceof IASTFunctionDeclarator || declarator instanceof IASTFieldDeclarator; appendDeclaratorString(buffer, nestedDeclarator, protectPointers, returnTypeOf); } else if (declarator instanceof ICPPASTDeclarator && ((ICPPASTDeclarator) declarator).declaresParameterPack()) { buffer.append(Keywords.cpELLIPSIS); } if (declarator instanceof IASTArrayDeclarator) { appendArrayQualifiersString(buffer, (IASTArrayDeclarator) declarator); } else if (declarator instanceof IASTFunctionDeclarator) { final IASTFunctionDeclarator functionDecl= (IASTFunctionDeclarator) declarator; appendParameterSignatureString(buffer, functionDecl); if (declarator instanceof ICPPASTFunctionDeclarator) { final ICPPASTFunctionDeclarator cppFunctionDecl= (ICPPASTFunctionDeclarator) declarator; if (cppFunctionDecl.isConst()) { buffer.append(Keywords.CONST).append(' '); } if (cppFunctionDecl.isVolatile()) { buffer.append(Keywords.VOLATILE).append(' '); } RefQualifier refQualifier = cppFunctionDecl.getRefQualifier(); if (refQualifier != null) { switch (refQualifier) { case LVALUE: buffer.append(Keywords.cpAMPER).append(' '); break; case RVALUE: buffer.append(Keywords.cpAND).append(' '); break; } } if (cppFunctionDecl.isPureVirtual()) { buffer.append("=0 "); //$NON-NLS-1$ } final IASTTypeId[] exceptionTypeIds= cppFunctionDecl.getExceptionSpecification(); if (exceptionTypeIds != ICPPASTFunctionDeclarator.NO_EXCEPTION_SPECIFICATION) { buffer.append(Keywords.THROW).append(" ("); //$NON-NLS-1$ for (int i= 0; i < exceptionTypeIds.length; i++) { if (i > 0) { buffer.append(COMMA_SPACE); } appendTypeIdString(buffer, exceptionTypeIds[i]); } buffer.append(')'); } } } else if (declarator instanceof IASTFieldDeclarator) { final IASTFieldDeclarator fieldDeclarator= (IASTFieldDeclarator) declarator; final IASTExpression bitFieldSize= fieldDeclarator.getBitFieldSize(); if (bitFieldSize != null) { buffer.append(Keywords.cpCOLON); appendExpressionString(buffer, bitFieldSize); } } else { // just a nested name } } if (useParenthesis) { trimRight(buffer); buffer.append(Keywords.cpRPAREN); } return buffer; } private static StringBuilder appendInitializerString(StringBuilder buffer, IASTInitializer initializer) { if (initializer instanceof IASTEqualsInitializer) { final IASTEqualsInitializer initializerExpression= (IASTEqualsInitializer) initializer; buffer.append(Keywords.cpASSIGN); appendInitClauseString(buffer, initializerExpression.getInitializerClause()); } else if (initializer instanceof IASTInitializerList) { final IASTInitializerList initializerList= (IASTInitializerList) initializer; final IASTInitializerClause[] initializers= initializerList.getClauses(); buffer.append(Keywords.cpASSIGN); buffer.append(Keywords.cpLBRACE); for (int i= 0; i < initializers.length; i++) { if (i > 0) { buffer.append(COMMA_SPACE); } appendInitClauseString(buffer, initializers[i]); } trimRight(buffer); buffer.append(Keywords.cpRBRACE); } else if (initializer instanceof ICASTDesignatedInitializer || initializer instanceof ICPPASTDesignatedInitializer) { //TODO handle ICASTDesignatedInitializer? // final ICASTDesignatedInitializer designatedInitializer= (ICASTDesignatedInitializer) initializer; // final ICASTDesignator[] designator= designatedInitializer.getDesignators(); } else if (initializer instanceof ICPPASTConstructorInitializer) { final ICPPASTConstructorInitializer constructorInitializer= (ICPPASTConstructorInitializer) initializer; final IASTInitializerClause[] clauses= constructorInitializer.getArguments(); buffer.append(Keywords.cpLPAREN); for (int i= 0; i < clauses.length; i++) { if (i > 0) { buffer.append(COMMA_SPACE); } appendInitClauseString(buffer, clauses[i]); } trimRight(buffer); buffer.append(Keywords.cpRPAREN); } else if (initializer != null) { assert false : "TODO: handle "+ initializer.getClass().getName(); //$NON-NLS-1$ } return buffer; } private static StringBuilder appendInitClauseString(StringBuilder buffer, IASTInitializerClause initializerClause) { if (initializerClause instanceof IASTExpression) { return appendExpressionString(buffer, (IASTExpression) initializerClause); } if (initializerClause instanceof IASTInitializer) { return appendInitializerString(buffer, (IASTInitializer) initializerClause); } return buffer; } private static StringBuilder appendTypeIdString(StringBuilder buffer, IASTTypeId typeId) { appendDeclSpecifierString(buffer, typeId.getDeclSpecifier()); appendDeclaratorString(buffer, typeId.getAbstractDeclarator(), false, null); if (typeId instanceof ICPPASTTypeId && ((ICPPASTTypeId) typeId).isPackExpansion()) buffer.append(Keywords.cpELLIPSIS); return buffer; } private static StringBuilder trimRight(StringBuilder buffer) { int length= buffer.length(); while (length > 0 && buffer.charAt(length - 1) == ' ') { --length; } buffer.setLength(length); return buffer; } private static StringBuilder appendArrayQualifiersString(StringBuilder buffer, IASTArrayDeclarator declarator) { final IASTArrayModifier[] modifiers= declarator.getArrayModifiers(); final int count= modifiers.length; for (int i = 0; i < count; i++) { buffer.append(Keywords.cpLBRACKET).append(Keywords.cpRBRACKET); } return buffer; } private static StringBuilder appendPointerOperatorsString(StringBuilder buffer, IASTPointerOperator[] pointerOperators) { for (final IASTPointerOperator pointerOperator : pointerOperators) { if (pointerOperator instanceof IASTPointer) { final IASTPointer pointer= (IASTPointer) pointerOperator; if (pointer instanceof ICPPASTPointerToMember) { final ICPPASTPointerToMember pointerToMember= (ICPPASTPointerToMember) pointer; appendQualifiedNameString(buffer, pointerToMember.getName()); } buffer.append(Keywords.cpSTAR); if (pointer.isConst()) { buffer.append(' ').append(Keywords.CONST); } if (pointer.isVolatile()) { buffer.append(' ').append(Keywords.VOLATILE); } if (pointer.isRestrict()) { buffer.append(' ').append(Keywords.RESTRICT); } } else if (pointerOperator instanceof ICPPASTReferenceOperator) { if (((ICPPASTReferenceOperator) pointerOperator).isRValueReference()) { buffer.append(Keywords.cpAND); } else { buffer.append(Keywords.cpAMPER); } } } return buffer; } private static StringBuilder appendParameterSignatureString(StringBuilder buffer, IASTFunctionDeclarator functionDeclarator) { if (functionDeclarator instanceof IASTStandardFunctionDeclarator) { final IASTStandardFunctionDeclarator standardFunctionDecl= (IASTStandardFunctionDeclarator) functionDeclarator; final IASTParameterDeclaration[] parameters= standardFunctionDecl.getParameters(); final boolean takesVarArgs= standardFunctionDecl.takesVarArgs(); buffer.append(Keywords.cpLPAREN); for (int i = 0; i < parameters.length; i++) { if (i > 0) { buffer.append(COMMA_SPACE); } appendParameterDeclarationString(buffer, parameters[i]); } if (takesVarArgs) { if (parameters.length > 0) { buffer.append(COMMA_SPACE); } buffer.append(Keywords.cpELLIPSIS); } trimRight(buffer); buffer.append(Keywords.cpRPAREN); } else if (functionDeclarator instanceof ICASTKnRFunctionDeclarator) { buffer.append(Keywords.cpLPAREN); final ICASTKnRFunctionDeclarator knrDeclarator= (ICASTKnRFunctionDeclarator) functionDeclarator; final IASTName[] names= knrDeclarator.getParameterNames(); for (int i = 0; i < names.length; i++) { if (i > 0) { buffer.append(COMMA_SPACE); } if (names[i] != null) { final IASTDeclarator declaratorForParameterName= knrDeclarator.getDeclaratorForParameterName(names[i]); if (declaratorForParameterName != null) { appendSignatureString(buffer, declaratorForParameterName); } } } trimRight(buffer); buffer.append(Keywords.cpRPAREN); } return buffer; } private static StringBuilder appendParameterDeclarationString(StringBuilder buffer, IASTParameterDeclaration parameter) { final IASTDeclSpecifier declSpecifier= parameter.getDeclSpecifier(); if (declSpecifier != null) { appendDeclSpecifierString(buffer, declSpecifier); trimRight(buffer); } final IASTDeclarator declarator= parameter.getDeclarator(); if (declarator != null) { appendDeclaratorString(buffer, declarator, false, null); appendInitializerString(buffer, declarator.getInitializer()); } return buffer; } private static StringBuilder appendDeclSpecifierString(StringBuilder buffer, IASTDeclSpecifier declSpecifier) { if (declSpecifier.isConst()) { buffer.append(Keywords.CONST).append(' '); } if (declSpecifier.isVolatile()) { buffer.append(Keywords.VOLATILE).append(' '); } // if (declSpecifier.isInline()) { // buffer.append(Keywords.INLINE).append(' '); // } // if (declSpecifier instanceof ICASTDeclSpecifier) { // final ICASTDeclSpecifier cDeclSpec= (ICASTDeclSpecifier) declSpecifier; // if (cDeclSpec.isRestrict()) { // buffer.append(Keywords.RESTRICT).append(' '); // } // } else if (declSpecifier instanceof ICPPASTDeclSpecifier) { // final ICPPASTDeclSpecifier cppDeclSpec= (ICPPASTDeclSpecifier) declSpecifier; // if (cppDeclSpec.isFriend()) { // buffer.append(Keywords.FRIEND).append(' '); // } // if (cppDeclSpec.isVirtual()) { // buffer.append(Keywords.VIRTUAL).append(' '); // } // if (cppDeclSpec.isExplicit()) { // buffer.append(Keywords.EXPLICIT).append(' '); // } // if (declSpecifier instanceof IGPPASTDeclSpecifier) { // final IGPPASTDeclSpecifier gppDeclSpec= (IGPPASTDeclSpecifier) declSpecifier; // if (gppDeclSpec.isRestrict()) { // buffer.append(Keywords.RESTRICT).append(' '); // } // } // } // storage class // final int storageClass= declSpecifier.getStorageClass(); // switch (storageClass) { // case IASTDeclSpecifier.sc_typedef: // buffer.append(Keywords.TYPEDEF).append(' '); // break; // case IASTDeclSpecifier.sc_extern: // buffer.append(Keywords.EXTERN).append(' '); // break; // case IASTDeclSpecifier.sc_static: // buffer.append(Keywords.STATIC).append(' '); // break; // case IASTDeclSpecifier.sc_auto: // buffer.append(Keywords.AUTO).append(' '); // break; // case IASTDeclSpecifier.sc_register: // buffer.append(Keywords.REGISTER).append(' '); // break; // case ICPPASTDeclSpecifier.sc_mutable: // buffer.append(Keywords.MUTABLE).append(' '); // break; // } if (declSpecifier instanceof IASTCompositeTypeSpecifier) { final IASTCompositeTypeSpecifier compositeTypeSpec= (IASTCompositeTypeSpecifier) declSpecifier; final int key= compositeTypeSpec.getKey(); switch (key) { case IASTCompositeTypeSpecifier.k_struct: buffer.append(Keywords.STRUCT).append(' '); break; case IASTCompositeTypeSpecifier.k_union: buffer.append(Keywords.UNION).append(' '); break; case ICPPASTCompositeTypeSpecifier.k_class: buffer.append(Keywords.CLASS).append(' '); break; default: } appendQualifiedNameString(buffer, compositeTypeSpec.getName()); } else if (declSpecifier instanceof IASTElaboratedTypeSpecifier) { final IASTElaboratedTypeSpecifier elaboratedTypeSpec= (IASTElaboratedTypeSpecifier) declSpecifier; switch (elaboratedTypeSpec.getKind()) { case IASTElaboratedTypeSpecifier.k_enum: buffer.append(Keywords.ENUM).append(' '); break; case IASTElaboratedTypeSpecifier.k_struct: buffer.append(Keywords.STRUCT).append(' '); break; case IASTElaboratedTypeSpecifier.k_union: buffer.append(Keywords.UNION).append(' '); break; case ICPPASTElaboratedTypeSpecifier.k_class: buffer.append(Keywords.CLASS).append(' '); break; default: assert false; } appendQualifiedNameString(buffer, elaboratedTypeSpec.getName()); } else if (declSpecifier instanceof IASTEnumerationSpecifier) { final IASTEnumerationSpecifier enumerationSpec= (IASTEnumerationSpecifier) declSpecifier; buffer.append(Keywords.ENUM).append(' '); appendQualifiedNameString(buffer, enumerationSpec.getName()); } else if (declSpecifier instanceof IASTSimpleDeclSpecifier) { final IASTSimpleDeclSpecifier simpleDeclSpec= (IASTSimpleDeclSpecifier) declSpecifier; if (simpleDeclSpec.isSigned()) { buffer.append(Keywords.SIGNED).append(' '); } if (simpleDeclSpec.isUnsigned()) { buffer.append(Keywords.UNSIGNED).append(' '); } if (simpleDeclSpec.isShort()) { buffer.append(Keywords.SHORT).append(' '); } if (simpleDeclSpec.isLong()) { buffer.append(Keywords.LONG).append(' '); } if (simpleDeclSpec.isLongLong()) { buffer.append(Keywords.LONG_LONG).append(' '); } if (simpleDeclSpec.isComplex()) { buffer.append(Keywords._COMPLEX).append(' '); } if (simpleDeclSpec.isImaginary()) { buffer.append(Keywords._IMAGINARY).append(' '); } switch (simpleDeclSpec.getType()) { case IASTSimpleDeclSpecifier.t_void: buffer.append(Keywords.VOID).append(' '); break; case IASTSimpleDeclSpecifier.t_char: buffer.append(Keywords.CHAR).append(' '); break; case IASTSimpleDeclSpecifier.t_int: buffer.append(Keywords.INT).append(' '); break; case IASTSimpleDeclSpecifier.t_int128: buffer.append(GCCKeywords.cp__int128).append(' '); break; case IASTSimpleDeclSpecifier.t_float: buffer.append(Keywords.FLOAT).append(' '); break; case IASTSimpleDeclSpecifier.t_double: buffer.append(Keywords.DOUBLE).append(' '); break; case IASTSimpleDeclSpecifier.t_float128: buffer.append(GCCKeywords.cp__float128).append(' '); break; case IASTSimpleDeclSpecifier.t_decimal32: buffer.append(GCCKeywords.cp_decimal32).append(' '); break; case IASTSimpleDeclSpecifier.t_decimal64: buffer.append(GCCKeywords.cp_decimal64).append(' '); break; case IASTSimpleDeclSpecifier.t_decimal128: buffer.append(GCCKeywords.cp_decimal128).append(' '); break; case IASTSimpleDeclSpecifier.t_bool: if (simpleDeclSpec instanceof ICASTSimpleDeclSpecifier) { buffer.append(Keywords.cBOOL).append(' '); } else { buffer.append(Keywords.BOOL).append(' '); } break; case IASTSimpleDeclSpecifier.t_wchar_t: buffer.append(Keywords.WCHAR_T).append(' '); break; case IASTSimpleDeclSpecifier.t_char16_t: buffer.append(Keywords.CHAR16_T).append(' '); break; case IASTSimpleDeclSpecifier.t_char32_t: buffer.append(Keywords.CHAR32_T).append(' '); break; default: } } else if (declSpecifier instanceof IASTNamedTypeSpecifier) { final IASTNamedTypeSpecifier namedTypeSpec= (IASTNamedTypeSpecifier) declSpecifier; appendQualifiedNameString(buffer, namedTypeSpec.getName()); } return buffer; } private static StringBuilder appendQualifiedNameString(StringBuilder buffer, IASTName name) { return appendNameString(buffer, name, true); } private static StringBuilder appendDecltypeSpecifier(StringBuilder buffer, ICPPASTDecltypeSpecifier decltypeSpec) { buffer.append(Keywords.DECLTYPE); buffer.append(Keywords.cpLPAREN); appendExpressionString(buffer, decltypeSpec.getDecltypeExpression()); buffer.append(Keywords.cpRPAREN); return buffer; } private static StringBuilder appendQualifiedNameString(StringBuilder buffer, ICPPASTNameSpecifier nameSpec) { if (nameSpec instanceof IASTName) { appendQualifiedNameString(buffer, (IASTName) nameSpec); } else if (nameSpec instanceof ICPPASTDecltypeSpecifier) { appendDecltypeSpecifier(buffer, (ICPPASTDecltypeSpecifier) nameSpec); } return buffer; } private static StringBuilder appendSimpleNameString(StringBuilder buffer, IASTName name) { return appendNameString(buffer, name, false); } private static StringBuilder appendNameString(StringBuilder buffer, IASTName name, boolean qualified) { if (name instanceof ICPPASTQualifiedName) { final ICPPASTQualifiedName qualifiedName= (ICPPASTQualifiedName) name; if (qualified) { final ICPPASTNameSpecifier[] segments= qualifiedName.getAllSegments(); for (int i = 0; i < segments.length; i++) { if (i > 0) { buffer.append(Keywords.cpCOLONCOLON); } appendQualifiedNameString(buffer, segments[i]); } } else { IASTName lastName = qualifiedName.getLastName(); appendNameString(buffer, lastName, false); } } else if (name instanceof ICPPASTTemplateId) { final ICPPASTTemplateId templateId= (ICPPASTTemplateId) name; appendQualifiedNameString(buffer, templateId.getTemplateName()); final IASTNode[] templateArguments= templateId.getTemplateArguments(); buffer.append(Keywords.cpLT); for (int i = 0; i < templateArguments.length; i++) { if (i > 0) { buffer.append(Keywords.cpCOMMA); } final IASTNode argument= templateArguments[i]; if (argument instanceof IASTTypeId) { appendTypeIdString(buffer, (IASTTypeId) argument); } else if (argument instanceof IASTExpression) { final IASTExpression expression= (IASTExpression) argument; appendExpressionString(buffer, expression); } trimRight(buffer); } buffer.append(Keywords.cpGT); } else if (name != null) { buffer.append(name.getSimpleID()); } return buffer; } private static StringBuilder appendTemplateParameterString(StringBuilder buffer, ICPPASTTemplateParameter parameter) { if (parameter instanceof ICPPASTParameterDeclaration) { appendParameterDeclarationString(buffer, (ICPPASTParameterDeclaration) parameter); } else if (parameter instanceof ICPPASTSimpleTypeTemplateParameter) { final ICPPASTSimpleTypeTemplateParameter simpletypeParameter= (ICPPASTSimpleTypeTemplateParameter) parameter; final IASTName name= simpletypeParameter.getName(); if (name != null) { appendSimpleNameString(buffer, name); } else { final int type= simpletypeParameter.getParameterType(); switch (type) { case ICPPASTSimpleTypeTemplateParameter.st_class: buffer.append(Keywords.CLASS); break; case ICPPASTSimpleTypeTemplateParameter.st_typename: buffer.append(Keywords.TYPENAME); break; } } } else if (parameter instanceof ICPPASTTemplatedTypeTemplateParameter) { final ICPPASTTemplatedTypeTemplateParameter templatedTypeParameter= (ICPPASTTemplatedTypeTemplateParameter) parameter; final ICPPASTTemplateParameter[] subParameters= templatedTypeParameter.getTemplateParameters(); buffer.append(Keywords.TEMPLATE).append(Keywords.cpLT); for (int i = 0; i < subParameters.length; i++) { final ICPPASTTemplateParameter templateParameter= subParameters[i]; if (i > 0) { buffer.append(COMMA_SPACE); } appendTemplateParameterString(buffer, templateParameter); } trimRight(buffer); buffer.append(Keywords.cpGT); } return buffer; } private static StringBuilder appendExpressionString(StringBuilder buffer, IASTExpression expression) { if (expression instanceof IASTIdExpression) { final IASTIdExpression idExpression= (IASTIdExpression) expression; return appendQualifiedNameString(buffer, idExpression.getName()); } if (expression instanceof IASTExpressionList) { final IASTExpressionList expressionList= (IASTExpressionList) expression; final IASTExpression[] expressions= expressionList.getExpressions(); for (int i = 0; i < expressions.length; i++) { if (i > 0) { buffer.append(COMMA_SPACE); } appendExpressionString(buffer, expressions[i]); } return buffer; } if (expression instanceof ICPPASTSimpleTypeConstructorExpression) { final ICPPASTSimpleTypeConstructorExpression typeCast= (ICPPASTSimpleTypeConstructorExpression) expression; appendDeclSpecifierString(buffer, typeCast.getDeclSpecifier()); trimRight(buffer); return appendInitializerString(buffer, typeCast.getInitializer()); } if (expression instanceof IASTArraySubscriptExpression) return appendArraySubscriptExpression(buffer, (IASTArraySubscriptExpression) expression); if (expression instanceof IASTBinaryExpression) return appendBinaryExpression(buffer, (IASTBinaryExpression) expression); if (expression instanceof IASTCastExpression) return appendCastExpression(buffer, (IASTCastExpression) expression); if (expression instanceof IASTConditionalExpression) return appendConditionalExpression(buffer, (IASTConditionalExpression) expression); if (expression instanceof IASTExpressionList) return appendExpressionList(buffer, (IASTExpressionList) expression); if (expression instanceof IASTFieldReference) return appendFieldReference(buffer, (IASTFieldReference) expression); if (expression instanceof IASTFunctionCallExpression) return appendFunctionCallExpression(buffer, (IASTFunctionCallExpression) expression); if (expression instanceof IASTLiteralExpression) return appendLiteralExpression(buffer, (IASTLiteralExpression) expression); if (expression instanceof IASTTypeIdExpression) return appendTypeIdExpression(buffer, (IASTTypeIdExpression) expression); if (expression instanceof IASTUnaryExpression) return appendUnaryExpression(buffer, (IASTUnaryExpression) expression); if (expression instanceof ICASTTypeIdInitializerExpression) return appendTypeIdInitializerExpression(buffer, (ICASTTypeIdInitializerExpression) expression); if (expression instanceof ICPPASTDeleteExpression) return appendDeleteExpression(buffer, (ICPPASTDeleteExpression) expression); if (expression instanceof ICPPASTNewExpression) return appendNewExpression(buffer, (ICPPASTNewExpression) expression); if (expression instanceof IGNUASTCompoundStatementExpression) return appendCompoundStatementExpression(buffer, (IGNUASTCompoundStatementExpression) expression); if (expression instanceof ICPPASTPackExpansionExpression) return appendPackExpansionExpression(buffer, (ICPPASTPackExpansionExpression) expression); return buffer; } private static StringBuilder appendArraySubscriptExpression(StringBuilder buffer, IASTArraySubscriptExpression expression) { appendExpressionString(buffer, expression.getArrayExpression()); buffer.append(Keywords.cpLBRACKET); appendInitClauseString(buffer, expression.getArgument()); return buffer.append(Keywords.cpRBRACKET); } private static StringBuilder appendCastExpression(StringBuilder buffer, IASTCastExpression expression) { if ((expression.getOperator() == IASTCastExpression.op_cast)) { buffer.append(Keywords.cpLPAREN); appendTypeIdString(buffer, expression.getTypeId()); buffer.append(Keywords.cpRPAREN); return appendExpressionString(buffer, expression.getOperand()); } buffer.append(getCastOperatorString(expression)); buffer.append(Keywords.cpLT); appendTypeIdString(buffer, expression.getTypeId()); trimRight(buffer); buffer.append(Keywords.cpGT); buffer.append(Keywords.cpLPAREN); appendExpressionString(buffer, expression.getOperand()); return buffer.append(Keywords.cpRPAREN); } private static StringBuilder appendFieldReference(StringBuilder buffer, IASTFieldReference expression) { appendExpressionString(buffer, expression.getFieldOwner()); buffer.append(expression.isPointerDereference() ? Keywords.cpARROW : Keywords.cpDOT); return appendNameString(buffer, expression.getFieldName(), true); } private static StringBuilder appendFunctionCallExpression(StringBuilder buffer, IASTFunctionCallExpression expression) { appendExpressionString(buffer, expression.getFunctionNameExpression()); buffer.append(Keywords.cpLPAREN); IASTInitializerClause[] clauses = expression.getArguments(); for (int i= 0; i < clauses.length; i++) { if (i > 0) { buffer.append(COMMA_SPACE); } appendInitClauseString(buffer, (clauses[i])); } return buffer.append(Keywords.cpRPAREN); } private static StringBuilder appendTypeIdInitializerExpression(StringBuilder buffer, ICASTTypeIdInitializerExpression expression) { buffer.append(Keywords.cpLPAREN); appendTypeIdString(buffer, expression.getTypeId()); buffer.append(Keywords.cpRPAREN); return appendInitializerString(buffer, expression.getInitializer()); } private static StringBuilder appendDeleteExpression(StringBuilder buffer, ICPPASTDeleteExpression expression) { buffer.append(Keywords.DELETE); buffer.append(SPACE); return appendExpressionString(buffer, expression.getOperand()); } private static StringBuilder appendCompoundStatementExpression(StringBuilder buffer, IGNUASTCompoundStatementExpression expression) { buffer.append(Keywords.cpLPAREN).append(Keywords.cpLBRACE); buffer.append(Keywords.cpELLIPSIS); return buffer.append(Keywords.cpRBRACE).append(Keywords.cpRPAREN); } private static StringBuilder appendTypeIdExpression(StringBuilder buffer, IASTTypeIdExpression expression) { buffer.append(getTypeIdExpressionOperator(expression)); buffer.append(Keywords.cpLPAREN); appendTypeIdString(buffer, expression.getTypeId()); trimRight(buffer); return buffer.append(Keywords.cpRPAREN); } private static StringBuilder appendExpressionList(StringBuilder buffer, IASTExpressionList expression) { IASTExpression[] exps = expression.getExpressions(); if (exps != null) { for (int i = 0; i < exps.length; i++) { if (i > 0) { buffer.append(COMMA_SPACE); } appendExpressionString(buffer, exps[i]); } } return buffer; } private static StringBuilder appendLiteralExpression(StringBuilder buffer, IASTLiteralExpression expression) { return buffer.append(expression.toString()); } private static StringBuilder appendConditionalExpression(StringBuilder buffer, IASTConditionalExpression expression) { appendExpressionString(buffer, expression.getLogicalConditionExpression()); buffer.append(SPACE); buffer.append(Keywords.cpQUESTION); buffer.append(SPACE); appendExpressionString(buffer, expression.getPositiveResultExpression()); buffer.append(SPACE); buffer.append(Keywords.cpCOLON); buffer.append(SPACE); return appendExpressionString(buffer, expression.getNegativeResultExpression()); } private static StringBuilder appendNewExpression(StringBuilder buffer, ICPPASTNewExpression expression) { buffer.append(Keywords.NEW); buffer.append(SPACE); final IASTInitializerClause[] args = expression.getPlacementArguments(); if (args != null) { buffer.append(Keywords.cpLPAREN); for (int i = 0; i < args.length; i++) { if (i != 0) { buffer.append(COMMA_SPACE); } appendInitClauseString(buffer, args[i]); } buffer.append(Keywords.cpRPAREN); } appendTypeIdString(buffer, expression.getTypeId()); return appendInitializerString(buffer, expression.getInitializer()); } private static StringBuilder appendBinaryExpression(StringBuilder buffer, IASTBinaryExpression expression) { appendExpressionString(buffer, expression.getOperand1()); buffer.append(SPACE); buffer.append(getBinaryOperatorString(expression)); buffer.append(SPACE); return appendExpressionString(buffer, expression.getOperand2()); } private static StringBuilder appendUnaryExpression(StringBuilder buffer, IASTUnaryExpression expression) { boolean postOperator = false; boolean primaryBracketed = false; switch (expression.getOperator()) { case IASTUnaryExpression.op_postFixDecr: case IASTUnaryExpression.op_postFixIncr: postOperator = true; break; case IASTUnaryExpression.op_bracketedPrimary: primaryBracketed = true; break; default: postOperator = false; break; } if (!postOperator && !primaryBracketed) buffer.append(getUnaryOperatorString(expression)); // Need to add a space to the unary expression if it is a specific operator. switch (expression.getOperator()) { case IASTUnaryExpression.op_sizeof: case ICPPASTUnaryExpression.op_noexcept: case ICPPASTUnaryExpression.op_throw: case ICPPASTUnaryExpression.op_typeid: buffer.append(SPACE); break; } if (primaryBracketed) buffer.append(Keywords.cpLPAREN); buffer.append(getExpressionString(expression.getOperand())); if (primaryBracketed) buffer.append(Keywords.cpRPAREN); if (postOperator && !primaryBracketed) buffer.append(getUnaryOperatorString(expression)); return buffer; } public static String getCastOperatorString(IASTCastExpression expression) { int op = expression.getOperator(); switch (op) { case ICPPASTCastExpression.op_const_cast: return Keywords.CONST_CAST; case ICPPASTCastExpression.op_dynamic_cast: return Keywords.DYNAMIC_CAST; case ICPPASTCastExpression.op_reinterpret_cast: return Keywords.REINTERPRET_CAST; case ICPPASTCastExpression.op_static_cast: return Keywords.STATIC_CAST; } return ""; //$NON-NLS-1$ } /** * Returns the String representation of the IASTUnaryExpression's operator. * * @param ue * @return the String representation of the IASTUnaryExpression's operator */ public static char[] getUnaryOperatorString(IASTUnaryExpression ue) { int op = ue.getOperator(); switch (op) { case IASTUnaryExpression.op_noexcept: return Keywords.cNOEXCEPT; case IASTUnaryExpression.op_throw: return Keywords.cTHROW; case IASTUnaryExpression.op_typeid: return Keywords.cTYPEID; case IASTUnaryExpression.op_alignOf: return Keywords.cALIGNOF; case IASTUnaryExpression.op_amper: return Keywords.cpAMPER; case IASTUnaryExpression.op_minus: return Keywords.cpMINUS; case IASTUnaryExpression.op_not: return Keywords.cpNOT; case IASTUnaryExpression.op_plus: return Keywords.cpPLUS; case IASTUnaryExpression.op_postFixDecr: case IASTUnaryExpression.op_prefixDecr: return Keywords.cpDECR; case IASTUnaryExpression.op_postFixIncr: case IASTUnaryExpression.op_prefixIncr: return Keywords.cpINCR; case IASTUnaryExpression.op_sizeof: return Keywords.cSIZEOF; case IASTUnaryExpression.op_sizeofParameterPack: return Keywords.cSIZEOFPACK; case IASTUnaryExpression.op_star: return Keywords.cpSTAR; case IASTUnaryExpression.op_tilde: return Keywords.cpCOMPL; } return CharArrayUtils.EMPTY; } /** * Returns the char[] representation of the IASTBinaryExpression's operator. */ public static char[] getBinaryOperatorString(IASTBinaryExpression be) { switch (be.getOperator()) { case IASTBinaryExpression.op_multiply: return Keywords.cpSTAR; case IASTBinaryExpression.op_divide: return Keywords.cpDIV; case IASTBinaryExpression.op_modulo: return Keywords.cpMOD; case IASTBinaryExpression.op_plus: return Keywords.cpPLUS; case IASTBinaryExpression.op_minus: return Keywords.cpMINUS; case IASTBinaryExpression.op_shiftLeft: return Keywords.cpSHIFTL; case IASTBinaryExpression.op_shiftRight: return Keywords.cpSHIFTR; case IASTBinaryExpression.op_lessThan: return Keywords.cpLT; case IASTBinaryExpression.op_greaterThan: return Keywords.cpGT; case IASTBinaryExpression.op_lessEqual: return Keywords.cpLTEQUAL; case IASTBinaryExpression.op_greaterEqual: return Keywords.cpGTEQUAL; case IASTBinaryExpression.op_binaryAnd: return Keywords.cpAMPER; case IASTBinaryExpression.op_binaryXor: return Keywords.cpXOR; case IASTBinaryExpression.op_binaryOr: return Keywords.cpBITOR; case IASTBinaryExpression.op_logicalAnd: return Keywords.cpAND; case IASTBinaryExpression.op_logicalOr: return Keywords.cpOR; case IASTBinaryExpression.op_assign: return Keywords.cpASSIGN; case IASTBinaryExpression.op_multiplyAssign: return Keywords.cpSTARASSIGN; case IASTBinaryExpression.op_divideAssign: return Keywords.cpDIVASSIGN; case IASTBinaryExpression.op_moduloAssign: return Keywords.cpMODASSIGN; case IASTBinaryExpression.op_plusAssign: return Keywords.cpPLUSASSIGN; case IASTBinaryExpression.op_minusAssign: return Keywords.cpMINUSASSIGN; case IASTBinaryExpression.op_shiftLeftAssign: return Keywords.cpSHIFTLASSIGN; case IASTBinaryExpression.op_shiftRightAssign: return Keywords.cpSHIFTRASSIGN; case IASTBinaryExpression.op_binaryAndAssign: return Keywords.cpAMPERASSIGN; case IASTBinaryExpression.op_binaryXorAssign: return Keywords.cpXORASSIGN; case IASTBinaryExpression.op_binaryOrAssign: return Keywords.cpBITORASSIGN; case IASTBinaryExpression.op_equals: return Keywords.cpEQUAL; case IASTBinaryExpression.op_notequals: return Keywords.cpNOTEQUAL; case IASTBinaryExpression.op_max: return Keywords.cpMAX; case IASTBinaryExpression.op_min: return Keywords.cpMIN; case IASTBinaryExpression.op_pmarrow: return Keywords.cpARROW; case IASTBinaryExpression.op_pmdot: return Keywords.cpDOT; } return CharArrayUtils.EMPTY; } private static String getTypeIdExpressionOperator(IASTTypeIdExpression expression) { switch (expression.getOperator()) { case IASTTypeIdExpression.op_alignof: return Keywords.ALIGNOF; case IASTTypeIdExpression.op_typeof: return Keywords.TYPEOF; case ICPPASTTypeIdExpression.op_typeid: return Keywords.TYPEID; case IASTTypeIdExpression.op_sizeof: return Keywords.SIZEOF; } return ""; //$NON-NLS-1$ } /** * Returns the String representation of the pack expansion expression. * @param buffer */ private static StringBuilder appendPackExpansionExpression(StringBuilder buffer, ICPPASTPackExpansionExpression expression) { appendExpressionString(buffer, expression.getPattern()); return buffer.append(Keywords.cpELLIPSIS); } }