memberdef.cpp 126 KB
Newer Older
mueller's avatar
mueller committed
1 2
/******************************************************************************
 *
dimitri's avatar
dimitri committed
3
 * 
mueller's avatar
mueller committed
4
 *
dimitri's avatar
dimitri committed
5
 * Copyright (C) 1997-2010 by Dimitri van Heesch.
mueller's avatar
mueller committed
6 7 8 9 10 11 12
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation under the terms of the GNU General Public License is hereby 
 * granted. No representations are made about the suitability of this software 
 * for any purpose. It is provided "as is" without express or implied warranty.
 * See the GNU General Public License for more details.
 *
dimitri's avatar
dimitri committed
13 14
 * Documents produced by Doxygen are derivative works derived from the
 * input used in their production; they are not affected by this license.
mueller's avatar
mueller committed
15 16 17 18 19
 *
 */

#include <stdio.h>
#include <qregexp.h>
dimitri's avatar
dimitri committed
20
#include <assert.h>
dimitri's avatar
dimitri committed
21
#include <md5.h>
mueller's avatar
mueller committed
22 23 24 25
#include "memberdef.h"
#include "membername.h"
#include "doxygen.h"
#include "util.h"
dimitri's avatar
dimitri committed
26
#include "code.h"
mueller's avatar
mueller committed
27
#include "message.h"
mueller's avatar
mueller committed
28 29
#include "htmlhelp.h"
#include "language.h"
mueller's avatar
mueller committed
30 31 32
#include "outputlist.h"
#include "example.h"
#include "membergroup.h"
dimitri's avatar
dimitri committed
33
#include "groupdef.h"
dimitri's avatar
dimitri committed
34
#include "defargs.h"
dimitri's avatar
dimitri committed
35
#include "docparser.h"
dimitri's avatar
dimitri committed
36
#include "dot.h"
dimitri's avatar
dimitri committed
37
#include "searchindex.h"
dimitri's avatar
dimitri committed
38
#include "parserintf.h"
dimitri's avatar
dimitri committed
39
#include "marshal.h"
dimitri's avatar
dimitri committed
40
#include "objcache.h"
dimitri's avatar
dimitri committed
41 42
#include "vhdlscanner.h"
#include "vhdldocgen.h"
dimitri's avatar
dimitri committed
43 44 45

#define START_MARKER 0x4D454D5B // MEM[
#define END_MARKER   0x4D454D5D // MEM]
dimitri's avatar
dimitri committed
46 47 48 49 50

//-----------------------------------------------------------------------------

int MemberDef::s_indentLevel = 0;

mueller's avatar
mueller committed
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
//-----------------------------------------------------------------------------

static QCString addTemplateNames(const QCString &s,const QCString &n,const QCString &t)
{
  QCString result;
  QCString clRealName=n;
  int p=0,i;
  if ((i=clRealName.find('<'))!=-1)
  {
    clRealName=clRealName.left(i); // strip template specialization
  }
  if ((i=clRealName.findRev("::"))!=-1)
  {
    clRealName=clRealName.right(clRealName.length()-i-2);
  }
  while ((i=s.find(clRealName,p))!=-1)
  {
    result+=s.mid(p,i-p);
    uint j=clRealName.length()+i;
    if (s.length()==j || (s.at(j)!='<' && !isId(s.at(j))))
    { // add template names
      //printf("Adding %s+%s\n",clRealName.data(),t.data());
      result+=clRealName+t; 
    }
    else 
    { // template names already present
      //printf("Adding %s\n",clRealName.data());
      result+=clRealName;
    }
    p=i+clRealName.length();
  }
  result+=s.right(s.length()-p);
  //printf("addTemplateNames(%s,%s,%s)=%s\n",s.data(),n.data(),t.data(),result.data());
  return result;
}

dimitri's avatar
dimitri committed
87
static bool writeDefArgumentList(OutputList &ol,ClassDef *cd,
dimitri's avatar
dimitri committed
88
                                 const QCString & /*scopeName*/,MemberDef *md)
mueller's avatar
mueller committed
89
{
dimitri's avatar
dimitri committed
90
  LockingPtr<ArgumentList> defArgList=(md->isDocsForDefinition()) ? 
dimitri's avatar
dimitri committed
91 92
                             md->argumentList() : md->declArgumentList();
  //printf("writeDefArgumentList `%s' isDocsForDefinition()=%d\n",md->name().data(),md->isDocsForDefinition());
dimitri's avatar
dimitri committed
93
  if (defArgList==0 || md->isProperty()) 
dimitri's avatar
dimitri committed
94 95 96
  {
    return FALSE; // member has no function like argument list
  }
dimitri's avatar
dimitri committed
97
  if (!md->isDefine()) ol.docify(" ");
dimitri's avatar
dimitri committed
98

dimitri's avatar
dimitri committed
99
  //printf("writeDefArgList(%d)\n",defArgList->count());
dimitri's avatar
dimitri committed
100
  ol.pushGeneratorState();
dimitri's avatar
dimitri committed
101 102 103
  //ol.disableAllBut(OutputGenerator::Html);
  bool htmlOn  = ol.isEnabled(OutputGenerator::Html);
  bool latexOn = ol.isEnabled(OutputGenerator::Latex);
dimitri's avatar
dimitri committed
104
  {
dimitri's avatar
dimitri committed
105 106 107
    // html and latex
    if (htmlOn)  ol.enable(OutputGenerator::Html);
    if (latexOn) ol.enable(OutputGenerator::Latex);
dimitri's avatar
dimitri committed
108 109 110
    ol.endMemberDocName();
    ol.startParameterList(!md->isObjCMethod()); 
  }
dimitri's avatar
dimitri committed
111 112
  ol.enableAll();
  ol.disable(OutputGenerator::Html);
dimitri's avatar
dimitri committed
113
  ol.disable(OutputGenerator::Latex);
dimitri's avatar
dimitri committed
114 115 116 117 118
  {
    // other formats
    if (!md->isObjCMethod()) ol.docify("("); // start argument list
    ol.endMemberDocName();
  }
dimitri's avatar
dimitri committed
119 120 121
  ol.popGeneratorState();
  //printf("===> name=%s isDefine=%d\n",md->name().data(),md->isDefine());

dimitri's avatar
dimitri committed
122
  Argument *a=defArgList->first();
mueller's avatar
mueller committed
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
  QCString cName;
  if (cd)
  {
    cName=cd->name();
    int il=cName.find('<');
    int ir=cName.findRev('>');
    if (il!=-1 && ir!=-1 && ir>il)
    {
      cName=cName.mid(il,ir-il+1);
      //printf("1. cName=%s\n",cName.data());
    }
    else if (cd->templateArguments())
    {
      cName=tempArgListToString(cd->templateArguments()); 
      //printf("2. cName=%s\n",cName.data());
    }
    else // no template specifier
    {
      cName.resize(0);
    }
  }
  //printf("~~~ %s cName=%s\n",md->name().data(),cName.data());
dimitri's avatar
dimitri committed
145

dimitri's avatar
dimitri committed
146
  bool first=TRUE;
dimitri's avatar
dimitri committed
147
  bool paramTypeStarted=FALSE;
dimitri's avatar
dimitri committed
148
  bool isDefine = md->isDefine();
mueller's avatar
mueller committed
149 150
  while (a)
  {
dimitri's avatar
dimitri committed
151
    if (isDefine || first) 
dimitri's avatar
dimitri committed
152 153 154
    {
      ol.startParameterType(first,md->isObjCMethod()?"dummy":0);
      paramTypeStarted=TRUE;
dimitri's avatar
dimitri committed
155 156 157 158 159
      if (isDefine)
      {
        ol.endParameterType();
        ol.startParameterName(TRUE);
      }
dimitri's avatar
dimitri committed
160
    }
dimitri's avatar
dimitri committed
161 162 163 164 165 166 167
    QRegExp re(")("),res("(.*\\*");
    int vp=a->type.find(re);
    int wp=a->type.find(res);

    // use the following to put the function pointer type before the name
    bool hasFuncPtrType=FALSE; 

dimitri's avatar
dimitri committed
168
    if (!a->attrib.isEmpty() && !md->isObjCMethod()) // argument has an IDL attribute
mueller's avatar
mueller committed
169 170 171
    {
      ol.docify(a->attrib+" ");
    }
dimitri's avatar
dimitri committed
172
    if (hasFuncPtrType) // argument type is a function pointer
mueller's avatar
mueller committed
173
    {
dimitri's avatar
dimitri committed
174
      //printf("a->type=`%s' a->name=`%s'\n",a->type.data(),a->name.data());
mueller's avatar
mueller committed
175
      QCString n=a->type.left(vp);
dimitri's avatar
dimitri committed
176
      if (hasFuncPtrType) n=a->type.left(wp);
dimitri's avatar
dimitri committed
177
      if (md->isObjCMethod()) { n.prepend("("); n.append(")"); }
dimitri's avatar
dimitri committed
178
      if (!cName.isEmpty()) n=addTemplateNames(n,cd->name(),cName);
dimitri's avatar
dimitri committed
179
      linkifyText(TextGeneratorOLImpl(ol),cd,md->getBodyDef(),md->name(),n);
mueller's avatar
mueller committed
180 181 182 183
    }
    else // non-function pointer type
    {
      QCString n=a->type;
dimitri's avatar
dimitri committed
184
      if (md->isObjCMethod()) { n.prepend("("); n.append(")"); }
dimitri's avatar
dimitri committed
185 186 187 188 189
      if (a->type!="...")
      {
        if (!cName.isEmpty()) n=addTemplateNames(n,cd->name(),cName);
        linkifyText(TextGeneratorOLImpl(ol),cd,md->getBodyDef(),md->name(),n);
      }
mueller's avatar
mueller committed
190
    }
dimitri's avatar
dimitri committed
191
    if (!isDefine)
dimitri's avatar
dimitri committed
192
    {
dimitri's avatar
dimitri committed
193 194 195 196 197
      if (paramTypeStarted) 
      {
        ol.endParameterType();
        paramTypeStarted=FALSE;
      }
dimitri's avatar
dimitri committed
198
      ol.startParameterName(defArgList->count()<2);
dimitri's avatar
dimitri committed
199
    }
dimitri's avatar
dimitri committed
200 201 202 203
    if (hasFuncPtrType)
    {
      ol.docify(a->type.mid(wp,vp-wp)); 
    }
dimitri's avatar
dimitri committed
204
    if (!a->name.isEmpty() || (a->name.isEmpty() && a->type=="...")) // argument has a name
mueller's avatar
mueller committed
205
    { 
dimitri's avatar
dimitri committed
206 207 208 209
      //if (!hasFuncPtrType)
      //{
      //  ol.docify(" ");
      //}
mueller's avatar
mueller committed
210
      ol.disable(OutputGenerator::Man);
dimitri's avatar
dimitri committed
211
      ol.disable(OutputGenerator::Latex);
mueller's avatar
mueller committed
212 213
      ol.startEmphasis();
      ol.enable(OutputGenerator::Man);
dimitri's avatar
dimitri committed
214
      if (latexOn) ol.enable(OutputGenerator::Latex);
dimitri's avatar
dimitri committed
215
      if (a->name.isEmpty()) ol.docify(a->type); else ol.docify(a->name);
mueller's avatar
mueller committed
216
      ol.disable(OutputGenerator::Man);
dimitri's avatar
dimitri committed
217
      ol.disable(OutputGenerator::Latex);
mueller's avatar
mueller committed
218 219
      ol.endEmphasis();
      ol.enable(OutputGenerator::Man);
dimitri's avatar
dimitri committed
220
      if (latexOn) ol.enable(OutputGenerator::Latex);
mueller's avatar
mueller committed
221
    }
dimitri's avatar
dimitri committed
222 223 224 225
    if (!a->array.isEmpty())
    {
      ol.docify(a->array);
    }
dimitri's avatar
dimitri committed
226 227
    if (hasFuncPtrType) // write the part of the argument type 
                        // that comes after the name
mueller's avatar
mueller committed
228
    {
dimitri's avatar
dimitri committed
229
      linkifyText(TextGeneratorOLImpl(ol),cd,md->getBodyDef(),
dimitri's avatar
dimitri committed
230
                  md->name(),a->type.right(a->type.length()-vp));
mueller's avatar
mueller committed
231
    }
dimitri's avatar
dimitri committed
232
    if (!a->defval.isEmpty()) // write the default value
mueller's avatar
mueller committed
233 234
    {
      QCString n=a->defval;
dimitri's avatar
dimitri committed
235
      if (!cName.isEmpty()) n=addTemplateNames(n,cd->name(),cName);
mueller's avatar
mueller committed
236
      ol.docify(" = ");
dimitri's avatar
dimitri committed
237 238 239 240 241

      ol.startTypewriter();
      linkifyText(TextGeneratorOLImpl(ol),cd,md->getBodyDef(),md->name(),n,FALSE,TRUE,TRUE); 
      ol.endTypewriter();

mueller's avatar
mueller committed
242
    }
dimitri's avatar
dimitri committed
243
    a=defArgList->next();
dimitri's avatar
dimitri committed
244 245
    if (a) 
    {
dimitri's avatar
dimitri committed
246
      if (!md->isObjCMethod()) ol.docify(", "); // there are more arguments
dimitri's avatar
dimitri committed
247
      if (!isDefine) 
dimitri's avatar
dimitri committed
248
      {
dimitri's avatar
dimitri committed
249
        QCString key;
dimitri's avatar
dimitri committed
250
        if (md->isObjCMethod() && a->attrib.length()>=2)
dimitri's avatar
dimitri committed
251 252 253
        {
          //printf("Found parameter keyword %s\n",a->attrib.data());
          // strip [ and ]
dimitri's avatar
dimitri committed
254 255
          key=a->attrib.mid(1,a->attrib.length()-2);
          if (key!=",") key+=":"; // for normal keywords add colon
dimitri's avatar
dimitri committed
256
        }
dimitri's avatar
dimitri committed
257
        ol.endParameterName(FALSE,FALSE,!md->isObjCMethod());
dimitri's avatar
dimitri committed
258 259 260 261
        if (paramTypeStarted) 
        {
          ol.endParameterType();
        }
dimitri's avatar
dimitri committed
262
        ol.startParameterType(FALSE,key);
dimitri's avatar
dimitri committed
263 264
        paramTypeStarted=TRUE;
      }
dimitri's avatar
dimitri committed
265
      else // isDefine
dimitri's avatar
dimitri committed
266 267
      {
        ol.endParameterName(FALSE,FALSE,TRUE);
dimitri's avatar
dimitri committed
268
      }
dimitri's avatar
dimitri committed
269
    }
dimitri's avatar
dimitri committed
270
    first=FALSE;
dimitri's avatar
dimitri committed
271
  }
dimitri's avatar
dimitri committed
272
  ol.pushGeneratorState();
dimitri's avatar
dimitri committed
273
  ol.disable(OutputGenerator::Html);
dimitri's avatar
dimitri committed
274
  ol.disable(OutputGenerator::Latex);
dimitri's avatar
dimitri committed
275
  if (!md->isObjCMethod()) ol.docify(")"); // end argument list
dimitri's avatar
dimitri committed
276
  ol.enableAll();
dimitri's avatar
dimitri committed
277 278
  if (htmlOn) ol.enable(OutputGenerator::Html);
  if (latexOn) ol.enable(OutputGenerator::Latex);
dimitri's avatar
dimitri committed
279 280
  if (first) ol.startParameterName(defArgList->count()<2);
  ol.endParameterName(TRUE,defArgList->count()<2,!md->isObjCMethod());
dimitri's avatar
dimitri committed
281
  ol.popGeneratorState();
dimitri's avatar
dimitri committed
282 283 284 285
  if (md->extraTypeChars())
  {
    ol.docify(md->extraTypeChars());
  }
dimitri's avatar
dimitri committed
286
  if (defArgList->constSpecifier)
mueller's avatar
mueller committed
287 288 289
  {
    ol.docify(" const");
  }
dimitri's avatar
dimitri committed
290
  if (defArgList->volatileSpecifier)
mueller's avatar
mueller committed
291 292 293
  {
    ol.docify(" volatile");
  }
dimitri's avatar
dimitri committed
294
  return TRUE;
mueller's avatar
mueller committed
295 296
}

dimitri's avatar
dimitri committed
297
static void writeTemplatePrefix(OutputList &ol,ArgumentList *al)
mueller's avatar
mueller committed
298 299 300 301 302 303
{
  ol.docify("template<");
  Argument *a=al->first();
  while (a)
  {
    ol.docify(a->type);
dimitri's avatar
dimitri committed
304
    ol.docify(" ");
mueller's avatar
mueller committed
305 306 307 308 309 310 311 312 313 314 315 316
    ol.docify(a->name);
    if (a->defval.length()!=0)
    {
      ol.docify(" = ");
      ol.docify(a->defval);
    } 
    a=al->next();
    if (a) ol.docify(", ");
  }
  ol.docify("> ");
}

dimitri's avatar
dimitri committed
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
QCString extractDirection(QCString &docs)
{
  QRegExp re("\\[[^\\]]+\\]"); // [...]
  int l=0;
  if (re.match(docs,0,&l)==0)
  {
    int  inPos  = docs.find("in", 1,FALSE);
    int outPos  = docs.find("out",1,FALSE);
    bool input  =  inPos!=-1 &&  inPos<l;
    bool output = outPos!=-1 && outPos<l;
    if (input || output) // in,out attributes
    {
      docs = docs.mid(l); // strip attributes
      if (input && output) return "[in,out]";
      else if (input)      return "[in]";
      else if (output)     return "[out]";
    }
  }
  return QCString();
}

dimitri's avatar
dimitri committed
338 339 340 341 342 343 344 345 346 347
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

class MemberDefImpl
{
  public:
    MemberDefImpl();
   ~MemberDefImpl();
    void init(Definition *def,const char *t,const char *a,const char *e,
dimitri's avatar
dimitri committed
348 349 350
              Protection p,Specifier v,bool s,Relationship r,
              MemberDef::MemberType mt,const ArgumentList *tal,
              const ArgumentList *al
dimitri's avatar
dimitri committed
351 352 353 354 355 356 357
             );

    ClassDef     *classDef;   // member of or related to 
    FileDef      *fileDef;    // member of file definition 
    NamespaceDef *nspace;     // the namespace this member is in.

    MemberDef  *enumScope;    // the enclosing scope, if this is an enum field
dimitri's avatar
dimitri committed
358
    MemberDef  *annEnumType;  // the anonymous enum that is the type of this member
dimitri's avatar
dimitri committed
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
    MemberList *enumFields;   // enumeration fields

    MemberDef  *redefines;    // the members that this member redefines 
    MemberList *redefinedBy;  // the list of members that redefine this one

    MemberDef  *memDef;       // member definition for this declaration
    MemberDef  *memDec;       // member declaration for this definition
    ClassDef   *relatedAlso;  // points to class marked by relatedAlso

    ExampleSDict *exampleSDict; // a dictionary of all examples for quick access

    QCString type;            // return type
    QCString args;            // function arguments/variable array specifiers
    QCString def;             // member definition in code (fully qualified name)
    QCString anc;             // HTML anchor name
    Specifier virt;           // normal/virtual/pure virtual
    Protection prot;          // protection type [Public/Protected/Private]
    QCString decl;            // member declaration in class

    QCString bitfields;       // struct member bitfields
    QCString read;            // property read accessor
    QCString write;           // property write accessor
    QCString exception;       // exceptions that can be thrown
    QCString initializer;     // initializer
dimitri's avatar
dimitri committed
383
    QCString extraTypeChars;  // extra type info found after the argument list
dimitri's avatar
dimitri committed
384 385 386 387 388 389 390 391 392 393 394 395
    int initLines;            // number of lines in the initializer

    int  memSpec;             // The specifiers present for this member
    MemberDef::MemberType mtype;         // returns the kind of member
    int maxInitLines;         // when the initializer will be displayed 
    int userInitLines;        // result of explicit \hideinitializer or \showinitializer
    MemberDef  *annMemb;

    ArgumentList *defArgList;    // argument list of this member definition
    ArgumentList *declArgList;   // argument list of this member declaration

    ArgumentList *tArgList;      // template argument list of function template
dimitri's avatar
dimitri committed
396
    ArgumentList *typeConstraints; // type constraints for template parameters
dimitri's avatar
dimitri committed
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418
    MemberDef *templateMaster;
    QList<ArgumentList> *defTmpArgLists; // lists of template argument lists 
                                         // (for template functions in nested template classes)

    ClassDef *cachedAnonymousType; // if the member has an anonymous compound
                                   // as its type then this is computed by
                                   // getClassDefOfAnonymousType() and 
                                   // cached here. 
    SDict<MemberList> *classSectionSDict; // not accessible

    MemberDef *groupAlias;    // Member containing the definition
    int grpId;                // group id
    MemberGroup *memberGroup; // group's member definition
    GroupDef *group;          // group in which this member is in
    Grouping::GroupPri_t grouppri; // priority of this definition
    QCString groupFileName;   // file where this grouping was defined
    int groupStartLine;       // line  "      "      "     "     "
    MemberDef *groupMember;

    bool isTypedefValCached;
    ClassDef *cachedTypedefValue;
    QCString cachedTypedefTemplSpec;
dimitri's avatar
dimitri committed
419
    QCString cachedResolvedType;
dimitri's avatar
dimitri committed
420 421
    
    // inbody documentation
dimitri's avatar
dimitri committed
422 423 424
    //int inbodyLine;
    //QCString inbodyFile;
    //QCString inbodyDocs;
dimitri's avatar
dimitri committed
425 426 427 428 429 430 431 432 433 434 435 436 437

    // documentation inheritance
    MemberDef *docProvider;

    // to store the output file base from tag files
    QCString explicitOutputFileBase;

    // objective-c
    bool implOnly; // function found in implementation but not 
                     // in the interface
    bool hasDocumentedParams;
    bool hasDocumentedReturnType;
    bool isDMember;
dimitri's avatar
dimitri committed
438
    Relationship related;     // relationship of this to the class
dimitri's avatar
dimitri committed
439 440 441 442 443 444 445 446 447 448 449 450 451
    bool stat;                // is it a static function?
    bool proto;               // is it a prototype;
    bool docEnumValues;       // is an enum with documented enum values.
    bool annScope;            // member is part of an annoymous scope
    bool annUsed;             
    bool hasCallGraph;
    bool hasCallerGraph;
    bool explExt;             // member was explicitly declared external
    bool tspec;               // member is a template specialization
    bool groupHasDocs;        // true if the entry that caused the grouping was documented
    bool docsForDefinition;   // TRUE => documentation block is put before
                              //         definition.
                              // FALSE => block is put before declaration.
dimitri's avatar
dimitri committed
452
    ClassDef *category;
dimitri's avatar
dimitri committed
453 454 455 456 457 458 459 460 461
};

MemberDefImpl::MemberDefImpl() :
    enumFields(0),
    redefinedBy(0),
    exampleSDict(0),
    defArgList(0),
    declArgList(0),
    tArgList(0),
dimitri's avatar
dimitri committed
462
    typeConstraints(0),
dimitri's avatar
dimitri committed
463
    defTmpArgLists(0),
dimitri's avatar
dimitri committed
464 465
    classSectionSDict(0),
    category(0)
dimitri's avatar
dimitri committed
466 467 468 469 470 471 472 473 474 475
{
}

MemberDefImpl::~MemberDefImpl()
{
  delete redefinedBy;
  delete exampleSDict;
  delete enumFields;
  delete defArgList;
  delete tArgList;
dimitri's avatar
dimitri committed
476
  delete typeConstraints;
dimitri's avatar
dimitri committed
477 478 479 480 481 482 483
  delete defTmpArgLists;
  delete classSectionSDict;
  delete declArgList;
}

void MemberDefImpl::init(Definition *def,
                     const char *t,const char *a,const char *e,
dimitri's avatar
dimitri committed
484 485 486
                     Protection p,Specifier v,bool s,Relationship r,
                     MemberDef::MemberType mt,const ArgumentList *tal,
                     const ArgumentList *al
dimitri's avatar
dimitri committed
487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
                    )
{
  classDef=0;
  fileDef=0;
  redefines=0;
  relatedAlso=0;
  redefinedBy=0;
  nspace=0;
  memDef=0;
  memDec=0;
  group=0;
  grpId=-1;
  exampleSDict=0;
  enumFields=0;
  enumScope=0;
  defTmpArgLists=0;
  hasCallGraph = FALSE;
  hasCallerGraph = FALSE;
  initLines=0;
  type=t;
  if (mt==MemberDef::Typedef) type.stripPrefix("typedef ");
dimitri's avatar
dimitri committed
508 509 510
  //  type.stripPrefix("struct ");
  //  type.stripPrefix("class " );
  //  type.stripPrefix("union " );
dimitri's avatar
dimitri committed
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577
  type=removeRedundantWhiteSpace(type);
  args=a;
  args=removeRedundantWhiteSpace(args);
  if (type.isEmpty()) decl=def->name()+args; else decl=type+" "+def->name()+args;

  memberGroup=0;
  virt=v;
  prot=p;
  related=r;
  stat=s;
  mtype=mt;
  exception=e;
  proto=FALSE;
  annScope=FALSE;
  memSpec=0;
  annMemb=0;
  annUsed=FALSE;
  annEnumType=0;
  groupAlias=0;
  explExt=FALSE;
  tspec=FALSE;
  cachedAnonymousType=0;
  maxInitLines=Config_getInt("MAX_INITIALIZER_LINES");
  userInitLines=-1;
  docEnumValues=FALSE;
  // copy function template arguments (if any)
  if (tal)
  {
    tArgList = new ArgumentList;
    tArgList->setAutoDelete(TRUE);
    ArgumentListIterator ali(*tal);
    Argument *a;
    for (;(a=ali.current());++ali)
    {
      tArgList->append(new Argument(*a));
    }
  }
  else
  {
    tArgList=0;
  }
  //printf("new member al=%p\n",al);
  // copy function definition arguments (if any)
  if (al)
  {
    defArgList = new ArgumentList;
    defArgList->setAutoDelete(TRUE);
    ArgumentListIterator ali(*al);
    Argument *a;
    for (;(a=ali.current());++ali)
    {
      //printf("copy argument %s (doc=%s)\n",a->name.data(),a->docs.data());
      defArgList->append(new Argument(*a));
    }
    defArgList->constSpecifier    = al->constSpecifier;
    defArgList->volatileSpecifier = al->volatileSpecifier;
    defArgList->pureSpecifier     = al->pureSpecifier;
    //printf("defArgList(%p)->constSpecifier=%d\n",defArgList,defArgList->constSpecifier);
  }
  else
  {
    defArgList=0;
  }
  // convert function declaration arguments (if any)
  if (!args.isEmpty())
  {
    declArgList = new ArgumentList;
dimitri's avatar
dimitri committed
578
    stringToArgumentList(args,declArgList,&extraTypeChars);
dimitri's avatar
dimitri committed
579 580
    //printf("setDeclArgList %s to %s const=%d\n",args.data(),
    //    argListToString(declArgList).data(),declArgList->constSpecifier);
dimitri's avatar
dimitri committed
581 582 583 584 585 586 587 588 589 590
  }
  else
  {
    declArgList = 0;
  }
  templateMaster = 0;
  classSectionSDict = 0;
  docsForDefinition = TRUE;
  isTypedefValCached = FALSE;
  cachedTypedefValue = 0;
dimitri's avatar
dimitri committed
591
  //inbodyLine = -1;
dimitri's avatar
dimitri committed
592 593 594 595 596 597 598 599 600 601 602
  implOnly=FALSE;
  groupMember = 0;
  hasDocumentedParams = FALSE;
  hasDocumentedReturnType = FALSE;
  docProvider = 0;
  isDMember = def->getDefFileName().right(2).lower()==".d";
}


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
mueller's avatar
mueller committed
603
//-----------------------------------------------------------------------------
mueller's avatar
mueller committed
604 605 606

