1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 14:12:10 +02:00

Bug 491026 - Improved Doxygen support

Added autogeneration of documentation for template parameters,
exception speficiation.

Prepare Doxygen class to manage class names, struct names, union names
enum names and preprocessor define.

Change-Id: Id8689eac209cc509196a7c87ee286bb3e7c49e67
Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
This commit is contained in:
Marco Stornelli 2020-01-04 11:31:06 +01:00
parent 3effb213fa
commit 5bd822cb85
4 changed files with 403 additions and 77 deletions

View file

@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2 Bundle-ManifestVersion: 2
Bundle-Name: %pluginName Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.cdt.ui; singleton:=true Bundle-SymbolicName: org.eclipse.cdt.ui; singleton:=true
Bundle-Version: 6.6.300.qualifier Bundle-Version: 6.7.0.qualifier
Bundle-Activator: org.eclipse.cdt.ui.CUIPlugin Bundle-Activator: org.eclipse.cdt.ui.CUIPlugin
Bundle-Vendor: %providerName Bundle-Vendor: %providerName
Bundle-Localization: plugin Bundle-Localization: plugin

View file

@ -24,7 +24,9 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
import org.eclipse.cdt.core.dom.ast.IASTNodeSelector; import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants; import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.CModelException;
@ -64,6 +66,14 @@ public class DefaultMultilineCommentAutoEditStrategy implements IAutoEditStrateg
private static String fgDefaultLineDelim = "\n"; //$NON-NLS-1$ private static String fgDefaultLineDelim = "\n"; //$NON-NLS-1$
private ICProject fProject; private ICProject fProject;
/**
* @since 6.7
*/
public interface IDocCustomizer {
StringBuilder customizeForDeclaration(IDocument doc, IASTNode dec, ITypedRegion region,
CustomizeOptions options);
}
public DefaultMultilineCommentAutoEditStrategy() { public DefaultMultilineCommentAutoEditStrategy() {
this(null); this(null);
} }
@ -183,7 +193,7 @@ public class DefaultMultilineCommentAutoEditStrategy implements IAutoEditStrateg
buf.append(lineDelim); buf.append(lineDelim);
// as we are auto-closing, the comment becomes eligible for auto-doc'ing // as we are auto-closing, the comment becomes eligible for auto-doc'ing
IASTDeclaration dec = null; IASTNode dec = null;
IIndex index = null; IIndex index = null;
ITranslationUnit unit = getTranslationUnitForActiveEditor(); ITranslationUnit unit = getTranslationUnitForActiveEditor();
if (unit != null) { if (unit != null) {
@ -197,22 +207,49 @@ public class DefaultMultilineCommentAutoEditStrategy implements IAutoEditStrateg
try { try {
IASTTranslationUnit ast = getAST(unit, index); IASTTranslationUnit ast = getAST(unit, index);
if (ast != null) { if (this instanceof IDocCustomizer) {
dec = findFollowingDeclaration(ast, offset); if (ast != null) {
if (dec == null) { dec = findNextDocumentNode(ast, offset);
IASTNodeSelector ans = ast.getNodeSelector(ast.getFilePath()); if (dec == null) {
IASTNode node = ans.findEnclosingNode(offset, 0); IASTNodeSelector ans = ast.getNodeSelector(ast.getFilePath());
if (node instanceof IASTDeclaration) { IASTNode node = ans.findEnclosingNode(offset, 0);
dec = (IASTDeclaration) node; if (node instanceof IASTDeclaration) {
dec = node;
}
} }
} }
}
if (dec != null) { if (dec != null) {
ITypedRegion partition = TextUtilities.getPartition(doc, ITypedRegion partition = TextUtilities.getPartition(doc,
ICPartitions.C_PARTITIONING /* this! */, offset, false); ICPartitions.C_PARTITIONING /* this! */, offset, false);
StringBuilder content = customizeAfterNewLineForDeclaration(doc, dec, partition); StringBuilder content = null;
buf.append(indent(content, indentation + MULTILINE_MID, lineDelim)); IDocCustomizer customizer = (IDocCustomizer) this;
CustomizeOptions options = new CustomizeOptions();
content = customizer.customizeForDeclaration(doc, dec, partition, options);
if (!options.addNewLine) {
buf.setLength(buf.length() - MULTILINE_MID.length() - lineDelim.length());
}
buf.append(indent(content, indentation + MULTILINE_MID, lineDelim));
}
} else {
if (ast != null) {
dec = findFollowingDeclaration(ast, offset);
if (dec == null) {
IASTNodeSelector ans = ast.getNodeSelector(ast.getFilePath());
IASTNode node = ans.findEnclosingNode(offset, 0);
if (node instanceof IASTDeclaration) {
dec = node;
}
}
}
if (dec != null) {
ITypedRegion partition = TextUtilities.getPartition(doc,
ICPartitions.C_PARTITIONING /* this! */, offset, false);
StringBuilder content = null;
content = customizeAfterNewLineForDeclaration(doc, (IASTDeclaration) dec, partition);
buf.append(indent(content, indentation + MULTILINE_MID, lineDelim));
}
} }
} finally { } finally {
if (index != null) { if (index != null) {
@ -233,6 +270,28 @@ public class DefaultMultilineCommentAutoEditStrategy implements IAutoEditStrateg
} }
} }
/**
* Options set by IDocCustomize
* @since 6.7
*/
public static class CustomizeOptions {
/**
* Child of IDocCustomize can decide to add a new line
* before their comment body or not. By default a new
* line is added.
*/
public boolean addNewLine;
public CustomizeOptions() {
addNewLine = true;
}
}
/**
* @deprecated This class is deprecated, clients should implement IDocCustomizer
* interface instead.
*/
@Deprecated
protected StringBuilder customizeAfterNewLineForDeclaration(IDocument doc, IASTDeclaration dec, protected StringBuilder customizeAfterNewLineForDeclaration(IDocument doc, IASTDeclaration dec,
ITypedRegion region) { ITypedRegion region) {
return new StringBuilder(); return new StringBuilder();
@ -242,6 +301,102 @@ public class DefaultMultilineCommentAutoEditStrategy implements IAutoEditStrateg
* Utilities * Utilities
*/ */
private static class SearchVisitor extends ASTVisitor {
public SearchVisitor(int offset) {
shouldVisitTranslationUnit = true;
shouldVisitDeclarations = true;
shouldVisitNamespaces = true;
this.offset = offset;
}
private int nearestOffset = Integer.MAX_VALUE;
private int offset;
private IASTDeclaration target;
public int getNearest() {
return nearestOffset;
}
public IASTDeclaration getTarget() {
return target;
}
@Override
public int visit(ICPPASTNamespaceDefinition namespace) {
IASTNodeLocation loc = namespace.getFileLocation();
if (loc != null) {
int candidateOffset = loc.getNodeOffset();
if (offset <= candidateOffset && candidateOffset <= nearestOffset) {
nearestOffset = candidateOffset;
target = namespace;
return PROCESS_ABORT;
}
}
return PROCESS_CONTINUE;
}
/**
* Holds the
*/
IASTDeclaration stopWhenLeaving;
@Override
public int visit(IASTDeclaration declaration) {
IASTNodeLocation loc = declaration.getFileLocation();
if (loc != null) {
int candidateOffset = loc.getNodeOffset();
int candidateEndOffset = candidateOffset + loc.getNodeLength();
if (offset <= candidateOffset && candidateOffset <= nearestOffset) {
nearestOffset = candidateOffset;
target = declaration;
return PROCESS_ABORT;
}
boolean candidateEnclosesOffset = (offset >= candidateOffset) && (offset < candidateEndOffset);
if (candidateEnclosesOffset) {
stopWhenLeaving = declaration;
}
}
return PROCESS_CONTINUE;
}
@Override
public int leave(IASTDeclaration declaration) {
if (declaration == stopWhenLeaving)
return PROCESS_ABORT;
return PROCESS_CONTINUE;
}
}
/**
* Locates the {@link IASTNode} most immediately following the specified offset
* @param unit the translation unit, or null (in which case the result will also be null)
* @param offset the offset to begin the search from
* @return the {@link IASTNode} most immediately following the specified offset, or null if there
* is no node suitable for documentation, i.e. a declaration or a macro definition
* @since 6.7
*/
public static IASTNode findNextDocumentNode(IASTTranslationUnit unit, final int offset) {
IASTNode bestNode = null;
if (unit != null) {
IASTPreprocessorMacroDefinition[] macros = unit.getMacroDefinitions();
SearchVisitor av = new SearchVisitor(offset);
unit.accept(av);
int nearest = av.getNearest();
bestNode = av.getTarget();
for (IASTPreprocessorMacroDefinition m : macros) {
if (m.getExpansionLocation() != null && m.getExpansionLocation().getNodeOffset() < nearest
&& offset <= m.getExpansionLocation().getNodeOffset()) {
bestNode = m;
nearest = m.getExpansionLocation().getNodeOffset();
}
}
}
return bestNode;
}
/** /**
* Locates the {@link IASTDeclaration} most immediately following the specified offset * Locates the {@link IASTDeclaration} most immediately following the specified offset
* @param unit the translation unit, or null (in which case the result will also be null) * @param unit the translation unit, or null (in which case the result will also be null)
@ -250,48 +405,11 @@ public class DefaultMultilineCommentAutoEditStrategy implements IAutoEditStrateg
* is no {@link IASTDeclaration} * is no {@link IASTDeclaration}
*/ */
public static IASTDeclaration findFollowingDeclaration(IASTTranslationUnit unit, final int offset) { public static IASTDeclaration findFollowingDeclaration(IASTTranslationUnit unit, final int offset) {
final IASTDeclaration[] dec = new IASTDeclaration[1]; IASTDeclaration[] dec = new IASTDeclaration[1];
final ASTVisitor av = new ASTVisitor() {
{
shouldVisitTranslationUnit = true;
shouldVisitDeclarations = true;
}
/**
* Holds the
*/
IASTDeclaration stopWhenLeaving;
@Override
public int visit(IASTDeclaration declaration) {
IASTNodeLocation loc = declaration.getFileLocation();
if (loc != null) {
int candidateOffset = loc.getNodeOffset();
int candidateEndOffset = candidateOffset + loc.getNodeLength();
if (offset <= candidateOffset) {
dec[0] = declaration;
return PROCESS_ABORT;
}
boolean candidateEnclosesOffset = (offset >= candidateOffset) && (offset < candidateEndOffset);
if (candidateEnclosesOffset) {
stopWhenLeaving = declaration;
}
}
return PROCESS_CONTINUE;
}
@Override
public int leave(IASTDeclaration declaration) {
if (declaration == stopWhenLeaving)
return PROCESS_ABORT;
return PROCESS_CONTINUE;
}
};
if (unit != null) { if (unit != null) {
SearchVisitor av = new SearchVisitor(offset);
unit.accept(av); unit.accept(av);
dec[0] = av.getTarget();
} }
return dec[0]; return dec[0];
} }

View file

@ -26,15 +26,27 @@ import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator; import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeId;
import org.eclipse.cdt.core.parser.IToken; import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
import org.eclipse.cdt.internal.core.model.ASTStringUtil;
import org.eclipse.cdt.ui.text.doctools.DefaultMultilineCommentAutoEditStrategy; import org.eclipse.cdt.ui.text.doctools.DefaultMultilineCommentAutoEditStrategy;
import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IAutoEditStrategy; import org.eclipse.jface.text.IAutoEditStrategy;
@ -49,19 +61,40 @@ import org.eclipse.jface.text.TextUtilities;
* @since 5.0 * @since 5.0
* @noextend This class is not intended to be subclassed by clients. * @noextend This class is not intended to be subclassed by clients.
*/ */
public class DoxygenMultilineAutoEditStrategy extends DefaultMultilineCommentAutoEditStrategy { public class DoxygenMultilineAutoEditStrategy extends DefaultMultilineCommentAutoEditStrategy
implements DefaultMultilineCommentAutoEditStrategy.IDocCustomizer {
private static final String SINGLELINE_COMMENT_PRECEDING = "//!< "; //$NON-NLS-1$ private static final String SINGLELINE_COMMENT_PRECEDING = "//!< "; //$NON-NLS-1$
private static final String PARAM = "@param "; //$NON-NLS-1$ private static final String CLASS = "class "; //$NON-NLS-1$
private static final String RETURN = "@return"; //$NON-NLS-1$ private static final String ENUM = "enum "; //$NON-NLS-1$
private static final String THROW = "throw "; //$NON-NLS-1$
private static final String STRUCT = "struct "; //$NON-NLS-1$
private static final String UNION = "union "; //$NON-NLS-1$
private static final String BRIEF = "brief "; //$NON-NLS-1$
private static final String PARAM = "param "; //$NON-NLS-1$
private static final String FUNC = "fn "; //$NON-NLS-1$
private static final String TPARAM = "tparam "; //$NON-NLS-1$
private static final String RETURN = "return"; //$NON-NLS-1$
private static final String DEF = "def "; //$NON-NLS-1$
private static final String NAMESPACE = "namespace "; //$NON-NLS-1$
private static final String PREFIX_JAVADOC = "@"; //$NON-NLS-1$
private static final String PREFIX_NO_JAVADOC = "\\"; //$NON-NLS-1$
protected boolean documentPureVirtuals = true; protected boolean documentPureVirtuals = true;
protected boolean documentDeclarations = true; protected boolean documentDeclarations = true;
private boolean javadocStyle = true;
private boolean useStructuralCommands = false;
private boolean useBriefTag = false;
private String fLineDelimiter; private String fLineDelimiter;
public DoxygenMultilineAutoEditStrategy() { public DoxygenMultilineAutoEditStrategy() {
} }
private String getPrefix() {
return javadocStyle ? PREFIX_JAVADOC : PREFIX_NO_JAVADOC;
}
/** /**
* @since 6.6 * @since 6.6
*/ */
@ -73,12 +106,62 @@ public class DoxygenMultilineAutoEditStrategy extends DefaultMultilineCommentAut
/** /**
* @param decl the function declarator to document * @param decl the function declarator to document
* @param ds the function specifier to document * @param ds the function specifier to document
* @param templateParams Template parameters for the function
* @return content describing the specified function * @return content describing the specified function
* @since 6.7
*/ */
protected StringBuilder documentFunction(IASTFunctionDeclarator decl, IASTDeclSpecifier ds) { protected StringBuilder documentComposite(IASTCompositeTypeSpecifier decl,
ICPPASTTemplateParameter[] templateParams) {
StringBuilder result = new StringBuilder();
if (useStructuralCommands) {
switch (decl.getKey()) {
case ICPPASTCompositeTypeSpecifier.k_class:
result.append(getPrefix()).append(CLASS).append(decl.getName().getSimpleID())
.append(getLineDelimiter());
break;
case IASTCompositeTypeSpecifier.k_struct:
result.append(getPrefix()).append(STRUCT).append(decl.getName().getSimpleID())
.append(getLineDelimiter());
break;
case IASTCompositeTypeSpecifier.k_union:
result.append(getPrefix()).append(UNION).append(decl.getName().getSimpleID())
.append(getLineDelimiter());
break;
}
}
if (useBriefTag)
result.append(getPrefix()).append(BRIEF).append(getLineDelimiter()).append(getLineDelimiter())
.append(getLineDelimiter()).append(documentTemplateParameters(templateParams));
return result;
}
/**
* Document a function/method
* @param decl the function declarator to document
* @param ds the function specifier to document
* @param templateParams Template parameters for the function
* @return content describing the specified function
* @since 6.7
*/
protected StringBuilder documentFunction(IASTFunctionDeclarator decl, IASTDeclSpecifier ds,
ICPPASTTemplateParameter[] templateParams) {
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
if (useStructuralCommands) {
result.append(getPrefix()).append(FUNC).append(ASTStringUtil.getSignatureString(ds, decl))
.append(getLineDelimiter());
}
if (useBriefTag) {
result.append(getPrefix()).append(BRIEF).append(getLineDelimiter()).append(getLineDelimiter())
.append(getLineDelimiter()).append(documentTemplateParameters(templateParams));
}
result.append(documentTemplateParameters(templateParams));
result.append(documentFunctionParameters(getParameterDecls(decl))); result.append(documentFunctionParameters(getParameterDecls(decl)));
if (decl instanceof ICPPASTFunctionDeclarator) {
ICPPASTFunctionDeclarator cppDecl = (ICPPASTFunctionDeclarator) decl;
result.append(documentExceptions(cppDecl.getExceptionSpecification(), cppDecl.getNoexceptExpression()));
}
boolean hasReturn = true; boolean hasReturn = true;
if (ds instanceof IASTSimpleDeclSpecifier) { if (ds instanceof IASTSimpleDeclSpecifier) {
@ -95,6 +178,23 @@ public class DoxygenMultilineAutoEditStrategy extends DefaultMultilineCommentAut
return result; return result;
} }
/**
* Document template parameters
* @param templateParams The list of template parameters
* @return The built string
* @since 6.7
*/
protected StringBuilder documentTemplateParameters(ICPPASTTemplateParameter[] templateParams) {
StringBuilder result = new StringBuilder();
if (templateParams == null || templateParams.length == 0)
return result;
for (ICPPASTTemplateParameter t : templateParams) {
IASTName name = CPPTemplates.getTemplateParameterName(t);
result.append(getPrefix()).append(TPARAM).append(new String(name.getSimpleID())).append(getLineDelimiter());
}
return result;
}
/** /**
* Returns the comment content to add to the documentation comment. * Returns the comment content to add to the documentation comment.
* @param decls The parameter declarations to describe * @param decls The parameter declarations to describe
@ -105,7 +205,7 @@ public class DoxygenMultilineAutoEditStrategy extends DefaultMultilineCommentAut
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
for (int i = 0; i < decls.length; i++) { for (int i = 0; i < decls.length; i++) {
if (!isVoidParameter(decls[i])) { if (!isVoidParameter(decls[i])) {
result.append(PARAM).append(getParameterName(decls[i])).append(getLineDelimiter()); result.append(getPrefix()).append(PARAM).append(getParameterName(decls[i])).append(getLineDelimiter());
} }
} }
return result; return result;
@ -156,7 +256,7 @@ public class DoxygenMultilineAutoEditStrategy extends DefaultMultilineCommentAut
* @return the comment content to describe the return * @return the comment content to describe the return
*/ */
protected StringBuilder documentFunctionReturn() { protected StringBuilder documentFunctionReturn() {
return new StringBuilder(RETURN).append(getLineDelimiter()); return new StringBuilder(getPrefix()).append(RETURN).append(getLineDelimiter());
} }
/** /**
@ -177,16 +277,14 @@ public class DoxygenMultilineAutoEditStrategy extends DefaultMultilineCommentAut
return result; return result;
} }
/* /**
* @see org.eclipse.cdt.ui.text.doctools.DefaultMultilineCommentAutoEditStrategy#customizeAfterNewLineForDeclaration(org.eclipse.jface.text.IDocument, org.eclipse.cdt.core.dom.ast.IASTDeclaration, org.eclipse.jface.text.ITypedRegion) * @since 6.7
*/ */
@Override @Override
protected StringBuilder customizeAfterNewLineForDeclaration(IDocument doc, IASTDeclaration dec, public StringBuilder customizeForDeclaration(IDocument doc, IASTNode declToDocument, ITypedRegion partition,
ITypedRegion partition) { CustomizeOptions options) {
fLineDelimiter = TextUtilities.getDefaultLineDelimiter(doc); fLineDelimiter = TextUtilities.getDefaultLineDelimiter(doc);
IASTDeclaration declToDocument = dec;
if (declToDocument instanceof ICPPASTLinkageSpecification) { if (declToDocument instanceof ICPPASTLinkageSpecification) {
ICPPASTLinkageSpecification linkageSpecification = (ICPPASTLinkageSpecification) declToDocument; ICPPASTLinkageSpecification linkageSpecification = (ICPPASTLinkageSpecification) declToDocument;
IASTDeclaration[] declarations = linkageSpecification.getDeclarations(); IASTDeclaration[] declarations = linkageSpecification.getDeclarations();
@ -214,20 +312,35 @@ public class DoxygenMultilineAutoEditStrategy extends DefaultMultilineCommentAut
} }
} }
if (options != null && (useBriefTag || useStructuralCommands))
options.addNewLine = false;
ICPPASTTemplateParameter[] params = null;
if (declToDocument instanceof ICPPASTTemplateDeclaration) {
params = ((ICPPASTTemplateDeclaration) declToDocument).getTemplateParameters();
}
while (declToDocument instanceof ICPPASTTemplateDeclaration) /* if? */ while (declToDocument instanceof ICPPASTTemplateDeclaration) /* if? */
declToDocument = ((ICPPASTTemplateDeclaration) declToDocument).getDeclaration(); declToDocument = ((ICPPASTTemplateDeclaration) declToDocument).getDeclaration();
if (declToDocument instanceof IASTFunctionDefinition) { if (declToDocument instanceof IASTFunctionDefinition) {
IASTFunctionDefinition fd = (IASTFunctionDefinition) declToDocument; IASTFunctionDefinition fd = (IASTFunctionDefinition) declToDocument;
return documentFunction(fd.getDeclarator(), fd.getDeclSpecifier()); return documentFunction(fd.getDeclarator(), fd.getDeclSpecifier(), params);
}
if (declToDocument instanceof IASTPreprocessorMacroDefinition) {
return documentDefine((IASTPreprocessorMacroDefinition) declToDocument);
}
if (declToDocument instanceof ICPPASTNamespaceDefinition) {
return documentNamespace((ICPPASTNamespaceDefinition) declToDocument);
} }
if (declToDocument instanceof IASTSimpleDeclaration) { if (declToDocument instanceof IASTSimpleDeclaration) {
IASTSimpleDeclaration sdec = (IASTSimpleDeclaration) declToDocument; IASTSimpleDeclaration sdec = (IASTSimpleDeclaration) declToDocument;
StringBuilder result = new StringBuilder();
if (sdec.getDeclSpecifier() instanceof IASTCompositeTypeSpecifier) { if (sdec.getDeclSpecifier() instanceof IASTCompositeTypeSpecifier) {
return result; return documentComposite((IASTCompositeTypeSpecifier) sdec.getDeclSpecifier(), params);
} else { } else {
IASTDeclarator[] dcs = sdec.getDeclarators(); IASTDeclarator[] dcs = sdec.getDeclarators();
if (dcs.length == 1 && dcs[0] instanceof IASTFunctionDeclarator) { if (dcs.length == 1 && dcs[0] instanceof IASTFunctionDeclarator) {
@ -239,25 +352,120 @@ public class DoxygenMultilineAutoEditStrategy extends DefaultMultilineCommentAut
} }
if (shouldDocument) { if (shouldDocument) {
return documentFunction(fdecl, sdec.getDeclSpecifier()); return documentFunction(fdecl, sdec.getDeclSpecifier(), params);
} }
} }
} }
} }
StringBuilder builder = new StringBuilder();
if (declToDocument instanceof IASTSimpleDeclaration
&& ((IASTSimpleDeclaration) declToDocument).getDeclSpecifier() instanceof IASTEnumerationSpecifier) {
builder = documentEnum(
(IASTEnumerationSpecifier) ((IASTSimpleDeclaration) declToDocument).getDeclSpecifier());
}
try { try {
alterDoc(doc, declToDocument); alterDoc(doc, declToDocument);
} catch (BadLocationException ble) { } catch (BadLocationException ble) {
/*ignore*/ /*ignore*/
} }
return new StringBuilder(); return builder;
}
/**
* Document preprocessor defines
* @param Macro definition
* @return The built buffer
* @since 6.7
*/
protected StringBuilder documentDefine(IASTPreprocessorMacroDefinition dec) {
StringBuilder result = new StringBuilder();
if (useStructuralCommands)
result.append(getPrefix()).append(DEF).append(new String(dec.getName().getSimpleID()))
.append(getLineDelimiter());
if (useBriefTag)
result.append(getPrefix()).append(BRIEF).append(getLineDelimiter()).append(getLineDelimiter())
.append(getLineDelimiter());
return result;
}
/**
* Document namespaces
* @param dec Namespace definition
* @return The built buffer
* @since 6.7
*/
protected StringBuilder documentNamespace(ICPPASTNamespaceDefinition dec) {
StringBuilder result = new StringBuilder();
if (useStructuralCommands)
result.append(getPrefix()).append(NAMESPACE).append(new String(dec.getName().getSimpleID()))
.append(getLineDelimiter());
if (useBriefTag)
result.append(getPrefix()).append(BRIEF).append(getLineDelimiter()).append(getLineDelimiter())
.append(getLineDelimiter());
return result;
}
/**
* Document enums
* @param dec Enumeration specifier
* @return The built buffer
* @since 6.7
*/
protected StringBuilder documentEnum(IASTEnumerationSpecifier dec) {
StringBuilder result = new StringBuilder();
if (useStructuralCommands)
result.append(getPrefix()).append(ENUM).append(new String(dec.getName().getSimpleID()))
.append(getLineDelimiter());
if (useBriefTag)
result.append(getPrefix()).append(BRIEF).append(getLineDelimiter()).append(getLineDelimiter())
.append(getLineDelimiter());
return result;
}
/**
* Document function exceptions
* @param exceptions A list of exceptions or NO_EXCEPTION_SPECIFICATION if no exceptions are present
* or EMPTY_TYPEID_ARRAY if no exceptions will be thrown.
* @param noexcept Noexcept expression, null if no present, NOEXCEPT_DEFAULT if noexcept has been used
* @return The built string
* @since 6.7
*/
protected StringBuilder documentExceptions(IASTTypeId[] exceptions, ICPPASTExpression noexcept) {
StringBuilder result = new StringBuilder();
if (exceptions == ICPPASTFunctionDeclarator.NO_EXCEPTION_SPECIFICATION
|| exceptions == IASTTypeId.EMPTY_TYPEID_ARRAY) {
if (noexcept != null && noexcept != ICPPASTFunctionDeclarator.NOEXCEPT_DEFAULT
&& !isNoexceptTrue(noexcept)) {
result.append(getPrefix()).append(THROW).append(getLineDelimiter());
}
} else {
for (int i = 0; i < exceptions.length; i++) {
result.append(getPrefix()).append(THROW);
if (exceptions[i] instanceof ICPPASTTypeId && ((ICPPASTTypeId) exceptions[i]).isPackExpansion()) {
result.append(getLineDelimiter());
continue;
}
result.append(ASTStringUtil.getSignatureString(exceptions[i].getAbstractDeclarator()))
.append(getLineDelimiter());
}
}
return result;
}
private boolean isNoexceptTrue(ICPPASTExpression expr) {
if (expr instanceof IASTLiteralExpression) {
return ((IASTLiteralExpression) expr).getKind() == IASTLiteralExpression.lk_true;
}
return false;
} }
/* /*
* Add post-declaration comments to enumerators, after initializing a doc-comment on an enumeration * Add post-declaration comments to enumerators, after initializing a doc-comment on an enumeration
*/ */
private void alterDoc(IDocument doc, IASTDeclaration dec) throws BadLocationException { private void alterDoc(IDocument doc, IASTNode dec) throws BadLocationException {
if (dec instanceof IASTSimpleDeclaration if (dec instanceof IASTSimpleDeclaration
&& ((IASTSimpleDeclaration) dec).getDeclSpecifier() instanceof IASTEnumerationSpecifier) { && ((IASTSimpleDeclaration) dec).getDeclSpecifier() instanceof IASTEnumerationSpecifier) {
IASTEnumerationSpecifier spc = (IASTEnumerationSpecifier) ((IASTSimpleDeclaration) dec).getDeclSpecifier(); IASTEnumerationSpecifier spc = (IASTEnumerationSpecifier) ((IASTSimpleDeclaration) dec).getDeclSpecifier();

View file

@ -152,16 +152,16 @@ public class DoxygenSingleAutoEditStrategy extends DoxygenMultilineAutoEditStrat
} }
private StringBuilder getDeclarationLines(IDocument doc, int offset) throws BadLocationException { private StringBuilder getDeclarationLines(IDocument doc, int offset) throws BadLocationException {
IASTDeclaration dec = null; IASTNode dec = null;
IASTTranslationUnit ast = getAST(); IASTTranslationUnit ast = getAST();
if (ast != null) { if (ast != null) {
dec = findFollowingDeclaration(ast, offset); dec = findNextDocumentNode(ast, offset);
if (dec == null) { if (dec == null) {
IASTNodeSelector ans = ast.getNodeSelector(ast.getFilePath()); IASTNodeSelector ans = ast.getNodeSelector(ast.getFilePath());
IASTNode node = ans.findEnclosingNode(offset, 0); IASTNode node = ans.findEnclosingNode(offset, 0);
if (node instanceof IASTDeclaration) { if (node instanceof IASTDeclaration) {
dec = (IASTDeclaration) node; dec = node;
} }
} }
} }
@ -169,7 +169,7 @@ public class DoxygenSingleAutoEditStrategy extends DoxygenMultilineAutoEditStrat
if (dec != null) { if (dec != null) {
ITypedRegion partition = TextUtilities.getPartition(doc, ICPartitions.C_PARTITIONING /* this! */, offset, ITypedRegion partition = TextUtilities.getPartition(doc, ICPartitions.C_PARTITIONING /* this! */, offset,
false); false);
return customizeAfterNewLineForDeclaration(doc, dec, partition); return customizeForDeclaration(doc, dec, partition, null);
} }
return null; return null;
} }