/******************************************************************************* * Copyright (c) 2008, 2010 Institute for Software, HSR Hochschule fuer Technik * Rapperswil, University of applied sciences 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: * Institute for Software - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.rewrite.astwriter; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier; import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier; import org.eclipse.cdt.core.dom.ast.c.ICASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.c.ICASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.c.ICASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.c.ICASTEnumerationSpecifier; import org.eclipse.cdt.core.dom.ast.c.ICASTSimpleDeclSpecifier; import org.eclipse.cdt.core.dom.ast.c.ICASTTypedefNameSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleDeclSpecifier; import org.eclipse.cdt.core.parser.Keywords; import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap; /** * Generates source code of declaration specifier nodes. The actual string operations are delegated * to the Scribe class. * * @see Scribe * @see IASTDeclSpecifier * @author Emanuel Graf IFS */ public class DeclSpecWriter extends NodeWriter { private static final String MUTABLE = "mutable "; //$NON-NLS-1$ private static final String _COMPLEX = "_Complex "; //$NON-NLS-1$ private static final String LONG_LONG = "long long "; //$NON-NLS-1$ private static final String REGISTER = "register "; //$NON-NLS-1$ private static final String AUTO = "auto "; //$NON-NLS-1$ private static final String TYPEDEF = "typedef "; //$NON-NLS-1$ private static final String UNION = "union"; //$NON-NLS-1$ private static final String STRUCT = "struct"; //$NON-NLS-1$ private static final String CLASS = "class"; //$NON-NLS-1$ private static final String FRIEND = "friend "; //$NON-NLS-1$ private static final String EXPLICIT = "explicit "; //$NON-NLS-1$ private static final String VIRTUAL = "virtual "; //$NON-NLS-1$ private static final String UNION_SPACE = "union "; //$NON-NLS-1$ private static final String STRUCT_SPACE = "struct "; //$NON-NLS-1$ private static final String ENUM = "enum "; //$NON-NLS-1$ private static final String _BOOL = "_Bool"; //$NON-NLS-1$ public DeclSpecWriter(Scribe scribe, ASTVisitor visitor, NodeCommentMap commentMap) { super(scribe, visitor, commentMap); } protected void writeDelcSpec(IASTDeclSpecifier declSpec) { // Write general DelcSpec Keywords writeDeclSpec(declSpec); if (declSpec instanceof ICPPASTDeclSpecifier) { writeCPPDeclSpec((ICPPASTDeclSpecifier) declSpec); } else if (declSpec instanceof ICASTDeclSpecifier) { writeCDeclSpec((ICASTDeclSpecifier) declSpec); } } private String getCPPSimpleDecSpecifier(ICPPASTSimpleDeclSpecifier simpDeclSpec) { return getASTSimpleDecSpecifier(simpDeclSpec.getType(), true); } private String getCSimpleDecSpecifier(ICASTSimpleDeclSpecifier simpDeclSpec) { return getASTSimpleDecSpecifier(simpDeclSpec.getType(), false); } private String getASTSimpleDecSpecifier(int type, boolean isCpp) { switch (type) { case IASTSimpleDeclSpecifier.t_unspecified: return ""; //$NON-NLS-1$ case IASTSimpleDeclSpecifier.t_void: return VOID; case IASTSimpleDeclSpecifier.t_char: return CHAR; case IASTSimpleDeclSpecifier.t_int: return INT; case IASTSimpleDeclSpecifier.t_float: return FLOAT; case IASTSimpleDeclSpecifier.t_double: return DOUBLE; case IASTSimpleDeclSpecifier.t_bool: return isCpp ? CPP_BOOL : _BOOL; case IASTSimpleDeclSpecifier.t_wchar_t: if (isCpp) return WCHAR_T; break; case IASTSimpleDeclSpecifier.t_char16_t: if (isCpp) return Keywords.CHAR16_T; break; case IASTSimpleDeclSpecifier.t_char32_t: if (isCpp) return Keywords.CHAR32_T; break; case IASTSimpleDeclSpecifier.t_auto: if (isCpp) return Keywords.AUTO; break; case IASTSimpleDeclSpecifier.t_typeof: if (isCpp) return Keywords.TYPEOF; break; case IASTSimpleDeclSpecifier.t_decltype: if (isCpp) return Keywords.DECLTYPE; break; } System.err.println("Unknown specifier type: " + type); //$NON-NLS-1$ throw new IllegalArgumentException("Unknown specifier type: " + type); //$NON-NLS-1$ } private void writeCDeclSpec(ICASTDeclSpecifier cDeclSpec) { if (cDeclSpec.isRestrict()) { scribe.print(RESTRICT); } if (cDeclSpec instanceof ICASTCompositeTypeSpecifier) { writeCompositeTypeSpecifier((ICASTCompositeTypeSpecifier) cDeclSpec); } else if (cDeclSpec instanceof ICASTEnumerationSpecifier) { writeEnumSpec((ICASTEnumerationSpecifier) cDeclSpec); } else if (cDeclSpec instanceof ICASTElaboratedTypeSpecifier) { writeElaboratedTypeSec((ICASTElaboratedTypeSpecifier) cDeclSpec); } else if (cDeclSpec instanceof ICASTSimpleDeclSpecifier) { writeCSimpleDeclSpec((ICASTSimpleDeclSpecifier) cDeclSpec); } else if (cDeclSpec instanceof ICASTTypedefNameSpecifier) { writeNamedTypeSpecifier((ICASTTypedefNameSpecifier) cDeclSpec); } } private void writeNamedTypeSpecifier(ICPPASTNamedTypeSpecifier namedSpc) { if ( namedSpc.isTypename() ){ scribe.print(TYPENAME); } namedSpc.getName().accept(visitor); } private void writeNamedTypeSpecifier(IASTNamedTypeSpecifier namedSpc) { namedSpc.getName().accept(visitor); } private void writeElaboratedTypeSec(IASTElaboratedTypeSpecifier elabType) { scribe.print(getElabTypeString(elabType.getKind())); elabType.getName().accept(visitor); } private String getElabTypeString(int kind) { switch(kind) { case IASTElaboratedTypeSpecifier.k_enum: return ENUM; case IASTElaboratedTypeSpecifier.k_struct: return STRUCT_SPACE; case IASTElaboratedTypeSpecifier.k_union: return UNION_SPACE; case ICPPASTElaboratedTypeSpecifier.k_class: return CLASS_SPACE; default: System.err.println("Unknown ElaboratedType: " + kind); //$NON-NLS-1$ throw new IllegalArgumentException("Unknown ElaboratedType: " + kind); //$NON-NLS-1$ } } private void writeCPPDeclSpec(ICPPASTDeclSpecifier cppDelcSpec) { if (cppDelcSpec.isVirtual()) { scribe.print(VIRTUAL); } if (cppDelcSpec.isExplicit()) { scribe.print(EXPLICIT); } if (cppDelcSpec.isFriend()) { scribe.print(FRIEND); } if (cppDelcSpec.getStorageClass() == IASTDeclSpecifier.sc_mutable) { scribe.print(MUTABLE); } if (cppDelcSpec instanceof ICPPASTCompositeTypeSpecifier) { writeCompositeTypeSpecifier((ICPPASTCompositeTypeSpecifier) cppDelcSpec); } else if (cppDelcSpec instanceof IASTEnumerationSpecifier) { writeEnumSpec((IASTEnumerationSpecifier) cppDelcSpec); } else if (cppDelcSpec instanceof ICPPASTElaboratedTypeSpecifier) { writeElaboratedTypeSec((ICPPASTElaboratedTypeSpecifier) cppDelcSpec); } else if (cppDelcSpec instanceof ICPPASTSimpleDeclSpecifier) { writeCPPSimpleDeclSpec((ICPPASTSimpleDeclSpecifier) cppDelcSpec); } else if (cppDelcSpec instanceof ICPPASTNamedTypeSpecifier) { writeNamedTypeSpecifier((ICPPASTNamedTypeSpecifier) cppDelcSpec); } } private void writeEnumSpec(IASTEnumerationSpecifier enumSpec) { scribe.print(ENUM); enumSpec.getName().accept(visitor); scribe.print('{'); scribe.printSpace(); IASTEnumerator[] enums = enumSpec.getEnumerators(); for (int i = 0; i< enums.length;++i) { writeEnumerator(enums[i]); if (i+1< enums.length) { scribe.print(NodeWriter.COMMA_SPACE); } } scribe.print('}'); } private void writeEnumerator(IASTEnumerator enumerator) { enumerator.getName().accept(visitor); IASTExpression value = enumerator.getValue(); if (value != null) { scribe.print(EQUALS); value.accept(visitor); } } private void writeCompositeTypeSpecifier(IASTCompositeTypeSpecifier compDeclSpec) { boolean hasTrailingComments = hasTrailingComments(compDeclSpec.getName()); scribe.printStringSpace(getCPPCompositeTypeString(compDeclSpec.getKey())); compDeclSpec.getName().accept(visitor); if (compDeclSpec instanceof ICPPASTCompositeTypeSpecifier) { ICPPASTCompositeTypeSpecifier cppComp = (ICPPASTCompositeTypeSpecifier) compDeclSpec; ICPPASTBaseSpecifier[] baseSpecifiers = cppComp.getBaseSpecifiers(); if (baseSpecifiers.length > 0) { scribe.print(SPACE_COLON_SPACE); for (int i = 0; i < baseSpecifiers.length;++i) { writeBaseSpecifiers(baseSpecifiers[i]); if (i+1 < baseSpecifiers.length) { scribe.print(COMMA_SPACE); } } hasTrailingComments = hasTrailingComments(baseSpecifiers[baseSpecifiers.length-1].getName()); } } if (!hasTrailingComments){ scribe.newLine(); } scribe.print('{'); scribe.newLine(); scribe.incrementIndentationLevel(); IASTDeclaration[] decls = getMembers(compDeclSpec); if (decls.length > 0) { for (IASTDeclaration declaration : decls) { declaration.accept(visitor); } } if (hasFreestandingComments(compDeclSpec)) { writeFreeStandingComments(compDeclSpec); } scribe.decrementIndentationLevel(); scribe.print('}'); if (hasTrailingComments(compDeclSpec)) { writeTrailingComments(compDeclSpec); } } protected IASTDeclaration[] getMembers(IASTCompositeTypeSpecifier compDeclSpec) { return compDeclSpec.getMembers(); } private void writeBaseSpecifiers(ICPPASTBaseSpecifier specifier) { switch(specifier.getVisibility()) { case ICPPASTBaseSpecifier.v_public: scribe.printStringSpace(PUBLIC); break; case ICPPASTBaseSpecifier.v_protected: scribe.printStringSpace(PROTECTED); break; case ICPPASTBaseSpecifier.v_private: scribe.printStringSpace(PRIVATE); break; } specifier.getName().accept(visitor); } private String getCPPCompositeTypeString(int key) { if (key <= IASTCompositeTypeSpecifier.k_last) { return getCompositeTypeString(key); } switch (key) { case ICPPASTCompositeTypeSpecifier.k_class: return CLASS; default: System.err.println("Unknow Specifiertype: " + key); //$NON-NLS-1$ throw new IllegalArgumentException("Unknow Specifiertype: " + key); //$NON-NLS-1$ } } private String getCompositeTypeString(int key) { switch (key) { case IASTCompositeTypeSpecifier.k_struct: return STRUCT; case IASTCompositeTypeSpecifier.k_union: return UNION; default: System.err.println("Unknow Specifiertype: " + key); //$NON-NLS-1$ throw new IllegalArgumentException("Unknow Specifiertype: " + key); //$NON-NLS-1$ } } private void writeDeclSpec(IASTDeclSpecifier declSpec) { if (declSpec.isInline()) { scribe.print(INLINE); } switch(declSpec.getStorageClass()) { case IASTDeclSpecifier.sc_typedef: scribe.print(TYPEDEF); break; case IASTDeclSpecifier.sc_extern: scribe.print(EXTERN); break; case IASTDeclSpecifier.sc_static: scribe.print(STATIC); break; case IASTDeclSpecifier.sc_auto: scribe.print(AUTO); break; case IASTDeclSpecifier.sc_register: scribe.print(REGISTER); break; } if (declSpec.isConst()) { scribe.printStringSpace(CONST); } if (declSpec.isVolatile()) { scribe.printStringSpace(VOLATILE); } } private void writeCPPSimpleDeclSpec(ICPPASTSimpleDeclSpecifier simpDeclSpec) { printQualifiers(simpDeclSpec); scribe.print(getCPPSimpleDecSpecifier(simpDeclSpec)); if (simpDeclSpec.getType() == IASTSimpleDeclSpecifier.t_typeof) { scribe.printSpace(); visitNodeIfNotNull(simpDeclSpec.getDeclTypeExpression()); } else if (simpDeclSpec.getType() == IASTSimpleDeclSpecifier.t_decltype) { scribe.print('('); visitNodeIfNotNull(simpDeclSpec.getDeclTypeExpression()); scribe.print(')'); } } private void printQualifiers(IASTSimpleDeclSpecifier simpDeclSpec) { if (simpDeclSpec.isSigned()) { scribe.printStringSpace(SIGNED); } else if (simpDeclSpec.isUnsigned()){ scribe.printStringSpace(UNSIGNED); } if (simpDeclSpec.isShort()) { scribe.printStringSpace(SHORT); } else if (simpDeclSpec.isLong()) { scribe.printStringSpace(LONG); } else if (simpDeclSpec.isLongLong()) { scribe.print(LONG_LONG); } if (simpDeclSpec instanceof ICASTSimpleDeclSpecifier) { ICASTSimpleDeclSpecifier cSimpDeclSpec = (ICASTSimpleDeclSpecifier) simpDeclSpec; if (cSimpDeclSpec.isComplex()) { scribe.print(_COMPLEX); } } } private void writeCSimpleDeclSpec(ICASTSimpleDeclSpecifier simpDeclSpec) { printQualifiers(simpDeclSpec); scribe.print(getCSimpleDecSpecifier(simpDeclSpec)); } }