/*! Creates a new member definition.
 *
dimitri's avatar
dimitri committed
607 608 609
 * \param df File containing the definition of this member.
 * \param dl Line at which the member definition was found.
 * \param t  A string representing the type of the member.
dimitri's avatar
dimitri committed
610
 * \param na A string representing the name of the member.
dimitri's avatar
dimitri committed
611
 * \param a  A string representing the arguments of the member.
dimitri's avatar
dimitri committed
612 613
 * \param e  A string representing the throw clause of the members.
 * \param p  The protection context of the member, possible values are:
dimitri's avatar
dimitri committed
614
 *           \c Public, \c Protected, \c Private.
dimitri's avatar
dimitri committed
615
 * \param v  The degree of `virtualness' of the member, possible values are:
dimitri's avatar
dimitri committed
616
 *           \c Normal, \c Virtual, \c Pure.
dimitri's avatar
dimitri committed
617
 * \param s  A boolean that is true iff the member is static.
dimitri's avatar
dimitri committed
618
 * \param r  The relationship between the class and the member.
mueller's avatar
mueller committed
619 620
 * \param mt The kind of member. See #MemberDef::MemberType for a list of 
 *           all types.
dimitri's avatar
dimitri committed
621 622 623
 * \param tal The template arguments of this member.
 * \param al  The arguments of this member. This is a structured form of 
 *            the string past as argument \a a.
mueller's avatar
mueller committed
624 625
 */

dimitri's avatar
dimitri committed
626 627
MemberDef::MemberDef(const char *df,int dl,
                     const char *t,const char *na,const char *a,const char *e,
dimitri's avatar
dimitri committed
628
                     Protection p,Specifier v,bool s,Relationship r,MemberType mt,
mueller's avatar
mueller committed
629
                     const ArgumentList *tal,const ArgumentList *al
dimitri's avatar
dimitri committed
630
                    ) : Definition(df,dl,removeRedundantWhiteSpace(na))
mueller's avatar
mueller committed
631
{
dimitri's avatar
dimitri committed
632
  //printf("MemberDef::MemberDef(%s)\n",na);
dimitri's avatar
dimitri committed
633 634
  m_storagePos=-1;
  m_cacheHandle=-1;
dimitri's avatar
dimitri committed
635 636
  m_impl = new MemberDefImpl;
  m_impl->init(this,t,a,e,p,v,s,r,mt,tal,al);
dimitri's avatar
dimitri committed
637
  m_flushPending = FALSE;
dimitri's avatar
dimitri committed
638 639 640
  m_isLinkableCached    = 0;
  m_isConstructorCached = 0;
  m_isDestructorCached  = 0;
mueller's avatar
mueller committed
641 642
}

dimitri's avatar
dimitri committed
643 644 645 646 647 648 649 650 651 652 653 654 655 656 657
void MemberDef::moveTo(Definition *scope)
{
   setOuterScope(scope);
   if (scope->definitionType()==Definition::TypeClass)
   {
     m_impl->classDef = (ClassDef*)scope;
   }
   else if (scope->definitionType()==Definition::TypeFile)
   {
     m_impl->fileDef = (FileDef*)scope;
   }
   else if (scope->definitionType()==Definition::TypeNamespace)
   {
     m_impl->nspace = (NamespaceDef*)scope;
   }
dimitri's avatar
dimitri committed
658 659
   m_isLinkableCached = 0; 
   m_isConstructorCached = 0; 
dimitri's avatar
dimitri committed
660 661 662
}


dimitri's avatar
dimitri committed
663
/*! Destroys the member definition. */
mueller's avatar
mueller committed
664 665
MemberDef::~MemberDef()
{
dimitri's avatar
dimitri committed
666
  delete m_impl;
dimitri's avatar
dimitri committed
667 668 669 670 671
  if (m_cacheHandle!=-1)
  {
    Doxygen::symbolCache->del(m_cacheHandle);
    m_cacheHandle=-1;
  }
mueller's avatar
mueller committed
672 673
}

dimitri's avatar
dimitri committed
674 675
void MemberDef::setReimplements(MemberDef *md)   
{ 
dimitri's avatar
dimitri committed
676
  makeResident();
dimitri's avatar
dimitri committed
677 678 679
  //if (redefines==0) redefines = new MemberList;
  //if (redefines->find(md)==-1) redefines->inSort(md);

dimitri's avatar
dimitri committed
680
  m_impl->redefines = md;
dimitri's avatar
dimitri committed
681 682
}

mueller's avatar
mueller committed
683 684
void MemberDef::insertReimplementedBy(MemberDef *md)
{
dimitri's avatar
dimitri committed
685 686
  makeResident();
  if (m_impl->templateMaster)
dimitri's avatar
dimitri committed
687
  {
dimitri's avatar
dimitri committed
688
    m_impl->templateMaster->insertReimplementedBy(md);
dimitri's avatar
dimitri committed
689
  }
dimitri's avatar
dimitri committed
690 691
  if (m_impl->redefinedBy==0) m_impl->redefinedBy = new MemberList(MemberList::redefinedBy);
  if (m_impl->redefinedBy->findRef(md)==-1) 
dimitri's avatar
dimitri committed
692
  {
dimitri's avatar
dimitri committed
693
    m_impl->redefinedBy->inSort(md);
dimitri's avatar
dimitri committed
694
  }
dimitri's avatar
dimitri committed
695 696
}

dimitri's avatar
dimitri committed
697
MemberDef *MemberDef::reimplements() const      
dimitri's avatar
dimitri committed
698
{ 
dimitri's avatar
dimitri committed
699 700
  makeResident();
  return m_impl->redefines; 
dimitri's avatar
dimitri committed
701 702
}

dimitri's avatar
dimitri committed
703
LockingPtr<MemberList> MemberDef::reimplementedBy() const   
dimitri's avatar
dimitri committed
704
{ 
dimitri's avatar
dimitri committed
705 706
  makeResident();
  return LockingPtr<MemberList>(this,m_impl->redefinedBy); 
mueller's avatar
mueller committed
707 708 709 710
}

void MemberDef::insertEnumField(MemberDef *md)
{
dimitri's avatar
dimitri committed
711 712 713
  makeResident();
  if (m_impl->enumFields==0) m_impl->enumFields=new MemberList(MemberList::enumFields);
  m_impl->enumFields->append(md);
mueller's avatar
mueller committed
714 715 716 717 718
}

bool MemberDef::addExample(const char *anchor,const char *nameStr,
                           const char *file)
{
dimitri's avatar
dimitri committed
719
  makeResident();
dimitri's avatar
dimitri committed
720
  //printf("%s::addExample(%s,%s,%s)\n",name().data(),anchor,nameStr,file);
dimitri's avatar
dimitri committed
721 722
  if (m_impl->exampleSDict==0) m_impl->exampleSDict = new ExampleSDict;
  if (m_impl->exampleSDict->find(nameStr)==0) 
mueller's avatar
mueller committed
723 724 725 726 727 728
  {
    //printf("Add reference to example %s to member %s\n",nameStr,name.data());
    Example *e=new Example;
    e->anchor=anchor;
    e->name=nameStr;
    e->file=file;
dimitri's avatar
dimitri committed
729
    m_impl->exampleSDict->inSort(nameStr,e);
mueller's avatar
mueller committed
730 731 732 733 734 735 736
    return TRUE;
  }
  return FALSE; 
}

bool MemberDef::hasExamples()
{
dimitri's avatar
dimitri committed
737 738
  makeResident();
  if (m_impl->exampleSDict==0) 
mueller's avatar
mueller committed
739 740
    return FALSE;
  else
dimitri's avatar
dimitri committed
741
    return m_impl->exampleSDict->count()>0;
mueller's avatar
mueller committed
742 743
}

mueller's avatar
mueller committed
744
QCString MemberDef::getOutputFileBase() const
mueller's avatar
mueller committed
745
{
dimitri's avatar
dimitri committed
746
  makeResident();
dimitri's avatar
dimitri committed
747
  static bool separateMemberPages = Config_getBool("SEPARATE_MEMBER_PAGES");
dimitri's avatar
dimitri committed
748
  QCString baseName;
dimitri's avatar
dimitri committed
749 750 751 752
  //printf("Member: %s: templateMaster=%p group=%p classDef=%p nspace=%p fileDef=%p\n",
  //    name().data(),m_impl->templateMaster,m_impl->group,m_impl->classDef,
  //    m_impl->nspace,m_impl->fileDef);
  if (!m_impl->explicitOutputFileBase.isEmpty())
dimitri's avatar
dimitri committed
753
  {
dimitri's avatar
dimitri committed
754
    return m_impl->explicitOutputFileBase;
dimitri's avatar
dimitri committed
755
  }
dimitri's avatar
dimitri committed
756
  else if (m_impl->templateMaster)
dimitri's avatar
dimitri committed
757
  {
dimitri's avatar
dimitri committed
758
    return m_impl->templateMaster->getOutputFileBase();
dimitri's avatar
dimitri committed
759
  }
dimitri's avatar
dimitri committed
760
  else if (m_impl->group)
dimitri's avatar
dimitri committed
761
  {
dimitri's avatar
dimitri committed
762
    baseName=m_impl->group->getOutputFileBase();
dimitri's avatar
dimitri committed
763
  }
dimitri's avatar
dimitri committed
764
  else if (m_impl->classDef)
mueller's avatar
mueller committed
765
  {
dimitri's avatar
dimitri committed
766
    baseName=m_impl->classDef->getOutputFileBase();
mueller's avatar
mueller committed
767
  }
dimitri's avatar
dimitri committed
768
  else if (m_impl->nspace)
mueller's avatar
mueller committed
769
  {
dimitri's avatar
dimitri committed
770
    baseName=m_impl->nspace->getOutputFileBase();
mueller's avatar
mueller committed
771
  }
dimitri's avatar
dimitri committed
772
  else if (m_impl->fileDef)
dimitri's avatar
dimitri committed
773
  {
dimitri's avatar
dimitri committed
774
    baseName=m_impl->fileDef->getOutputFileBase();
dimitri's avatar
dimitri committed
775
  }
dimitri's avatar
dimitri committed
776 777 778
  
  if (baseName.isEmpty())
  {
dimitri's avatar
dimitri committed
779
    warn(getDefFileName(),getDefLine(),
dimitri's avatar
dimitri committed
780 781
       "warning: Internal inconsistency: member %s does not belong to any"
       " container!",qPrint(name())
dimitri's avatar
dimitri committed
782
      );
dimitri's avatar
dimitri committed
783 784
    return "dummy";
  }
dimitri's avatar
dimitri committed
785
  else if (separateMemberPages)
dimitri's avatar
dimitri committed
786 787 788 789 790 791 792 793 794 795 796
  {
    if (getEnumScope()) // enum value, which is part of enum's documentation
    {
      baseName+="_"+getEnumScope()->anchor();
    }
    else
    {
      baseName+="_"+anchor();
    }
  }
  return baseName;
mueller's avatar
mueller committed
797
}
mueller's avatar
mueller committed
798

dimitri's avatar
dimitri committed
799 800
QCString MemberDef::getReference() const
{
dimitri's avatar
dimitri committed
801
  makeResident();
dimitri's avatar
dimitri committed
802 803 804 805 806
  QCString ref = Definition::getReference();
  if (!ref.isEmpty())
  {
    return ref;
  }
dimitri's avatar
dimitri committed
807
  if (m_impl->templateMaster)
dimitri's avatar
dimitri committed
808
  {
dimitri's avatar
dimitri committed
809
    return m_impl->templateMaster->getReference();
dimitri's avatar
dimitri committed
810
  }
dimitri's avatar
dimitri committed
811
  else if (m_impl->group)
dimitri's avatar
dimitri committed
812
  {
dimitri's avatar
dimitri committed
813
    return m_impl->group->getReference();
dimitri's avatar
dimitri committed
814
  }
dimitri's avatar
dimitri committed
815
  else if (m_impl->classDef)
dimitri's avatar
dimitri committed
816
  {
dimitri's avatar
dimitri committed
817
    return m_impl->classDef->getReference();
dimitri's avatar
dimitri committed
818
  }
dimitri's avatar
dimitri committed
819
  else if (m_impl->nspace)
dimitri's avatar
dimitri committed
820
  {
dimitri's avatar
dimitri committed
821
    return m_impl->nspace->getReference();
dimitri's avatar
dimitri committed
822
  }
dimitri's avatar
dimitri committed
823
  else if (m_impl->fileDef)
dimitri's avatar
dimitri committed
824
  {
dimitri's avatar
dimitri committed
825
    return m_impl->fileDef->getReference();
dimitri's avatar
dimitri committed
826 827 828 829 830 831
  }
  return "";
}

QCString MemberDef::anchor() const
{
dimitri's avatar
dimitri committed
832 833 834 835
  makeResident();
  QCString result=m_impl->anc;
  if (m_impl->groupAlias)     return m_impl->groupAlias->anchor();
  if (m_impl->templateMaster) return m_impl->templateMaster->anchor();
dimitri's avatar
dimitri committed
836 837 838 839
  if (m_impl->enumScope && m_impl->enumScope!=this) // avoid recursion for C#'s public enum E { E, F }
  {
    result.prepend(m_impl->enumScope->anchor());
  }
dimitri's avatar
dimitri committed
840
  if (m_impl->group) 
dimitri's avatar
dimitri committed
841
  {
dimitri's avatar
dimitri committed
842
    if (m_impl->groupMember)
dimitri's avatar
dimitri committed
843
    {
dimitri's avatar
dimitri committed
844
      result=m_impl->groupMember->anchor();
dimitri's avatar
dimitri committed
845
    }
dimitri's avatar
dimitri committed
846
    else if (getReference().isEmpty())
dimitri's avatar
dimitri committed
847 848 849 850
    {
      result.prepend("g");
    }
  }
dimitri's avatar
dimitri committed
851 852 853
  return result;
}

dimitri's avatar
dimitri committed
854
void MemberDef::_computeLinkableInProject()
dimitri's avatar
dimitri committed
855
{
dimitri's avatar
dimitri committed
856
  makeResident();
dimitri's avatar
dimitri committed
857 858
  static bool extractPrivate = Config_getBool("EXTRACT_PRIVATE");
  static bool extractStatic  = Config_getBool("EXTRACT_STATIC");
dimitri's avatar
dimitri committed
859
  m_isLinkableCached = 2; // linkable
dimitri's avatar
dimitri committed
860
  //printf("MemberDef::isLinkableInProject(name=%s)\n",name().data());
dimitri's avatar
dimitri committed
861 862 863
  if (isHidden()) 
  {
    //printf("is hidden\n");
dimitri's avatar
dimitri committed
864 865
    m_isLinkableCached = 1;
    return;
dimitri's avatar
dimitri committed
866
  }
dimitri's avatar
dimitri committed
867
  if (m_impl->templateMaster)
dimitri's avatar
dimitri committed
868
  {
dimitri's avatar
dimitri committed
869
    //printf("has template master\n");
dimitri's avatar
dimitri committed
870
    m_isLinkableCached = m_impl->templateMaster->isLinkableInProject() ? 2 : 1;
dimitri's avatar
dimitri committed
871 872 873 874
  }
  if (name().isEmpty() || name().at(0)=='@') 
  {
    //printf("name invalid\n");
dimitri's avatar
dimitri committed
875 876
    m_isLinkableCached = 1; // not a valid or a dummy name
    return;
dimitri's avatar
dimitri committed
877 878 879 880
  }
  if (!hasDocumentation() && !isReference()) 
  {
    //printf("no docs or reference\n");
dimitri's avatar
dimitri committed
881 882
    m_isLinkableCached = 1; // no documentation
    return;
dimitri's avatar
dimitri committed
883
  }
dimitri's avatar
dimitri committed
884
  if (m_impl->group && !m_impl->group->isLinkableInProject()) 
dimitri's avatar
dimitri committed
885 886
  {
    //printf("group but group not linkable!\n");
dimitri's avatar
dimitri committed
887 888
    m_isLinkableCached = 1; // group but group not linkable
    return;
dimitri's avatar
dimitri committed
889
  }
dimitri's avatar
dimitri committed
890
  if (!m_impl->group && m_impl->classDef && !m_impl->classDef->isLinkableInProject()) 
dimitri's avatar
dimitri committed
891 892
  {
    //printf("in a class but class not linkable!\n");
dimitri's avatar
dimitri committed
893 894
    m_isLinkableCached = 1; // in class but class not linkable
    return;
dimitri's avatar
dimitri committed
895
  }
dimitri's avatar
dimitri committed
896
  if (!m_impl->group && m_impl->nspace && !m_impl->related && !m_impl->nspace->isLinkableInProject()) 
dimitri's avatar
dimitri committed
897 898
  {
    //printf("in a namespace but namespace not linkable!\n");
dimitri's avatar
dimitri committed
899 900
    m_isLinkableCached = 1; // in namespace but namespace not linkable
    return;
dimitri's avatar
dimitri committed
901
  }
dimitri's avatar
dimitri committed
902 903 904
  if (!m_impl->group && !m_impl->nspace && 
      !m_impl->related && !m_impl->classDef && 
      m_impl->fileDef && !m_impl->fileDef->isLinkableInProject()) 
dimitri's avatar
dimitri committed
905 906
  {
    //printf("in a file but file not linkable!\n");
dimitri's avatar
dimitri committed
907 908
    m_isLinkableCached = 1; // in file (and not in namespace) but file not linkable
    return;
dimitri's avatar
dimitri committed
909
  }
dimitri's avatar
dimitri committed
910
  if (m_impl->prot==Private && !extractPrivate && m_impl->mtype!=Friend) 
dimitri's avatar
dimitri committed
911 912
  {
    //printf("private and invisible!\n");
dimitri's avatar
dimitri committed
913 914
    m_isLinkableCached = 1; // hidden due to protection
    return;
dimitri's avatar
dimitri committed
915
  }
dimitri's avatar
dimitri committed
916
  if (m_impl->stat && m_impl->classDef==0 && !extractStatic) 
dimitri's avatar
dimitri committed
917 918
  {
    //printf("static and invisible!\n");
dimitri's avatar
dimitri committed
919 920
    m_isLinkableCached = 1; // hidden due to staticness
    return;
dimitri's avatar
dimitri committed
921 922
  }
  //printf("linkable!\n");
dimitri's avatar
dimitri committed
923 924 925
  return; // linkable!
}

dimitri's avatar
dimitri committed
926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946
void MemberDef::setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace)
{
  makeResident();
  Definition::setDocumentation(d,docFile,docLine,stripWhiteSpace);
  m_isLinkableCached = 0;
}

void MemberDef::setBriefDescription(const char *b,const char *briefFile,int briefLine)
{
  makeResident();
  Definition::setBriefDescription(b,briefFile,briefLine);
  m_isLinkableCached = 0;
}

void MemberDef::setInbodyDocumentation(const char *d,const char *inbodyFile,int inbodyLine)
{
  makeResident();
  Definition::setInbodyDocumentation(d,inbodyFile,inbodyLine);
  m_isLinkableCached = 0;
}

dimitri's avatar
dimitri committed
947 948 949 950 951 952 953 954 955
bool MemberDef::isLinkableInProject() const
{
  if (m_isLinkableCached==0)
  {
    MemberDef *that = (MemberDef*)this;
    that->_computeLinkableInProject();
  }
  ASSERT(m_isLinkableCached>0);
  return m_isLinkableCached==2;
dimitri's avatar
dimitri committed
956 957 958 959
}

bool MemberDef::isLinkable() const
{
dimitri's avatar
dimitri committed
960 961
  makeResident();
  if (m_impl->templateMaster)
dimitri's avatar
dimitri committed
962
  {
dimitri's avatar
dimitri committed
963
    return m_impl->templateMaster->isLinkable();
dimitri's avatar
dimitri committed
964 965 966 967 968 969 970 971
  }
  else
  {
    return isLinkableInProject() || isReference();
  }
}


dimitri's avatar
dimitri committed
972
void MemberDef::setDefinitionTemplateParameterLists(QList<ArgumentList> *lists)
mueller's avatar
mueller committed
973
{
dimitri's avatar
dimitri committed
974
  if (lists)
mueller's avatar
mueller committed
975
  {
dimitri's avatar
dimitri committed
976 977 978
    makeResident();
    if (m_impl->defTmpArgLists) delete m_impl->defTmpArgLists;
    m_impl->defTmpArgLists = copyArgumentLists(lists);
mueller's avatar
mueller committed
979 980 981
  }
}

dimitri's avatar
dimitri committed
982
void MemberDef::writeLink(OutputList &ol,ClassDef *,NamespaceDef *,
dimitri's avatar
dimitri committed
983
                      FileDef *fd,GroupDef *gd,bool onlyText)
mueller's avatar
mueller committed
984
{
dimitri's avatar
dimitri committed
985 986
  static bool optimizeOutputJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA");
  static bool hideScopeNames     = Config_getBool("HIDE_SCOPE_NAMES");
dimitri's avatar
dimitri committed
987 988
  makeResident();
  LockingPtr<MemberDef> lock(this,this);
dimitri's avatar
dimitri committed
989
  QCString sep = optimizeOutputJava ? "." : "::";
dimitri's avatar
dimitri committed
990
  QCString n = name();
dimitri's avatar
dimitri committed
991 992
  if (!hideScopeNames && m_impl->classDef && gd) n.prepend(m_impl->classDef->name()+sep);
  else if (!hideScopeNames && m_impl->nspace && (gd || fd)) n.prepend(m_impl->nspace->name()+sep);
dimitri's avatar
dimitri committed
993 994 995 996
  if (isObjCMethod())
  {
    if (isStatic()) ol.docify("+ "); else ol.docify("- ");
  }
dimitri's avatar
dimitri committed
997 998
  if (!onlyText) // write link
  {
dimitri's avatar
dimitri committed
999
    if (m_impl->mtype==EnumValue && getGroupDef()==0 &&          // enum value is not grouped
dimitri's avatar
dimitri committed
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
        getEnumScope() && getEnumScope()->getGroupDef()) // but its container is
    {
      GroupDef *enumValGroup = getEnumScope()->getGroupDef();
      ol.writeObjectLink(enumValGroup->getReference(),
                         enumValGroup->getOutputFileBase(),
                         anchor(),n);
    }
    else
    {
      ol.writeObjectLink(getReference(),getOutputFileBase(),anchor(),n);
    }
dimitri's avatar
dimitri committed
1011 1012 1013 1014 1015 1016 1017
  }
  else // write only text
  {
    ol.startBold();
    ol.docify(n);
    ol.endBold();
  }
mueller's avatar
mueller committed
1018 1019
}

dimitri's avatar
dimitri committed
1020 1021 1022
/*! If this member has an anonymous class/struct/union as its type, then
 *  this method will return the ClassDef that describes this return type.
 */
