Doxygen: hiding private/protected method...and tips [closed] - c#

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 5 years ago.
Improve this question
I am using Doxygen to generate documentation for our API, written in C#. However, it exposes private/protected members. Is there a way to hide those?
I figured out how to hide files: EXCLUDE = List of file names
Yet, I need more granularity and thus shield users from unnecessary API noise. A sample Doxygen file would be appreciated as well as tips/tricks.
What tools do you use to generate API from the source code?
I feel somewhat left in the 18th century as I use Doxygen in C# by way of C++.

I don't know how well C# is supported by Doxygen.
For hiding private members, you change Doxyfile configuration file as following:
EXTRACT_PRIVATE = YES
Many other options can be set for various kinds of extracting/hiding code elements, e.g., citing Doxyfile itself:
# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
# documentation are documented, even if no documentation was available.
# Private class members and static file members will be hidden unless
# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
EXTRACT_ALL = YES
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
# will be included in the documentation.
EXTRACT_PRIVATE = YES
# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
EXTRACT_STATIC = YES
# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
# defined locally in source files will be included in the documentation.
# If set to NO only classes defined in header files are included.
EXTRACT_LOCAL_CLASSES = YES
# This flag is only useful for Objective-C code. When set to YES local
# methods, which are defined in the implementation section but not in
# the interface are included in the documentation.
# If set to NO (the default) only methods in the interface are included.
EXTRACT_LOCAL_METHODS = YES
# If this flag is set to YES, the members of anonymous namespaces will be
# extracted and appear in the documentation as a namespace called
# 'anonymous_namespace{file}', where file will be replaced with the base
# name of the file that contains the anonymous namespace. By default
# anonymous namespace are hidden.
EXTRACT_ANON_NSPACES = NO
# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
# undocumented members of documented classes, files or namespaces.
# If set to NO (the default) these members will be included in the
# various overviews, but no documentation section is generated.
# This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy.
# If set to NO (the default) these classes will be included in the various
# overviews. This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
# friend (class|struct|union) declarations.
# If set to NO (the default) these declarations will be included in the
# documentation.
HIDE_FRIEND_COMPOUNDS = NO

Check out the #cond flag for doxygen. In C# I hide some of our password encryption members like this:
//! #cond
private const String ENCRYPTEDFLAG = "xxxENCFLAGxxx";
private const String SEED = "hi_i_r_#_seed";
//! #endcond
The doxygen documentation would have you believe that you need a conditional symbol defined to doxygen and used on the #cond line, but that did not work for me. This method did.

This works for me, to hide big chunks of code and documentation:
/*! \cond PRIVATE */
<here goes private documented source code>
/*! \endcond */
Run with ENABLED_SECTIONS = PRIVATE to create your internal version of the docs. You can have several conditions and enable/disable them according to the audience.
To hide just part of a documentation block, use \internal (will hide until the end of the block unless \endinternal is found)
Note: you can use # notation if you prefer it over backslashes.

A few possibilities, from the doxygen manual:
HIDE_UNDOC_MEMBERS, HIDE_UNDOC_CLASSES: Obviously works only if you only document the public members.
INTERNAL_DOCS: Allows you to use the \internal markup to exclude comments from the "public" version of the documentation.
ENABLED_SECTIONS: Are more general version of INTERNAL_DOCS

Related

Get raw decodated name of IDiaSymbol

