summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authordimitri <dimitri@afe2bf4a-e733-0410-8a33-86f594647bc7>2007-07-27 08:53:22 (GMT)
committerdimitri <dimitri@afe2bf4a-e733-0410-8a33-86f594647bc7>2007-07-27 08:53:22 (GMT)
commitcfa9d4d590cdbf4940f88159f72853e8501cc168 (patch)
tree096d7be65663d2b1088aed9714e8047edf65961d /src
parent54e919c70d5a43e260b188d5c71fd7c54ce874f0 (diff)
downloadDoxygen-cfa9d4d590cdbf4940f88159f72853e8501cc168.zip
Doxygen-cfa9d4d590cdbf4940f88159f72853e8501cc168.tar.gz
Doxygen-cfa9d4d590cdbf4940f88159f72853e8501cc168.tar.bz2
Release-1.5.3
Diffstat (limited to 'src')
-rw-r--r--src/code.l43
-rw-r--r--src/commentscan.l11
-rw-r--r--src/config.l14
-rw-r--r--src/definition.cpp115
-rw-r--r--src/definition.h3
-rw-r--r--src/docparser.cpp112
-rw-r--r--src/doxygen.cpp107
-rw-r--r--src/latexgen.cpp3
-rw-r--r--src/memberdef.cpp19
-rw-r--r--src/memberlist.cpp9
-rw-r--r--src/pyscanner.l2
-rw-r--r--src/scanner.l99
-rw-r--r--src/textdocvisitor.cpp2
-rw-r--r--src/util.cpp60
-rw-r--r--src/util.h3
15 files changed, 470 insertions, 132 deletions
diff --git a/src/code.l b/src/code.l
index 7ee6a82..fd5722a 100644
--- a/src/code.l
+++ b/src/code.l
@@ -222,7 +222,7 @@ void VariableContext::addVariable(const QCString &type,const QCString &name)
ltype = ltype.right(ltype.length()-6);
}
if (ltype.isEmpty() || lname.isEmpty()) return;
- DBG_CTX((stderr,"** addVariable trying: type=%s name=%s g_currentDefinition=%s\n",
+ DBG_CTX((stderr,"** addVariable trying: type='%s' name='%s' g_currentDefinition=%s\n",
ltype.data(),lname.data(),g_currentDefinition?g_currentDefinition->name().data():"<none>"));
Scope *scope = m_scopes.count()==0 ? &m_globalScope : m_scopes.getLast();
ClassDef *varType;
@@ -232,7 +232,7 @@ void VariableContext::addVariable(const QCString &type,const QCString &name)
(varType=getResolvedClass(g_currentDefinition,g_sourceFileDef,ltype)) // look for global class definitions
)
{
- DBG_CTX((stderr,"** addVariable type=%s name=%s\n",ltype.data(),lname.data()));
+ DBG_CTX((stderr,"** addVariable type='%s' name='%s'\n",ltype.data(),lname.data()));
scope->append(lname,varType); // add it to a list
}
else if ((i=ltype.find('<'))!=-1)
@@ -253,7 +253,7 @@ void VariableContext::addVariable(const QCString &type,const QCString &name)
}
if (newDef)
{
- DBG_CTX((stderr,"** addVariable type=%s templ=%s name=%s\n",typeName.data(),templateArgs.data(),lname.data()));
+ DBG_CTX((stderr,"** addVariable type='%s' templ='%s' name='%s'\n",typeName.data(),templateArgs.data(),lname.data()));
scope->append(lname, newDef);
}
else
@@ -268,7 +268,7 @@ void VariableContext::addVariable(const QCString &type,const QCString &name)
// is hidden to avoid false links to global variables with the same name
// TODO: make this work for namespaces as well!
{
- DBG_CTX((stderr,"** addVariable: dummy context\n"));
+ DBG_CTX((stderr,"** addVariable: dummy context for '%s'\n",lname.data()));
scope->append(lname,dummyContext);
}
else
@@ -876,7 +876,7 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName,
}
QCString className=clName;
if (className.isEmpty()) return;
- if (g_insideProtocolList)
+ if (g_insideProtocolList) // for Obj-C
{
className+="-p";
}
@@ -919,10 +919,14 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName,
{
//printf("non-dummy context lcd=%s!\n",lcd->name().data());
g_theCallContext.setClass(lcd);
- if (getLink(g_classScope,clName,ol,clName))
- {
- return;
- }
+
+ // to following is needed for links to a global variable, but is
+ // no good for a link to a local variable that is also a global symbol.
+
+ //if (getLink(g_classScope,clName,ol,clName))
+ //{
+ //return;
+ //}
}
isLocal=TRUE;
//fprintf(stderr,"is a local variable cd=%p!\n",cd);
@@ -1750,6 +1754,7 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
if (!g_curClassName.isEmpty()) // valid class name
{
pushScope(g_curClassName);
+ DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
g_scopeStack.push(SCOPEBLOCK);
}
}
@@ -1859,6 +1864,7 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
<Body,FuncCall>"{" {
g_theVarContext.pushScope();
+ DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
g_scopeStack.push(INNERBLOCK);
if (g_searchingForBody)
@@ -1874,11 +1880,15 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
}
g_type.resize(0);
g_name.resize(0);
+ BEGIN( Body );
}
<Body,MemberCall,MemberCall2>"}" {
g_theVarContext.popScope();
+ g_type.resize(0);
+ g_name.resize(0);
int *scope = g_scopeStack.pop();
+ DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK));
if (scope==SCOPEBLOCK || scope==CLASSBLOCK)
{
popScope();
@@ -1914,6 +1924,7 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
g_theVarContext.popScope();
int *scope = g_scopeStack.pop();
+ DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK));
if (scope==SCOPEBLOCK || scope==CLASSBLOCK)
{
popScope();
@@ -1980,7 +1991,10 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
<ClassVar>{ID} {
g_type = g_curClassName.copy();
g_name = yytext;
- g_theVarContext.addVariable(g_type,g_name);
+ if (g_insideBody)
+ {
+ g_theVarContext.addVariable(g_type,g_name);
+ }
generateClassOrGlobalLink(*g_code,yytext);
}
<ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*":"{B}* {
@@ -2005,6 +2019,7 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
if (g_insideBody) g_bodyCurlyCount++;
if (!g_curClassName.isEmpty()) // valid class name
{
+ DBG_CTX((stderr,"** scope stack push CLASSBLOCK\n"));
g_scopeStack.push(CLASSBLOCK);
pushScope(g_curClassName);
//fprintf(stderr,"***** g_curClassName=%s\n",g_curClassName.data());
@@ -2032,6 +2047,7 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
}
else // not a class name -> assume inner block
{
+ DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
g_scopeStack.push(INNERBLOCK);
}
g_curClassName.resize(0);
@@ -2185,6 +2201,7 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
if (*yytext==')')
{
g_theCallContext.popScope();
+ g_bracketCount--;
BEGIN(FuncCall);
}
}
@@ -2440,6 +2457,7 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
g_saveType = g_type.copy();
if (*yytext!='[' && !g_type.isEmpty())
{
+ //printf("g_scopeStack.bottom()=%p\n",g_scopeStack.bottom());
if (g_scopeStack.top()!=CLASSBLOCK)
{
//printf("AddVariable: '%s' '%s' context=%d\n",
@@ -2625,6 +2643,7 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
g_parmType.resize(0);g_parmName.resize(0);
}
<MemberCall2,FuncCall>"(" {
+ g_parmType.resize(0);g_parmName.resize(0);
g_code->codify(yytext);
g_bracketCount++;
g_theCallContext.pushScope();
@@ -2717,10 +2736,12 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
{
setClassScope(g_realScope);
}
+ DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
g_scopeStack.push(SCOPEBLOCK);
}
else
{
+ DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
g_scopeStack.push(INNERBLOCK);
}
yytext[yyleng-1]='\0';
@@ -2806,11 +2827,13 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
if (g_insideBody) g_bodyCurlyCount++;
if (g_name.find("::")!=-1)
{
+ DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n"));
g_scopeStack.push(SCOPEBLOCK);
setClassScope(g_realScope);
}
else
{
+ DBG_CTX((stderr,"** scope stack push INNERBLOCK\n"));
g_scopeStack.push(INNERBLOCK);
}
g_type.resize(0); g_name.resize(0);
diff --git a/src/commentscan.l b/src/commentscan.l
index 9a7f698..1b55244 100644
--- a/src/commentscan.l
+++ b/src/commentscan.l
@@ -272,7 +272,7 @@ class DocCmdMapper
{
if (m_map.find(p->cmdName)!=0)
{
- printf("Error: command %s already added\n",p->cmdName);
+ printf("Error: DocCmdMapper: command %s already added\n",p->cmdName);
exit(1);
}
Cmd *cmd = new Cmd;
@@ -687,7 +687,14 @@ static inline void setOutput(OutputContext ctx)
current->briefLine = yyLineNr;
}
}
- pOutputString = &current->brief;
+ if (current->brief.isEmpty())
+ {
+ pOutputString = &current->brief;
+ }
+ else
+ {
+ pOutputString = &current->doc;
+ }
break;
case OutputXRef:
pOutputString = &outputXRef;
diff --git a/src/config.l b/src/config.l
index cb73dfb..35b1b8c 100644
--- a/src/config.l
+++ b/src/config.l
@@ -647,6 +647,8 @@ static void readIncludeFile(const char *incName)
tmpString.resize(0);
}
<GetQuotedString>"\""|"\n" {
+ // we add a bogus space to signal that the string was quoted. This space will be stripped later on.
+ tmpString+=" ";
//printf("Quoted String = `%s'\n",tmpString.data());
if (lastState==GetString)
{
@@ -790,6 +792,8 @@ static void substEnvVarsInString(QCString &s)
s = s.left(i)+env+s.right(s.length()-i-l);
p=i+env.length(); // next time start at the end of the expanded string
}
+ s=s.stripWhiteSpace(); // to strip the bogus space that was added when an argument
+ // has quotes
//printf("substEnvVarInString(%s) end\n",s.data());
}
@@ -799,7 +803,9 @@ static void substEnvVarsInStrList(QStrList &sl)
while (s)
{
QCString result(s);
+ // an argument with quotes will have an extra space at the end, so wasQuoted will be TRUE.
bool wasQuoted = (result.find(' ')!=-1) || (result.find('\t')!=-1);
+ // here we strip the quote again
substEnvVarsInString(result);
//printf("Result %s was quoted=%d\n",result.data(),wasQuoted);
@@ -1718,6 +1724,14 @@ void Config::create()
FALSE
);
cb = addBool(
+ "EXTRACT_ANON_NSPACES",
+ "If this flag is set to YES, the members of anonymous namespaces will be extracted \n"
+ "and appear in the documentation as a namespace called 'anonymous_namespace{file}', \n"
+ "where file will be replaced with the base name of the file that contains the anonymous \n"
+ "namespace. By default anonymous namespace are hidden. \n",
+ FALSE
+ );
+ cb = addBool(
"HIDE_UNDOC_MEMBERS",
"If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all \n"
"undocumented members of documented classes, files or namespaces. \n"
diff --git a/src/definition.cpp b/src/definition.cpp
index 668e566..ba0bcd2 100644
--- a/src/definition.cpp
+++ b/src/definition.cpp
@@ -18,6 +18,7 @@
#include "qtbc.h"
#include <ctype.h>
#include <qregexp.h>
+#include <md5.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
@@ -63,6 +64,7 @@ class DefinitionImpl
DocInfo *details; // not exported
BriefInfo *brief; // not exported
BodyInfo *body; // not exported
+ QCString docSignatures;
QCString localName; // local (unqualified) name of the definition
// in the future m_name should become m_localName
@@ -280,7 +282,7 @@ Definition::Definition(const char *df,int dl,
m_isSymbol = isSymbol;
if (isSymbol) addToMap(name,this);
_setBriefDescription(b,df,dl);
- _setDocumentation(d,df,dl,TRUE);
+ _setDocumentation(d,df,dl,TRUE,FALSE);
if (matchExcludedSymbols(name)) m_impl->hidden = TRUE;
}
@@ -348,7 +350,25 @@ void Definition::writeDocAnchorsToTagFile()
}
}
-void Definition::_setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace)
+bool Definition::_docsAlreadyAdded(const QString &doc)
+{
+ uchar md5_sig[16];
+ QCString sigStr(33);
+ MD5Buffer((const unsigned char *)doc.data(),doc.length(),md5_sig);
+ MD5SigToString(md5_sig,sigStr.data(),33);
+ if (m_impl->docSignatures.find(sigStr)==-1) // new docs, add signature to prevent re-adding it
+ {
+ m_impl->docSignatures+=":"+sigStr;
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+void Definition::_setDocumentation(const char *d,const char *docFile,int docLine,
+ bool stripWhiteSpace,bool atTop)
{
if (d==0) return;
//printf("Definition::setDocumentation(%s,%s,%d,%d)\n",d,docFile,docLine,stripWhiteSpace);
@@ -361,52 +381,82 @@ void Definition::_setDocumentation(const char *d,const char *docFile,int docLine
{
doc=d;
}
- //printf("setting docs for %s: `%s'\n",name().data(),m_doc.data());
- if (m_impl->details==0)
+ if (!_docsAlreadyAdded(doc))
{
- m_impl->details = new DocInfo;
+ //printf("setting docs for %s: `%s'\n",name().data(),m_doc.data());
+ if (m_impl->details==0)
+ {
+ m_impl->details = new DocInfo;
+ }
+ if (m_impl->details->doc.isEmpty()) // fresh detailed description
+ {
+ m_impl->details->doc = doc;
+ }
+ else if (atTop) // another detailed description, append it to the start
+ {
+ m_impl->details->doc = doc+"\n\n"+m_impl->details->doc;
+ }
+ else // another detailed description, append it to the end
+ {
+ m_impl->details->doc += "\n\n"+doc;
+ }
+ if (docLine!=-1) // store location if valid
+ {
+ m_impl->details->file = docFile;
+ m_impl->details->line = docLine;
+ }
}
- m_impl->details->doc = doc;
- m_impl->details->file = docFile;
- m_impl->details->line = docLine;
}
void Definition::setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace)
{
if (d==0) return;
makeResident();
- _setDocumentation(d,docFile,docLine,stripWhiteSpace);
+ _setDocumentation(d,docFile,docLine,stripWhiteSpace,FALSE);
}
#define uni_isupper(c) (QChar(c).category()==QChar::Letter_Uppercase)
void Definition::_setBriefDescription(const char *b,const char *briefFile,int briefLine)
{
- if (b==0) return;
static QCString outputLanguage = Config_getEnum("OUTPUT_LANGUAGE");
static bool needsDot = outputLanguage!="Japanese" &&
outputLanguage!="Chinese" &&
outputLanguage!="Korean";
- //fprintf(stderr,"Definition::setBriefDescription(%s,%s,%d)\n",b,briefFile,briefLine);
- if (m_impl->brief==0)
- {
- m_impl->brief = new BriefInfo;
- }
- m_impl->brief->doc=QCString(b).stripWhiteSpace();
- int bl=m_impl->brief->doc.length();
+ QCString brief = b;
+ brief = brief.stripWhiteSpace();
+ if (brief.isEmpty()) return;
+ int bl = brief.length();
if (bl>0 && needsDot) // add punctuation if needed
{
- switch(m_impl->brief->doc.at(bl-1))
+ switch(brief.at(bl-1))
{
case '.': case '!': case '?': break;
default:
- if (uni_isupper(m_impl->brief->doc.at(0))) m_impl->brief->doc+='.';
+ if (uni_isupper(brief.at(0))) brief+='.';
break;
}
}
- m_impl->brief->file = briefFile;
- m_impl->brief->line = briefLine;
- m_impl->brief->tooltip = parseCommentAsText(m_impl->brief->doc,briefFile,briefLine);
+
+ if (m_impl->brief && !m_impl->brief->doc.isEmpty())
+ {
+ //printf("adding to details\n");
+ _setDocumentation(brief,briefFile,briefLine,FALSE,TRUE);
+ }
+ else if (!_docsAlreadyAdded(brief))
+ {
+ //fprintf(stderr,"Definition::setBriefDescription(%s,%s,%d)\n",b,briefFile,briefLine);
+ if (m_impl->brief==0)
+ {
+ m_impl->brief = new BriefInfo;
+ }
+ m_impl->brief->doc=brief;
+ if (briefLine!=-1)
+ {
+ m_impl->brief->file = briefFile;
+ m_impl->brief->line = briefLine;
+ }
+ }
}
void Definition::setBriefDescription(const char *b,const char *briefFile,int briefLine)
@@ -1100,7 +1150,24 @@ QCString Definition::briefDescription() const
QCString Definition::briefDescriptionAsTooltip() const
{
makeResident();
- return m_impl->brief ? m_impl->brief->tooltip : QCString("");
+ if (m_impl->brief)
+ {
+ if (m_impl->brief->tooltip.isEmpty() && !m_impl->brief->doc.isEmpty())
+ {
+ static bool reentering=FALSE;
+ if (!reentering)
+ {
+ reentering=TRUE; // prevent requests for tooltips while parsing a tooltip
+ m_impl->brief->tooltip = parseCommentAsText(
+ m_impl->brief->doc,
+ m_impl->brief->file,
+ m_impl->brief->line);
+ reentering=FALSE;
+ }
+ }
+ return m_impl->brief->tooltip;
+ }
+ return QCString("");
}
int Definition::briefLine() const
@@ -1245,6 +1312,7 @@ void Definition::flushToDisk() const
marshalDocInfo (Doxygen::symbolStorage,m_impl->details);
marshalBriefInfo (Doxygen::symbolStorage,m_impl->brief);
marshalBodyInfo (Doxygen::symbolStorage,m_impl->body);
+ marshalQCString (Doxygen::symbolStorage,m_impl->docSignatures);
marshalQCString (Doxygen::symbolStorage,m_impl->localName);
marshalQCString (Doxygen::symbolStorage,m_impl->qualifiedName);
marshalQCString (Doxygen::symbolStorage,m_impl->ref);
@@ -1274,6 +1342,7 @@ void Definition::loadFromDisk() const
m_impl->details = unmarshalDocInfo (Doxygen::symbolStorage);
m_impl->brief = unmarshalBriefInfo (Doxygen::symbolStorage);
m_impl->body = unmarshalBodyInfo (Doxygen::symbolStorage);
+ m_impl->docSignatures = unmarshalQCString (Doxygen::symbolStorage);
m_impl->localName = unmarshalQCString (Doxygen::symbolStorage);
m_impl->qualifiedName = unmarshalQCString (Doxygen::symbolStorage);
m_impl->ref = unmarshalQCString (Doxygen::symbolStorage);
diff --git a/src/definition.h b/src/definition.h
index 0b8b95e..2bbc682 100644
--- a/src/definition.h
+++ b/src/definition.h
@@ -310,7 +310,8 @@ class Definition : public DefinitionIntf, public LockableObj
void _writeSourceRefList(OutputList &ol,const char *scopeName,
const QCString &text,MemberSDict *members,bool);
void _setBriefDescription(const char *b,const char *briefFile,int briefLine);
- void _setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace);
+ void _setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace,bool atTop);
+ bool _docsAlreadyAdded(const QString &doc);
DefinitionImpl *m_impl; // internal structure holding all private data
QCString m_name;
bool m_isSymbol;
diff --git a/src/docparser.cpp b/src/docparser.cpp
index e9d16af..dff6940 100644
--- a/src/docparser.cpp
+++ b/src/docparser.cpp
@@ -68,23 +68,7 @@ static const char *sectionLevelToName[] =
//---------------------------------------------------------------------------
-// global variables during a call to validatingParseDoc
-static bool g_hasParamCommand;
-static bool g_hasReturnCommand;
-static MemberDef * g_memberDef;
-static QDict<void> g_paramsFound;
-static bool g_isExample;
-static QCString g_exampleName;
-static SectionDict *g_sectionDict;
-
-static QCString g_searchUrl;
-
-// include file state
-static QString g_includeFileText;
-static uint g_includeFileOffset;
-static uint g_includeFileLength;
-
-// parser state
+// Parser state: global variables during a call to validatingParseDoc
static QString g_context;
static bool g_inSeeBlock;
static bool g_insideHtmlLink;
@@ -95,6 +79,20 @@ static QList<Definition> g_copyStack;
static QString g_fileName;
static QString g_relPath;
+static bool g_hasParamCommand;
+static bool g_hasReturnCommand;
+static MemberDef * g_memberDef;
+static QDict<void> g_paramsFound;
+static bool g_isExample;
+static QCString g_exampleName;
+static SectionDict * g_sectionDict;
+static QCString g_searchUrl;
+
+static QString g_includeFileText;
+static uint g_includeFileOffset;
+static uint g_includeFileLength;
+
+// parser's context to store all global variables
struct DocParserContext
{
QString context;
@@ -104,9 +102,23 @@ struct DocParserContext
QStack<DocStyleChange> styleStack;
QStack<DocStyleChange> initialStyleStack;
QList<Definition> copyStack;
- MemberDef *memberDef;
QString fileName;
QString relPath;
+
+ bool hasParamCommand;
+ bool hasReturnCommand;
+ MemberDef * memberDef;
+ QDict<void> paramsFound;
+ bool isExample;
+ QCString exampleName;
+ SectionDict *sectionDict;
+ QCString searchUrl;
+
+ QString includeFileText;
+ uint includeFileOffset;
+ uint includeFileLength;
+
+ TokenInfo *token;
};
static QStack<DocParserContext> g_parserStack;
@@ -115,6 +127,10 @@ static QStack<DocParserContext> g_parserStack;
static void docParserPushContext()
{
+ //QCString indent;
+ //indent.fill(' ',g_parserStack.count()*2+2);
+ //printf("%sdocParserPushContext() count=%d\n",indent.data(),g_nodeStack.count());
+
doctokenizerYYpushContext();
DocParserContext *ctx = new DocParserContext;
ctx->context = g_context;
@@ -126,6 +142,23 @@ static void docParserPushContext()
ctx->copyStack = g_copyStack;
ctx->fileName = g_fileName;
ctx->relPath = g_relPath;
+
+ ctx->hasParamCommand = g_hasParamCommand;
+ ctx->hasReturnCommand = g_hasReturnCommand;
+ ctx->memberDef = g_memberDef;
+ ctx->paramsFound = g_paramsFound;
+ ctx->isExample = g_isExample;
+ ctx->exampleName = g_exampleName;
+ ctx->sectionDict = g_sectionDict;
+ ctx->searchUrl = g_searchUrl;
+
+ ctx->includeFileText = g_includeFileText;
+ ctx->includeFileOffset = g_includeFileOffset;
+ ctx->includeFileLength = g_includeFileLength;
+
+ ctx->token = g_token;
+ g_token = new TokenInfo;
+
g_parserStack.push(ctx);
}
@@ -141,8 +174,29 @@ static void docParserPopContext()
g_copyStack = ctx->copyStack;
g_fileName = ctx->fileName;
g_relPath = ctx->relPath;
+
+ g_hasParamCommand = ctx->hasParamCommand;
+ g_hasReturnCommand = ctx->hasReturnCommand;
+ g_memberDef = ctx->memberDef;
+ g_paramsFound = ctx->paramsFound;
+ g_isExample = ctx->isExample;
+ g_exampleName = ctx->exampleName;
+ g_sectionDict = ctx->sectionDict;
+ g_searchUrl = ctx->searchUrl;
+
+ g_includeFileText = ctx->includeFileText;
+ g_includeFileOffset = ctx->includeFileOffset;
+ g_includeFileLength = ctx->includeFileLength;
+
+ delete g_token;
+ g_token = ctx->token;
+
delete ctx;
doctokenizerYYpopContext();
+
+ //QCString indent;
+ //indent.fill(' ',g_parserStack.count()*2+2);
+ //printf("%sdocParserPopContext() count=%d\n",indent.data(),g_nodeStack.count());
}
//---------------------------------------------------------------------------
@@ -5876,7 +5930,10 @@ DocNode *validatingParseDoc(const char *fileName,int startLine,
// md?md->name().data():"<none>");
//printf("========== validating %s at line %d\n",fileName,startLine);
//printf("---------------- input --------------------\n%s\n----------- end input -------------------\n",input);
- g_token = new TokenInfo;
+ //g_token = new TokenInfo;
+
+ // store parser state so we can re-enter this function if needed
+ docParserPushContext();
if (ctx &&
(ctx->definitionType()==Definition::TypeClass ||
@@ -5999,10 +6056,12 @@ DocNode *validatingParseDoc(const char *fileName,int startLine,
doctokenizerYYlineno=startLine;
doctokenizerYYinit(input,g_fileName);
+
// build abstract syntax tree
DocRoot *root = new DocRoot(md!=0,singleLine);
root->parse();
+
if (Debug::isFlagSet(Debug::PrintTree))
{
// pretty print the result
@@ -6011,24 +6070,29 @@ DocNode *validatingParseDoc(const char *fileName,int startLine,
delete v;
}
+
checkUndocumentedParams();
detectNoDocumentedParams();
- delete g_token;
-
// TODO: These should be called at the end of the program.
//doctokenizerYYcleanup();
//Mappers::cmdMapper->freeInstance();
//Mappers::htmlTagMapper->freeInstance();
+ // restore original parser state
+ docParserPopContext();
+
return root;
}
DocNode *validatingParseText(const char *input)
{
+ // store parser state so we can re-enter this function if needed
+ docParserPushContext();
+
//printf("------------ input ---------\n%s\n"
// "------------ end input -----\n",input);
- g_token = new TokenInfo;
+ //g_token = new TokenInfo;
g_context = "";
g_fileName = "<parseText>";
g_relPath = "";
@@ -6068,8 +6132,8 @@ DocNode *validatingParseText(const char *input)
}
}
- delete g_token;
-
+ // restore original parser state
+ docParserPopContext();
return txt;
}
diff --git a/src/doxygen.cpp b/src/doxygen.cpp
index 54ace8a..49ea331 100644
--- a/src/doxygen.cpp
+++ b/src/doxygen.cpp
@@ -488,6 +488,7 @@ static void buildGroupListFiltered(EntryNav *rootNav,bool additional)
if ((gd=Doxygen::groupSDict->find(root->name)))
{
+#if 0
if ( root->groupDocType==Entry::GROUPDOC_NORMAL )
{
warn(root->fileName,root->startLine,
@@ -496,6 +497,7 @@ static void buildGroupListFiltered(EntryNav *rootNav,bool additional)
root->name.data());
}
else
+#endif
{
if ( !gd->hasGroupTitle() )
gd->setGroupTitle( root->type );
@@ -503,12 +505,10 @@ static void buildGroupListFiltered(EntryNav *rootNav,bool additional)
warn( root->fileName,root->startLine,
"group %s: ignoring title \"%s\" that does not match old title \"%s\"\n",
root->name.data(), root->type.data(), gd->groupTitle() );
- if ( gd->briefDescription().isEmpty() )
+ //if ( gd->briefDescription().isEmpty() )
gd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- if ( !root->doc.stripWhiteSpace().isEmpty() )
- gd->setDocumentation( gd->documentation().isEmpty() ? root->doc :
- gd->documentation() + "\n\n" + root->doc,
- root->docFile, root->docLine );
+ //if ( !root->doc.stripWhiteSpace().isEmpty() )
+ gd->setDocumentation( root->doc, root->docFile, root->docLine );
gd->addSectionsToDefinition(root->anchors);
gd->setRefItems(root->sli);
//addGroupToGroups(root,gd);
@@ -637,6 +637,7 @@ static void buildFileList(EntryNav *rootNav)
//printf("**************** root->name=%s fd=%p\n",root->name.data(),fd);
if (fd && !ambig)
{
+#if 0
if ((!root->doc.isEmpty() && !fd->documentation().isEmpty()) ||
(!root->brief.isEmpty() && !fd->briefDescription().isEmpty()))
{
@@ -648,6 +649,7 @@ static void buildFileList(EntryNav *rootNav)
);
}
else
+#endif
{
//printf("Adding documentation!\n");
// using FALSE in setDocumentation is small hack to make sure a file
@@ -1088,6 +1090,7 @@ static void addClassToContext(EntryNav *rootNav)
// //printf("existing ClassDef tempArgList=%p specScope=%s\n",root->tArgList,root->scopeSpec.data());
// cd->setTemplateArguments(tArgList);
//}
+#if 0
if (!root->doc.isEmpty() || !root->brief.isEmpty() ||
(root->bodyLine!=-1 && Config_getBool("SOURCE_BROWSER"))
)
@@ -1103,9 +1106,11 @@ static void addClassToContext(EntryNav *rootNav)
);
}
else if (!root->doc.isEmpty())
+#endif
{
cd->setDocumentation(root->doc,root->docFile,root->docLine);
}
+#if 0
if (!root->brief.isEmpty() && !cd->briefDescription().isEmpty())
{
warn(
@@ -1116,6 +1121,7 @@ static void addClassToContext(EntryNav *rootNav)
);
}
else if (!root->brief.isEmpty())
+#endif
{
cd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
}
@@ -1125,7 +1131,9 @@ static void addClassToContext(EntryNav *rootNav)
cd->setBodyDef(fd);
}
//cd->setName(fullName); // change name to match docs
+#if 0
}
+#endif
if (cd->templateArguments()==0)
{
@@ -1360,13 +1368,13 @@ static void buildNamespaceList(EntryNav *rootNav)
//printf("** buildNamespaceList(%s)\n",root->name.data());
- QCString fullName = root->name;
+ QCString fName = root->name;
if (root->section==Entry::PACKAGEDOC_SEC)
{
- fullName=substitute(fullName,".","::");
+ fName=substitute(fName,".","::");
}
-
- fullName = stripAnonymousNamespaceScope(fullName);
+
+ QCString fullName = stripAnonymousNamespaceScope(fName);
if (!fullName.isEmpty())
{
//printf("Found namespace %s in %s at line %d\n",root->name.data(),
@@ -1374,13 +1382,16 @@ static void buildNamespaceList(EntryNav *rootNav)
NamespaceDef *nd;
if ((nd=Doxygen::namespaceSDict->find(fullName))) // existing namespace
{
+#if 0
if (!root->doc.isEmpty() || !root->brief.isEmpty()) // block contains docs
{
if (nd->documentation().isEmpty() && !root->doc.isEmpty())
{
+#endif
nd->setDocumentation(root->doc,root->docFile,root->docLine);
nd->setName(fullName); // change name to match docs
nd->addSectionsToDefinition(root->anchors);
+#if 0
}
else if (!nd->documentation().isEmpty() && !root->doc.isEmpty())
{
@@ -1392,7 +1403,9 @@ static void buildNamespaceList(EntryNav *rootNav)
}
if (nd->briefDescription().isEmpty() && !root->brief.isEmpty())
{
+#endif
nd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
+#if 0
nd->setName(fullName); // change name to match docs
}
else if (!nd->briefDescription().isEmpty() && !root->brief.isEmpty())
@@ -1404,6 +1417,7 @@ static void buildNamespaceList(EntryNav *rootNav)
);
}
}
+#endif
// file definition containing the namespace nd
FileDef *fd=rootNav->fileDef();
@@ -2199,7 +2213,8 @@ static int findFunctionPtr(const QCString &type,int *pLength=0)
if (!type.isEmpty() && // return type is non-empty
(i=re.match(type,0,&l))!=-1 && // contains (...*...)
type.find("operator")==-1 && // not an operator
- type.find(")(")==-1 // not a function pointer return type
+ (type.find(")(")==-1 || type.find("typedef ")!=-1)
+ // not a function pointer return type
)
{
if (pLength) *pLength=l;
@@ -2392,6 +2407,7 @@ static void buildVarList(EntryNav *rootNav)
else
{
int i=isFuncPtr;
+ if (i==-1) i=findFunctionPtr(root->type); // for typedefs isFuncPtr is not yet set
if (i!=-1) // function pointer
{
int ai = root->type.find('[',i);
@@ -2847,10 +2863,16 @@ static void buildFunctionList(EntryNav *rootNav)
{
NamespaceDef *mnd = md->getNamespaceDef();
NamespaceDef *rnd = 0;
- if (!rootNav->parent()->name().isEmpty())
+ //printf("root namespace=%s\n",rootNav->parent()->name().data());
+ QCString fullScope = scope;
+ QCString parentScope = rootNav->parent()->name();
+ if (!parentScope.isEmpty() && !leftScopeMatch(parentScope,scope))
{
- rnd = getResolvedNamespace(rootNav->parent()->name());
+ if (!scope.isEmpty()) fullScope.prepend("::");
+ fullScope.prepend(parentScope);
}
+ //printf("fullScope=%s\n",fullScope.data());
+ rnd = getResolvedNamespace(fullScope);
FileDef *mfd = md->getFileDef();
QCString nsName,rnsName;
if (mnd) nsName = mnd->name().copy();
@@ -2870,6 +2892,7 @@ static void buildFunctionList(EntryNav *rootNav)
gd = Doxygen::groupSDict->find(root->groups->first()->groupname.data());
}
//printf("match!\n");
+ //printf("mnd=%p rnd=%p nsName=%s rnsName=%s\n",mnd,rnd,nsName.data(),rnsName.data());
// see if we need to create a new member
found=(mnd && rnd && nsName==rnsName) || // members are in the same namespace
((mnd==0 && rnd==0 && mfd!=0 && // no external reference and
@@ -2893,9 +2916,6 @@ static void buildFunctionList(EntryNav *rootNav)
// merge documentation
if (md->documentation().isEmpty() && !root->doc.isEmpty())
{
- md->setDocumentation(root->doc,root->docFile,root->docLine);
- md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
- md->setDocsForDefinition(!root->proto);
ArgumentList *argList = new ArgumentList;
stringToArgumentList(root->args,argList);
if (root->proto)
@@ -2908,21 +2928,28 @@ static void buildFunctionList(EntryNav *rootNav)
md->setArgumentList(argList);
}
}
+#if 0
else if (!md->documentation().isEmpty() && !root->doc.isEmpty() && mnd==rnd)
{
warn(root->docFile,root->docLine,"Warning: member %s: ignoring the detailed description found here, since another one was found at line %d of file %s!",md->name().data(),md->docLine(),md->docFile().data());
//printf("md->docs=[%s] root->docs=[%s]\n",md->documentation().data(),root->doc.data());
}
+#endif
+ md->setDocumentation(root->doc,root->docFile,root->docLine);
+ md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
+ md->setDocsForDefinition(!root->proto);
if (md->briefDescription().isEmpty() && !root->brief.isEmpty())
{
- md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
md->setArgsString(root->args);
}
+#if 0
else if (!md->briefDescription().isEmpty() && !root->brief.isEmpty() && mnd==rnd)
{
warn(root->briefFile,root->briefLine,"Warning: member %s: ignoring the brief description found here, since another one was found at line %d of file %s!",md->name().data(),md->briefLine(),md->briefFile().data());
}
+#endif
+ md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
md->addSectionsToDefinition(root->anchors);
@@ -4648,6 +4675,8 @@ static void addMemberDocs(EntryNav *rootNav,
//printf("Adding docs md->docs=`%s' root->docs=`%s'!\n",
// md->documentation().data(),root->doc.data());
// documentation outside a compound overrides the documentation inside it
+
+#if 0
if ( /* !md->isStatic() && !root->stat && do not replace doc of a static */
(
md->documentation().isEmpty() || /* no docs yet */
@@ -4656,6 +4685,7 @@ static void addMemberDocs(EntryNav *rootNav,
)
) && !root->doc.isEmpty()
)
+#endif
{
//printf("overwrite!\n");
md->setDocumentation(root->doc,root->docFile,root->docLine);
@@ -4666,12 +4696,14 @@ static void addMemberDocs(EntryNav *rootNav,
// md->briefDescription().data(),root->brief.data());
// brief descriptions inside a compound override the documentation
// outside it
+#if 0
if ( /* !md->isStatic() && !root->stat && do not replace doc of static */
(
md->briefDescription().isEmpty() || /* no docs yet */
!rootNav->parent()->name().isEmpty() /* member of a class */
) && !root->brief.isEmpty()
)
+#endif
{
//printf("overwrite!\n");
md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
@@ -5715,6 +5747,7 @@ static void findMember(EntryNav *rootNav,
// root->argList ? (int)root->argList->count() : -1);
// new related (member) function
+#if 0 // removed as it doesn't handle related template functions correctly
ArgumentList *tArgList =
getTemplateArgumentsFromName(scopeName+"::"+funcName,root->tArgLists);
MemberDef *md=new MemberDef(
@@ -5722,7 +5755,37 @@ static void findMember(EntryNav *rootNav,
funcType,funcName,funcArgs,exceptions,
root->protection,root->virt,root->stat,TRUE,
mtype,tArgList,funcArgs.isEmpty() ? 0 : root->argList);
+#endif
+ // first note that we pass:
+ // (root->tArgLists ? root->tArgLists->last() : 0)
+ // for the template arguments fo the new "member."
+ // this accurately reflects the template arguments of
+ // the related function, which don't have to do with
+ // those of the related class.
+ MemberDef *md=new MemberDef(
+ root->fileName,root->startLine,
+ funcType,funcName,funcArgs,exceptions,
+ root->protection,root->virt,root->stat,TRUE,
+ mtype,
+ (root->tArgLists ? root->tArgLists->last() : 0),
+ funcArgs.isEmpty() ? 0 : root->argList);
+ //
+ // we still have the problem that
+ // MemberDef::writeDocumentation() in memberdef.cpp
+ // writes the template argument list for the class,
+ // as if this member is a member of the class.
+ // fortunately, MemberDef::writeDocumentation() has
+ // a special mechanism that allows us to totally
+ // override the set of template argument lists that
+ // are printed. We use that and set it to the
+ // template argument lists of the related function.
+ //
+ md->setDefinitionTemplateParameterLists(root->tArgLists);
+
md->setTagInfo(rootNav->tagInfo());
+
+
+
//printf("Related member name=`%s' decl=`%s' bodyLine=`%d'\n",
// funcName.data(),funcDecl.data(),root->bodyLine);
@@ -6541,7 +6604,9 @@ static void findEnumDocumentation(EntryNav *rootNav)
if (cd && cd->name()==className && md->isEnumerate())
{
// documentation outside a compound overrides the documentation inside it
+#if 0
if (!md->documentation() || rootNav->parent()->name().isEmpty())
+#endif
{
md->setDocumentation(root->doc,root->docFile,root->docLine);
md->setDocsForDefinition(!root->proto);
@@ -6549,7 +6614,9 @@ static void findEnumDocumentation(EntryNav *rootNav)
// brief descriptions inside a compound override the documentation
// outside it
+#if 0
if (!md->briefDescription() || !rootNav->parent()->name().isEmpty())
+#endif
{
md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
}
@@ -7374,12 +7441,16 @@ static void findDefineDocumentation(EntryNav *rootNav)
{
if (md->memberType()==MemberDef::Define)
{
+#if 0
if (md->documentation().isEmpty())
+#endif
{
md->setDocumentation(root->doc,root->docFile,root->docLine);
md->setDocsForDefinition(!root->proto);
}
+#if 0
if (md->briefDescription().isEmpty())
+#endif
{
md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
}
@@ -7416,12 +7487,16 @@ static void findDefineDocumentation(EntryNav *rootNav)
if (fd && fd->absFilePath()==root->fileName)
// doc and define in the same file assume they belong together.
{
+#if 0
if (md->documentation().isEmpty())
+#endif
{
md->setDocumentation(root->doc,root->docFile,root->docLine);
md->setDocsForDefinition(!root->proto);
}
+#if 0
if (md->briefDescription().isEmpty())
+#endif
{
md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
}
diff --git a/src/latexgen.cpp b/src/latexgen.cpp
index 356c7b4..d7257f1 100644
--- a/src/latexgen.cpp
+++ b/src/latexgen.cpp
@@ -184,7 +184,8 @@ void LatexGenerator::init()
}
else // use pdflatex for higher quality output
{
- t << "all: clean refman.pdf" << endl << endl;
+ t << "all: clean refman.pdf" << endl << endl
+ << "pdf: refman.pdf" << endl << endl;
t << "refman.pdf: refman.tex" << endl;
t << "\tpdflatex refman.tex" << endl;
t << "\tmakeindex refman.idx" << endl;
diff --git a/src/memberdef.cpp b/src/memberdef.cpp
index bc8c76e..14d1c2d 100644
--- a/src/memberdef.cpp
+++ b/src/memberdef.cpp
@@ -150,7 +150,7 @@ static bool writeDefArgumentList(OutputList &ol,ClassDef *cd,
// or use the following to put the function pointer as it appears in
// the prototype.
- // bool hasFuncPtrType=vp!=-1 && wp!=-1 && wp<vp;
+ //bool hasFuncPtrType=vp!=-1 && wp!=-1 && wp<vp;
if (!a->attrib.isEmpty() && !md->isObjCMethod()) // argument has an IDL attribute
{
@@ -455,9 +455,9 @@ void MemberDefImpl::init(Definition *def,
initLines=0;
type=t;
if (mt==MemberDef::Typedef) type.stripPrefix("typedef ");
- type.stripPrefix("struct ");
- type.stripPrefix("class " );
- type.stripPrefix("union " );
+ // type.stripPrefix("struct ");
+ // type.stripPrefix("class " );
+ // type.stripPrefix("union " );
type=removeRedundantWhiteSpace(type);
args=a;
args=removeRedundantWhiteSpace(args);
@@ -970,10 +970,11 @@ bool MemberDef::isBriefSectionVisible() const
makeResident();
LockingPtr<MemberDef> lock(this,this);
MemberGroupInfo *info = Doxygen::memGrpInfoDict[m_impl->grpId];
+ //printf("name=%s m_impl->grpId=%d info=%p\n",name().data(),m_impl->grpId,info);
//QCString *pMemGrp = Doxygen::memberDocDict[grpId];
bool hasDocs = hasDocumentation() ||
// part of a documented member group
- (m_impl->grpId!=-1 && info && !info->doc.isEmpty());
+ (m_impl->grpId!=-1 && info && !(info->doc.isEmpty() && info->header.isEmpty()));
// only include static members with file/namespace scope if
// explicitly enabled in the config file
@@ -1033,9 +1034,9 @@ bool MemberDef::isBriefSectionVisible() const
);
//printf("visibleIfStatic=%d visibleIfDocumented=%d visibleIfEnabled=%d"
- // "visibleIfPrivate=%d visibleIfDocVirtual=%d visibltIfNotDefaultCDTor=%d "
+ // "visibleIfPrivate=%d visibltIfNotDefaultCDTor=%d "
// "visibleIfFriendCompound=%d\n",visibleIfStatic,visibleIfDocumented,
- // visibleIfEnabled,visibleIfPrivate,visibleIfDocVirtual,visibleIfNotDefaultCDTor,
+ // visibleIfEnabled,visibleIfPrivate,visibleIfNotDefaultCDTor,
// visibleIfFriendCompound);
bool visible = visibleIfStatic && visibleIfDocumented &&
@@ -1222,7 +1223,7 @@ void MemberDef::writeDeclaration(OutputList &ol,
}
else
{
- ltype = ltype.left(i) + " { ... } " + ltype.right(ltype.length()-i-l);
+ ltype = ltype.left(i) + " { ... } " + removeAnonymousScopes(ltype.right(ltype.length()-i-l));
linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),name(),ltype,TRUE);
}
}
@@ -1575,7 +1576,7 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol,
}
// get member name
- QCString doxyName=name().copy();
+ QCString doxyName=name();
// prepend scope if there is any. TODO: make this optional for C only docs
if (scopeName) doxyName.prepend((QCString)scopeName+"::");
QCString doxyArgs=argsString();
diff --git a/src/memberlist.cpp b/src/memberlist.cpp
index 6bb14af..3f04712 100644
--- a/src/memberlist.cpp
+++ b/src/memberlist.cpp
@@ -67,6 +67,7 @@ void MemberList::countDecMembers(bool countEnumValues)
MemberDef *md;
for (mli.toFirst();(md=mli.current());++mli)
{
+ //printf("MemberList::countDecMembers(md=%s,%d)\n",md->name().data(),md->isBriefSectionVisible());
if (md->isBriefSectionVisible())
{
switch(md->memberType())
@@ -177,8 +178,12 @@ void MemberList::writePlainDeclarations(OutputList &ol,
{
//printf("----- writePlainDeclaration() ----\n");
countDecMembers();
- if (numDecMembers()==0) return; // no members in this list
- //printf("----> writePlainDeclaration() numDecMembers()=%d\n",
+ if (numDecMembers()==0)
+ {
+ //printf(" --> no members!\n");
+ return; // no members in this list
+ }
+ //printf(" --> writePlainDeclaration() numDecMembers()=%d\n",
// numDecMembers());
ol.pushGeneratorState();
diff --git a/src/pyscanner.l b/src/pyscanner.l
index ed3f10b..5b5f6cb 100644
--- a/src/pyscanner.l
+++ b/src/pyscanner.l
@@ -1000,7 +1000,7 @@ STARTDOCSYMS ^{B}"##"/[^#]
// prepend scope in case of nested classes
if (current_root->section&Entry::SCOPE_MASK)
{
- printf("*** Prepending scope %s to class %s\n",current_root->name.data(),current->name.data());
+ //printf("*** Prepending scope %s to class %s\n",current_root->name.data(),current->name.data());
current->name.prepend(current_root->name+"::");
}
diff --git a/src/scanner.l b/src/scanner.l
index 09c52fb..584f1b2 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -114,6 +114,7 @@ static bool insideD = FALSE; //!< processing D code?
static bool insidePHP = FALSE; //!< processing PHP code?
static bool insideObjC = FALSE; //!< processing Objective C code?
static bool insideCli = FALSE; //!< processing C++/CLI code?
+static bool insideJS = FALSE; //!< processing JavaScript code?
static bool insideCppQuote = FALSE;
static bool insideProtocolList = FALSE;
@@ -330,6 +331,7 @@ static void setContext()
insideD = langExt==SrcLangExt_D;
insidePHP = langExt==SrcLangExt_PHP;
insideObjC = langExt==SrcLangExt_ObjC;
+ insideJS = langExt==SrcLangExt_JS;
if ( insidePHP )
{
useOverrideCommands = TRUE;
@@ -506,6 +508,23 @@ static void addKnRArgInfo(const QCString &type,const QCString &name,
}
//-----------------------------------------------------------------------------
+
+
+void fixArgumentListForJavaScript(ArgumentList *al)
+{
+ if (al==0) return;
+ ArgumentListIterator ali(*al);
+ Argument *a;
+ for (ali.toFirst();(a=ali.current());++ali)
+ {
+ if (!a->type.isEmpty() && a->name.isEmpty())
+ { // a->type is actually the (typeless) parameter name, so move it
+ a->name=a->type;
+ a->type.resize(0);
+ }
+ }
+}
+
/* ----------------------------------------------------------------- */
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
@@ -750,6 +769,9 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
unput(*yytext);
BEGIN( FindMembers );
}
+<FindMembers>"<?php" { // PHP code with unsupported extension?
+ insidePHP = TRUE;
+ }
<FindMembersPHP>"<?"("php"?) { // PHP code start
BEGIN( FindMembers );
}
@@ -902,7 +924,7 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
}
<CliPropertyType>"{" {
curlyCount=0;
- printf("event: '%s' '%s'\n",current->type.data(),current->name.data());
+ //printf("event: '%s' '%s'\n",current->type.data(),current->name.data());
BEGIN( CSAccessorDecl );
}
<CliPropertyType>";" {
@@ -1762,13 +1784,21 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
insideTryBlock=FALSE;
BEGIN(TryFunctionBlock);
}
+ else if (insideJS && strcmp(yytext,"var")==0)
+ { // javascript variable
+ current->type="var";
+ }
+ else if (insideJS && strcmp(yytext,"function")==0)
+ { // javascript function
+ current->type="function";
+ }
else
{
if (YY_START==FindMembers)
{
addType( current ) ;
}
- bool javaLike = insideJava || insideCS || insideD || insidePHP;
+ bool javaLike = insideJava || insideCS || insideD || insidePHP || insideJS;
if (javaLike && strcmp(yytext,"public")==0)
{
current->protection = Public;
@@ -1781,6 +1811,14 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
{
current->protection = Private;
}
+ else if (javaLike && strcmp(yytext,"static")==0)
+ {
+ if (YY_START==FindMembers)
+ current->name = yytext;
+ else
+ current->name += yytext;
+ current->stat = TRUE;
+ }
else
{
if (YY_START==FindMembers)
@@ -2866,7 +2904,7 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
current = new Entry(*current);
if (current->section==Entry::NAMESPACE_SEC ||
(current->spec==Entry::Interface) ||
- insideJava || insidePHP || insideCS || insideD
+ insideJava || insidePHP || insideCS || insideD || insideJS
)
{ // namespaces and interfaces and java classes ends with a closing bracket without semicolon
current->reset();
@@ -2902,6 +2940,10 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
BEGIN( TypedefName );
}
}
+<TypedefName>("const"|"volatile"){BN} { // late "const" or "volatile" keyword
+ lineCount();
+ current->type.prepend(yytext);
+ }
<TypedefName>{ID} {
if (current->section == Entry::ENUM_SEC)
{
@@ -3285,6 +3327,10 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
*copyArgString+=*yytext;
fullArgString+=*yytext;
stringToArgumentList(fullArgString,current->argList);
+ if (insideJS)
+ {
+ fixArgumentListForJavaScript(current->argList);
+ }
handleParametersCommentBlocks(current->argList);
/* remember the current documentation block, since
@@ -4193,7 +4239,7 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
roundCount=0;
BEGIN(SkipUnionSwitch);
}
- else if ((insideJava || insidePHP) && (strcmp(yytext,"implements")==0 || strcmp(yytext,"extends")==0))
+ else if ((insideJava || insidePHP || insideJS) && (strcmp(yytext,"implements")==0 || strcmp(yytext,"extends")==0))
{
current->type.resize(0);
baseProt=Public;
@@ -4362,7 +4408,14 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
{
if (current->section==Entry::NAMESPACE_SEC) // allow reopening of anonymous namespaces
{
- current->name.sprintf("@%d",anonNSCount);
+ if (Config_getBool("EXTRACT_ANON_NSPACES")) // use visible name
+ {
+ current->name="anonymous_namespace{"+stripPath(current->fileName)+"}";
+ }
+ else // use invisible name
+ {
+ current->name.sprintf("@%d",anonNSCount);
+ }
}
else
{
@@ -4573,12 +4626,23 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
//printf("Start doc block at %d\n",yyLineNr);
removeSlashes=(yytext[1]=='/');
tmpDocType=-1;
+#if 0
if (YY_START!=SkipCurly)
{
current->doc.resize(0);
+ }
+#endif
+ if (!current->doc.isEmpty())
+ {
+ current->doc+="\n\n";
+ }
+ else
+ {
current->docLine = yyLineNr;
current->docFile = yyFileName;
}
+//
+
lastDocContext = YY_START;
if (current_root->section & Entry::SCOPE_MASK)
{
@@ -4597,6 +4661,7 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
current->briefLine = yyLineNr;
current->briefFile = yyFileName;
}
+#if 0
if (!docBlockInBody)
{
current->doc.resize(0);
@@ -4605,6 +4670,7 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
current->brief.resize(0);
}
}
+#endif
startCommentBlock(FALSE);
BEGIN( DocBlock );
}
@@ -4631,6 +4697,7 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
current->briefLine = yyLineNr;
current->briefFile = yyFileName;
}
+#if 0
if (!docBlockInBody)
{
current->doc.resize(0);
@@ -4639,16 +4706,19 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
current->brief.resize(0);
}
}
+#endif
startCommentBlock(FALSE);
BEGIN( DocBlock );
}
<FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>"//!" {
+#if 0
if (YY_START!=SkipCurly)
{
current->brief.resize(0);
current->briefFile=yyFileName;
current->briefLine=yyLineNr;
}
+#endif
tmpDocType=-1;
lastDocContext = YY_START;
if (current_root->section & Entry::SCOPE_MASK)
@@ -4663,16 +4733,18 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
docBlockInBody = YY_START==SkipCurly;
docBlockAutoBrief = FALSE;
docBlock.resize(0);
- startCommentBlock(TRUE);
+ startCommentBlock(current->brief.isEmpty());
BEGIN( DocLine );
}
<FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>"///"/[^/] {
+#if 0
if (YY_START!=SkipCurly)
{
current->brief.resize(0);
current->briefFile=yyFileName;
current->briefLine=yyLineNr;
}
+#endif
tmpDocType=-1;
lastDocContext = YY_START;
if (current_root->section & Entry::SCOPE_MASK)
@@ -4687,7 +4759,7 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
docBlockInBody = YY_START==SkipCurly;
docBlockAutoBrief = FALSE;
docBlock.resize(0);
- startCommentBlock(TRUE);
+ startCommentBlock(current->brief.isEmpty());
BEGIN( DocLine );
}
<FindMembers>"extern"{BN}*"\"C"("++")?"\""{BN}*("{")? {
@@ -4777,7 +4849,7 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
}
<DocLine>[^\n]*/"\n" { // whole line
docBlock+=yytext;
- handleCommentBlock(docBlock,TRUE);
+ handleCommentBlock(docBlock,current->brief.isEmpty());
BEGIN( docBlockContext );
}
@@ -5148,7 +5220,7 @@ static void parseCompounds(Entry *rt)
BEGIN( FindMembers ) ;
current_root = ce ;
yyFileName = ce->fileName;
- setContext();
+ //setContext();
yyLineNr = ce->startLine ;
insideObjC = ce->objc;
//printf("---> Inner block starts at line %d objC=%d\n",yyLineNr,insideObjC);
@@ -5160,15 +5232,12 @@ static void parseCompounds(Entry *rt)
// set default protection based on the compound type
if( ce->section==Entry::CLASS_SEC ) // class
{
- if (
- ce->fileName.right(4)==".php" ||
- ce->fileName.right(4)==".inc" ||
- ce->fileName.right(2)==".d"
- )
+
+ if (insidePHP || insideD || insideJS)
{
current->protection = protection = Public ;
}
- else if (ce->fileName.right(5)==".java")
+ else if (insideJava)
{
current->protection = protection = Package ;
}
diff --git a/src/textdocvisitor.cpp b/src/textdocvisitor.cpp
index 9e5cd21..88afcb2 100644
--- a/src/textdocvisitor.cpp
+++ b/src/textdocvisitor.cpp
@@ -73,7 +73,7 @@ void TextDocVisitor::filter(const char *str)
{
case '\n': m_t << " "; break;
case '"': m_t << "&quot;"; break;
- case '\'': m_t << "&apos;"; break;
+ case '\'': m_t << "&#39;"; break;
case '<': m_t << "&lt;"; break;
case '>': m_t << "&gt;"; break;
case '&': m_t << "&amp;"; break;
diff --git a/src/util.cpp b/src/util.cpp
index fde2dab..5ab4a29 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -163,8 +163,8 @@ QCString removeAnonymousScopes(const QCString &s)
return result;
}
-// replace anonymous scopes with __anonymous__
-QCString replaceAnonymousScopes(const QCString &s)
+// replace anonymous scopes with __anonymous__ or replacement if provided
+QCString replaceAnonymousScopes(const QCString &s,const char *replacement)
{
QCString result;
if (s.isEmpty()) return result;
@@ -174,7 +174,14 @@ QCString replaceAnonymousScopes(const QCString &s)
while ((i=re.match(s,p,&l))!=-1)
{
result+=s.mid(p,i-p);
- result+="__anonymous__";
+ if (replacement)
+ {
+ result+=replacement;
+ }
+ else
+ {
+ result+="__anonymous__";
+ }
p=i+l;
}
result+=s.right(sl-p);
@@ -4556,6 +4563,8 @@ QCString escapeCharsInString(const char *name,bool allowDots)
case '!': result+="_9"; break;
case ',': result+="_00"; break;
case ' ': result+="_01"; break;
+ case '{': result+="_02"; break;
+ case '}': result+="_03"; break;
default:
if (caseSenseNames || !isupper(c))
{
@@ -4654,6 +4663,7 @@ QCString convertNameToFile(const char *name,bool allowDots)
#endif
result.prepend(QCString().sprintf("d%x/d%02x/",l1Dir,l2Dir));
}
+ //printf("*** convertNameToFile(%s)->%s\n",name,result.data());
return result;
}
@@ -4821,12 +4831,6 @@ QCString stripScope(const char *name)
}
-/*! Convert nibble (range 0..15) to hex char */
-//static char nibbleToHex(int n)
-//{
-// return (n < 10) ? ('0'+n) : ('a'+n-10);
-//}
-
/*! Converts a string to an XML-encoded string */
QCString convertToXML(const char *s)
{
@@ -4843,19 +4847,7 @@ QCString convertToXML(const char *s)
case '&': result+="&amp;"; break;
case '\'': result+="&apos;"; break;
case '"': result+="&quot;"; break;
- default:
- //if (c<0)
- //{ <- this doesn't work for languages that use
- // characters with codes beyond 255
- // result+=(QCString)"&#x" +
- // nibbleToHex((((uchar)c)>>4)&0xf)+
- // nibbleToHex(c&0xf)+";";
- //}
- //else
- //{
- result+=c;
- //}
- break;
+ default: result+=c; break;
}
}
return result;
@@ -4864,7 +4856,23 @@ QCString convertToXML(const char *s)
/*! Converts a string to a HTML-encoded string */
QCString convertToHtml(const char *s)
{
- return convertToXML(s);
+ QCString result;
+ if (s==0) return result;
+ const char *p=s;
+ char c;
+ while ((c=*p++))
+ {
+ switch (c)
+ {
+ case '<': result+="&lt;"; break;
+ case '>': result+="&gt;"; break;
+ case '&': result+="&amp;"; break;
+ case '\'': result+="&#39;"; break;
+ case '"': result+="&quot;"; break;
+ default: result+=c; break;
+ }
+ }
+ return result;
}
/*! Returns the standard string that is generated when the \\overload
@@ -5304,7 +5312,7 @@ PageDef *addRelatedPage(const char *name,const QCString &ptitle,
if ((pd=Doxygen::pageSDict->find(name)) && !tagInfo)
{
// append documentation block to the page.
- pd->setDocumentation(pd->documentation()+"\n\n"+doc,fileName,startLine);
+ pd->setDocumentation(doc,fileName,startLine);
//printf("Adding page docs `%s' pi=%p name=%s\n",doc.data(),pi,name);
}
else // new page
@@ -5999,8 +6007,8 @@ SrcLangExt getLanguageFromFileName(const QCString fileName)
extLookup.insert(".odl", new int(SrcLangExt_IDL));
extLookup.insert(".ddl", new int(SrcLangExt_IDL));
extLookup.insert(".java", new int(SrcLangExt_Java));
- extLookup.insert(".jsl", new int(SrcLangExt_Java));
- extLookup.insert(".as", new int(SrcLangExt_Java));
+ extLookup.insert(".as", new int(SrcLangExt_JS));
+ extLookup.insert(".js", new int(SrcLangExt_JS));
extLookup.insert(".cs", new int(SrcLangExt_CSharp));
extLookup.insert(".d", new int(SrcLangExt_D));
extLookup.insert(".php", new int(SrcLangExt_PHP));
diff --git a/src/util.h b/src/util.h
index 8d36a6f..d594a2e 100644
--- a/src/util.h
+++ b/src/util.h
@@ -92,6 +92,7 @@ enum SrcLangExt
SrcLangExt_PHP = 0x080,
SrcLangExt_ObjC = 0x100,
SrcLangExt_Cpp = 0x200,
+ SrcLangExt_JS = 0x400,
};
//--------------------------------------------------------------------
@@ -215,7 +216,7 @@ int getPrefixIndex(const QCString &name);
QCString removeAnonymousScopes(const QCString &s);
-QCString replaceAnonymousScopes(const QCString &s);
+QCString replaceAnonymousScopes(const QCString &s,const char *replacement=0);
void initClassHierarchy(ClassSDict *cl);