dimitri's avatar
dimitri committed
1023
ClassDef *MemberDef::getClassDefOfAnonymousType() 
mueller's avatar
mueller committed
1024
{
dimitri's avatar
dimitri committed
1025 1026 1027
  makeResident();
  if (m_impl->cachedAnonymousType) return m_impl->cachedAnonymousType;
  LockingPtr<MemberDef> lock(this,this);
dimitri's avatar
dimitri committed
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037

  QCString cname;
  if (getClassDef()!=0) 
  {
    cname=getClassDef()->name().copy();
  }
  else if (getNamespaceDef()!=0)
  {
    cname=getNamespaceDef()->name().copy();
  }
dimitri's avatar
dimitri committed
1038
  QCString ltype(m_impl->type);
dimitri's avatar
dimitri committed
1039
  // strip `static' keyword from ltype
dimitri's avatar
dimitri committed
1040
  //if (ltype.left(7)=="static ") ltype=ltype.right(ltype.length()-7);
dimitri's avatar
dimitri committed
1041
  // strip `friend' keyword from ltype
dimitri's avatar
dimitri committed
1042
  ltype.stripPrefix("friend ");
dimitri's avatar
dimitri committed
1043
  static QRegExp r("@[0-9]+");
dimitri's avatar
dimitri committed
1044
  int l,i=r.match(ltype,0,&l);
dimitri's avatar
dimitri committed
1045
  //printf("ltype=`%s' i=%d\n",ltype.data(),i);
dimitri's avatar
dimitri committed
1046 1047 1048
  // search for the last anonymous scope in the member type
  ClassDef *annoClassDef=0;
  if (i!=-1) // found anonymous scope in type
mueller's avatar
mueller committed
1049
  {
dimitri's avatar
dimitri committed
1050 1051 1052
    int il=i-1,ir=i+l;
    // extract anonymous scope
    while (il>=0 && (isId(ltype.at(il)) || ltype.at(il)==':' || ltype.at(il)=='@')) il--;
dimitri's avatar
dimitri committed
1053
    if (il>0) il++; else if (il<0) il=0;
dimitri's avatar
dimitri committed
1054 1055 1056 1057 1058 1059
    while (ir<(int)ltype.length() && (isId(ltype.at(ir)) || ltype.at(ir)==':' || ltype.at(ir)=='@')) ir++;

    QCString annName = ltype.mid(il,ir-il);

    // if inside a class or namespace try to prepend the scope name
    if (!cname.isEmpty() && annName.left(cname.length()+2)!=cname+"::") 
mueller's avatar
mueller committed
1060
    {
dimitri's avatar
dimitri committed
1061 1062 1063
      QCString ts=stripAnonymousNamespaceScope(cname+"::"+annName);
      //printf("Member::writeDeclaration: Trying %s\n",ts.data());
      annoClassDef=getClass(ts);
mueller's avatar
mueller committed
1064
    }
dimitri's avatar
dimitri committed
1065 1066
    // if not found yet, try without scope name
    if (annoClassDef==0)
mueller's avatar
mueller committed
1067
    {
dimitri's avatar
dimitri committed
1068 1069 1070
      QCString ts=stripAnonymousNamespaceScope(annName);
      //printf("Member::writeDeclaration: Trying %s\n",ts.data());
      annoClassDef=getClass(ts);
mueller's avatar
mueller committed
1071
    }
dimitri's avatar
dimitri committed
1072
  }
dimitri's avatar
dimitri committed
1073
  m_impl->cachedAnonymousType = annoClassDef;
dimitri's avatar
dimitri committed
1074 1075 1076 1077 1078 1079 1080 1081
  return annoClassDef;
}
    
/*! This methods returns TRUE iff the brief section (also known as
 *  declaration section) is visible in the documentation.
 */
bool MemberDef::isBriefSectionVisible() const
{
dimitri's avatar
dimitri committed
1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
  static bool extractStatic       = Config_getBool("EXTRACT_STATIC");
  static bool hideUndocMembers    = Config_getBool("HIDE_UNDOC_MEMBERS");
  static bool briefMemberDesc     = Config_getBool("BRIEF_MEMBER_DESC");
  static bool repeatBrief         = Config_getBool("REPEAT_BRIEF");
  static bool hideFriendCompounds = Config_getBool("HIDE_FRIEND_COMPOUNDS");
  static bool extractPrivate      = Config_getBool("EXTRACT_PRIVATE");

  //printf("Member %s grpId=%d docs=%s file=%s args=%s\n",
  //    name().data(),
  //    0,"", //grpId,grpId==-1?"<none>":Doxygen::memberDocDict[grpId]->data(),
  //    "", //getFileDef()->name().data(),
  //    argsString());

  makeResident();
  LockingPtr<MemberDef> lock(this,this);
  MemberGroupInfo *info = Doxygen::memGrpInfoDict[m_impl->grpId];
dimitri's avatar
dimitri committed
1098
  //printf("name=%s m_impl->grpId=%d info=%p\n",name().data(),m_impl->grpId,info);
dimitri's avatar
dimitri committed
1099 1100 1101
  //QCString *pMemGrp = Doxygen::memberDocDict[grpId];
  bool hasDocs = hasDocumentation() || 
                  // part of a documented member group
dimitri's avatar
dimitri committed
1102
                 (m_impl->grpId!=-1 && info && !(info->doc.isEmpty() && info->header.isEmpty()));
dimitri's avatar
dimitri committed
1103 1104 1105 1106 1107 1108 1109

  // only include static members with file/namespace scope if 
  // explicitly enabled in the config file
  bool visibleIfStatic = !(getClassDef()==0 && 
                           isStatic() && 
                           !extractStatic
                          );
dimitri's avatar
dimitri committed
1110

dimitri's avatar
dimitri committed
1111 1112 1113 1114 1115
  // only include members is the are documented or 
  // HIDE_UNDOC_MEMBERS is NO in the config file
  bool visibleIfDocumented = (!hideUndocMembers || 
                              hasDocs || 
                              isDocumentedFriendClass()
dimitri's avatar
dimitri committed
1116 1117
                             );

dimitri's avatar
dimitri committed
1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160
  // hide members with no detailed description and brief descriptions 
  // explicitly disabled.
  bool visibleIfEnabled = !(hideUndocMembers && 
                            documentation().isEmpty() &&
                            !briefMemberDesc && 
                            !repeatBrief
                           );

  // Hide friend (class|struct|union) declarations if HIDE_FRIEND_COMPOUNDS is true
  bool visibleIfFriendCompound = !(hideFriendCompounds &&
                                   isFriend() &&
                                   (m_impl->type=="friend class" || 
                                    m_impl->type=="friend struct" ||
                                    m_impl->type=="friend union"
                                   )
                                  );
  
  // only include members that are non-private unless EXTRACT_PRIVATE is
  // set to YES or the member is part of a group
  bool visibleIfPrivate = (protection()!=Private || 
                           extractPrivate ||
                           m_impl->mtype==Friend
                          );
  
  // hide member if it overrides a member in a superclass and has no
  // documentation of its own
  //bool visibleIfDocVirtual = !reimplements() || 
  //                           !Config_getBool("INHERIT_DOCS") ||  
  //                           hasDocs;

  // true if this member is a constructor or destructor
  bool cOrDTor = isConstructor() || isDestructor();

  // hide default constructors or destructors (no args) without
  // documentation
  bool visibleIfNotDefaultCDTor = !(cOrDTor &&
                                   m_impl->defArgList &&
                                   (m_impl->defArgList->isEmpty() ||
                                    m_impl->defArgList->first()->type == "void"
                                   ) &&
                                   !hasDocs
                                  );

dimitri's avatar
dimitri committed
1161
  //printf("visibleIfStatic=%d visibleIfDocumented=%d visibleIfEnabled=%d "
dimitri's avatar
dimitri committed
1162
  //       "visibleIfPrivate=%d visibltIfNotDefaultCDTor=%d "
dimitri's avatar
dimitri committed
1163 1164
  //       "visibleIfFriendCompound=%d !annScope=%d\n",
  //       visibleIfStatic,visibleIfDocumented,
dimitri's avatar
dimitri committed
1165
  //       visibleIfEnabled,visibleIfPrivate,visibleIfNotDefaultCDTor,
dimitri's avatar
dimitri committed
1166
  //       visibleIfFriendCompound,!m_impl->annScope);
dimitri's avatar
dimitri committed
1167 1168 1169 1170 1171 1172 1173 1174
  
  bool visible = visibleIfStatic     && visibleIfDocumented      && 
                 visibleIfEnabled    && visibleIfPrivate         &&
                 /*visibleIfDocVirtual &&*/ visibleIfNotDefaultCDTor && 
                 visibleIfFriendCompound &&
                 !m_impl->annScope;
  //printf("MemberDef::isBriefSectionVisible() %d\n",visible);
  return visible;
dimitri's avatar
dimitri committed
1175
}
dimitri's avatar
dimitri committed
1176

dimitri's avatar
dimitri committed
1177

dimitri's avatar
dimitri committed
1178 1179 1180 1181 1182
void MemberDef::writeDeclaration(OutputList &ol,
               ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
               bool inGroup
               )
{
dimitri's avatar
dimitri committed
1183
  //printf("%s MemberDef::writeDeclaration() inGroup=%d\n",name().data(),inGroup);
dimitri's avatar
dimitri committed
1184

dimitri's avatar
dimitri committed
1185 1186
  // hide enum value, since they appear already as part of the enum, unless they
  // are explicitly grouped.
dimitri's avatar
dimitri committed
1187 1188 1189
  makeResident();
  if (!inGroup && m_impl->mtype==EnumValue) return;
  LockingPtr<MemberDef> lock(this,this);
dimitri's avatar
dimitri committed
1190

dimitri's avatar
dimitri committed
1191
  // hide members whose brief section should not be visible
dimitri's avatar
dimitri committed
1192
  //if (!isBriefSectionVisible()) return;
mueller's avatar
mueller committed
1193

dimitri's avatar
dimitri committed
1194 1195 1196 1197
  Definition *d=0;
  ASSERT (cd!=0 || nd!=0 || fd!=0 || gd!=0); // member should belong to something
  if (cd) d=cd; else if (nd) d=nd; else if (fd) d=fd; else d=gd;

dimitri's avatar
dimitri committed
1198
  // write tag file information of this member
dimitri's avatar
dimitri committed
1199
  if (!Config_getString("GENERATE_TAGFILE").isEmpty() && !isReference())
dimitri's avatar
dimitri committed
1200 1201
  {
    Doxygen::tagFile << "    <member kind=\"";
dimitri's avatar
dimitri committed
1202
    switch (m_impl->mtype)
mueller's avatar
mueller committed
1203
    {
dimitri's avatar
dimitri committed
1204 1205 1206
      case Define:      Doxygen::tagFile << "define";      break;
      case EnumValue:   Doxygen::tagFile << "enumvalue";   break;
      case Property:    Doxygen::tagFile << "property";    break;
dimitri's avatar
dimitri committed
1207
      case Event:       Doxygen::tagFile << "event";       break;
dimitri's avatar
dimitri committed
1208 1209 1210 1211 1212
      case Variable:    Doxygen::tagFile << "variable";    break;
      case Typedef:     Doxygen::tagFile << "typedef";     break;
      case Enumeration: Doxygen::tagFile << "enumeration"; break;
      case Function:    Doxygen::tagFile << "function";    break;
      case Signal:      Doxygen::tagFile << "signal";      break;
dimitri's avatar
dimitri committed
1213
      //case Prototype:   Doxygen::tagFile << "prototype";   break;
dimitri's avatar
dimitri committed
1214 1215 1216
      case Friend:      Doxygen::tagFile << "friend";      break;
      case DCOP:        Doxygen::tagFile << "dcop";        break;
      case Slot:        Doxygen::tagFile << "slot";        break;
mueller's avatar
mueller committed
1217
    }
dimitri's avatar
dimitri committed
1218
    if (m_impl->prot!=Public)
dimitri's avatar
dimitri committed
1219
    {
dimitri's avatar
dimitri committed
1220
      Doxygen::tagFile << "\" protection=\"";
dimitri's avatar
dimitri committed
1221 1222 1223
      if (m_impl->prot==Protected)    Doxygen::tagFile << "protected";
      else if (m_impl->prot==Package) Doxygen::tagFile << "package";
      else /* Private */              Doxygen::tagFile << "private"; 
dimitri's avatar
dimitri committed
1224
    }
dimitri's avatar
dimitri committed
1225
    if (m_impl->virt!=Normal)
mueller's avatar
mueller committed
1226
    {
dimitri's avatar
dimitri committed
1227
      Doxygen::tagFile << "\" virtualness=\"";
dimitri's avatar
dimitri committed
1228 1229
      if (m_impl->virt==Virtual) Doxygen::tagFile << "virtual";
      else /* Pure */            Doxygen::tagFile << "pure"; 
mueller's avatar
mueller committed
1230
    }
dimitri's avatar
dimitri committed
1231
    if (isStatic())
mueller's avatar
mueller committed
1232
    {
dimitri's avatar
dimitri committed
1233
      Doxygen::tagFile << "\" static=\"yes";
mueller's avatar
mueller committed
1234
    }
dimitri's avatar
dimitri committed
1235
    Doxygen::tagFile << "\">" << endl;
dimitri's avatar
dimitri committed
1236
    Doxygen::tagFile << "      <type>" << convertToXML(typeString()) << "</type>" << endl;
dimitri's avatar
dimitri committed
1237
    Doxygen::tagFile << "      <name>" << convertToXML(name()) << "</name>" << endl;
dimitri's avatar
dimitri committed
1238
    Doxygen::tagFile << "      <anchorfile>" << convertToXML(getOutputFileBase()+Doxygen::htmlFileExtension) << "</anchorfile>" << endl;
dimitri's avatar
dimitri committed
1239 1240 1241 1242 1243 1244
    Doxygen::tagFile << "      <anchor>" << convertToXML(anchor()) << "</anchor>" << endl;
    Doxygen::tagFile << "      <arglist>" << convertToXML(argsString()) << "</arglist>" << endl;
    writeDocAnchorsToTagFile();
    Doxygen::tagFile << "    </member>" << endl;
  }

dimitri's avatar
dimitri committed
1245
  // write search index info
dimitri's avatar
dimitri committed
1246 1247 1248 1249 1250 1251
  if (Doxygen::searchIndex && isLinkableInProject())
  {
    Doxygen::searchIndex->setCurrentDoc(qualifiedName(),getOutputFileBase(),anchor());
    Doxygen::searchIndex->addWord(localName(),TRUE);
    Doxygen::searchIndex->addWord(qualifiedName(),FALSE);
  }
dimitri's avatar
dimitri committed
1252

dimitri's avatar
dimitri committed
1253
  QCString cname  = d->name();
dimitri's avatar
dimitri committed
1254
  QCString cfname = getOutputFileBase();
dimitri's avatar
dimitri committed
1255
  //QCString osname = cname;
dimitri's avatar
dimitri committed
1256 1257
  // in case of class members that are put in a group the name of the outerscope
  // differs from the cname.
dimitri's avatar
dimitri committed
1258
  //if (getOuterScope()) osname=getOuterScope()->name();
dimitri's avatar
dimitri committed
1259

dimitri's avatar
dimitri committed
1260 1261 1262
  //HtmlHelp *htmlHelp=0;
  //bool hasHtmlHelp = Config_getBool("GENERATE_HTML") && Config_getBool("GENERATE_HTMLHELP");
  //if (hasHtmlHelp) htmlHelp = HtmlHelp::getInstance();
dimitri's avatar
dimitri committed
1263 1264

  // search for the last anonymous scope in the member type
dimitri's avatar
dimitri committed
1265
  ClassDef *annoClassDef=getClassDefOfAnonymousType();
dimitri's avatar
dimitri committed
1266 1267

  // start a new member declaration
dimitri's avatar
dimitri committed
1268
  bool isAnonymous = annoClassDef || m_impl->annMemb || m_impl->annEnumType;
dimitri's avatar
dimitri committed
1269
  ///printf("startMemberItem for %s\n",name().data());
dimitri's avatar
dimitri committed
1270
  ol.startMemberItem( isAnonymous ? 1 : m_impl->tArgList ? 3 : 0);
dimitri's avatar
dimitri committed
1271 1272

  // If there is no detailed description we need to write the anchor here.
dimitri's avatar
dimitri committed
1273
  bool detailsVisible = isDetailedSectionLinkable();
dimitri's avatar
dimitri committed
1274
  if (!detailsVisible && !m_impl->annMemb)
dimitri's avatar
dimitri committed
1275 1276 1277
  {
    QCString doxyName=name().copy();
    if (!cname.isEmpty()) doxyName.prepend(cname+"::");
dimitri's avatar
dimitri committed
1278 1279
    QCString doxyArgs=argsString();
    ol.startDoxyAnchor(cfname,cname,anchor(),doxyName,doxyArgs);
dimitri's avatar
dimitri committed
1280 1281 1282

    ol.pushGeneratorState();
    ol.disable(OutputGenerator::Man);
dimitri's avatar
dimitri committed
1283
    ol.disable(OutputGenerator::Latex);
dimitri's avatar
dimitri committed
1284 1285 1286
    ol.docify("\n");
    ol.popGeneratorState();
  }
mueller's avatar
mueller committed
1287

dimitri's avatar
dimitri committed
1288
  if (annoClassDef || m_impl->annMemb)
dimitri's avatar
dimitri committed
1289 1290
  {
    int j;
dimitri's avatar
dimitri committed
1291
    for (j=0;j<s_indentLevel;j++) 
mueller's avatar
mueller committed
1292
    {
dimitri's avatar
dimitri committed
1293
      ol.writeNonBreakableSpace(3);
mueller's avatar
mueller committed
1294
    }
dimitri's avatar
dimitri committed
1295 1296
  }

dimitri's avatar
dimitri committed
1297
  // *** write template lists
dimitri's avatar
dimitri committed
1298
  if (m_impl->tArgList)
dimitri's avatar
dimitri committed
1299
  {
dimitri's avatar
dimitri committed
1300
    if (!isAnonymous) ol.startMemberTemplateParams();
dimitri's avatar
dimitri committed
1301
    writeTemplatePrefix(ol,m_impl->tArgList);
dimitri's avatar
dimitri committed
1302
    if (!isAnonymous) ol.endMemberTemplateParams();
dimitri's avatar
dimitri committed
1303 1304
  }

dimitri's avatar
dimitri committed
1305
  // *** write type
dimitri's avatar
dimitri committed
1306 1307
  QCString ltype(m_impl->type);
  if (m_impl->mtype==Typedef) ltype.prepend("typedef ");
dimitri's avatar
dimitri committed
1308
  // strip `friend' keyword from ltype
dimitri's avatar
dimitri committed
1309
  ltype.stripPrefix("friend ");
dimitri's avatar
dimitri committed
1310 1311
  static QRegExp r("@[0-9]+");

dimitri's avatar
dimitri committed
1312
  bool endAnonScopeNeeded=FALSE;
dimitri's avatar
dimitri committed
1313 1314 1315 1316 1317 1318 1319
  int l,i=r.match(ltype,0,&l);
  if (i!=-1) // member has an anonymous type
  {
    //printf("annoClassDef=%p annMemb=%p scopeName=`%s' anonymous=`%s'\n",
    //    annoClassDef,annMemb,cname.data(),ltype.mid(i,l).data());

    if (annoClassDef) // type is an anonymous compound
dimitri's avatar
dimitri committed
1320
    {
dimitri's avatar
dimitri committed
1321
      int ir=i+l;
dimitri's avatar
dimitri committed
1322 1323
      //printf("<<<<<<<<<<<<<<\n");
      ol.startAnonTypeScope(s_indentLevel++);
dimitri's avatar
dimitri committed
1324
      annoClassDef->writeDeclaration(ol,m_impl->annMemb,inGroup);
dimitri's avatar
dimitri committed
1325
      //printf(">>>>>>>>>>>>>> startMemberItem(2)\n");
dimitri's avatar
dimitri committed
1326 1327
      ol.startMemberItem(2);
      int j;
dimitri's avatar
dimitri committed
1328
      for (j=0;j< s_indentLevel-1;j++) 
dimitri's avatar
dimitri committed
1329 1330 1331 1332 1333 1334 1335 1336 1337 1338
      {
        ol.writeNonBreakableSpace(3);
      }
      QCString varName=ltype.right(ltype.length()-ir).stripWhiteSpace();
      //printf(">>>>>> indDepth=%d ltype=`%s' varName=`%s'\n",indDepth,ltype.data(),varName.data());
      ol.docify("}");
      if (varName.isEmpty() && (name().isEmpty() || name().at(0)=='@')) 
      {
        ol.docify(";"); 
      }
dimitri's avatar
dimitri committed
1339
      endAnonScopeNeeded=TRUE;
dimitri's avatar
dimitri committed
1340
    }
dimitri's avatar
dimitri committed
1341
    else
mueller's avatar
mueller committed
1342
    {
dimitri's avatar
dimitri committed
1343
      if (getAnonymousEnumType()) // type is an anonymous enum
mueller's avatar
mueller committed
1344
      {
dimitri's avatar
dimitri committed
1345
        linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),name(),ltype.left(i),TRUE); 
dimitri's avatar
dimitri committed
1346 1347
        getAnonymousEnumType()->writeEnumDeclaration(ol,cd,nd,fd,gd);
        //ol+=*getAnonymousEnumType()->enumDecl();
dimitri's avatar
dimitri committed
1348
        linkifyText(TextGeneratorOLImpl(ol),d,m_impl->fileDef,name(),ltype.right(ltype.length()-i-l),TRUE); 
mueller's avatar
mueller committed
1349
      }
dimitri's avatar
dimitri committed
1350
      else
mueller's avatar
mueller committed
1351
      {
dimitri's avatar
dimitri committed
1352
        ltype = ltype.left(i) + " { ... } " + removeAnonymousScopes(ltype.right(ltype.length()-i-l));
dimitri's avatar
dimitri committed
1353
        linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),name(),ltype,TRUE); 
mueller's avatar
mueller committed
1354 1355
      }
    }
dimitri's avatar
dimitri committed
1356
  }
dimitri's avatar
dimitri committed
1357 1358 1359 1360
  else if (ltype=="@") // rename type from enum values
  {
    ltype="";
  }
dimitri's avatar
dimitri committed
1361 1362
  else
  {
dimitri's avatar
dimitri committed
1363 1364 1365 1366 1367
    if (isObjCMethod())
    {
      ltype.prepend("(");
      ltype.append(")");
    }
dimitri's avatar
dimitri committed
1368
    linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),name(),ltype,TRUE); 
dimitri's avatar
dimitri committed
1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379
  }
  bool htmlOn = ol.isEnabled(OutputGenerator::Html);
  if (htmlOn && Config_getBool("HTML_ALIGN_MEMBERS") && !ltype.isEmpty())
  {
    ol.disable(OutputGenerator::Html);
  }
  if (!ltype.isEmpty()) ol.docify(" ");
  if (htmlOn) 
  {
    ol.enable(OutputGenerator::Html);
  }
mueller's avatar
mueller committed
1380

dimitri's avatar
dimitri committed
1381
  if (m_impl->annMemb) 
dimitri's avatar
dimitri committed
1382 1383 1384 1385 1386 1387 1388 1389
  {
    ol.pushGeneratorState();
    ol.disableAllBut(OutputGenerator::Html);
    ol.writeNonBreakableSpace(3);
    ol.popGeneratorState();
  }
  else
  {
dimitri's avatar
dimitri committed
1390
    ol.insertMemberAlign(m_impl->tArgList!=0);
dimitri's avatar
dimitri committed
1391
  }
mueller's avatar
mueller committed
1392

dimitri's avatar
dimitri committed
1393
  // *** write name
dimitri's avatar
dimitri committed
1394
  if (!name().isEmpty() && name().at(0)!='@') // hide anonymous stuff 
dimitri's avatar
dimitri committed
1395
  {
dimitri's avatar
dimitri committed
1396
    //printf("Member name=`%s gd=%p md->groupDef=%p inGroup=%d isLinkable()=%d\n",name().data(),gd,getGroupDef(),inGroup,isLinkable());
dimitri's avatar
dimitri committed
1397 1398
    if (!(name().isEmpty() || name().at(0)=='@') && // name valid
        (hasDocumentation() || isReference()) && // has docs
dimitri's avatar
dimitri committed
1399 1400
        !(m_impl->prot==Private && !Config_getBool("EXTRACT_PRIVATE") && m_impl->mtype!=Friend) && // hidden due to protection
        !(isStatic() && m_impl->classDef==0 && !Config_getBool("EXTRACT_STATIC")) // hidden due to static-ness
dimitri's avatar
dimitri committed
1401
       )
mueller's avatar
mueller committed
1402
    {
dimitri's avatar
dimitri committed
1403
      if (m_impl->annMemb)
dimitri's avatar
dimitri committed
1404 1405
      {
        //printf("anchor=%s ann_anchor=%s\n",anchor(),annMemb->anchor());
dimitri's avatar
dimitri committed
1406 1407 1408 1409 1410
        m_impl->annMemb->writeLink(ol,
            m_impl->annMemb->getClassDef(),
            m_impl->annMemb->getNamespaceDef(),
            m_impl->annMemb->getFileDef(),
            m_impl->annMemb->getGroupDef()
dimitri's avatar
dimitri committed
1411
                          );
dimitri's avatar
dimitri committed
1412 1413
        m_impl->annMemb->setAnonymousUsed();
        setAnonymousUsed();
dimitri's avatar
dimitri committed
1414 1415
      }
      else
dimitri's avatar
dimitri committed
1416
      {
dimitri's avatar
dimitri committed
1417
        //printf("writeLink %s->%d\n",name.data(),hasDocumentation());
dimitri's avatar
dimitri committed
1418
        ClassDef *rcd = cd;
dimitri's avatar
dimitri committed
1419
        if (isReference() && m_impl->classDef) rcd = m_impl->classDef; 
dimitri's avatar
dimitri committed
1420
        writeLink(ol,rcd,nd,fd,gd);
dimitri's avatar
dimitri committed
1421
      }
mueller's avatar
mueller committed
1422
    }
dimitri's avatar
dimitri committed
1423 1424 1425 1426 1427 1428 1429 1430
    else if (isDocumentedFriendClass())
      // if the member is an undocumented friend declaration for some class, 
      // then maybe we can link to the class
    {
      writeLink(ol,getClass(name()),0,0,0);
    }
    else
      // there is a brief member description and brief member 
dimitri's avatar
dimitri committed
1431
      // descriptions are enabled or there is no detailed description.
mueller's avatar
mueller committed
1432
    {
dimitri's avatar
dimitri committed
1433 1434 1435 1436 1437
      if (m_impl->annMemb)  
      {
        m_impl->annMemb->setAnonymousUsed();
        setAnonymousUsed();
      }
dimitri's avatar
dimitri committed
1438
      ClassDef *rcd = cd;
dimitri's avatar
dimitri committed
1439
      if (isReference() && m_impl->classDef) rcd = m_impl->classDef; 
dimitri's avatar
dimitri committed
1440
      writeLink(ol,rcd,nd,fd,gd,TRUE);
mueller's avatar
mueller committed
1441
    }
dimitri's avatar
dimitri committed
1442 1443
  }

dimitri's avatar
dimitri committed
1444 1445 1446 1447 1448 1449 1450
  // add to index
  if (isEnumerate() && name().at(0)=='@')
  {
    // don't add to index
  }
  else // index member
  {
dimitri's avatar
dimitri committed
1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461
    //static bool separateMemPages = Config_getBool("SEPARATE_MEMBER_PAGES");
    //QCString cfname = getOutputFileBase();
    //QCString cfiname = d->getOutputFileBase();
    //Doxygen::indexList.addIndexItem(
    //    cname,                                 // level1
    //    name(),                                // level2
    //    separateMemPages ? cfname : cfiname,   // contRef
    //    cfname,                                // memRef
    //    anchor(),                              // anchor
    //    this);                                 // memberdef
    Doxygen::indexList.addIndexItem(d,this);
dimitri's avatar
dimitri committed
1462 1463
  }