I'm trying to improve SymbolSort library, which reads PDB files with DIA SDK. I need to match the symbols read from object files with the symbols read from PDB.
The question is: given an IDiaSymbol variable, how can I obtain its real name? I'm not interesting in the undecorated or human-readable name, I need the mangled name, exactly as it appears in the object file, exactly as linker sees it.
The undecorated name can be easily obtained via IDiaSymbol::get_undecoratedName (ref). For decorated name, I use the following code:
string rawName;
IDiaSymbolUndecoratedNameExFlags flags = Flags.UNDNAME_32_BIT_DECODE | Flags.UNDNAME_TYPE_ONLY;
diaSymbol.get_undecoratedNameEx((uint)flags, out rawName);
It was found empirically that this hack seems to work well in most cases (for no reason). But sometimes it gives some trash as result, e.g.:
diaSymbol.undecoratedName:
"private: bool __cdecl idPhysics_Player::SlideMove(bool,bool,bool,bool) __ptr64"
rawSymbol:
" ?? :: ?? ::Z::_N_N000 & __ptr64 volatile "
I was reading only private symbols from the PDB. The private symbols in general do not provide raw symbol name (in some cases they don't even have one).
The problem is solved by reading public symbols instead (using SymTagEnum.SymTagPublicSymbol). For them, diaSymbol.name always gives the raw name of the symbol.
All this is well documented in public and private symbols article.

Dollar ($) character used in resource.GetObject

I just spotted this line in an old Windows Forms app (created by the designer):
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
it seems to be using ResourceManager.GetObject() in order to get the icon. My question is regarding the significance of the $ prefixing this. There is no mention of the dollar symbol in the docs.
Does the dollar have a special meaning (reflection possibly?) or merely just to do with the implementation of GetObject()?
In addition where is the icon actually stored?
This is a pretty standard trick used in .NET, the compiler uses it too when it needs to generate a name for a auto-generated class or field. Using a character like $ ensures that there can never be a name collision with an identifier in the program.
There isn't much chance of that when you only program in C#, this is a keyword. But certainly in other languages. You could for example create a VB.NET Winforms project, drop a button on the form and name it "this". When you localize the form, the button's Text property source appears as:
<data name="this.Text" xml:space="preserve">
<value>Button1</value>
</data>
That would be a name collision with the form's Text property resource if it didn't put the $ in front of it. Not until you program in a language that permits $ in an identifier name anyway. None of the standard VS languages do.
Yet another detail is that you'll have trouble referencing that button from C# code. There's an escape hatch for that as well, you can use #this in your code. The # prefix makes sure that the compiler doesn't recognize it as a keyword but just a plain identifier.
The WinForms designer actually dumps quite a bit of hidden items like this into the resource file (.resx) assocaited with each form in order to support, mostly, internationalization (though other designer meta-data is there as well). While text and icons may be obvious, even layout information can be there. I suppose those German words are pretty long so when internationalizaing the form you may actually need to change label widths.
The $ I would assume is a way to make sure the designer-added resources don't conflict with user resources.
It turns out that the icon is stored within the corresponding .resx file and was actually defined with the dollar prefix $this.Icon. This would imply that the dollar doesn't have a special meaning at all.

Parser Generator: How to use GPLEX and GPPG together?

After looking through posts for good C# parser generators, I stumbled across GPLEX and GPPG. I'd like to use GPLEX to generate tokens for GPPG to parse and create a tree (similar to the lex/yacc relationship). However, I can't seem to find an example on how these two interact together. With lex/yacc, lex returns tokens that are defined by yacc, and can store values in yylval. How is this done in GPLEX/GPPG (it is missing from their documentation)?
Attached is the lex code I would like to convert over to GPLEX:
%{
#include <stdio.h>
#include "y.tab.h"
%}
%%
[Oo][Rr] return OR;
[Aa][Nn][Dd] return AND;
[Nn][Oo][Tt] return NOT;
[A-Za-z][A-Za-z0-9_]* yylval=yytext; return ID;
%%
Thanks!
Andrew
First: include the reference "QUT.ShiftReduceParser.dll" in your Project. It is provided in the download-package from GPLEX.
Sample-Code for Main-Program:
using System;
using ....;
using QUT.Gppg;
using Scanner;
using Parser;
namespace NCParser
{
class Program
{
static void Main(string[] args)
{
string pathTXT = #"C:\temp\testFile.txt";
FileStream file = new FileStream(pathTXT, FileMode.Open);
Scanner scanner = new Scanner();
scanner.SetSource(file, 0);
Parser parser = new Parser(scanner);
}
}
}
Sample-Code for GPLEX:
%using Parser; //include the namespace of the generated Parser-class
%Namespace Scanner //names the Namespace of the generated Scanner-class
%visibility public //visibility of the types "Tokens","ScanBase","Scanner"
%scannertype Scanner //names the Scannerclass to "Scanner"
%scanbasetype ScanBase //names the Scanbaseclass to "ScanBase"
%tokentype Tokens //names the Tokenenumeration to "Tokens"
%option codePage:65001 out:Scanner.cs /*see the documentation of GPLEX for further Options you can use */
%{ //user-specified code will be copied in the Output-file
%}
OR [Oo][Rr]
AND [Aa][Nn][Dd]
Identifier [A-Za-z][A-Za-z0-9_]*
%% //Rules Section
%{ //user-code that will be executed before getting the next token
%}
{OR} {return (int)Tokens.kwAND;}
{AND} {return (int)Tokens.kwAND;}
{Identifier} {yylval = yytext; return (int)Tokens.ID;}
%% //User-code Section
Sample-Code for GPPG-input-file:
%using Scanner //include the Namespace of the scanner-class
%output=Parser.cs //names the output-file
%namespace Parser //names the namespace of the Parser-class
%parsertype Parser //names the Parserclass to "Parser"
%scanbasetype ScanBase //names the ScanBaseclass to "ScanBase"
%tokentype Tokens //names the Tokensenumeration to "Tokens"
%token kwAND "AND", kwOR "OR" //the received Tokens from GPLEX
%token ID
%% //Grammar Rules Section
program : /* nothing */
| Statements
;
Statements : EXPR "AND" EXPR
| EXPR "OR" EXPR
;
EXPR : ID
;
%% User-code Section
// Don't forget to declare the Parser-Constructor
public Parser(Scanner scnr) : base(scnr) { }
c#parsegppggplex
I had a similar issue - not knowing how to use my output from GPLEX with GPPG due to an apparent lack of documentation. I think the problem stems from the fact that the GPLEX distribution includes gppg.exe along with gplex.exe, but only documentation for GPLEX.
If you go the GPPG homepage and download that distribution, you'll get the documentation for GPPG, which describes the requirements for the input file, how to construct your grammar, etc. Oh, and you'll also get both binaries again - gppg.exe and gplex.exe.
It almost seems like it would be simpler to just include everything in one package. It could definitely clear up some confusion, especially for those who may be new to lexical analysis (tokenization) and parsing (and may not be 100% familiar yet with the differences between the two).
So anyways, for those who may doing this for the first time:
GPLEX http://gplex.codeplex.com - used for tokenization/scanning/lexical analysis (same thing)
GPPG http://gppg.codeplex.com/ - takes output from a tokenizer as input to parse. For example, parsers use grammars and can do things a simple tokenizer cannot, like detect whether sets of parentheses match up.
Some time ago I have had the same need of using both GPLEX and GPPG together and for making the job much more easier I have created a nuget package for using GPPG and GPLEX together in Visual Studio.
This package can be installed in C# projects based on .Net Framework and adds some command-lets to the Package Manager Console in Visual Studio. This command-lets help you in configuring the C# project for integrating GPPG and GPLEX in the build process. Essentially in your project you will edit YACC and LEX files as source code and during the build of the project, the parser and the scanner will be generated. In addition the command-lets add to the projects the files needed for customizing the parser and the scanner.
You can find it here:
https://www.nuget.org/packages/YaccLexTools/
And here is a link to the blog post that explains how to use it:
http://ecianciotta-en.abriom.com/2013/08/yacclex-tools-v02.html
Have you considered using Roslyn? (This isn't a proper answer but I don't have enough reputation to post this as a comment)
Irony, because when I jumped into parsers in C# I started exactly from those 2 tools (about a year ago). Then lexer has tiny bug (easy to fix):
http://gplex.codeplex.com/workitem/11308
but parser had more severe:
http://gppg.codeplex.com/workitem/11344
Lexer should be fixed (release date is June 2013), but parser probably still has this bug (May 2012).
So I wrote my own suite :-) https://sourceforge.net/projects/naivelangtools/ and use and develop it since then.
Your example translates (in NLT) to:
/[Oo][Rr]/ -> OR;
/[Aa][Nn][Dd]/ -> AND;
/[Nn][Oo][Tt]/ -> NOT;
// by default text is returned as value
/[A-Za-z][A-Za-z0-9_]*/ -> ID;
Entire suite is similar to lex/yacc, when possible it does not rely on side effects (so you return appropriate value).

Is it possible to define an enum in C# with values that are keywords?

I have some client data that I am reading in, and I've defined an Enum for one of the values, so I can use Enum.Parse(type, somestring).
The problem is they just added a new value: "public". Is it possible to define an enum value that is also a reserved word?
I.E.:
public enum MyEnum {
SomeVal,
SomeOtherVal,
public,
YouGetTheIdea
}
If not I guess I'll be writing a parse method instead.
You can prepend a # to the variable name. This allows you to use keywords as variable names - so #public.
See here.
From the C# spec:
The prefix "#" enables the use of keywords as identifiers, which is useful when interfacing with other programming languages. The character # is not actually part of the identifier, so the identifier might be seen in other languages as a normal identifier, without the prefix. An identifier with an # prefix is called a verbatim identifier. Use of the # prefix for identifiers that are not keywords is permitted, but strongly discouraged as a matter of style.
yes, prefix the name with an #. i.e. #public
If you capitalize public to Public it won't be recognized as a keyword. Keywords are case sensitive.
As a general practice, however, it's a bad idea to use names that are keywords (even when they differ by case) as it can cause confusions, or even subtle defects if the keyword is accidentally used in place of the identifier.
It's also possible to use the # in certain contexts (like variable or member declarations) to use reserved words as non-keywords. However, it's not a common practice and should only be a means of last resort, when you can't use a different name.
So in your case you could also use #public to use the reserved word as an enum identifier.
If you chose to use #, be aware that the symbol is only used in your source code to differentiate the identifier from the reserved word. To the outside world (and in methods like Enum.Parse()), the name of the enum value is simply public.
It's not really a great idea to do this though. Instead, add a bit more info to the enum:
PublicAccess etc
In VB.Net use square braces [...] to delineate a keyword as an identifier.
Example:
Public Sub Test(ByVal [public] As String)
MessageBox.Show("Test string: " & [public])
End Sub
For VB.NET do the following:
Public Enum MyEnum As Integer
Disabled = 0
[New] = 1
[Public] = 2
Super = 4
[Error] = 5
End Enum