dimitri's avatar
dimitri committed
1464
  // *** write arguments
dimitri's avatar
dimitri committed
1465
  if (argsString() && !isObjCMethod()) 
dimitri's avatar
dimitri committed
1466 1467 1468
  {
    if (!isDefine()) ol.writeString(" ");
    //ol.docify(argsString());
dimitri's avatar
dimitri committed
1469
    linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),name(),argsString()); 
dimitri's avatar
dimitri committed
1470 1471
  }

dimitri's avatar
dimitri committed
1472
  // *** write exceptions
dimitri's avatar
dimitri committed
1473 1474 1475 1476 1477
  if (excpString())
  {
    ol.writeString(" ");
    ol.docify(excpString());
  }
mueller's avatar
mueller committed
1478

dimitri's avatar
dimitri committed
1479
  // *** write bitfields
dimitri's avatar
dimitri committed
1480
  if (!m_impl->bitfields.isEmpty()) // add bitfields
dimitri's avatar
dimitri committed
1481
  {
dimitri's avatar
dimitri committed
1482
    linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),name(),m_impl->bitfields.simplifyWhiteSpace());
dimitri's avatar
dimitri committed
1483
  }
dimitri's avatar
dimitri committed
1484 1485 1486
  else if (hasOneLineInitializer()
      //!init.isEmpty() && initLines==0 && // one line initializer
      //((maxInitLines>0 && userInitLines==-1) || userInitLines>0) // enabled by default or explicitly
dimitri's avatar
dimitri committed
1487 1488 1489
          ) // add initializer
  {
    if (!isDefine()) 
dimitri's avatar
dimitri committed
1490
    {
dimitri's avatar
dimitri committed
1491
      ol.writeString(" = "); 
dimitri's avatar
dimitri committed
1492
      linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),name(),m_impl->initializer.simplifyWhiteSpace());
dimitri's avatar
dimitri committed
1493
    }
dimitri's avatar
dimitri committed
1494
    else 
dimitri's avatar
dimitri committed
1495
    {
dimitri's avatar
dimitri committed
1496
      ol.writeNonBreakableSpace(3);
dimitri's avatar
dimitri committed
1497
      linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),name(),m_impl->initializer);
dimitri's avatar
dimitri committed
1498
    }
dimitri's avatar
dimitri committed
1499
  }
dimitri's avatar
dimitri committed
1500

dimitri's avatar
dimitri committed
1501 1502 1503 1504 1505 1506
  if (isObjCMethod() && isImplementation())
  {
    ol.startTypewriter();
    ol.docify(" [implementation]");
    ol.endTypewriter();
  }
dimitri's avatar
dimitri committed
1507

dimitri's avatar
dimitri committed
1508
  if (isProperty() && (isSettable() || isGettable()))
dimitri's avatar
dimitri committed
1509 1510 1511 1512 1513
  {
      ol.writeLatexSpacing();
      ol.startTypewriter();
      ol.docify(" [");
      QStrList sl;
dimitri's avatar
dimitri committed
1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535
      if (isGettable())  sl.append("get");
      if (isSettable())  sl.append("set");
      const char *s=sl.first();
      while (s)
      {
         ol.docify(s);
         s=sl.next();
         if (s) ol.docify(", ");
      }
      ol.docify("]");
      ol.endTypewriter();
  }

  if (isEvent() && (isAddable() || isRemovable() || isRaisable()))
  {
      ol.writeLatexSpacing();
      ol.startTypewriter();
      ol.docify(" [");
      QStrList sl;
      if (isAddable())   sl.append("add");
      if (isRemovable()) sl.append("remove");
      if (isRaisable())  sl.append("raise");
dimitri's avatar
dimitri committed
1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546
      const char *s=sl.first();
      while (s)
      {
         ol.docify(s);
         s=sl.next();
         if (s) ol.docify(", ");
      }
      ol.docify("]");
      ol.endTypewriter();
  }

dimitri's avatar
dimitri committed
1547
  if (!detailsVisible && !m_impl->annMemb)
dimitri's avatar
dimitri committed
1548 1549 1550
  {
    ol.endDoxyAnchor(cfname,anchor());
  }
mueller's avatar
mueller committed
1551

dimitri's avatar
dimitri committed
1552 1553 1554
  //printf("endMember %s annoClassDef=%p annEnumType=%p\n",
  //    name().data(),annoClassDef,annEnumType);
  ol.endMemberItem();
dimitri's avatar
dimitri committed
1555 1556 1557 1558
  if (endAnonScopeNeeded) 
  {
    ol.endAnonTypeScope(--s_indentLevel);
  }
dimitri's avatar
dimitri committed
1559 1560

  // write brief description
dimitri's avatar
dimitri committed
1561
  if (!briefDescription().isEmpty() && 
dimitri's avatar
dimitri committed
1562 1563 1564
      Config_getBool("BRIEF_MEMBER_DESC") 
      /* && !annMemb */
     )
dimitri's avatar
dimitri committed
1565 1566
  {
    ol.startMemberDescription();
dimitri's avatar
dimitri committed
1567 1568 1569
    ol.parseDoc(briefFile(),briefLine(),
                getOuterScope()?getOuterScope():d,this,briefDescription(),
                TRUE,FALSE,0,TRUE,FALSE);
dimitri's avatar
dimitri committed
1570
    if (detailsVisible) 
mueller's avatar
mueller committed
1571
    {
dimitri's avatar
dimitri committed
1572 1573
      ol.pushGeneratorState();
      ol.disableAllBut(OutputGenerator::Html);
dimitri's avatar
dimitri committed
1574
      //ol.endEmphasis();
dimitri's avatar
dimitri committed
1575
      ol.docify(" ");
dimitri's avatar
dimitri committed
1576
      if (m_impl->group!=0 && gd==0) // forward link to the group
mueller's avatar
mueller committed
1577
      {
dimitri's avatar
dimitri committed
1578
        ol.startTextLink(getOutputFileBase(),anchor());
dimitri's avatar
dimitri committed
1579
      }
dimitri's avatar
dimitri committed
1580
      else // local link
dimitri's avatar
dimitri committed
1581 1582
      {
        ol.startTextLink(0,anchor());
mueller's avatar
mueller committed
1583
      }
dimitri's avatar
dimitri committed
1584
      ol.endTextLink();
dimitri's avatar
dimitri committed
1585
      //ol.startEmphasis();
dimitri's avatar
dimitri committed
1586
      ol.popGeneratorState();
mueller's avatar
mueller committed
1587
    }
dimitri's avatar
dimitri committed
1588 1589 1590 1591 1592 1593
    // for RTF we need to add an extra empty paragraph
    ol.pushGeneratorState();
    ol.disableAllBut(OutputGenerator::RTF);
      ol.startParagraph();
      ol.endParagraph();
    ol.popGeneratorState();
dimitri's avatar
dimitri committed
1594
    ol.endMemberDescription();
mueller's avatar
mueller committed
1595
  }
mueller's avatar
mueller committed
1596
  warnIfUndocumented();
mueller's avatar
mueller committed
1597 1598
}

dimitri's avatar
dimitri committed
1599
bool MemberDef::isDetailedSectionLinkable() const          
dimitri's avatar
dimitri committed
1600
{ 
dimitri's avatar
dimitri committed
1601 1602 1603 1604 1605 1606 1607 1608
  static bool extractAll        = Config_getBool("EXTRACT_ALL");
  static bool alwaysDetailedSec = Config_getBool("ALWAYS_DETAILED_SEC");
  static bool repeatBrief       = Config_getBool("REPEAT_BRIEF");
  static bool briefMemberDesc   = Config_getBool("BRIEF_MEMBER_DESC");
  static bool hideUndocMembers  = Config_getBool("HIDE_UNDOC_MEMBERS");
  static bool extractStatic     = Config_getBool("EXTRACT_STATIC");
  static bool extractPrivate    = Config_getBool("EXTRACT_PRIVATE");

dimitri's avatar
dimitri committed
1609
  makeResident();
dimitri's avatar
dimitri committed
1610 1611 1612
  // the member has details documentation for any of the following reasons
  bool docFilter = 
         // treat everything as documented
dimitri's avatar
dimitri committed
1613
         extractAll ||          
dimitri's avatar
dimitri committed
1614 1615
         // has detailed docs
         !documentation().isEmpty() ||             
dimitri's avatar
dimitri committed
1616 1617
         // has inbody docs
         !inbodyDocumentation().isEmpty() ||
dimitri's avatar
dimitri committed
1618
         // is an enum with values that are documented
dimitri's avatar
dimitri committed
1619
         (m_impl->mtype==Enumeration && m_impl->docEnumValues) ||  
dimitri's avatar
dimitri committed
1620
         // is documented enum value
dimitri's avatar
dimitri committed
1621
         (m_impl->mtype==EnumValue && !briefDescription().isEmpty()) || 
dimitri's avatar
dimitri committed
1622
         // has brief description that is part of the detailed description
dimitri's avatar
dimitri committed
1623
         (!briefDescription().isEmpty() &&           // has brief docs
dimitri's avatar
dimitri committed
1624 1625 1626 1627 1628
          (alwaysDetailedSec &&                      // they are visible in
           (repeatBrief ||                           // detailed section or
            !briefMemberDesc                         // they are explicitly not
           )                                         // shown in brief section
          )                                       
dimitri's avatar
dimitri committed
1629 1630
         ) ||
         // has a multi-line initialization block
dimitri's avatar
dimitri committed
1631
         //(initLines>0 && initLines<maxInitLines) || 
dimitri's avatar
dimitri committed
1632
         (hasMultiLineInitializer() && !hideUndocMembers) ||
dimitri's avatar
dimitri committed
1633
         // has one or more documented arguments
dimitri's avatar
dimitri committed
1634 1635 1636 1637
         (m_impl->defArgList!=0 && m_impl->defArgList->hasDocumentation()) ||
         // has user comments
         Doxygen::userComments
         ; 
dimitri's avatar
dimitri committed
1638 1639
         
  // this is not a global static or global statics should be extracted
dimitri's avatar
dimitri committed
1640
  bool staticFilter = getClassDef()!=0 || !isStatic() || extractStatic; 
dimitri's avatar
dimitri committed
1641
         
dimitri's avatar
dimitri committed
1642
  // only include members that are non-private unless EXTRACT_PRIVATE is
dimitri's avatar
dimitri committed
1643
  // set to YES or the member is part of a   group
dimitri's avatar
dimitri committed
1644
  bool privateFilter = (protection()!=Private || extractPrivate ||
dimitri's avatar
dimitri committed
1645
                           m_impl->mtype==Friend
dimitri's avatar
dimitri committed
1646 1647
                          );

dimitri's avatar
dimitri committed
1648 1649 1650
  // member is part of an anonymous scope that is the type of
  // another member in the list.
  //
dimitri's avatar
dimitri committed
1651
  //bool inAnonymousScope = !briefDescription().isEmpty() && annUsed;
dimitri's avatar
dimitri committed
1652

dimitri's avatar
dimitri committed
1653 1654 1655 1656
  // hide friend (class|struct|union) member if HIDE_FRIEND_COMPOUNDS
  // is true
  bool friendCompoundFilter = !(Config_getBool("HIDE_FRIEND_COMPOUNDS") &&
                                isFriend() &&
dimitri's avatar
dimitri committed
1657 1658 1659
                                (m_impl->type=="friend class" || 
                                 m_impl->type=="friend struct" ||
                                 m_impl->type=="friend union"
dimitri's avatar
dimitri committed
1660 1661 1662
                                )
                               );
  
dimitri's avatar
dimitri committed
1663
  return ((docFilter && staticFilter && privateFilter && friendCompoundFilter) /*|| inAnonymousScope*/);
dimitri's avatar
dimitri committed
1664 1665
}

dimitri's avatar
dimitri committed
1666
bool MemberDef::isDetailedSectionVisible(bool inGroup,bool inFile) const          
dimitri's avatar
dimitri committed
1667
{ 
dimitri's avatar
dimitri committed
1668 1669
  static bool separateMemPages = Config_getBool("SEPARATE_MEMBER_PAGES");
  bool groupFilter = getGroupDef()==0 || inGroup || separateMemPages; 
dimitri's avatar
dimitri committed
1670
  bool fileFilter  = getNamespaceDef()==0 || !inFile;
dimitri's avatar
dimitri committed
1671

dimitri's avatar
dimitri committed
1672 1673
  bool visible = isDetailedSectionLinkable() && groupFilter && fileFilter && 
                 !isReference();
dimitri's avatar
dimitri committed
1674 1675
  //printf("MemberDef::isDetailedSectionVisible() %d\n",visible);
  return visible;
dimitri's avatar
dimitri committed
1676 1677
}

dimitri's avatar
dimitri committed
1678 1679 1680
/*! Writes the "detailed documentation" section of this member to
 *  all active output formats.
 */
dimitri's avatar
dimitri committed
1681
void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol,
dimitri's avatar
dimitri committed
1682
                                   const char *scName,
dimitri's avatar
dimitri committed
1683
                                   Definition *container,
dimitri's avatar
dimitri committed
1684 1685
                                   bool inGroup,
                                   bool showEnumValues
dimitri's avatar
dimitri committed
1686
                                  )
mueller's avatar
mueller committed
1687
{
dimitri's avatar
dimitri committed
1688
  // if this member is in a group find the real scope name.
dimitri's avatar
dimitri committed
1689
  bool hasParameterList = FALSE;
dimitri's avatar
dimitri committed
1690 1691
  bool inFile = container->definitionType()==Definition::TypeFile;
  bool hasDocs = isDetailedSectionVisible(inGroup,inFile);
dimitri's avatar
dimitri committed
1692
  static bool optVhdl          = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
dimitri's avatar
dimitri committed
1693 1694
  //printf("MemberDef::writeDocumentation(): name=`%s' hasDocs=`%d' containerType=%d inGroup=%d\n",
  //    name().data(),hasDocs,container->definitionType(),inGroup);
dimitri's avatar
dimitri committed
1695
  if ( !hasDocs ) return;
dimitri's avatar
dimitri committed
1696
  if (isEnumValue() && !showEnumValues) return;
dimitri's avatar
dimitri committed
1697

dimitri's avatar
dimitri committed
1698 1699 1700
  makeResident();
  LockingPtr<MemberDef> lock(this,this);

dimitri's avatar
dimitri committed
1701
  QCString scopeName = scName;
dimitri's avatar
dimitri committed
1702
  QCString memAnchor = anchor();
dimitri's avatar
dimitri committed
1703
  QCString ciname = container->name();
dimitri's avatar
dimitri committed
1704
  if (container->definitionType()==TypeGroup)
dimitri's avatar
dimitri committed
1705
  {
dimitri's avatar
dimitri committed
1706 1707 1708
    if (getClassDef())          scopeName=getClassDef()->name();
    else if (getNamespaceDef()) scopeName=getNamespaceDef()->name();
    else if (getFileDef())      scopeName=getFileDef()->name();
dimitri's avatar
dimitri committed
1709
    ciname = ((GroupDef *)container)->groupTitle();
dimitri's avatar
dimitri committed
1710
  }
dimitri's avatar
dimitri committed
1711 1712 1713 1714 1715
  else if (container->definitionType()==TypeFile && getNamespaceDef())
  { // member is in a namespace, but is written as part of the file documentation
    // as well, so we need to make sure its label is unique.
    memAnchor.prepend("file_");
  }
mueller's avatar
mueller committed
1716

dimitri's avatar
dimitri committed
1717
  QCString cname  = container->name();
dimitri's avatar
dimitri committed
1718 1719
  QCString cfname = getOutputFileBase();
  QCString cfiname = container->getOutputFileBase();
dimitri's avatar
dimitri committed
1720

dimitri's avatar
dimitri committed
1721
  // get member name
dimitri's avatar
dimitri committed
1722
  QCString doxyName=name();
dimitri's avatar
dimitri committed
1723 1724
  // prepend scope if there is any. TODO: make this optional for C only docs
  if (scopeName) doxyName.prepend((QCString)scopeName+"::");
dimitri's avatar
dimitri committed
1725
  QCString doxyArgs=argsString();
mueller's avatar
mueller committed
1726

dimitri's avatar
dimitri committed
1727 1728 1729 1730 1731
  QCString ldef = definition();
  //printf("member `%s' def=`%s'\n",name().data(),ldef.data());
  if (isEnumerate()) 
  {
    if (name().at(0)=='@')
dimitri's avatar
dimitri committed
1732
    {
dimitri's avatar
dimitri committed
1733
      ldef = "anonymous enum";
dimitri's avatar
dimitri committed
1734
    }
dimitri's avatar
dimitri committed
1735 1736 1737 1738 1739
    else
    {
      ldef.prepend("enum ");
    }
  }
dimitri's avatar
dimitri committed
1740 1741 1742 1743 1744 1745 1746
  else if (isEnumValue())
  {
    if (ldef.at(0)=='@')
    {
      ldef=ldef.mid(2);
    }
  }
dimitri's avatar
dimitri committed
1747 1748
  int i=0,l;
  static QRegExp r("@[0-9]+");
dimitri's avatar
dimitri committed
1749

dimitri's avatar
dimitri committed
1750
  //----------------------------------------
mueller's avatar
mueller committed
1751

dimitri's avatar
dimitri committed
1752
  ol.pushGeneratorState();
dimitri's avatar
dimitri committed
1753

mueller's avatar
mueller committed
1754

dimitri's avatar
dimitri committed
1755 1756 1757 1758 1759 1760 1761
  if ((isVariable() || isTypedef()) && (i=r.match(ldef,0,&l))!=-1)
  {
    // find enum type and insert it in the definition
    MemberListIterator vmli(*ml);
    MemberDef *vmd;
    bool found=FALSE;
    for ( ; (vmd=vmli.current()) && !found ; ++vmli)
mueller's avatar
mueller committed
1762
    {
dimitri's avatar
dimitri committed
1763
      if (vmd->isEnumerate() && ldef.mid(i,l)==vmd->name())
mueller's avatar
mueller committed
1764
      {
dimitri's avatar
dimitri committed
1765
        ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs);
dimitri's avatar
dimitri committed
1766
        ol.startMemberDoc(cname,name(),memAnchor,name());
dimitri's avatar
dimitri committed
1767 1768 1769 1770 1771
        linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),name(),ldef.left(i));
        vmd->writeEnumDeclaration(ol,getClassDef(),getNamespaceDef(),getFileDef(),getGroupDef());
        linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),name(),ldef.right(ldef.length()-i-l));

        found=TRUE;
mueller's avatar
mueller committed
1772
      }
mueller's avatar
mueller committed
1773
    }
dimitri's avatar
dimitri committed
1774
    if (!found) // anonymous compound
mueller's avatar
mueller committed
1775
    {
dimitri's avatar
dimitri committed
1776
      //printf("Anonymous compound `%s'\n",cname.data());
dimitri's avatar
dimitri committed
1777
      ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs);
dimitri's avatar
dimitri committed
1778
      ol.startMemberDoc(cname,name(),memAnchor,name());
dimitri's avatar
dimitri committed
1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794
      // strip anonymous compound names from definition
      int si=ldef.find(' '),pi,ei=i+l;
      if (si==-1) si=0;
      while ((pi=r.match(ldef,i+l,&l))!=-1) ei=i=pi+l;
      // first si characters of ldef contain compound type name
      ol.startMemberDocName(isObjCMethod());
      ol.docify(ldef.left(si));
      ol.docify(" { ... } ");
      // last ei characters of ldef contain pointer/reference specifiers
      int ni=ldef.find("::",si);
      if (ni>=ei) ei=ni+2;
      linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),name(),ldef.right(ldef.length()-ei));
    }
  }
  else // not an enum value
  {
dimitri's avatar
dimitri committed
1795
    ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs);
dimitri's avatar
dimitri committed
1796
    ol.startMemberDoc(cname,name(),memAnchor,name());
mueller's avatar
mueller committed
1797

dimitri's avatar
dimitri committed
1798 1799 1800 1801
    ClassDef *cd=getClassDef();
    if (!Config_getBool("HIDE_SCOPE_NAMES"))
    {
      bool first=TRUE;
dimitri's avatar
dimitri committed
1802
      if (m_impl->defTmpArgLists) 
dimitri's avatar
dimitri committed
1803 1804
        // definition has explicit template parameter declarations
      {
dimitri's avatar
dimitri committed
1805
        QListIterator<ArgumentList> ali(*m_impl->defTmpArgLists);
dimitri's avatar
dimitri committed
1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819
        ArgumentList *tal;
        for (ali.toFirst();(tal=ali.current());++ali)
        {
          if (tal->count()>0)
          {
            if (!first) ol.docify(" ");
            ol.startMemberDocPrefixItem();
            writeTemplatePrefix(ol,tal);
            ol.endMemberDocPrefixItem();
          }
        }
      }
      else // definition gets it template parameters from its class
        // (since no definition was found)
mueller's avatar
mueller committed
1820
      {
dimitri's avatar
dimitri committed
1821
        if (cd && !isTemplateSpecialization())
mueller's avatar
mueller committed
1822
        {
dimitri's avatar
dimitri committed
1823 1824 1825 1826
          QList<ArgumentList> tempParamLists;
          cd->getTemplateParameterLists(tempParamLists);
          //printf("#tempParamLists=%d\n",tempParamLists.count());
          QListIterator<ArgumentList> ali(tempParamLists);
dimitri's avatar
dimitri committed
1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837
          ArgumentList *tal;
          for (ali.toFirst();(tal=ali.current());++ali)
          {
            if (tal->count()>0)
            {
              if (!first) ol.docify(" ");
              ol.startMemberDocPrefixItem();
              writeTemplatePrefix(ol,tal);
              ol.endMemberDocPrefixItem();
            }
          }
mueller's avatar
mueller committed
1838
        }
dimitri's avatar
dimitri committed
1839
        if (m_impl->tArgList) // function template prefix
mueller's avatar
mueller committed
1840
        {
dimitri's avatar
dimitri committed
1841
          ol.startMemberDocPrefixItem();
dimitri's avatar
dimitri committed
1842
          writeTemplatePrefix(ol,m_impl->tArgList);
dimitri's avatar
dimitri committed
1843
          ol.endMemberDocPrefixItem();
mueller's avatar
mueller committed
1844 1845
        }
      }
dimitri's avatar
dimitri committed
1846
    }
dimitri's avatar
dimitri committed
1847

dimitri's avatar
dimitri committed
1848 1849 1850 1851 1852 1853
    ol.startMemberDocName(isObjCMethod());
    if (cd && cd->isObjectiveC())
    {
      // strip scope name
      int ep = ldef.find("::");
      if (ep!=-1) 
dimitri's avatar
dimitri committed
1854
      {
dimitri's avatar
dimitri committed
1855 1856
        int sp=ldef.findRev(' ',ep);
        if (sp!=-1)
dimitri's avatar
dimitri committed
1857
        {
dimitri's avatar
dimitri committed
1858
          ldef=ldef.left(sp+1)+ldef.mid(ep+2);
dimitri's avatar
dimitri committed
1859 1860
        }
      }
dimitri's avatar
dimitri committed
1861 1862 1863
      // strip keywords
      int dp = ldef.find(':');
      if (dp!=-1)
dimitri's avatar
dimitri committed
1864
      {
dimitri's avatar
dimitri committed
1865
        ldef=ldef.left(dp+1);
dimitri's avatar
dimitri committed
1866
      }
dimitri's avatar
dimitri committed
1867 1868 1869 1870 1871 1872
      int l=ldef.length();
      //printf("start >%s<\n",ldef.data());
      int i=l-1;
      while (i>=0 && (isId(ldef.at(i)) || ldef.at(i)==':')) i--;
      while (i>=0 && isspace((uchar)ldef.at(i))) i--;
      if (i>0)
mueller's avatar
mueller committed
1873
      {
dimitri's avatar
dimitri committed
1874 1875 1876
        // insert braches around the type
        QCString tmp("("+ldef.left(i+1)+")"+ldef.mid(i+1));
        ldef=tmp;
mueller's avatar
mueller committed
1877
      }
dimitri's avatar
dimitri committed
1878 1879
      //printf("end   >%s< i=%d\n",ldef.data(),i);
      if (isStatic()) ldef.prepend("+ "); else ldef.prepend("- ");
mueller's avatar
mueller committed
1880
    }
dimitri's avatar
dimitri committed
1881

dimitri's avatar
dimitri committed
1882 1883 1884 1885 1886 1887 1888 1889 1890
    if (optVhdl)
    {
      VhdlDocGen::writeVHDLTypeDocumentation(this,container,ol);
    }
    else
    {
      linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),name(),ldef);
      hasParameterList=writeDefArgumentList(ol,cd,scopeName,this);
    }
dimitri's avatar
dimitri committed
1891

dimitri's avatar
dimitri committed
1892
    if (hasOneLineInitializer()) // add initializer
mueller's avatar
mueller committed
1893
    {
dimitri's avatar
dimitri committed
1894
      if (!isDefine()) 
mueller's avatar
mueller committed
1895
      {
dimitri's avatar
dimitri committed
1896
        ol.docify(" = "); 
dimitri's avatar
dimitri committed
1897
        linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),name(),m_impl->initializer.simplifyWhiteSpace());
mueller's avatar
mueller committed
1898
      }
dimitri's avatar
dimitri committed
1899
      else 
mueller's avatar
mueller committed
1900
      {
dimitri's avatar
dimitri committed
1901
        ol.writeNonBreakableSpace(3);
dimitri's avatar
dimitri committed
1902
        linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),name(),m_impl->initializer);
mueller's avatar
mueller committed
1903 1904
      }
    }
dimitri's avatar
dimitri committed
1905
    if (excpString()) // add exception list
dimitri's avatar
dimitri committed
1906
    {
dimitri's avatar
dimitri committed
1907 1908
      ol.docify(" ");
      linkifyText(TextGeneratorOLImpl(ol),container,getBodyDef(),name(),excpString());
dimitri's avatar
dimitri committed
1909
    }
dimitri's avatar
dimitri committed
1910
  }
mueller's avatar
mueller committed
1911

dimitri's avatar
dimitri committed
1912
  Specifier lvirt=virtualness();
dimitri's avatar
dimitri committed
1913

dimitri's avatar
dimitri committed
1914
  if ((!isObjCMethod() || isOptional() || isRequired()) &&
dimitri's avatar
dimitri committed
1915
      (protection()!=Public || lvirt!=Normal ||
dimitri's avatar
dimitri committed
1916 1917
       isFriend() || isRelated() || 
       (isInline() && Config_getBool("INLINE_INFO")) ||
dimitri's avatar
dimitri committed
1918
       isSignal() || isSlot() ||
dimitri's avatar
dimitri committed
1919
       isStatic() || (m_impl->classDef && m_impl->classDef!=container) ||
dimitri's avatar
dimitri committed
1920
       (m_impl->memSpec & ~Entry::Inline)!=0 
dimitri's avatar
dimitri committed
1921 1922 1923 1924 1925 1926 1927 1928
      )
     )
  {
    // write the member specifier list
    ol.writeLatexSpacing();
    ol.startTypewriter();
    ol.docify(" [");
    QStrList sl;
dimitri's avatar
dimitri committed
1929 1930 1931 1932
    if (optVhdl)
    {
      sl.append(VhdlDocGen::trTypeString(getMemberSpecifiers()));
    }
dimitri's avatar
dimitri committed
1933
    else
dimitri's avatar
dimitri committed
1934
    {
dimitri's avatar
dimitri committed
1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960
      if (isFriend()) sl.append("friend");
      else if (isRelated()) sl.append("related");
      else
      {
        if      (Config_getBool("INLINE_INFO") && isInline()) sl.append("inline");
        if      (isExplicit())            sl.append("explicit");
        if      (isMutable())             sl.append("mutable");
        if      (isStatic())              sl.append("static");
        if      (isGettable())            sl.append("get");
        if      (isSettable())            sl.append("set");
        if      (isAddable())             sl.append("add");
        if      (isRemovable())           sl.append("remove");
        if      (isRaisable())            sl.append("raise");
        if      (isReadable())            sl.append("read");
        if      (isWritable())            sl.append("write");
        if      (isFinal())               sl.append("final");
        if      (isAbstract())            sl.append("abstract");
        if      (isOverride())            sl.append("override");
        if      (isInitonly())            sl.append("initonly");
        if      (isSealed())              sl.append("sealed");
        if      (isNew())                 sl.append("new");
        if      (isOptional())            sl.append("optional");
        if      (isRequired())            sl.append("required");
        if      (isAssign())              sl.append("assign");
        else if (isCopy())                sl.append("copy");
        else if (isRetain())              sl.append("retain");
dimitri's avatar
dimitri committed
1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972

        if (!isObjCMethod())
        {
          if      (protection()==Protected) sl.append("protected");
          else if (protection()==Private)   sl.append("private");
          else if (protection()==Package)   sl.append("package");

          if      (lvirt==Virtual)          sl.append("virtual");
          else if (lvirt==Pure)             sl.append("pure virtual");
          if      (isSignal())              sl.append("signal");
          if      (isSlot())                sl.append("slot");
        }
dimitri's avatar
dimitri committed
1973 1974 1975
      }
      if (m_impl->classDef && m_impl->classDef!=container) sl.append("inherited");
    }
dimitri's avatar
dimitri committed
1976 1977 1978 1979 1980 1981
    const char *s=sl.first();
    while (s)
    {
      ol.docify(s);
      s=sl.next();
      if (s) ol.docify(", ");
mueller's avatar
mueller committed
1982
    }
dimitri's avatar
dimitri committed
1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002
    ol.docify("]");
    ol.endTypewriter();
  }
  else if (isObjCMethod() && isImplementation())
  {
    ol.writeLatexSpacing();
    ol.startTypewriter();
    ol.docify(" [implementation]");
    ol.endTypewriter();
  }
  if (hasParameterList) 
  {
    ol.endParameterList();
    ol.endMemberDoc(TRUE);
  }
  else
  {
    ol.endMemberDocName();
    ol.endMemberDoc(FALSE);
  }
dimitri's avatar
dimitri committed
2003
  ol.endDoxyAnchor(cfname,memAnchor);
dimitri's avatar
dimitri committed
2004
  ol.startIndent();
dimitri's avatar
dimitri committed
2005

dimitri's avatar
dimitri committed
2006 2007 2008 2009 2010
  // FIXME:PARA
  //ol.pushGeneratorState();
  //ol.disable(OutputGenerator::RTF);
  //ol.newParagraph();
  //ol.popGeneratorState();
dimitri's avatar
dimitri committed
2011 2012 2013 2014 2015 2016 2017 2018 2019 2020

  /* write multi-line initializer (if any) */
  if (hasMultiLineInitializer()
      //initLines>0 && ((initLines<maxInitLines && userInitLines==-1) // implicitly enabled
      //                || initLines<userInitLines // explicitly enabled
      //               )
     )
  {
    //printf("md=%s initLines=%d init=`%s'\n",name().data(),initLines,init.data());
    ol.startBold();
dimitri's avatar
dimitri committed
2021
    if (m_impl->mtype==Define)
dimitri's avatar
dimitri committed
2022 2023 2024 2025
      ol.parseText(theTranslator->trDefineValue());
    else
      ol.parseText(theTranslator->trInitialValue());
    ol.endBold();
dimitri's avatar
dimitri committed
2026 2027
    ParserInterface *pIntf = Doxygen::parserManager->getParser(getDefFileExtension());
    pIntf->resetCodeParserState();
dimitri's avatar
dimitri committed
2028
    ol.startCodeFragment();
dimitri's avatar
dimitri committed
2029 2030
    pIntf->parseCode(ol,scopeName,m_impl->initializer,FALSE,0,getFileDef(),
                     -1,-1,TRUE,this,FALSE);
dimitri's avatar
dimitri committed
2031 2032 2033
    ol.endCodeFragment();
  }

dimitri's avatar
dimitri committed
2034 2035 2036 2037 2038 2039 2040 2041 2042
  QCString brief           = briefDescription();
  QCString detailed        = documentation();
  LockingPtr<ArgumentList> docArgList = LockingPtr<ArgumentList>(this,m_impl->defArgList);
  if (m_impl->templateMaster)
  {
    brief      = m_impl->templateMaster->briefDescription();
    detailed   = m_impl->templateMaster->documentation();
    docArgList = m_impl->templateMaster->argumentList();
  }
dimitri's avatar
dimitri committed
2043 2044 2045 2046 2047 2048 2049 2050

  /* write brief description */
  if (!brief.isEmpty() && 
      (Config_getBool("REPEAT_BRIEF") || 
       !Config_getBool("BRIEF_MEMBER_DESC")
      ) 
     )  
  { 
dimitri's avatar
dimitri committed
2051 2052 2053 2054 2055
    ol.startParagraph();
    ol.parseDoc(briefFile(),briefLine(),
                getOuterScope()?getOuterScope():container,this,
                brief,FALSE,FALSE,0,TRUE,FALSE);
    ol.endParagraph();
dimitri's avatar
dimitri committed
2056 2057 2058
  }

  /* write detailed description */
dimitri's avatar
dimitri committed
2059 2060
  if (!detailed.isEmpty() || 
      !inbodyDocumentation().isEmpty())
dimitri's avatar
dimitri committed
2061 2062
  { 
    ol.parseDoc(docFile(),docLine(),getOuterScope()?getOuterScope():container,this,detailed+"\n",TRUE,FALSE);
dimitri's avatar
dimitri committed
2063
    if (!inbodyDocumentation().isEmpty())
dimitri's avatar
dimitri committed
2064
    {
dimitri's avatar
dimitri committed
2065
      ol.startParagraph();
dimitri's avatar
dimitri committed
2066
      ol.parseDoc(inbodyFile(),inbodyLine(),getOuterScope()?getOuterScope():container,this,inbodyDocumentation()+"\n",TRUE,FALSE);
dimitri's avatar
dimitri committed
2067
      ol.endParagraph();
mueller's avatar
mueller committed
2068
    }
dimitri's avatar
dimitri committed
2069
  }
dimitri's avatar
dimitri committed
2070
  else if (!brief.isEmpty() && (Config_getBool("REPEAT_BRIEF") ||
dimitri's avatar
dimitri committed
2071 2072
        !Config_getBool("BRIEF_MEMBER_DESC")))
  {
dimitri's avatar
dimitri committed
2073
    if (!inbodyDocumentation().isEmpty())
dimitri's avatar
dimitri committed
2074
    {
dimitri's avatar
dimitri committed
2075
      ol.parseDoc(inbodyFile(),inbodyLine(),getOuterScope()?getOuterScope():container,this,inbodyDocumentation()+"\n",TRUE,FALSE);
dimitri's avatar
dimitri committed
2076
    }
dimitri's avatar
dimitri committed
2077
  }
dimitri's avatar
dimitri committed
2078

mueller's avatar
mueller committed
2079

dimitri's avatar
dimitri committed
2080 2081 2082
  //printf("***** defArgList=%p name=%s docs=%s hasDocs=%d\n",
  //     defArgList, 
  //     defArgList?defArgList->hasDocumentation():-1);
dimitri's avatar
dimitri committed
2083
  if (docArgList!=0 && docArgList->hasDocumentation())
dimitri's avatar
dimitri committed
2084
  {
dimitri's avatar
dimitri committed
2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106
    QCString paramDocs;
    ArgumentListIterator ali(*docArgList);
    Argument *a;
    // convert the parameter documentation into a list of @param commands
    for (ali.toFirst();(a=ali.current());++ali)
    {
      if (a->hasDocumentation())
      {
        QCString direction = extractDirection(a->docs);
        paramDocs+="@param"+direction+" "+a->name+" "+a->docs;
      }
    }
    // feed the result to the documentation parser
    ol.parseDoc(
        docFile(),docLine(),
        getOuterScope()?getOuterScope():container,
        this,         // memberDef
        paramDocs,    // docStr
        TRUE,         // indexWords
        FALSE         // isExample
        );

dimitri's avatar
dimitri committed
2107 2108
  }

dimitri's avatar
dimitri committed
2109
  // For enum, we also write the documented enum values
dimitri's avatar
dimitri committed
2110 2111 2112
  if (isEnumerate())
  {
    bool first=TRUE;
dimitri's avatar
dimitri committed
2113 2114
    LockingPtr<MemberList> fmdl=enumFieldList();
    if (fmdl!=0)
mueller's avatar
mueller committed
2115
    {
dimitri's avatar
dimitri committed
2116 2117
      MemberDef *fmd=fmdl->first();
      while (fmd)
mueller's avatar
mueller committed
2118
      {
dimitri's avatar
dimitri committed
2119
        //printf("Enum %p: isLinkable()=%d\n",fmd,fmd->isLinkable());
dimitri's avatar
dimitri committed
2120
        if (fmd->isLinkable())
mueller's avatar
mueller committed
2121
        {
dimitri's avatar
dimitri committed
2122
          if (first)
mueller's avatar
mueller committed
2123
          {
dimitri's avatar
dimitri committed
2124
            ol.startSimpleSect(BaseOutputDocInterface::EnumValues,0,0,theTranslator->trEnumerationValues()+": ");
dimitri's avatar
dimitri committed
2125
            ol.startDescForItem();
dimitri's avatar
dimitri committed
2126
            ol.startDescTable();
mueller's avatar
mueller committed
2127 2128
          }

dimitri's avatar
dimitri committed
2129 2130
          ol.addIndexItem(fmd->name(),cname);
          ol.addIndexItem(cname,fmd->name());
mueller's avatar
mueller committed
2131

dimitri's avatar
dimitri committed
2132 2133 2134 2135 2136 2137 2138 2139 2140
          //Doxygen::indexList.addIndexItem(
          //                       ciname,                                // level1
          //                       fmd->name(),                           // level2
          //                       separateMemPages ? cfname : cfiname,   // contRef
          //                       cfname,                                // memRef
          //                       fmd->anchor(),                         // anchor
          //                       fmd);                                  // memberdef
          Doxygen::indexList.addIndexItem(container,fmd);

dimitri's avatar
dimitri committed
2141 2142
          //ol.writeListItem();
          ol.startDescTableTitle(); // this enables emphasis!
dimitri's avatar
dimitri committed
2143
          ol.startDoxyAnchor(cfname,cname,fmd->anchor(),fmd->name(),fmd->argsString());
dimitri's avatar
dimitri committed
2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158
          first=FALSE;
          //ol.startEmphasis();
          ol.docify(fmd->name());
          //ol.endEmphasis();
          ol.disableAllBut(OutputGenerator::Man);
          ol.writeString(" ");
          ol.enableAll();
          ol.endDoxyAnchor(cfname,fmd->anchor());
          ol.endDescTableTitle();
          //ol.newParagraph();
          ol.startDescTableData();

          if (!fmd->briefDescription().isEmpty())
          { 
            ol.parseDoc(fmd->briefFile(),fmd->briefLine(),getOuterScope()?getOuterScope():container,fmd,fmd->briefDescription(),TRUE,FALSE);
mueller's avatar
mueller committed
2159
          }
dimitri's avatar
dimitri committed
2160 2161 2162 2163 2164 2165
          // FIXME:PARA
          //if (!fmd->briefDescription().isEmpty() && 
          //    !fmd->documentation().isEmpty())
          //{
          //  ol.newParagraph();
          //}
dimitri's avatar
dimitri committed
2166 2167 2168 2169 2170
          if (!fmd->documentation().isEmpty())
          { 
            ol.parseDoc(fmd->docFile(),fmd->docLine(),getOuterScope()?getOuterScope():container,fmd,fmd->documentation()+"\n",TRUE,FALSE);
          }
          ol.endDescTableData();
mueller's avatar
mueller committed
2171
        }
dimitri's avatar
dimitri committed
2172
        fmd=fmdl->next();
mueller's avatar
mueller committed
2173
      }
mueller's avatar
mueller committed
2174
    }
dimitri's avatar
dimitri committed
2175 2176 2177 2178
    if (!first) 
    { 
      //ol.endItemList(); 
      ol.endDescTable();
dimitri's avatar
dimitri committed
2179
      ol.endDescForItem();
dimitri's avatar
dimitri committed
2180 2181 2182 2183
      ol.endSimpleSect();
      ol.writeChar('\n'); 
    }
  }
dimitri's avatar
dimitri committed
2184

dimitri's avatar
dimitri committed
2185 2186 2187 2188 2189 2190
  MemberDef *bmd=reimplements();
  ClassDef *bcd=0;
  if (bmd && (bcd=bmd->getClassDef()))
  {
    // write class that contains a member that is reimplemented by this one
    if (bcd->isLinkable())
mueller's avatar
mueller committed
2191
    {
dimitri's avatar
dimitri committed
2192
      ol.startParagraph();
dimitri's avatar
dimitri committed
2193 2194
      QCString reimplFromLine; 
      if (bmd->virtualness()!=Pure && bcd->compoundType()!=ClassDef::Interface)
mueller's avatar
mueller committed
2195
      {
dimitri's avatar
dimitri committed
2196
        reimplFromLine = theTranslator->trReimplementedFromList(1);
mueller's avatar
mueller committed
2197
      }
dimitri's avatar
dimitri committed
2198
      else
mueller's avatar
mueller committed
2199
      {
dimitri's avatar
dimitri committed
2200 2201 2202 2203 2204 2205 2206
        reimplFromLine = theTranslator->trImplementedFromList(1);
      }
      int markerPos = reimplFromLine.find("@0");
      if (markerPos!=-1) // should always pass this.
      {
        ol.parseText(reimplFromLine.left(markerPos)); //text left from marker
        if (bmd->isLinkable()) // replace marker with link
dimitri's avatar
dimitri committed
2207
        {
dimitri's avatar
dimitri committed
2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218
          //Definition *bd=bmd->group;
          //if (bd==0) bd=bcd;
          ol.writeObjectLink(bmd->getReference(),bmd->getOutputFileBase(),
              bmd->anchor(),bcd->displayName());

          //ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(),
          //    bmd->anchor(),bcd->name());
          if ( bmd->isLinkableInProject() ) 
          {
            writePageRef(ol,bmd->getOutputFileBase(),bmd->anchor());
          }
dimitri's avatar
dimitri committed
2219 2220 2221
        }
        else
        {
dimitri's avatar
dimitri committed
2222 2223 2224
          ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(),
              0,bcd->displayName());
          if (bcd->isLinkableInProject()/* && !Config_getBool("PDF_HYPERLINKS")*/ )
mueller's avatar
mueller committed
2225
          {
dimitri's avatar
dimitri committed
2226
            writePageRef(ol,bcd->getOutputFileBase(),0);
mueller's avatar
mueller committed
2227
          }
dimitri's avatar
dimitri committed
2228 2229 2230
        }
        ol.parseText(reimplFromLine.right(
              reimplFromLine.length()-markerPos-2)); // text right from marker
mueller's avatar
mueller committed
2231 2232

      }
dimitri's avatar
dimitri committed
2233 2234
      else
      {
dimitri's avatar
dimitri committed
2235
        err("error: translation error: no marker in trReimplementsFromList()\n");
dimitri's avatar
dimitri committed
2236
      }
dimitri's avatar
dimitri committed
2237
      ol.endParagraph();
mueller's avatar
mueller committed
2238
    }
dimitri's avatar
dimitri committed
2239 2240 2241 2242

    //ol.writeString(".");
  }

dimitri's avatar
dimitri committed
2243 2244
  LockingPtr<MemberList> bml=reimplementedBy();
  if (bml!=0)
dimitri's avatar
dimitri committed
2245 2246 2247 2248 2249 2250
  {
    MemberListIterator mli(*bml);
    MemberDef *bmd=0;
    uint count=0;
    ClassDef *bcd=0;
    for (mli.toFirst();(bmd=mli.current()) && (bcd=bmd->getClassDef());++mli)
mueller's avatar
mueller committed
2251
    {
dimitri's avatar
dimitri committed
2252 2253 2254 2255 2256 2257
      // count the members that directly inherit from md and for
      // which the member and class are visible in the docs.
      if ( bmd->isLinkable() && bcd->isLinkable() ) 
      {
        count++;
      }
mueller's avatar
mueller committed
2258
    }
dimitri's avatar
dimitri committed
2259 2260 2261 2262
    if (count>0)
    {
      mli.toFirst();
      // write the list of classes that overwrite this member
dimitri's avatar
dimitri committed
2263
      ol.startParagraph();
dimitri's avatar
dimitri committed
2264

dimitri's avatar
dimitri committed
2265
      QCString reimplInLine;
dimitri's avatar
dimitri committed
2266
      if (m_impl->virt==Pure || (m_impl->classDef && m_impl->classDef->compoundType()==ClassDef::Interface))
dimitri's avatar
dimitri committed
2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293
      {
        reimplInLine = theTranslator->trImplementedInList(count);
      }
      else
      {
        reimplInLine = theTranslator->trReimplementedInList(count);
      }
      static QRegExp marker("@[0-9]+");
      int index=0,newIndex,matchLen;
      // now replace all markers in reimplInLine with links to the classes
      while ((newIndex=marker.match(reimplInLine,index,&matchLen))!=-1)
      {
        ol.parseText(reimplInLine.mid(index,newIndex-index));
        bool ok;
        uint entryIndex = reimplInLine.mid(newIndex+1,matchLen-1).toUInt(&ok);
        //bmd=bml->at(entryIndex);

        count=0;
        // find the entryIndex-th documented entry in the inheritance list.
        for (mli.toLast();(bmd=mli.current()) && (bcd=bmd->getClassDef());--mli)
        {
          if ( bmd->isLinkable() && bcd->isLinkable()) 
          {
            if (count==entryIndex) break;
            count++;
          }
        }
dimitri's avatar
dimitri committed
2294

dimitri's avatar
dimitri committed
2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310
        if (ok && bcd && bmd) // write link for marker
        {
          //ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(),
          //    bmd->anchor(),bcd->name());
          ol.writeObjectLink(bmd->getReference(),bmd->getOutputFileBase(),
              bmd->anchor(),bcd->displayName());

          if (bmd->isLinkableInProject() ) 
          {
            writePageRef(ol,bmd->getOutputFileBase(),bmd->anchor());
          }
        }
        ++mli;
        index=newIndex+matchLen;
      } 
      ol.parseText(reimplInLine.right(reimplInLine.length()-index));
dimitri's avatar
dimitri committed
2311
      ol.endParagraph();
dimitri's avatar
dimitri committed
2312 2313
    }
  }
dimitri's avatar
dimitri committed
2314

dimitri's avatar
dimitri committed
2315 2316 2317 2318
  // write the list of examples that use this member
  if (hasExamples())
  {
    ol.startSimpleSect(BaseOutputDocInterface::Examples,0,0,theTranslator->trExamples()+": ");
dimitri's avatar
dimitri committed
2319
    ol.startDescForItem();
dimitri's avatar
dimitri committed
2320
    writeExample(ol,m_impl->exampleSDict);
dimitri's avatar
dimitri committed
2321
    ol.endDescForItem();
dimitri's avatar
dimitri committed
2322 2323
    ol.endSimpleSect();
  }
dimitri's avatar
dimitri committed
2324

dimitri's avatar
dimitri committed
2325 2326 2327 2328 2329
  if (m_impl->typeConstraints)
  {
    writeTypeConstraints(ol,this,m_impl->typeConstraints);
  }

dimitri's avatar
dimitri committed
2330 2331 2332 2333 2334
  // write reference to the source
  writeSourceDef(ol,cname);
  writeSourceRefs(ol,cname);
  writeSourceReffedBy(ol,cname);
  writeInlineCode(ol,cname);
mueller's avatar
mueller committed
2335

dimitri's avatar
dimitri committed
2336
  // write call graph
dimitri's avatar
dimitri committed
2337
  if ((m_impl->hasCallGraph || Config_getBool("CALL_GRAPH")) 
dimitri's avatar
dimitri committed
2338
      && (isFunction() || isSlot() || isSignal()) && Config_getBool("HAVE_DOT")
dimitri's avatar
dimitri committed
2339 2340
     )
  {
dimitri's avatar
dimitri committed
2341
    DotCallGraph callGraph(this,FALSE);
dimitri's avatar
dimitri committed
2342
    if (!callGraph.isTrivial() && !callGraph.isTooBig())
dimitri's avatar
dimitri committed
2343
    {
dimitri's avatar
dimitri committed
2344
      msg("Generating call graph for function %s\n",qPrint(qualifiedName()));
dimitri's avatar
dimitri committed
2345
      ol.disable(OutputGenerator::Man);
dimitri's avatar
dimitri committed
2346
      ol.startParagraph();
dimitri's avatar
dimitri committed
2347 2348 2349
      ol.startCallGraph();
      ol.parseText(theTranslator->trCallGraph());
      ol.endCallGraph(callGraph);
dimitri's avatar
dimitri committed
2350
      ol.endParagraph(); 
dimitri's avatar
dimitri committed
2351
      ol.enableAll();
dimitri's avatar
dimitri committed
2352
    }
mueller's avatar
mueller committed
2353
  }
dimitri's avatar
dimitri committed
2354
  if ((m_impl->hasCallerGraph || Config_getBool("CALLER_GRAPH")) 
dimitri's avatar
dimitri committed
2355
      && (isFunction() || isSlot() || isSignal()) && Config_getBool("HAVE_DOT")
dimitri's avatar
dimitri committed
2356 2357
     )
  {
dimitri's avatar
dimitri committed
2358 2359
    DotCallGraph callerGraph(this, TRUE);
    if (!callerGraph.isTrivial() && !callerGraph.isTooBig())
dimitri's avatar
dimitri committed
2360
    {
dimitri's avatar
dimitri committed
2361
      msg("Generating caller graph for function %s\n",qPrint(qualifiedName()));
dimitri's avatar
dimitri committed
2362
      ol.disable(OutputGenerator::Man);
dimitri's avatar
dimitri committed
2363
      ol.startParagraph();
dimitri's avatar
dimitri committed
2364 2365 2366
      ol.startCallGraph();
      ol.parseText(theTranslator->trCallerGraph());
      ol.endCallGraph(callerGraph);
dimitri's avatar
dimitri committed
2367
      ol.endParagraph();
dimitri's avatar
dimitri committed
2368 2369 2370
      ol.enableAll();
    }
  }
dimitri's avatar
dimitri committed
2371

dimitri's avatar
dimitri committed
2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382
  if (Doxygen::userComments)
  {
    ol.pushGeneratorState();
    ol.disableAllBut(OutputGenerator::Html);
    QCString cmd = "<? $root=$_SERVER['DOCUMENT_ROOT']; "
                   "passthru(\"$root/doxynotes --lookup "+
                   getOutputFileBase()+":"+anchor()+"\") ?>";
    ol.writeString(cmd);
    ol.popGeneratorState();
  }

dimitri's avatar
dimitri committed
2383 2384
  ol.endIndent();

dimitri's avatar
dimitri committed
2385 2386 2387 2388
  // enable LaTeX again
  //if (Config_getBool("EXTRACT_ALL") && !hasDocs) ol.enable(OutputGenerator::Latex); 
  ol.popGeneratorState();

dimitri's avatar
dimitri committed
2389 2390
  //------------------------------------------------

dimitri's avatar
dimitri committed
2391 2392
  if (!Config_getBool("EXTRACT_ALL") &&
      Config_getBool("WARN_IF_UNDOCUMENTED") &&
dimitri's avatar
dimitri committed
2393 2394
      Config_getBool("WARN_NO_PARAMDOC") &&
      !Doxygen::suppressDocWarnings)