How do I display only the class name in doxygen class diagrams?

Using doxygen and graphviz with my C# project, I can generate class diagrams in the documentation pages. These diagrams have the full class names and namespaces in them, e.g.
Acme.MyProduct.MyClasses.MyClass
Is it possible to configure doxygen to cut this down a bit to just the class name?
MyClass
The fully qualified paths make even simple diagrams rather wide and unwieldy. I'd like to minimize the need for horizontal scrolling.
I suspect that you've already solved this as it is a year old, but an answer might be useful for anyone else searching for this (as I just did). You can use the "HIDE_SCOPE_NAMES" option. Setting it to YES (or checking it in the doxywizard GUI) will hide namespaces. From my doxygen file:
# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
# will show members with their full class and namespace scopes in the
# documentation. If set to YES the scope will be hidden.
HIDE_SCOPE_NAMES = YES
The HIDE_SCOPE_NAMES works great but only hides the scope in the class diagram but not the caller/callee graphs for each method.
To reduce the width of those diagrams to a readable size you can rename the scope using the input filter. This will not remove the namespace but will reduce it to a more readable width.
For example to rename the namespace "COMPANY_NAMESPACE" to "sf" use:
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command <filter> <input-file>, where <filter>
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
# input file. Doxygen will then use the output that the filter program writes
# to standard output. If FILTER_PATTERNS is specified, this tag will be
# ignored.
INPUT_FILTER = "sed 's,COMPANY_NAMESPACE,sf,'"

Categories