dimitri's avatar
dimitri committed
2395 2396 2397 2398
  {
    if (!hasDocumentedParams())
    {
      warn_doc_error(docFile(),docLine(),
dimitri's avatar
dimitri committed
2399 2400
          "warning: parameters of member %s are not (all) documented",
          qPrint(qualifiedName()));
dimitri's avatar
dimitri committed
2401
    }
dimitri's avatar
dimitri committed
2402
    if (!hasDocumentedReturnType() && isFunction() && hasDocumentation())
dimitri's avatar
dimitri committed
2403 2404
    {
      warn_doc_error(docFile(),docLine(),
dimitri's avatar
dimitri committed
2405 2406
          "warning: return type of member %s is not documented",
          qPrint(qualifiedName()));
dimitri's avatar
dimitri committed
2407 2408 2409
    }
  }

mueller's avatar
mueller committed
2410 2411
}

dimitri's avatar
dimitri committed
2412 2413
QCString MemberDef::memberTypeName() const
{
dimitri's avatar
dimitri committed
2414 2415
  makeResident();
  switch (m_impl->mtype)
dimitri's avatar
dimitri committed
2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432
  {
    case Define:      return "define";
    case Function:    return "function";
    case Variable:    return "variable";
    case Typedef:     return "typedef";
    case Enumeration: return "enumeration"; 
    case EnumValue:   return "enumvalue";
    case Signal:      return "signal";
    case Slot:        return "slot";
    case Friend:      return "friend";
    case DCOP:        return "dcop";
    case Property:    return "property";
    case Event:       return "event";
    default:          return "unknown";
  }
}

mueller's avatar
mueller committed
2433 2434
void MemberDef::warnIfUndocumented()
{
dimitri's avatar
dimitri committed
2435 2436
  makeResident();
  if (m_impl->memberGroup) return;
dimitri's avatar
dimitri committed
2437 2438
  ClassDef     *cd = getClassDef();
  NamespaceDef *nd = getNamespaceDef();
mueller's avatar
mueller committed
2439
  FileDef      *fd = getFileDef();
dimitri's avatar
dimitri committed
2440
  GroupDef     *gd = getGroupDef();
mueller's avatar
mueller committed
2441 2442 2443 2444 2445 2446
  Definition *d=0;
  const char *t=0;
  if (cd) 
    t="class", d=cd; 
  else if (nd) 
    t="namespace", d=nd; 
dimitri's avatar
dimitri committed
2447
  else if (gd)
dimitri's avatar
dimitri committed
2448
    t="group", d=gd;
dimitri's avatar
dimitri committed
2449 2450
  else
    t="file", d=fd;
dimitri's avatar
dimitri committed
2451
  static bool extractAll = Config_getBool("EXTRACT_ALL");
mueller's avatar
mueller committed
2452

dimitri's avatar
dimitri committed
2453 2454 2455 2456
  //printf("warnIfUndoc: d->isLinkable()=%d isLinkable()=%d "
  //       "isDocumentedFriendClass()=%d name()=%s prot=%d\n",
  //       d->isLinkable(),isLinkable(),isDocumentedFriendClass(),
  //       name().data(),prot);
dimitri's avatar
dimitri committed
2457
  if ((!hasUserDocumentation() && !extractAll) &&
dimitri's avatar
dimitri committed
2458
      !isFriendClass() && 
dimitri's avatar
dimitri committed
2459
      name().find('@')==-1 && d->name().find('@')==-1 &&
dimitri's avatar
dimitri committed
2460
      (m_impl->prot!=Private || Config_getBool("EXTRACT_PRIVATE"))
dimitri's avatar
dimitri committed
2461 2462
     )
  {
dimitri's avatar
dimitri committed
2463 2464
    warn_undoc(getDefFileName(),getDefLine(),"warning: Member %s%s (%s) of %s %s is not documented.",
         qPrint(name()),qPrint(argsString()),qPrint(memberTypeName()),t,qPrint(d->name()));
dimitri's avatar
dimitri committed
2465
  }
mueller's avatar
mueller committed
2466 2467 2468
}


dimitri's avatar
dimitri committed
2469

dimitri's avatar
dimitri committed
2470
bool MemberDef::isFriendClass() const
dimitri's avatar
dimitri committed
2471
{
dimitri's avatar
dimitri committed
2472
  makeResident();
dimitri's avatar
dimitri committed
2473
  return (isFriend() && 
dimitri's avatar
dimitri committed
2474 2475
         (m_impl->type=="friend class" || m_impl->type=="friend struct" || 
          m_impl->type=="friend union"));
dimitri's avatar
dimitri committed
2476 2477 2478 2479
}

bool MemberDef::isDocumentedFriendClass() const
{
dimitri's avatar
dimitri committed
2480
  makeResident();
dimitri's avatar
dimitri committed
2481 2482 2483 2484 2485 2486
  ClassDef *fcd=0;
  QCString baseName=name();
  int i=baseName.find('<');
  if (i!=-1) baseName=baseName.left(i);
  return (isFriendClass() &&
         (fcd=getClass(baseName)) && fcd->isLinkable()); 
dimitri's avatar
dimitri committed
2487 2488
}

dimitri's avatar
dimitri committed
2489
bool MemberDef::hasDocumentation() const
dimitri's avatar
dimitri committed
2490
{ 
dimitri's avatar
dimitri committed
2491
  makeResident();
dimitri's avatar
dimitri committed
2492
  return Definition::hasDocumentation() || 
dimitri's avatar
dimitri committed
2493 2494
         (m_impl->mtype==Enumeration && m_impl->docEnumValues) ||  // has enum values
         (m_impl->defArgList!=0 && m_impl->defArgList->hasDocumentation()); // has doc arguments
dimitri's avatar
dimitri committed
2495
}
dimitri's avatar
dimitri committed
2496

dimitri's avatar
dimitri committed
2497
#if 0
dimitri's avatar
dimitri committed
2498 2499
bool MemberDef::hasUserDocumentation() const
{
dimitri's avatar
dimitri committed
2500
  bool hasDocs = Definition::hasUserDocumentation();
dimitri's avatar
dimitri committed
2501 2502
  return hasDocs;
}
dimitri's avatar
dimitri committed
2503
#endif
dimitri's avatar
dimitri committed
2504 2505


dimitri's avatar
dimitri committed
2506 2507
void MemberDef::setMemberGroup(MemberGroup *grp)
{
dimitri's avatar
dimitri committed
2508 2509
  makeResident();
  m_impl->memberGroup = grp;
dimitri's avatar
dimitri committed
2510
}
dimitri's avatar
dimitri committed
2511 2512 2513

bool MemberDef::visibleMemberGroup(bool hideNoHeader) 
{ 
dimitri's avatar
dimitri committed
2514 2515 2516
  makeResident();
  return m_impl->memberGroup!=0 && 
          (!hideNoHeader || m_impl->memberGroup->header()!="[NOHEADER]"); 
dimitri's avatar
dimitri committed
2517
}
dimitri's avatar
dimitri committed
2518 2519 2520

QCString MemberDef::getScopeString() const
{
dimitri's avatar
dimitri committed
2521
  makeResident();
dimitri's avatar
dimitri committed
2522
  QCString result;
dimitri's avatar
dimitri committed
2523 2524
  if (getClassDef()) result=getClassDef()->displayName();
  else if (getNamespaceDef()) result=getNamespaceDef()->displayName();
dimitri's avatar
dimitri committed
2525 2526
  return result;
}
dimitri's avatar
dimitri committed
2527

dimitri's avatar
dimitri committed
2528
#if 0
dimitri's avatar
dimitri committed
2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550
static QCString escapeAnchor(const QCString &anchor)
{
  QCString result;
  int l = anchor.length(),i;
  for (i=0;i<l;i++)
  {
    char c = anchor.at(i);
    if ((c>='a' && c<='z') || (c>='A' && c<='Z'))
    {
      result+=c;
    }
    else
    {
      static char hexStr[]="0123456789ABCDEF";
      char escChar[]={ '_', 0, 0, 0 };
      escChar[1]=hexStr[c>>4];
      escChar[2]=hexStr[c&0xf];
      result+=escChar;
    }
  }
  return result;
}
dimitri's avatar
dimitri committed
2551
#endif
dimitri's avatar
dimitri committed
2552

dimitri's avatar
dimitri committed
2553 2554
void MemberDef::setAnchor(const char *a)
{
dimitri's avatar
dimitri committed
2555
  makeResident();
dimitri's avatar
dimitri committed
2556 2557 2558
  //anc=a;
  a=a;
  QCString memAnchor = name();
dimitri's avatar
dimitri committed
2559
  if (!m_impl->args.isEmpty()) memAnchor+=m_impl->args;
dimitri's avatar
dimitri committed
2560 2561 2562 2563

  // include definition as well, to distinguish between two template
  // specializations that only differ in the template parameters.
  memAnchor.prepend(definition());
dimitri's avatar
dimitri committed
2564 2565 2566 2567 2568 2569
  
  // convert to md5 hash
  uchar md5_sig[16];
  QCString sigStr(33);
  MD5Buffer((const unsigned char *)memAnchor.data(),memAnchor.length(),md5_sig);
  MD5SigToString(md5_sig,sigStr.data(),33);
dimitri's avatar
dimitri committed
2570
  m_impl->anc = "a"+sigStr;
dimitri's avatar
dimitri committed
2571 2572
}

dimitri's avatar
dimitri committed
2573 2574 2575
void MemberDef::setGroupDef(GroupDef *gd,Grouping::GroupPri_t pri,
                            const QCString &fileName,int startLine,
                            bool hasDocs,MemberDef *member)
dimitri's avatar
dimitri committed
2576
{
dimitri's avatar
dimitri committed
2577
  //printf("%s MemberDef::setGroupDef(%s)\n",name().data(),gd->name().data());
dimitri's avatar
dimitri committed
2578 2579 2580 2581 2582 2583 2584
  makeResident();
  m_impl->group=gd;
  m_impl->grouppri=pri;
  m_impl->groupFileName=fileName;
  m_impl->groupStartLine=startLine;
  m_impl->groupHasDocs=hasDocs;
  m_impl->groupMember=member;
dimitri's avatar
dimitri committed
2585
  m_isLinkableCached = 0; 
dimitri's avatar
dimitri committed
2586
}
dimitri's avatar
dimitri committed
2587 2588 2589

void MemberDef::setEnumScope(MemberDef *md) 
{ 
dimitri's avatar
dimitri committed
2590 2591 2592
  makeResident();
  m_impl->enumScope=md; 
  if (md->getGroupDef())
dimitri's avatar
dimitri committed
2593
  {
dimitri's avatar
dimitri committed
2594 2595 2596 2597 2598
    m_impl->group=md->getGroupDef();
    m_impl->grouppri=md->getGroupPri();
    m_impl->groupFileName=md->getGroupFileName();
    m_impl->groupStartLine=md->getGroupStartLine();
    m_impl->groupHasDocs=md->getGroupHasDocs();
dimitri's avatar
dimitri committed
2599
    m_isLinkableCached = 0; 
dimitri's avatar
dimitri committed
2600 2601 2602
  }
}

dimitri's avatar
dimitri committed
2603 2604
void MemberDef::setMemberClass(ClassDef *cd)     
{ 
dimitri's avatar
dimitri committed
2605 2606
  makeResident();
  m_impl->classDef=cd; 
dimitri's avatar
dimitri committed
2607 2608
  m_isLinkableCached = 0; 
  m_isConstructorCached = 0; 
dimitri's avatar
dimitri committed
2609 2610 2611 2612 2613
  setOuterScope(cd); 
}

void MemberDef::setNamespace(NamespaceDef *nd) 
{ 
dimitri's avatar
dimitri committed
2614 2615
  makeResident();
  m_impl->nspace=nd; 
dimitri's avatar
dimitri committed
2616 2617 2618
  setOuterScope(nd); 
}

dimitri's avatar
dimitri committed
2619 2620 2621
MemberDef *MemberDef::createTemplateInstanceMember(
        ArgumentList *formalArgs,ArgumentList *actualArgs)
{
dimitri's avatar
dimitri committed
2622 2623
  makeResident();
  LockingPtr<MemberDef> lock(this,this);
dimitri's avatar
dimitri committed
2624 2625
  //printf("  Member %s %s %s\n",typeString(),name().data(),argsString());
  ArgumentList *actualArgList = 0;
dimitri's avatar
dimitri committed
2626
  if (m_impl->defArgList)
dimitri's avatar
dimitri committed
2627 2628
  {
    actualArgList = new ArgumentList;
dimitri's avatar
dimitri committed
2629
    ArgumentListIterator ali(*m_impl->defArgList);
dimitri's avatar
dimitri committed
2630 2631 2632 2633 2634 2635 2636
    Argument *arg;
    for (;(arg=ali.current());++ali)
    {
      Argument *actArg = new Argument(*arg);
      actArg->type = substituteTemplateArgumentsInString(actArg->type,formalArgs,actualArgs);
      actualArgList->append(actArg);
    }
dimitri's avatar
dimitri committed
2637 2638 2639
    actualArgList->constSpecifier    = m_impl->defArgList->constSpecifier;
    actualArgList->volatileSpecifier = m_impl->defArgList->volatileSpecifier;
    actualArgList->pureSpecifier     = m_impl->defArgList->pureSpecifier;
dimitri's avatar
dimitri committed
2640 2641
  }

dimitri's avatar
dimitri committed
2642 2643 2644 2645 2646 2647
  QCString methodName=name();
  if (methodName.left(9)=="operator ") // conversion operator
  {
    methodName=substituteTemplateArgumentsInString(methodName,formalArgs,actualArgs);
  }

dimitri's avatar
dimitri committed
2648 2649
  MemberDef *imd = new MemberDef(
                       getDefFileName(),getDefLine(),
dimitri's avatar
dimitri committed
2650
                       substituteTemplateArgumentsInString(m_impl->type,formalArgs,actualArgs), 
dimitri's avatar
dimitri committed
2651
                       methodName, 
dimitri's avatar
dimitri committed
2652 2653 2654
                       substituteTemplateArgumentsInString(m_impl->args,formalArgs,actualArgs), 
                       m_impl->exception, m_impl->prot,
                       m_impl->virt, m_impl->stat, m_impl->related, m_impl->mtype, 0, 0
dimitri's avatar
dimitri committed
2655
                   );
dimitri's avatar
dimitri committed
2656 2657
  imd->setArgumentList(actualArgList);
  imd->setDefinition(substituteTemplateArgumentsInString(m_impl->def,formalArgs,actualArgs));
dimitri's avatar
dimitri committed
2658 2659
  imd->setBodyDef(getBodyDef());
  imd->setBodySegment(getStartBodyLine(),getEndBodyLine());
dimitri's avatar
dimitri committed
2660
  //imd->setBodyMember(this);
dimitri's avatar
dimitri committed
2661

dimitri's avatar
dimitri committed
2662
  // TODO: init other member variables (if needed).
dimitri's avatar
dimitri committed
2663
  // TODO: reimplemented info
dimitri's avatar
dimitri committed
2664 2665 2666
  return imd; 
}

dimitri's avatar
dimitri committed
2667 2668
bool MemberDef::hasOneLineInitializer() const
{
dimitri's avatar
dimitri committed
2669
  makeResident();
dimitri's avatar
dimitri committed
2670
  //printf("%s: init=%s, initLines=%d maxInitLines=%d userInitLines=%d\n",
dimitri's avatar
dimitri committed
2671 2672
  //    name().data(),m_impl->initializer.data(),m_impl->initLines,
  //    m_impl->maxInitLines,m_impl->userInitLines);
dimitri's avatar
dimitri committed
2673 2674
  return !m_impl->initializer.isEmpty() && m_impl->initLines==0 && // one line initializer
         ((m_impl->maxInitLines>0 && m_impl->userInitLines==-1) || m_impl->userInitLines>0); // enabled by default or explicitly
dimitri's avatar
dimitri committed
2675 2676 2677 2678
}

bool MemberDef::hasMultiLineInitializer() const
{
dimitri's avatar
dimitri committed
2679
  makeResident();
dimitri's avatar
dimitri committed
2680 2681
  //printf("initLines=%d userInitLines=%d maxInitLines=%d\n",
  //    initLines,userInitLines,maxInitLines);
dimitri's avatar
dimitri committed
2682 2683 2684
  return m_impl->initLines>0 && 
         ((m_impl->initLines<m_impl->maxInitLines && m_impl->userInitLines==-1) // implicitly enabled
          || m_impl->initLines<m_impl->userInitLines // explicitly enabled
dimitri's avatar
dimitri committed
2685 2686
         );
}
dimitri's avatar
dimitri committed
2687 2688 2689

void MemberDef::setInitializer(const char *initializer)    
{ 
dimitri's avatar
dimitri committed
2690 2691 2692 2693 2694 2695
  makeResident();
  m_impl->initializer=initializer; 
  int p=m_impl->initializer.length()-1;
  while (p>=0 && isspace((uchar)m_impl->initializer.at(p))) p--;
  m_impl->initializer=m_impl->initializer.left(p+1);
  m_impl->initLines=m_impl->initializer.contains('\n');
dimitri's avatar
dimitri committed
2696
}
dimitri's avatar
dimitri committed
2697

dimitri's avatar
dimitri committed
2698
void MemberDef::addListReference(Definition *)
dimitri's avatar
dimitri committed
2699
{
dimitri's avatar
dimitri committed
2700
  makeResident();
dimitri's avatar
dimitri committed
2701
  static bool optimizeOutputForC = Config_getBool("OPTIMIZE_OUTPUT_FOR_C");
dimitri's avatar
dimitri committed
2702
  //static bool hideScopeNames     = Config_getBool("HIDE_SCOPE_NAMES");
dimitri's avatar
dimitri committed
2703
  static bool optimizeOutputJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA");
dimitri's avatar
dimitri committed
2704
  static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");  
dimitri's avatar
dimitri committed
2705
  visited=TRUE;
dimitri's avatar
dimitri committed
2706
  if (!isLinkableInProject()) return;
dimitri's avatar
dimitri committed
2707
  QCString memLabel;
dimitri's avatar
dimitri committed
2708
  if (optimizeOutputForC) 
dimitri's avatar
dimitri committed
2709 2710 2711
  {
    memLabel=theTranslator->trGlobal(TRUE,TRUE);
  }
dimitri's avatar
dimitri committed
2712 2713 2714 2715
  else if (fortranOpt)
  {
    memLabel=theTranslator->trSubprogram(TRUE,TRUE);
  }
dimitri's avatar
dimitri committed
2716 2717 2718 2719
  else
  {
    memLabel=theTranslator->trMember(TRUE,TRUE);
  }
dimitri's avatar
dimitri committed
2720
  QCString memName = name();
dimitri's avatar
dimitri committed
2721
  Definition *pd=getOuterScope();
dimitri's avatar
dimitri committed
2722 2723 2724
  QCString pdName = pd->definitionType()==Definition::TypeClass ? 
                    ((ClassDef*)pd)->displayName() : pd->name();
  QCString sep = optimizeOutputJava ? "." : "::";
dimitri's avatar
dimitri committed
2725
  QCString memArgs;
dimitri's avatar
dimitri committed
2726 2727
  if (!isRelated() 
      /* && commented out as a result of bug 597016
dimitri's avatar
dimitri committed
2728
      (
dimitri's avatar
dimitri committed
2729
       (!hideScopeNames &&                    // there is a scope
dimitri's avatar
dimitri committed
2730
        pd && pd!=Doxygen::globalScope)       // and we can show it
dimitri's avatar
dimitri committed
2731 2732
       ||
       (pd=getClassDef())                     // it's a class so we
dimitri's avatar
dimitri committed
2733
                                              // show the scope anyway
dimitri's avatar
dimitri committed
2734
      )
dimitri's avatar
dimitri committed
2735
      */
dimitri's avatar
dimitri committed
2736
     )
dimitri's avatar
dimitri committed
2737
  {
dimitri's avatar
dimitri committed
2738 2739 2740 2741
    if (isObjCMethod())
    {
      memName = "[" + pd->name() + " " + name() + "]";
    }
dimitri's avatar
dimitri committed
2742
    else 
dimitri's avatar
dimitri committed
2743
    {
dimitri's avatar
dimitri committed
2744
      if (pd!=Doxygen::globalScope) memName.prepend(pdName+sep);
dimitri's avatar
dimitri committed
2745
      memArgs = argsString();
dimitri's avatar
dimitri committed
2746 2747
    }
  }
dimitri's avatar
dimitri committed
2748 2749
  LockingPtr< QList<ListItemInfo> > xrefItems = xrefListItems();
  if (xrefItems!=0)
dimitri's avatar
dimitri committed
2750
  {
dimitri's avatar
dimitri committed
2751
    addRefItem(xrefItems.pointer(),
dimitri's avatar
dimitri committed
2752
        qualifiedName()+argsString(), // argsString is needed for overloaded functions (see bug 609624)
dimitri's avatar
dimitri committed
2753
        memLabel,
dimitri's avatar
dimitri committed
2754
        getOutputFileBase()+"#"+anchor(),memName,memArgs);
dimitri's avatar
dimitri committed
2755
  }
dimitri's avatar
dimitri committed
2756 2757
}

dimitri's avatar
dimitri committed
2758 2759
MemberList *MemberDef::getSectionList(Definition *d) const 
{ 
dimitri's avatar
dimitri committed
2760 2761 2762 2763
  makeResident();
  char key[20];
  sprintf(key,"%p",d);
  return (d!=0 && m_impl->classSectionSDict) ? m_impl->classSectionSDict->find(key) : 0;
dimitri's avatar
dimitri committed
2764 2765 2766 2767
}

void MemberDef::setSectionList(Definition *d, MemberList *sl)   
{ 
dimitri's avatar
dimitri committed
2768
  makeResident();
dimitri's avatar
dimitri committed
2769
  //printf("MemberDef::setSectionList(%p,%p) name=%s\n",d,sl,name().data());
dimitri's avatar
dimitri committed
2770 2771 2772 2773 2774 2775 2776
  char key[20];
  sprintf(key,"%p",d);
  if (m_impl->classSectionSDict==0) 
  {
    m_impl->classSectionSDict = new SDict<MemberList>(7);
  }
  m_impl->classSectionSDict->append(key,sl);
dimitri's avatar
dimitri committed
2777 2778
}

dimitri's avatar
dimitri committed
2779
Specifier MemberDef::virtualness(int count) const
dimitri's avatar
dimitri committed
2780
{
dimitri's avatar
dimitri committed
2781 2782 2783
  if (count>25) 
  {
     warn(getDefFileName(),getDefLine(),
dimitri's avatar
dimitri committed
2784 2785
       "warning: Internal inconsistency: recursion detected in overload relation for member %s!"
       ,qPrint(name())
dimitri's avatar
dimitri committed
2786 2787 2788
      );
     return Normal;
  }
dimitri's avatar
dimitri committed
2789 2790
  makeResident();
  Specifier v = m_impl->virt;
dimitri's avatar
dimitri committed
2791 2792 2793
  MemberDef *rmd = reimplements();
  while (rmd && v==Normal)
  {
dimitri's avatar
dimitri committed
2794
    v = rmd->virtualness(count+1)==Normal ? Normal : Virtual;
dimitri's avatar
dimitri committed
2795 2796 2797 2798 2799
    rmd = rmd->reimplements();
  }
  return v;
}

dimitri's avatar
dimitri committed
2800 2801
void MemberDef::_computeIsConstructor()
{
dimitri's avatar
dimitri committed
2802
  makeResident();
dimitri's avatar
dimitri committed
2803
  m_isConstructorCached=1; // FALSE
dimitri's avatar
dimitri committed
2804
  if (m_impl->classDef) 
dimitri's avatar
dimitri committed
2805
  {
dimitri's avatar
dimitri committed
2806
    if (m_impl->isDMember) // for D
dimitri's avatar
dimitri committed
2807
    {
dimitri's avatar
dimitri committed
2808 2809
      m_isConstructorCached = name()=="this" ? 2 : 1;
      return;
dimitri's avatar
dimitri committed
2810
    }
dimitri's avatar
dimitri committed
2811 2812
    else if (m_impl->fileDef && 
             getLanguageFromFileName(m_impl->fileDef->name())==SrcLangExt_PHP)
dimitri's avatar
dimitri committed
2813
    {                // for PHP
dimitri's avatar
dimitri committed
2814 2815
      m_isConstructorCached = name()=="__construct" ? 2 : 1;
      return;
dimitri's avatar
dimitri committed
2816
    }
dimitri's avatar
dimitri committed
2817 2818 2819 2820 2821 2822 2823
    else if (name()=="__init__" && m_impl->fileDef &&
             getLanguageFromFileName(m_impl->fileDef->name())==SrcLangExt_Python) 
               // for Python
    {
      m_isConstructorCached=2; // TRUE
      return;
    }
dimitri's avatar
dimitri committed
2824 2825
    else // for other languages
    {
dimitri's avatar
dimitri committed
2826
      QCString locName = m_impl->classDef->localName();
dimitri's avatar
dimitri committed
2827 2828 2829
      int i=locName.find('<');
      if (i==-1) // not a template class
      {
dimitri's avatar
dimitri committed
2830
        m_isConstructorCached = name()==locName ? 2 : 1;
dimitri's avatar
dimitri committed
2831 2832 2833
      }
      else
      {
dimitri's avatar
dimitri committed
2834
        m_isConstructorCached = name()==locName.left(i) ? 2 : 1;
dimitri's avatar
dimitri committed
2835
      }
dimitri's avatar
dimitri committed
2836
      return;
dimitri's avatar
dimitri committed
2837 2838
    }
  }
dimitri's avatar
dimitri committed
2839 2840
}

dimitri's avatar
dimitri committed
2841
bool MemberDef::isConstructor() const            
dimitri's avatar
dimitri committed
2842
{ 
dimitri's avatar
dimitri committed
2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854
  if (m_isConstructorCached==0)
  {
    MemberDef *that = (MemberDef*)this;
    that->_computeIsConstructor();
  }
  ASSERT(m_isConstructorCached>0);
  return m_isConstructorCached==2;

}

void MemberDef::_computeIsDestructor()
{
dimitri's avatar
dimitri committed
2855
  makeResident();
dimitri's avatar
dimitri committed
2856
  bool isDestructor;
dimitri's avatar
dimitri committed
2857
  if (m_impl->isDMember) // for D
dimitri's avatar
dimitri committed
2858
  {
dimitri's avatar
dimitri committed
2859
    isDestructor = name()=="~this";
dimitri's avatar
dimitri committed
2860
  }
dimitri's avatar
dimitri committed
2861 2862
  else if (m_impl->fileDef && 
      getLanguageFromFileName(m_impl->fileDef->name())==SrcLangExt_PHP)
dimitri's avatar
dimitri committed
2863
  {                // for PHP
dimitri's avatar
dimitri committed
2864
    isDestructor = name()=="__destruct";
dimitri's avatar
dimitri committed
2865
  }
dimitri's avatar
dimitri committed
2866 2867 2868 2869 2870 2871
  else if (name()=="__del__" && m_impl->fileDef &&
           getLanguageFromFileName(m_impl->fileDef->name())==SrcLangExt_Python) 
               // for Python
  {
    isDestructor=TRUE;
  }
dimitri's avatar
dimitri committed
2872 2873
  else // other languages
  {
dimitri's avatar
dimitri committed
2874 2875
    isDestructor =
           (name().find('~')!=-1 || name().find('!')!=-1)  // The ! is for C++/CLI
dimitri's avatar
dimitri committed
2876
           && name().find("operator")==-1; 
dimitri's avatar
dimitri committed
2877
  }
dimitri's avatar
dimitri committed
2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890
  m_isDestructorCached = isDestructor ? 2 : 1;
}

bool MemberDef::isDestructor() const
{ 
  if (m_isDestructorCached==0)
  {
    MemberDef *that=(MemberDef*)this;
    that->_computeIsDestructor();
  }
  ASSERT(m_isDestructorCached>0);
  return m_isDestructorCached==2;

dimitri's avatar
dimitri committed
2891 2892
}

dimitri's avatar
dimitri committed
2893 2894 2895
void MemberDef::writeEnumDeclaration(OutputList &typeDecl,
     ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd)
{
dimitri's avatar
dimitri committed
2896 2897
  makeResident();
  LockingPtr<MemberDef> lock(this,this);
dimitri's avatar
dimitri committed
2898 2899
  int enumMemCount=0;

dimitri's avatar
dimitri committed
2900
  QList<MemberDef> *fmdl=m_impl->enumFields;
dimitri's avatar
dimitri committed
2901 2902 2903 2904 2905 2906 2907 2908 2909 2910
  uint numVisibleEnumValues=0;
  if (fmdl)
  {
    MemberDef *fmd=fmdl->first();
    while (fmd)
    {
      if (fmd->isBriefSectionVisible()) numVisibleEnumValues++;
      fmd=fmdl->next();
    }
  }
dimitri's avatar
dimitri committed
2911 2912 2913 2914
  if (numVisibleEnumValues==0 && !isBriefSectionVisible()) 
  {
    return;
  }
dimitri's avatar
dimitri committed
2915 2916 2917 2918 2919 2920 2921 2922

  QCString n = name();
  int i=n.findRev("::");
  if (i!=-1) n=n.right(n.length()-i-2); // strip scope (TODO: is this needed?)
  if (n[0]!='@') // not an anonymous enum
  {
    if (isLinkableInProject() || hasDocumentedEnumValues())
    {
dimitri's avatar
dimitri committed
2923
      if (!Config_getString("GENERATE_TAGFILE").isEmpty() && !isReference())
dimitri's avatar
dimitri committed
2924 2925 2926
      {
        Doxygen::tagFile << "    <member kind=\"enumeration\">" << endl;
        Doxygen::tagFile << "      <name>" << convertToXML(name()) << "</name>" << endl; 
dimitri's avatar
dimitri committed
2927
        Doxygen::tagFile << "      <anchorfile>" << convertToXML(getOutputFileBase()+Doxygen::htmlFileExtension) << "</anchorfile>" << endl;
dimitri's avatar
dimitri committed
2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942
        Doxygen::tagFile << "      <anchor>" << convertToXML(anchor()) << "</anchor>" << endl; 
        Doxygen::tagFile << "      <arglist>" << convertToXML(argsString()) << "</arglist>" << endl; 
        Doxygen::tagFile << "    </member>" << endl;
      }
      writeLink(typeDecl,cd,nd,fd,gd);
    }
    else
    {
      typeDecl.startBold();
      typeDecl.docify(n);
      typeDecl.endBold();
    }
    typeDecl.writeChar(' ');
  }

dimitri's avatar
dimitri committed
2943 2944
  uint enumValuesPerLine = (uint)Config_getInt("ENUM_VALUES_PER_LINE");
  if (numVisibleEnumValues>0 && enumValuesPerLine>0)
dimitri's avatar
dimitri committed
2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961
  {
    typeDecl.docify("{ ");
    if (fmdl)
    {
      MemberDef *fmd=fmdl->first();
      bool fmdVisible = fmd->isBriefSectionVisible();
      while (fmd)
      {
        if (fmdVisible)
        {
          /* in html we start a new line after a number of items */
          if (numVisibleEnumValues>enumValuesPerLine
              && (enumMemCount%enumValuesPerLine)==0
             )
          {
            typeDecl.pushGeneratorState();
            typeDecl.disableAllBut(OutputGenerator::Html);
dimitri's avatar
dimitri committed
2962
            typeDecl.enable(OutputGenerator::Latex);
dimitri's avatar
dimitri committed
2963
            typeDecl.lineBreak(); 
dimitri's avatar
dimitri committed
2964
            typeDecl.disable(OutputGenerator::Latex);
dimitri's avatar
dimitri committed
2965
            typeDecl.writeString("&#160;&#160;");
dimitri's avatar
dimitri committed
2966 2967 2968 2969 2970
            typeDecl.popGeneratorState();
          }

          if (fmd->hasDocumentation()) // enum value has docs
          {
dimitri's avatar
dimitri committed
2971
            if (!Config_getString("GENERATE_TAGFILE").isEmpty() && !fmd->isReference())
dimitri's avatar
dimitri committed
2972 2973 2974
            {
              Doxygen::tagFile << "    <member kind=\"enumvalue\">" << endl;
              Doxygen::tagFile << "      <name>" << convertToXML(fmd->name()) << "</name>" << endl; 
dimitri's avatar
dimitri committed
2975
              Doxygen::tagFile << "      <anchorfile>" << convertToXML(getOutputFileBase()+Doxygen::htmlFileExtension) << "</anchorfile>" << endl;              
dimitri's avatar
dimitri committed
2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020
              Doxygen::tagFile << "      <anchor>" << convertToXML(fmd->anchor()) << "</anchor>" << endl; 
              Doxygen::tagFile << "      <arglist>" << convertToXML(fmd->argsString()) << "</arglist>" << endl; 
              Doxygen::tagFile << "    </member>" << endl;
            }
            fmd->writeLink(typeDecl,cd,nd,fd,gd);
          }
          else // no docs for this enum value
          {
            typeDecl.startBold();
            typeDecl.docify(fmd->name());
            typeDecl.endBold();
          }
          if (fmd->hasOneLineInitializer()) // enum value has initializer
          {
            typeDecl.writeString(" = ");
            typeDecl.parseText(fmd->initializer());
          }
        }

        bool prevVisible = fmdVisible;
        fmd=fmdl->next();
        if (fmd && (fmdVisible=fmd->isBriefSectionVisible())) 
        {
          typeDecl.writeString(", ");
        }
        if (prevVisible)
        {
          typeDecl.disable(OutputGenerator::Man);
          typeDecl.writeString("\n"); // to prevent too long lines in LaTeX
          typeDecl.enable(OutputGenerator::Man);
          enumMemCount++;
        }
      }
      if (numVisibleEnumValues>enumValuesPerLine)
      {
        typeDecl.pushGeneratorState();
        typeDecl.disableAllBut(OutputGenerator::Html);
        typeDecl.lineBreak(); 
        typeDecl.popGeneratorState();
      }
    }
    typeDecl.docify(" }");
  }
}

dimitri's avatar
dimitri committed
3021 3022
void MemberDef::setArgumentList(ArgumentList *al) 
{ 
dimitri's avatar
dimitri committed
3023 3024 3025
  makeResident();
  if (m_impl->defArgList) delete m_impl->defArgList;
  m_impl->defArgList = al;
dimitri's avatar
dimitri committed
3026
}
dimitri's avatar
dimitri committed
3027

dimitri's avatar
dimitri committed
3028 3029
void MemberDef::setDeclArgumentList(ArgumentList *al)
{
dimitri's avatar
dimitri committed
3030 3031 3032
  makeResident();
  if (m_impl->declArgList) delete m_impl->declArgList;
  m_impl->declArgList = al;
dimitri's avatar
dimitri committed
3033
}
dimitri's avatar
dimitri committed
3034

dimitri's avatar
dimitri committed
3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049
void MemberDef::setTypeConstraints(ArgumentList *al)
{
  if (al==0) return;
  makeResident();
  if (m_impl->typeConstraints) delete m_impl->typeConstraints;
  m_impl->typeConstraints = new ArgumentList;
  m_impl->typeConstraints->setAutoDelete(TRUE);
  ArgumentListIterator ali(*al);
  Argument *a;
  for (;(a=ali.current());++ali)
  {
    m_impl->typeConstraints->append(new Argument(*a));
  }
}

dimitri's avatar
dimitri committed
3050 3051
void MemberDef::findSectionsInDocumentation()
{
dimitri's avatar
dimitri committed
3052
  makeResident();
dimitri's avatar
dimitri committed
3053
  docFindSections(documentation(),this,0,docFile());  
dimitri's avatar
dimitri committed
3054 3055
}

dimitri's avatar
dimitri committed
3056 3057
void MemberDef::enableCallGraph(bool e) 
{ 
dimitri's avatar
dimitri committed
3058 3059
  makeResident();
  m_impl->hasCallGraph=e; 
dimitri's avatar
dimitri committed
3060 3061 3062
  if (e) Doxygen::parseSourcesNeeded = TRUE;
}

dimitri's avatar
dimitri committed
3063 3064
void MemberDef::enableCallerGraph(bool e) 
{ 
dimitri's avatar
dimitri committed
3065 3066
  makeResident();
  m_impl->hasCallerGraph=e; 
dimitri's avatar
dimitri committed
3067 3068 3069
  if (e) Doxygen::parseSourcesNeeded = TRUE;
}

dimitri's avatar
dimitri committed
3070 3071
bool MemberDef::protectionVisible() const
{
dimitri's avatar
dimitri committed
3072 3073 3074 3075 3076
  makeResident();
  return m_impl->prot==Public || 
         (m_impl->prot==Private   && Config_getBool("EXTRACT_PRIVATE"))   ||
         (m_impl->prot==Protected && Config_getBool("EXTRACT_PROTECTED")) ||
         (m_impl->prot==Package   && Config_getBool("EXTRACT_PACKAGE"));
dimitri's avatar
dimitri committed
3077 3078
}

dimitri's avatar
dimitri committed
3079
#if 0
dimitri's avatar
dimitri committed
3080 3081 3082
void MemberDef::setInbodyDocumentation(const char *docs,
                  const char *docFile,int docLine)
{
dimitri's avatar
dimitri committed
3083 3084 3085 3086 3087
  makeResident();
  m_impl->inbodyDocs = docs;
  m_impl->inbodyDocs = m_impl->inbodyDocs.stripWhiteSpace();
  m_impl->inbodyLine = docLine;
  m_impl->inbodyFile = docFile;
dimitri's avatar
dimitri committed
3088
}
dimitri's avatar
dimitri committed
3089
#endif
dimitri's avatar
dimitri committed
3090

dimitri's avatar
dimitri committed
3091 3092
bool MemberDef::isObjCMethod() const
{
dimitri's avatar
dimitri committed
3093 3094
  makeResident();
  if (m_impl->classDef && m_impl->classDef->isObjectiveC() && isFunction()) return TRUE;
dimitri's avatar
dimitri committed
3095 3096 3097
  return FALSE; 
}

dimitri's avatar
dimitri committed
3098 3099 3100 3101 3102 3103 3104
bool MemberDef::isObjCProperty() const
{
  makeResident();
  if (m_impl->classDef && m_impl->classDef->isObjectiveC() && isProperty()) return TRUE;
  return FALSE; 
}

dimitri's avatar
dimitri committed
3105
QCString MemberDef::qualifiedName() const
dimitri's avatar
dimitri committed
3106
{
dimitri's avatar
dimitri committed
3107
  makeResident();
dimitri's avatar
dimitri committed
3108 3109 3110 3111 3112
  if (isObjCMethod())
  {
    QCString qm;
    if (isStatic()) qm="+"; else qm="-";
    qm+="[";
dimitri's avatar
dimitri committed
3113
    qm+=m_impl->classDef->name()+" ";
dimitri's avatar
dimitri committed
3114 3115 3116 3117 3118 3119 3120 3121 3122
    qm+=name();
    qm+="]";
    return qm;
  }
  else
  {
    return Definition::qualifiedName();
  }  
}
dimitri's avatar
dimitri committed
3123

dimitri's avatar
dimitri committed
3124 3125 3126 3127
void MemberDef::setTagInfo(TagInfo *ti)
{
  if (ti)
  {
dimitri's avatar
dimitri committed
3128
    makeResident();
dimitri's avatar
dimitri committed
3129
    //printf("%s: Setting tag name=%s anchor=%s\n",name().data(),ti->tagName.data(),ti->anchor.data());
dimitri's avatar
dimitri committed
3130
    m_impl->anc=ti->anchor;
dimitri's avatar
dimitri committed
3131
    setReference(ti->tagName);
dimitri's avatar
dimitri committed
3132
    m_impl->explicitOutputFileBase = stripExtension(ti->fileName);
dimitri's avatar
dimitri committed
3133 3134 3135
  }
}

dimitri's avatar
dimitri committed
3136 3137
QCString MemberDef::objCMethodName(bool localLink,bool showStatic) const
{
dimitri's avatar
dimitri committed
3138
  makeResident();
dimitri's avatar
dimitri committed
3139 3140 3141 3142 3143 3144 3145 3146 3147
  QCString qm;
  if (showStatic)
  {
    if (isStatic()) qm="+ "; else qm="- ";
  }
  qm+=name();
  if (!localLink) // link to method of same class
  {
    qm+=" (";
dimitri's avatar
dimitri committed
3148
    qm+=m_impl->classDef->name();
dimitri's avatar
dimitri committed
3149 3150 3151 3152 3153
    qm+=")";
  }
  return qm;
}

dimitri's avatar
dimitri committed
3154 3155 3156 3157 3158 3159 3160 3161 3162
const char *MemberDef::declaration() const
{ 
  makeResident();
  return m_impl->decl; 
}

const char *MemberDef::definition() const
{ 
  makeResident();
dimitri's avatar
dimitri committed
3163 3164 3165 3166 3167 3168 3169
  return m_impl->def;
}

const char *MemberDef::extraTypeChars() const
{
  makeResident();
  return m_impl->extraTypeChars;
dimitri's avatar
dimitri committed
3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360
}

const char *MemberDef::typeString() const
{ 
  makeResident();
  return m_impl->type; 
}

const char *MemberDef::argsString() const
{ 
  makeResident();
  return m_impl->args; 
}

const char *MemberDef::excpString() const
{ 
  makeResident();
  return m_impl->exception; 
}

const char *MemberDef::bitfieldString() const
{ 
  makeResident();
  return m_impl->bitfields; 
}

const QCString &MemberDef::initializer() const
{ 
  makeResident();
  return m_impl->initializer; 
}

int MemberDef::initializerLines() const
{ 
  makeResident();
  return m_impl->initLines; 
}

int  MemberDef::getMemberSpecifiers() const
{ 
  makeResident();
  return m_impl->memSpec; 
}

ClassDef *MemberDef::getClassDef() const
{ 
  makeResident();
  return m_impl->classDef; 
}

FileDef  *MemberDef::getFileDef() const
{ 
  makeResident();
  return m_impl->fileDef; 
}

NamespaceDef* MemberDef::getNamespaceDef() const
{ 
  makeResident();
  return m_impl->nspace; 
}

const char *MemberDef::getReadAccessor() const
{ 
  makeResident();
  return m_impl->read; 
}

const char *MemberDef::getWriteAccessor() const
{ 
  makeResident();
  return m_impl->write; 
}

GroupDef *MemberDef::getGroupDef() const
{ 
  makeResident();
  return m_impl->group; 
}

Grouping::GroupPri_t MemberDef::getGroupPri() const
{ 
  makeResident();
  return m_impl->grouppri; 
}

const char *MemberDef::getGroupFileName() const
{ 
  makeResident();
  return m_impl->groupFileName; 
}

int MemberDef::getGroupStartLine() const
{ 
  makeResident();
  return m_impl->groupStartLine; 
}

bool MemberDef::getGroupHasDocs() const
{ 
  makeResident();
  return m_impl->groupHasDocs; 
}

Protection MemberDef::protection() const
{ 
  makeResident();
  return m_impl->prot; 
}

MemberDef::MemberType MemberDef::memberType() const
{ 
  makeResident();
  return m_impl->mtype; 
}

bool MemberDef::isSignal() const
{ 
  makeResident();
  return m_impl->mtype==Signal;      
}

bool MemberDef::isSlot() const
{ 
  makeResident();
  return m_impl->mtype==Slot;        
}

bool MemberDef::isVariable() const
{ 
  makeResident();
  return m_impl->mtype==Variable;    
}

bool MemberDef::isEnumerate() const
{ 
  makeResident();
  return m_impl->mtype==Enumeration; 
}

bool MemberDef::isEnumValue() const
{ 
  makeResident();
  return m_impl->mtype==EnumValue;   
}

bool MemberDef::isTypedef() const
{ 
  makeResident();
  return m_impl->mtype==Typedef;     
}

bool MemberDef::isFunction() const
{ 
  makeResident();
  return m_impl->mtype==Function;    
}

bool MemberDef::isDefine() const
{ 
  makeResident();
  return m_impl->mtype==Define;      
}

bool MemberDef::isFriend() const
{ 
  makeResident();
  return m_impl->mtype==Friend;      
}

bool MemberDef::isDCOP() const
{ 
  makeResident();
  return m_impl->mtype==DCOP;        
}

bool MemberDef::isProperty() const
{ 
  makeResident();
  return m_impl->mtype==Property;    
}

bool MemberDef::isEvent() const
{ 
  makeResident();
  return m_impl->mtype==Event;       
}

bool MemberDef::isRelated() const
{ 
  makeResident();
dimitri's avatar
dimitri committed
3361 3362 3363 3364 3365 3366 3367
  return m_impl->related == Related;
}

bool MemberDef::isForeign() const
{ 
  makeResident();
  return m_impl->related == Foreign; 
dimitri's avatar
dimitri committed
3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405
}

bool MemberDef::isStatic() const
{ 
  makeResident();
  return m_impl->stat; 
}

bool MemberDef::isInline() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::Inline)!=0; 
}

bool MemberDef::isExplicit() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::Explicit)!=0; 
}

bool MemberDef::isMutable() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::Mutable)!=0; 
}

bool MemberDef::isGettable() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::Gettable)!=0; 
}

bool MemberDef::isSettable() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::Settable)!=0; 
}

dimitri's avatar
dimitri committed
3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423
bool MemberDef::isAddable() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::Addable)!=0; 
}

bool MemberDef::isRemovable() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::Removable)!=0; 
}

bool MemberDef::isRaisable() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::Raisable)!=0; 
}

dimitri's avatar
dimitri committed
3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441
bool MemberDef::isReadable() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::Readable)!=0; 
}

bool MemberDef::isWritable() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::Writable)!=0; 
}

bool MemberDef::isFinal() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::Final)!=0; 
}

dimitri's avatar
dimitri committed
3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465
bool MemberDef::isNew() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::New)!=0; 
}

bool MemberDef::isSealed() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::Sealed)!=0; 
}

bool MemberDef::isOverride() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::Override)!=0; 
}

bool MemberDef::isInitonly() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::Initonly)!=0; 
}

dimitri's avatar
dimitri committed
3466 3467 3468 3469 3470 3471
bool MemberDef::isAbstract() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::Abstract)!=0; 
}

dimitri's avatar
dimitri committed
3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508
bool MemberDef::isOptional() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::Optional)!=0; 
}

bool MemberDef::isRequired() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::Required)!=0; 
}

bool MemberDef::isNonAtomic() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::NonAtomic)!=0; 
}

bool MemberDef::isCopy() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::Copy)!=0; 
}

bool MemberDef::isAssign() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::Assign)!=0; 
}

bool MemberDef::isRetain() const
{ 
  makeResident();
  return (m_impl->memSpec&Entry::Retain)!=0; 
}


dimitri's avatar
dimitri committed
3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538
bool MemberDef::isImplementation() const
{ 
  makeResident();
  return m_impl->implOnly; 
}

bool MemberDef::isExternal() const
{ 
  makeResident();
  return m_impl->explExt; 
}

bool MemberDef::isTemplateSpecialization() const
{ 
  makeResident();
  return m_impl->tspec; 
}

bool MemberDef::hasDocumentedParams() const
{ 
  makeResident();
  return m_impl->hasDocumentedParams; 
}

bool MemberDef::hasDocumentedReturnType() const
{ 
  makeResident();
  return m_impl->hasDocumentedReturnType; 
}

dimitri's avatar
dimitri committed
3539
#if 0
dimitri's avatar
dimitri committed
3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556
int MemberDef::inbodyLine() const
{ 
  makeResident();
  return m_impl->inbodyLine; 
}

QCString MemberDef::inbodyFile() const
{ 
  makeResident();
  return m_impl->inbodyFile; 
}

const QCString &MemberDef::inbodyDocumentation() const
{ 
  makeResident();
  return m_impl->inbodyDocs; 
}
dimitri's avatar
dimitri committed
3557
#endif
dimitri's avatar
dimitri committed
3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696

ClassDef *MemberDef::relatedAlso() const
{ 
  makeResident();
  return m_impl->relatedAlso; 
}

bool MemberDef::hasDocumentedEnumValues() const
{ 
  makeResident();
  return m_impl->docEnumValues; 
}

MemberDef *MemberDef::getAnonymousEnumType() const
{ 
  makeResident();
  return m_impl->annEnumType; 
}

bool MemberDef::isDocsForDefinition() const
{ 
  makeResident();
  return m_impl->docsForDefinition; 
}

MemberDef *MemberDef::getEnumScope() const
{ 
  makeResident();
  return m_impl->enumScope; 
}

LockingPtr<MemberList> MemberDef::enumFieldList() const
{ 
  makeResident();
  return LockingPtr<MemberList>(this,m_impl->enumFields); 
}

LockingPtr<ExampleSDict> MemberDef::getExamples() const
{ 
  makeResident();
  return LockingPtr<ExampleSDict>(this,m_impl->exampleSDict); 
}

bool MemberDef::isPrototype() const
{ 
  makeResident();
  return m_impl->proto; 
}

LockingPtr<ArgumentList> MemberDef::argumentList() const
{ 
  makeResident();
  return LockingPtr<ArgumentList>(this,m_impl->defArgList); 
}

LockingPtr<ArgumentList> MemberDef::declArgumentList() const
{ 
  makeResident();
  return LockingPtr<ArgumentList>(this,m_impl->declArgList); 
}

LockingPtr<ArgumentList> MemberDef::templateArguments() const
{ 
  makeResident();
  return LockingPtr<ArgumentList>(this,m_impl->tArgList); 
}

LockingPtr< QList<ArgumentList> > MemberDef::definitionTemplateParameterLists() const
{ 
  makeResident();
  return LockingPtr< QList<ArgumentList> >(this,m_impl->defTmpArgLists); 
}

int MemberDef::getMemberGroupId() const
{ 
  makeResident();
  return m_impl->grpId; 
}

MemberGroup *MemberDef::getMemberGroup() const
{ 
  makeResident();
  return m_impl->memberGroup; 
}

bool MemberDef::fromAnonymousScope() const
{ 
  makeResident();
  return m_impl->annScope; 
}

bool MemberDef::anonymousDeclShown() const
{ 
  makeResident();
  return m_impl->annUsed; 
}

void MemberDef::setAnonymousUsed() 
{
  makeResident();
  m_impl->annUsed = TRUE;
}

bool MemberDef::hasCallGraph() const
{ 
  makeResident();
  return m_impl->hasCallGraph; 
}

bool MemberDef::hasCallerGraph() const
{ 
  makeResident();
  return m_impl->hasCallerGraph; 
}

MemberDef *MemberDef::templateMaster() const
{ 
  makeResident();
  return m_impl->templateMaster; 
}

bool MemberDef::isTypedefValCached() const
{ 
  makeResident();
  return m_impl->isTypedefValCached; 
}

ClassDef *MemberDef::getCachedTypedefVal() const
{ 
  makeResident();
  return m_impl->cachedTypedefValue; 
}

QCString MemberDef::getCachedTypedefTemplSpec() const
{ 
  makeResident();
  return m_impl->cachedTypedefTemplSpec; 
}

dimitri's avatar
dimitri committed
3697 3698 3699
QCString MemberDef::getCachedResolvedTypedef() const
{ 
  makeResident();
dimitri's avatar
dimitri committed
3700
  //printf("MemberDef::getCachedResolvedTypedef()=%s m_impl=%p\n",m_impl->cachedResolvedType.data(),m_impl);
dimitri's avatar
dimitri committed
3701 3702 3703
  return m_impl->cachedResolvedType; 
}

dimitri's avatar
dimitri committed
3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731
MemberDef *MemberDef::memberDefinition() const
{ 
  makeResident();
  return m_impl->memDef; 
}

MemberDef *MemberDef::memberDeclaration() const
{ 
  makeResident();
  return m_impl->memDec; 
}

MemberDef *MemberDef::inheritsDocsFrom() const
{ 
  makeResident();
  return m_impl->docProvider; 
}

MemberDef *MemberDef::getGroupAlias() const
{ 
  makeResident();
  return m_impl->groupAlias; 
}

void MemberDef::setMemberType(MemberType t)
{ 
  makeResident();
  m_impl->mtype=t; 
dimitri's avatar
dimitri committed
3732
  m_isLinkableCached = 0;
dimitri's avatar
dimitri committed
3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744
}

void MemberDef::setDefinition(const char *d)
{ 
  makeResident();
  m_impl->def=d; 
}

void MemberDef::setFileDef(FileDef *fd)
{ 
  makeResident();
  m_impl->fileDef=fd; 
dimitri's avatar
dimitri committed
3745 3746 3747
  m_isLinkableCached = 0;
  m_isConstructorCached = 0;
  m_isDestructorCached = 0;
dimitri's avatar
dimitri committed
3748 3749 3750 3751 3752 3753
}

void MemberDef::setProtection(Protection p)
{ 
  makeResident();
  m_impl->prot=p; 
dimitri's avatar
dimitri committed
3754
  m_isLinkableCached = 0;
dimitri's avatar
dimitri committed
3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776
}

void MemberDef::setMemberSpecifiers(int s)
{ 
  makeResident();
  m_impl->memSpec=s; 
}

void MemberDef::mergeMemberSpecifiers(int s)
{ 
  makeResident();
  m_impl->memSpec|=s; 
}

void MemberDef::setBitfields(const char *s)
{ 
  makeResident();
  m_impl->bitfields = s; 
}

void MemberDef::setMaxInitLines(int lines)
{ 
dimitri's avatar
dimitri committed
3777 3778 3779 3780 3781
  if (lines!=-1)
  {
    makeResident();
    m_impl->userInitLines=lines; 
  }
dimitri's avatar
dimitri committed
3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810
}

void MemberDef::setExplicitExternal(bool b)
{ 
  makeResident();
  m_impl->explExt=b; 
}

void MemberDef::setReadAccessor(const char *r)
{ 
  makeResident();
  m_impl->read=r; 
}

void MemberDef::setWriteAccessor(const char *w)
{ 
  makeResident();
  m_impl->write=w; 
}

void MemberDef::setTemplateSpecialization(bool b)
{ 
  makeResident();
  m_impl->tspec=b; 
}

void MemberDef::makeRelated()
{ 
  makeResident();
dimitri's avatar
dimitri committed
3811
  m_impl->related = Related; 
dimitri's avatar
dimitri committed
3812
  m_isLinkableCached = 0;
dimitri's avatar
dimitri committed
3813 3814 3815 3816 3817 3818
}

void MemberDef::makeForeign()
{ 
  makeResident();
  m_impl->related = Foreign; 
dimitri's avatar
dimitri committed
3819
  m_isLinkableCached = 0;
dimitri's avatar
dimitri committed
3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855
}

void MemberDef::setHasDocumentedParams(bool b)
{ 
  makeResident();
  m_impl->hasDocumentedParams = b; 
}

void MemberDef::setHasDocumentedReturnType(bool b)
{ 
  makeResident();
  m_impl->hasDocumentedReturnType = b; 
}

void MemberDef::setInheritsDocsFrom(MemberDef *md)
{ 
  makeResident();
  m_impl->docProvider = md; 
}

void MemberDef::setArgsString(const char *as)
{ 
  makeResident();
  m_impl->args = as; 
}

void MemberDef::setRelatedAlso(ClassDef *cd)
{ 
  makeResident();
  m_impl->relatedAlso=cd; 
}

void MemberDef::setEnumClassScope(ClassDef *cd)
{ 
  makeResident();
  m_impl->classDef = cd; 
dimitri's avatar
dimitri committed
3856 3857
  m_isLinkableCached = 0; 
  m_isConstructorCached = 0; 
dimitri's avatar
dimitri committed
3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905
}

void MemberDef::setDocumentedEnumValues(bool value)
{ 
  makeResident();
  m_impl->docEnumValues=value; 
}

void MemberDef::setAnonymousEnumType(MemberDef *md)
{ 
  makeResident();
  m_impl->annEnumType = md; 
}

void MemberDef::setPrototype(bool p)
{ 
  makeResident();
  m_impl->proto=p; 
}

void MemberDef::setMemberGroupId(int id)
{ 
  makeResident();
  m_impl->grpId=id; 
}

void MemberDef::makeImplementationDetail()
{ 
  makeResident();
  m_impl->implOnly=TRUE; 
}

void MemberDef::setFromAnonymousScope(bool b)
{ 
  makeResident();
  m_impl->annScope=b; 
}

void MemberDef::setFromAnonymousMember(MemberDef *m)
{ 
  makeResident();
  m_impl->annMemb=m; 
}

void MemberDef::setTemplateMaster(MemberDef *mt)
{ 
  makeResident();
  m_impl->templateMaster=mt; 
dimitri's avatar
dimitri committed
3906
  m_isLinkableCached = 0; 
dimitri's avatar
dimitri committed
3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938
}

void MemberDef::setDocsForDefinition(bool b)
{ 
  makeResident();
  m_impl->docsForDefinition = b; 
}

void MemberDef::setGroupAlias(MemberDef *md)
{ 
  makeResident();
  m_impl->groupAlias = md; 
}

void MemberDef::invalidateTypedefValCache()
{ 
  makeResident();
  m_impl->isTypedefValCached=FALSE; 
}

void MemberDef::setMemberDefinition(MemberDef *md)
{ 
  makeResident();
  m_impl->memDef=md; 
}

void MemberDef::setMemberDeclaration(MemberDef *md)
{ 
  makeResident();
  m_impl->memDec=md; 
}

dimitri's avatar
dimitri committed
3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951
ClassDef *MemberDef::category() const
{
  makeResident();
  return m_impl->category;
}

void MemberDef::setCategory(ClassDef *def)
{
  makeResident();
  m_impl->category = def;
}


dimitri's avatar
dimitri committed
3952
void MemberDef::cacheTypedefVal(ClassDef*val, const QCString & templSpec, const QCString &resolvedType)
dimitri's avatar
dimitri committed
3953 3954 3955 3956 3957
{
  makeResident();
  m_impl->isTypedefValCached=TRUE; 
  m_impl->cachedTypedefValue=val; 
  m_impl->cachedTypedefTemplSpec=templSpec; 
dimitri's avatar
dimitri committed
3958
  m_impl->cachedResolvedType=resolvedType;
dimitri's avatar
dimitri committed
3959
  //printf("MemberDef::cacheTypedefVal=%s m_impl=%p\n",m_impl->cachedResolvedType.data(),m_impl);
dimitri's avatar
dimitri committed
3960 3961 3962 3963
}

void MemberDef::flushToDisk() const
{
dimitri's avatar
dimitri committed
3964 3965 3966
  if (isLocked()) return;
  MemberDef *that = (MemberDef*)this;
  that->m_storagePos = Doxygen::symbolStorage->alloc();
dimitri's avatar
dimitri committed
3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998
  //printf("%p: MemberDef::flushToDisk()\n",this);
  // write the definition base class member variables to disk
  Definition::flushToDisk();

  //printf("%p:   flushing specific part\n",this);

  // write the memberdef member variables to disk
  marshalUInt(Doxygen::symbolStorage,START_MARKER);
  marshalObjPointer   (Doxygen::symbolStorage,m_impl->classDef);
  marshalObjPointer   (Doxygen::symbolStorage,m_impl->fileDef);
  marshalObjPointer   (Doxygen::symbolStorage,m_impl->nspace);
  marshalObjPointer   (Doxygen::symbolStorage,m_impl->enumScope);
  marshalObjPointer   (Doxygen::symbolStorage,m_impl->annEnumType);
  marshalMemberList   (Doxygen::symbolStorage,m_impl->enumFields);
  marshalObjPointer   (Doxygen::symbolStorage,m_impl->redefines);
  marshalMemberList   (Doxygen::symbolStorage,m_impl->redefinedBy);
  marshalObjPointer   (Doxygen::symbolStorage,m_impl->memDef);
  marshalObjPointer   (Doxygen::symbolStorage,m_impl->memDec);
  marshalObjPointer   (Doxygen::symbolStorage,m_impl->relatedAlso);
  marshalExampleSDict (Doxygen::symbolStorage,m_impl->exampleSDict);
  marshalQCString     (Doxygen::symbolStorage,m_impl->type);
  marshalQCString     (Doxygen::symbolStorage,m_impl->args);
  marshalQCString     (Doxygen::symbolStorage,m_impl->def);
  marshalQCString     (Doxygen::symbolStorage,m_impl->anc);
  marshalInt          (Doxygen::symbolStorage,(int)m_impl->virt);
  marshalInt          (Doxygen::symbolStorage,(int)m_impl->prot);
  marshalQCString     (Doxygen::symbolStorage,m_impl->decl);
  marshalQCString     (Doxygen::symbolStorage,m_impl->bitfields);
  marshalQCString     (Doxygen::symbolStorage,m_impl->read);
  marshalQCString     (Doxygen::symbolStorage,m_impl->write);
  marshalQCString     (Doxygen::symbolStorage,m_impl->exception);
  marshalQCString     (Doxygen::symbolStorage,m_impl->initializer);
dimitri's avatar
dimitri committed
3999
  marshalQCString     (Doxygen::symbolStorage,m_impl->extraTypeChars);
dimitri's avatar
dimitri committed
4000 4001 4002 4003 4004 4005 4006 4007 4008
  marshalInt          (Doxygen::symbolStorage,m_impl->initLines);
  marshalInt          (Doxygen::symbolStorage,m_impl->memSpec);
  marshalInt          (Doxygen::symbolStorage,(int)m_impl->mtype);
  marshalInt          (Doxygen::symbolStorage,m_impl->maxInitLines);
  marshalInt          (Doxygen::symbolStorage,m_impl->userInitLines);
  marshalObjPointer   (Doxygen::symbolStorage,m_impl->annMemb);
  marshalArgumentList (Doxygen::symbolStorage,m_impl->defArgList);
  marshalArgumentList (Doxygen::symbolStorage,m_impl->declArgList);
  marshalArgumentList (Doxygen::symbolStorage,m_impl->tArgList);
dimitri's avatar
dimitri committed
4009
  marshalArgumentList (Doxygen::symbolStorage,m_impl->typeConstraints);
dimitri's avatar
dimitri committed
4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024
  marshalObjPointer   (Doxygen::symbolStorage,m_impl->templateMaster);
  marshalArgumentLists(Doxygen::symbolStorage,m_impl->defTmpArgLists);
  marshalObjPointer   (Doxygen::symbolStorage,m_impl->cachedAnonymousType);
  marshalMemberLists  (Doxygen::symbolStorage,m_impl->classSectionSDict);
  marshalObjPointer   (Doxygen::symbolStorage,m_impl->groupAlias);
  marshalInt          (Doxygen::symbolStorage,m_impl->grpId);
  marshalObjPointer   (Doxygen::symbolStorage,m_impl->memberGroup);
  marshalObjPointer   (Doxygen::symbolStorage,m_impl->group);
  marshalInt          (Doxygen::symbolStorage,(int)m_impl->grouppri);
  marshalQCString     (Doxygen::symbolStorage,m_impl->groupFileName);
  marshalInt          (Doxygen::symbolStorage,m_impl->groupStartLine);
  marshalObjPointer   (Doxygen::symbolStorage,m_impl->groupMember);
  marshalBool         (Doxygen::symbolStorage,m_impl->isTypedefValCached);
  marshalObjPointer   (Doxygen::symbolStorage,m_impl->cachedTypedefValue);
  marshalQCString     (Doxygen::symbolStorage,m_impl->cachedTypedefTemplSpec);
dimitri's avatar
dimitri committed
4025
  marshalQCString     (Doxygen::symbolStorage,m_impl->cachedResolvedType);
dimitri's avatar
dimitri committed
4026 4027 4028 4029 4030 4031
  marshalObjPointer   (Doxygen::symbolStorage,m_impl->docProvider);
  marshalQCString     (Doxygen::symbolStorage,m_impl->explicitOutputFileBase);
  marshalBool         (Doxygen::symbolStorage,m_impl->implOnly); 
  marshalBool         (Doxygen::symbolStorage,m_impl->hasDocumentedParams);
  marshalBool         (Doxygen::symbolStorage,m_impl->hasDocumentedReturnType);
  marshalBool         (Doxygen::symbolStorage,m_impl->isDMember);
dimitri's avatar
dimitri committed
4032
  marshalInt          (Doxygen::symbolStorage,(int)m_impl->related);
dimitri's avatar
dimitri committed
4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043
  marshalBool         (Doxygen::symbolStorage,m_impl->stat);
  marshalBool         (Doxygen::symbolStorage,m_impl->proto);
  marshalBool         (Doxygen::symbolStorage,m_impl->docEnumValues);
  marshalBool         (Doxygen::symbolStorage,m_impl->annScope);
  marshalBool         (Doxygen::symbolStorage,m_impl->annUsed);
  marshalBool         (Doxygen::symbolStorage,m_impl->hasCallGraph);
  marshalBool         (Doxygen::symbolStorage,m_impl->hasCallerGraph);
  marshalBool         (Doxygen::symbolStorage,m_impl->explExt);
  marshalBool         (Doxygen::symbolStorage,m_impl->tspec);
  marshalBool         (Doxygen::symbolStorage,m_impl->groupHasDocs);
  marshalBool         (Doxygen::symbolStorage,m_impl->docsForDefinition);
dimitri's avatar
dimitri committed
4044
  marshalObjPointer   (Doxygen::symbolStorage,m_impl->category);
dimitri's avatar
dimitri committed
4045 4046 4047 4048 4049
  marshalUInt(Doxygen::symbolStorage,END_MARKER);

  // function doesn't modify the object conceptually but compiler doesn't know this.
  delete that->m_impl;
  that->m_impl=0;
dimitri's avatar
dimitri committed
4050
  that->m_flushPending=FALSE;
dimitri's avatar
dimitri committed
4051 4052 4053 4054 4055
}

void MemberDef::loadFromDisk() const
{
  //printf("%p: MemberDef::loadFromDisk()\n",this);
dimitri's avatar
dimitri committed
4056
  MemberDef *that = (MemberDef *)this;
dimitri's avatar
dimitri committed
4057 4058 4059 4060 4061 4062
  if (isLocked()) 
  {
    assert(m_impl!=0);
    return;
  }
  assert(m_impl==0);
dimitri's avatar
dimitri committed
4063 4064 4065 4066

  Doxygen::symbolStorage->seek(m_storagePos);
  Definition::loadFromDisk();

dimitri's avatar
dimitri committed
4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096
  //printf("%p:   loading specific part\n",this);

  that->m_impl = new MemberDefImpl;

  uint marker = unmarshalUInt(Doxygen::symbolStorage);
  assert(marker==START_MARKER);
  m_impl->classDef                = (ClassDef*)unmarshalObjPointer     (Doxygen::symbolStorage);
  m_impl->fileDef                 = (FileDef*)unmarshalObjPointer      (Doxygen::symbolStorage);
  m_impl->nspace                  = (NamespaceDef*)unmarshalObjPointer (Doxygen::symbolStorage);
  m_impl->enumScope               = (MemberDef*)unmarshalObjPointer    (Doxygen::symbolStorage);
  m_impl->annEnumType             = (MemberDef*)unmarshalObjPointer    (Doxygen::symbolStorage);
  m_impl->enumFields              = unmarshalMemberList                (Doxygen::symbolStorage);
  m_impl->redefines               = (MemberDef*)unmarshalObjPointer    (Doxygen::symbolStorage);
  m_impl->redefinedBy             = unmarshalMemberList                (Doxygen::symbolStorage);
  m_impl->memDef                  = (MemberDef*)unmarshalObjPointer    (Doxygen::symbolStorage);
  m_impl->memDec                  = (MemberDef*)unmarshalObjPointer    (Doxygen::symbolStorage);
  m_impl->relatedAlso             = (ClassDef*)unmarshalObjPointer     (Doxygen::symbolStorage);
  m_impl->exampleSDict            = unmarshalExampleSDict (Doxygen::symbolStorage);
  m_impl->type                    = unmarshalQCString     (Doxygen::symbolStorage);
  m_impl->args                    = unmarshalQCString     (Doxygen::symbolStorage);
  m_impl->def                     = unmarshalQCString     (Doxygen::symbolStorage);
  m_impl->anc                     = unmarshalQCString     (Doxygen::symbolStorage);
  m_impl->virt                    = (Specifier)unmarshalInt (Doxygen::symbolStorage);
  m_impl->prot                    = (Protection)unmarshalInt(Doxygen::symbolStorage);
  m_impl->decl                    = unmarshalQCString     (Doxygen::symbolStorage);
  m_impl->bitfields               = unmarshalQCString     (Doxygen::symbolStorage);
  m_impl->read                    = unmarshalQCString     (Doxygen::symbolStorage);
  m_impl->write                   = unmarshalQCString     (Doxygen::symbolStorage);
  m_impl->exception               = unmarshalQCString     (Doxygen::symbolStorage);
  m_impl->initializer             = unmarshalQCString     (Doxygen::symbolStorage);
dimitri's avatar
dimitri committed
4097
  m_impl->extraTypeChars          = unmarshalQCString     (Doxygen::symbolStorage);
dimitri's avatar
dimitri committed
4098 4099 4100 4101 4102 4103 4104 4105 4106
  m_impl->initLines               = unmarshalInt          (Doxygen::symbolStorage);
  m_impl->memSpec                 = unmarshalInt          (Doxygen::symbolStorage);
  m_impl->mtype                   = (MemberDef::MemberType)unmarshalInt          (Doxygen::symbolStorage);
  m_impl->maxInitLines            = unmarshalInt          (Doxygen::symbolStorage);
  m_impl->userInitLines           = unmarshalInt          (Doxygen::symbolStorage);
  m_impl->annMemb                 = (MemberDef*)unmarshalObjPointer   (Doxygen::symbolStorage);
  m_impl->defArgList              = unmarshalArgumentList (Doxygen::symbolStorage);
  m_impl->declArgList             = unmarshalArgumentList (Doxygen::symbolStorage);
  m_impl->tArgList                = unmarshalArgumentList (Doxygen::symbolStorage);
dimitri's avatar
dimitri committed
4107
  m_impl->typeConstraints         = unmarshalArgumentList (Doxygen::symbolStorage);
dimitri's avatar
dimitri committed
4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122
  m_impl->templateMaster          = (MemberDef*)unmarshalObjPointer   (Doxygen::symbolStorage);
  m_impl->defTmpArgLists          = unmarshalArgumentLists(Doxygen::symbolStorage);
  m_impl->cachedAnonymousType     = (ClassDef*)unmarshalObjPointer   (Doxygen::symbolStorage);
  m_impl->classSectionSDict       = unmarshalMemberLists  (Doxygen::symbolStorage);
  m_impl->groupAlias              = (MemberDef*)unmarshalObjPointer   (Doxygen::symbolStorage);
  m_impl->grpId                   = unmarshalInt          (Doxygen::symbolStorage);
  m_impl->memberGroup             = (MemberGroup*)unmarshalObjPointer   (Doxygen::symbolStorage);
  m_impl->group                   = (GroupDef*)unmarshalObjPointer   (Doxygen::symbolStorage);
  m_impl->grouppri                = (Grouping::GroupPri_t)unmarshalInt          (Doxygen::symbolStorage);
  m_impl->groupFileName           = unmarshalQCString     (Doxygen::symbolStorage);
  m_impl->groupStartLine          = unmarshalInt          (Doxygen::symbolStorage);
  m_impl->groupMember             = (MemberDef*)unmarshalObjPointer   (Doxygen::symbolStorage);
  m_impl->isTypedefValCached      = unmarshalBool         (Doxygen::symbolStorage);
  m_impl->cachedTypedefValue      = (ClassDef*)unmarshalObjPointer   (Doxygen::symbolStorage);
  m_impl->cachedTypedefTemplSpec  = unmarshalQCString     (Doxygen::symbolStorage);
dimitri's avatar
dimitri committed
4123
  m_impl->cachedResolvedType      = unmarshalQCString     (Doxygen::symbolStorage);
dimitri's avatar
dimitri committed
4124 4125 4126 4127 4128 4129
  m_impl->docProvider             = (MemberDef*)unmarshalObjPointer   (Doxygen::symbolStorage);
  m_impl->explicitOutputFileBase  = unmarshalQCString     (Doxygen::symbolStorage);
  m_impl->implOnly                = unmarshalBool         (Doxygen::symbolStorage); 
  m_impl->hasDocumentedParams     = unmarshalBool         (Doxygen::symbolStorage);
  m_impl->hasDocumentedReturnType = unmarshalBool         (Doxygen::symbolStorage);
  m_impl->isDMember               = unmarshalBool         (Doxygen::symbolStorage);
dimitri's avatar
dimitri committed
4130
  m_impl->related                 = (Relationship)unmarshalInt(Doxygen::symbolStorage);
dimitri's avatar
dimitri committed
4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141
  m_impl->stat                    = unmarshalBool         (Doxygen::symbolStorage);
  m_impl->proto                   = unmarshalBool         (Doxygen::symbolStorage);
  m_impl->docEnumValues           = unmarshalBool         (Doxygen::symbolStorage);
  m_impl->annScope                = unmarshalBool         (Doxygen::symbolStorage);
  m_impl->annUsed                 = unmarshalBool         (Doxygen::symbolStorage);
  m_impl->hasCallGraph            = unmarshalBool         (Doxygen::symbolStorage);
  m_impl->hasCallerGraph          = unmarshalBool         (Doxygen::symbolStorage);
  m_impl->explExt                 = unmarshalBool         (Doxygen::symbolStorage);
  m_impl->tspec                   = unmarshalBool         (Doxygen::symbolStorage);
  m_impl->groupHasDocs            = unmarshalBool         (Doxygen::symbolStorage);
  m_impl->docsForDefinition       = unmarshalBool         (Doxygen::symbolStorage);
dimitri's avatar
dimitri committed
4142
  m_impl->category                = (ClassDef*)unmarshalObjPointer   (Doxygen::symbolStorage);
dimitri's avatar
dimitri committed
4143 4144 4145 4146
  marker = unmarshalUInt(Doxygen::symbolStorage);
  assert(marker==END_MARKER);
}

dimitri's avatar
dimitri committed
4147 4148
void MemberDef::makeResident() const
{ 
dimitri's avatar
dimitri committed
4149
  if (Doxygen::symbolCache==0) return;
dimitri's avatar
dimitri committed
4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226
  if (m_cacheHandle==-1) // not yet in cache
  { 
    MemberDef *victim = 0;
    MemberDef *that = (MemberDef*)this; // fake method constness
    that->m_cacheHandle = Doxygen::symbolCache->add(that,(void **)&victim);
    //printf("adding %s to cache, handle=%d\n",m_impl->name.data(),that->m_cacheHandle);
    if (victim)  // cache was full, victim was the least recently used item and has to go
    {
      victim->m_cacheHandle=-1; // invalidate cache handle
      victim->saveToDisk();     // store the item on disk
    }
    else // cache not yet full
    {
      //printf("Adding %s to cache, handle=%d\n",m_impl->name.data(),m_cacheHandle);
    }
    if (m_storagePos!=-1) // already been written to disk
    {
      if (isLocked()) // locked in memory
      {
        assert(m_impl!=0);
        that->m_flushPending=FALSE; // no need to flush anymore
      }
      else // not locked in memory
      {
        assert(m_impl==0);
        loadFromDisk();
      }
    }
  }
  else // already cached, make this object the most recently used.
  {
    assert(m_impl!=0);
    //printf("Touching symbol %s\n",m_impl->name.data());
    Doxygen::symbolCache->use(m_cacheHandle);
  }
}

void MemberDef::saveToDisk() const
{
  assert(m_impl!=0);
  MemberDef *that = (MemberDef *)this;
  if (isLocked()) // cannot flush the item as it is locked
  {
    that->m_flushPending=TRUE; // flush when unlocked
  }
  else // ready to flush the item to disk
  {
    //printf("Adding %s to cache, handle=%d by replacing %s\n",
    //    m_impl->name.data(),m_cacheHandle,victim->m_impl->name.data());
    if (m_storagePos!=-1) 
      // if victim was stored on disk already and is not locked
    {
      // free the storage space occupied by the old store item
      Doxygen::symbolStorage->release(m_storagePos); // free up space for others
    }
    // write a the new (possibly modified) instance to disk
    flushToDisk();
    // end to write sequence (unless nothing was written due to the lock)
    Doxygen::symbolStorage->end();
  }
}

void MemberDef::lock() const
{
}

void MemberDef::unlock() const
{
  if (m_flushPending && !isLocked())
  {
    // write a the new (possibly modified) instance to disk
    flushToDisk();
    // end to write sequence (unless nothing was written due to the lock)
    Doxygen::symbolStorage->end();
  }
}

dimitri's avatar
dimitri committed
4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244
void MemberDef::copyArgumentNames(MemberDef *bmd)
{
  makeResident();
  {
    LockingPtr<ArgumentList> arguments = bmd->argumentList();
    if (m_impl->defArgList && arguments!=0)
    {
      ArgumentListIterator aliDst(*m_impl->defArgList);
      ArgumentListIterator aliSrc(*arguments);
      Argument *argDst, *argSrc;
      for (;(argDst=aliDst.current()) && (argSrc=aliSrc.current());++aliDst,++aliSrc)
      {
        argDst->name = argSrc->name;
      }
    }
  }
  {
    LockingPtr<ArgumentList> arguments = bmd->declArgumentList();
dimitri's avatar
dimitri committed
4245
    if (m_impl->declArgList && arguments!=0)
dimitri's avatar
dimitri committed
4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256
    {
      ArgumentListIterator aliDst(*m_impl->declArgList);
      ArgumentListIterator aliSrc(*arguments);
      Argument *argDst, *argSrc;
      for (;(argDst=aliDst.current()) && (argSrc=aliSrc.current());++aliDst,++aliSrc)
      {
        argDst->name = argSrc->name;
      }
    }
  }
}
dimitri's avatar
dimitri committed
4257

dimitri's avatar
dimitri committed
4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276
static void invalidateCachedTypesInArgumentList(ArgumentList *al)
{
  if (al)
  {
    ArgumentListIterator ali(*al);
    Argument *a;
    for (ali.toFirst();(a=ali.current());++ali)
    {
      a->canType.resize(0);
    }
  }
}

void MemberDef::invalidateCachedArgumentTypes()
{
  makeResident();
  invalidateCachedTypesInArgumentList(m_impl->defArgList);
  invalidateCachedTypesInArgumentList(m_impl->declArgList);
}
dimitri's avatar
dimitri committed
4277