pike.git / lib / modules / Tools.pmod / AutoDoc.pmod / PikeExtractor.pmod

version» Context lines:

pike.git/lib/modules/Tools.pmod/AutoDoc.pmod/PikeExtractor.pmod:7:   // #pragma strict_types      protected inherit .DocParser;      #include "./debug.h"      //========================================================================   // DOC EXTRACTION   //========================================================================    - protected private class Extractor { + private class Extractor {    protected constant WITH_NL = .PikeParser.WITH_NL;    -  // static private string filename; -  protected private .PikeParser parser; +  // private string filename; +  private .PikeParser parser;       protected .Flags flags;    protected int verbosity;       protected string report(SourcePosition pos, int level,    sprintf_format fmt, sprintf_args ... args)    {    string msg = fmt;    if (sizeof(args)) {    msg = sprintf("PikeExtractor: " + fmt, @args);
pike.git/lib/modules/Tools.pmod/AutoDoc.pmod/PikeExtractor.pmod:33:       if (level <= verbosity) {    if (pos->lastline) {    werror("%s:%d..%d: %s",    pos->filename||"-", pos->firstline, pos->lastline, msg);    } else {    werror("%s:%d: %s",    pos->filename||"-", pos->firstline, msg);    }    } +  msg = (pos->filename||"-")+":"+(pos->firstline)+": "+msg;    return msg;    }       protected void report_error(SourcePosition pos, int level,    sprintf_format fmt, sprintf_args ... args)    {    string msg = report(pos, level, fmt, @args);    if (!(flags & .FLAG_KEEP_GOING)) {    error("%s", msg);    }    }       protected void create(string s, string filename, .Flags flags) { -  this_program::flags = flags; +  this::flags = flags;    verbosity = flags & .FLAG_VERB_MASK;       parser = .PikeParser(0, filename, flags);       array(string) tokens;    array(int) positions;    [tokens, positions] = parser->tokenize(s, 1);       array(string) new_tokens = ({});    array(int) new_positions = ({});       ADT.Stack ignores = ADT.Stack();    ignores->push(0); // End sentinel.    for(int i; i<sizeof(tokens); i++) {    string s = tokens[i];    int pos = positions[i];    if (has_prefix(s, DOC_COMMENT)) { -  s = String.trim_all_whites(s[sizeof(DOC_COMMENT) .. ]); +  s = String.trim(s[sizeof(DOC_COMMENT) .. ]);    if (s == "@ignore") {    ignores->push(pos);    continue;    } else if (s == "@endignore") {    if (ignores->top())    ignores->pop();    else    report_error(SourcePosition(filename, pos), .FLAG_NORMAL,    "@endignore without matching @ignore.\n");    continue;
pike.git/lib/modules/Tools.pmod/AutoDoc.pmod/PikeExtractor.pmod:197:    if (!isIdent(parser->peekToken(WITH_NL)))    extractorError("expected enum constant");    [consts, got_nl] = parseAdjacentEnumConstants();    // consumes the "\n" after them too...    if (isDocComment(parser->peekToken(WITH_NL)))    extractorError("cant have doc both before and after enum constant");    }    else if (parser->peekToken() == "}")    // reached the end of the enum { ... }.    return; -  else +  else {    extractorError("expected doc comment or enum constant, got %O",    parser->peekToken()); -  +  // NB: Only reached in FLAG_KEEP_GOING mode.    -  +  if (parser->peekToken() == "") return; // EOF. +  +  // Get rid of the erroneous token. +  parser->readToken(); +  continue; +  } +     if (doc) {    .DocParser.Parse parse =    .DocParser.Parse(doc->text, doc->position, flags);    .DocParser.MetaData metadata = parse->metadata();    if (metadata->appears || metadata->belongs)    extractorError("@appears or @belongs not allowed in "    "doc for enum constant");    if (metadata->type)    extractorError("@%s not allowed in doc for enum constant",    metadata->type);    doc->xml = parse->doc("_enumconstant"); -  +  }    parent->addChild(DocGroup(consts, doc));    } -  // ignore constants without any adjacent doc comment... +     } -  } +        // parseAdjacentDecls consumes the "\n" that may follow the last decl -  protected array(array(PikeObject)|int(0..1)) parseAdjacentDecls(Class|Module c) +  protected array(array(PikeObject)|int(0..1)) parseAdjacentDecls(AutoDoc root, +  Class|Module c)    {    array(PikeObject) res = ({ });    for (;;) {    // To get the correct line# :    parser->skipNewlines();    SourcePosition pos = parser->currentPosition->copy();       object(PikeObject)|array(PikeObject) p = parser->parseDecl();       multiset(string) allowSqueeze = (<
pike.git/lib/modules/Tools.pmod/AutoDoc.pmod/PikeExtractor.pmod:255:    parser->eat("(");    parseCreateArgList([object(Class)] p);    parser->eat(")");    if (isDocComment(parser->peekToken())) {    Documentation doc = readAdjacentDocLines();    p->squeezedInDoc = doc;    }    }    if (parser->peekToken() == "{") {    parser->eat("{"); -  parseClassBody([object(Class)] p, 0); +  parseClassBody(root, [object(Class)] p, 0);    parser->eat("}");    }    }    else if (objectp(p) && p->objtype == "modifier" &&    parser->peekToken() == "{") {    parser->eat("{"); -  parseClassBody(c, p->modifiers); +  parseClassBody(root, c, p->modifiers);    parser->eat("}");    }    else if (objectp(p) && p->objtype == "enum") {    parser->eat("{"); // after ("enum" opt_id) must come "{"    parseEnumBody([object(Enum)] p);    parser->eat("}");    }    else if (parser->peekToken() == "{") {    int mark1 = parser->getReadDocComments();    parser->skipBlock();
pike.git/lib/modules/Tools.pmod/AutoDoc.pmod/PikeExtractor.pmod:297:    int(0..1) terminating_nl;    if (parser->peekToken(WITH_NL) == "\n") { // we allow ONE "\n" inbetween    terminating_nl = 1;    parser->readToken(WITH_NL);    }    string s = parser->peekToken(WITH_NL);    if (isDelimiter(s) || isDocComment(s))    return ({ res, terminating_nl });    }    } +     // parseClassBody does the main work and scans the stream looking for:    // 1. doclines + decls, no blank line in between    // 2. decls + doclines, ----- " " -----    // 3. doclines (stand-alone doc)    // 4. decls (undocumented decls, discarded)    //    // If 'filename' is supplied, it will look for standalone doc comments    // at the beginning of the file, and then the return value is that    // Documentation for the file. -  Documentation parseClassBody(Class|Module c, +  Documentation parseClassBody(AutoDoc root, Class|Module c,    array(string) defModifiers,    void|string filename, -  void|string inAt) { +  void|string inAt) +  {    Documentation filedoc = 0;    mainloop:    for (;;) {    Documentation doc = 0;    array(PikeObject) decls = ({ });    int(0..1) got_nl;       int docsMark = parser->getReadDocComments();       string s = parser->peekToken();
pike.git/lib/modules/Tools.pmod/AutoDoc.pmod/PikeExtractor.pmod:332:    parser->eat(";");    continue;    }       if (s == EOF || s == "}") // end of class body reached    return filedoc;    if (isDocComment(s)) {    doc = readAdjacentDocLines(); // read the doc comment lines    s = parser->peekToken(WITH_NL);    if (!isDelimiter(s)) { // and decls that may follow -  [decls, got_nl] = parseAdjacentDecls(c); +  [decls, got_nl] = parseAdjacentDecls(root, c);    s = parser->peekToken(WITH_NL);    if (isDocComment(s))    extractorError("doc + decl + doc is forbidden!");    }    }    else { -  [decls, got_nl] = parseAdjacentDecls(c); +  [decls, got_nl] = parseAdjacentDecls(root, c);    s = parser->peekToken(WITH_NL);    if (isDocComment(s))    doc = readAdjacentDocLines();    if (got_nl) {    s = parser->peekToken(WITH_NL);    if ( !isDelimiter(s) )    extractorError("decl + doc + decl is forbidden!");    }    }   
pike.git/lib/modules/Tools.pmod/AutoDoc.pmod/PikeExtractor.pmod:364:    "declaration with sqeezed in documentation must stand alone"    );    if (doc)    extractorError("duplicate documentation");    doc = obj->squeezedInDoc;    }    array(PikeObject) docDecls = ({ });       if (!doc) {    foreach (decls, PikeObject obj) -  if (obj->objtype == "class" && -  ([object(Class)]obj)->containsDoc() && -  sizeof(filter(obj->docGroups->documentation, `!=, EmptyDoc))) { -  extractorWarning("undocumented class %O contains doc comments", -  obj->name); +  if ((< "class", "enum" >)[obj->objtype] && obj->containsDoc()) { +  extractorWarning("undocumented %s %O contains doc comments", +  obj->objtype, obj->name);    doc = EmptyDoc;    }    }          object(.DocParser.Parse) parse = 0;    string appears = 0;    string belongs = 0;    if (doc) {    parse = .DocParser.Parse(doc->text, doc->position, flags);    MetaData meta = parse->metadata(); -  +  object(Class)|Module parent = c;    if (meta->type && meta->type != "decl") {    string what = meta->type;    switch(what) { -  +  case "namespace": +  parent = root; +  // FALL_THROUGH    case "module": -  if (c->objtype == "class" && what == "module") -  extractorError("@module not allowed in class files"); +  // if (c->objtype == "class" && what == "module") +  // extractorError("@module not allowed in class files");    // fall through    case "class":    if (sizeof(decls)) -  extractorError("@module doc comment must stand alone"); +  extractorError("@%s doc comment must stand alone", what);    object(Class)|object(Module) alreadyChild = -  c->findChild(meta->name); +  parent->findChild(meta->name);    object(Class)|object(Module) m;    if (alreadyChild) {    m = alreadyChild;    if (m->objtype != what)    extractorError("found @%s %s, but %s has "    "previously been defined as %s",    what, m->name, m->name, m->objtype);    }    else {    m = what == "class" ? Class() : Module();    m->appears = meta->appears;    m->belongs = meta->belongs;    m->name = meta->name;    }    doc->xml = parse->doc("_" + what); -  m->documentation = doc; -  if (alreadyChild) -  if (doc->xml && doc->xml != "") +  if (doc->xml && doc->xml != "") { +  if (alreadyChild && alreadyChild->documentation && +  alreadyChild->documentation->xml && +  alreadyChild->documentation->xml != "") {    extractorError("doc not allowed on reentrance into '%s %s'",    m->objtype, m->name); -  +  } +  m->documentation = doc; +  }    if (!alreadyChild) -  c->AddChild(m); -  parseClassBody(m, 0, 0, what); +  parent->addChild(m); +  parseClassBody(root, m, 0, 0, what);    continue mainloop; -  +     case "endclass":    case "endmodule": -  +  case "endnamespace":    if (sizeof(decls))    extractorError("@%s doc comment must stand alone", meta->type);    if (inAt != what - "end")    extractorError("@%s has no matching %s",    meta->type, meta->type - "end");    if (meta->name && meta->name != c->name)    extractorError("'@%s %s' doesn't match '@%s %s'",    meta->type, meta->name, c->objtype, c->name || "");    return 0; // no filedoc possible -  +     default:    extractorError("@%s is not allowed in Pike files", meta->type);    }    }    docDecls = meta->decls;    appears = meta->appears;    belongs = meta->belongs;    }    // Objects added by @decl replace the true objects:    if (sizeof(docDecls)) {
pike.git/lib/modules/Tools.pmod/AutoDoc.pmod/PikeExtractor.pmod:490:    foreach(decls, PikeObject obj)    obj->modifiers |= defModifiers;       mapping(string:int) contexts = ([]);       foreach(decls, PikeObject obj)    contexts[obj->objtype] = 1;       if (doc) {    if (wasNonGroupable) { -  object(PikeObject) d = [object(PikeObject)] decls[0]; +  object(PikeObject) d; +  foreach(decls, object(PikeObject) po) { +  if (object_variablep(po, "documentation")) { +  d = po; +  break; +  } +  werror("Warning: Skipping declaration %O.\n", po); +  } +  if (!d) { +  werror("No documentation variable in documented declarations.\n"); +  werror("decls: %O\n", decls); +  exit(1); +  }    d->documentation = doc;    d->appears = appears;    d->belongs = belongs; -  c->AddChild(d); +  c->addChild(d);    }    else {    DocGroup d = DocGroup(decls, doc);    d->appears = appears;    d->belongs = belongs; -  c->AddGroup(d); +  c->addGroup(d);    }       string context;    if (sizeof(indices(contexts)) == 1)    context = "_" + indices(contexts)[0];    else    context = "_general";    doc->xml = parse->doc(context);    } else {    // Make sure that all inherits and imports are added:    foreach(decls, PikeObject obj) {    if ((obj->objtype == "inherit") ||    (obj->objtype == "import")) { -  c->AddInherit(obj); +  c->addInherit(obj);    }    }    }    } // for (;;)    }       void parseCreateArgList(Class c) {    Method createMethod = Method();    createMethod->name = "create"; -  createMethod->modifiers = ({ "static" }); +  createMethod->modifiers = ({ "protected" });    createMethod->returntype = VoidType();    createMethod->argnames = ({});    createMethod->argtypes = ({});       array(Variable) createVars = ({});       for (;;) {    Documentation doc;    if (isDocComment(parser->peekToken())) {    doc = readAdjacentDocLines();
pike.git/lib/modules/Tools.pmod/AutoDoc.pmod/PikeExtractor.pmod:587:    c->docGroups += ({    DocGroup(({ createMethod }), EmptyDoc),    });    if (sizeof(createVars)) {    c->docGroups += ({    DocGroup(createVars, EmptyDoc),    });    }    }    - } // static private class Extractor + } // private class Extractor      //! Extract documentation for a Pike namespace.   //!   //! @seealso   //! @[extractModule()], @[extractClass()] - NameSpace extractNamespace(string s, void|string filename, -  void|string namespaceName, void|.Flags flags) { -  if (zero_type(flags)) flags = .FLAG_NORMAL; + void extractNamespace(AutoDoc root, string s, void|string filename, +  void|string namespaceName, void|.Flags flags) + { +  if (undefinedp(flags)) flags = .FLAG_NORMAL;    Extractor e = Extractor(s, filename, flags);    NameSpace ns = NameSpace();    ns->name = namespaceName || filename; -  Documentation doc = e->parseClassBody(ns, 0, filename); +  root->addChild(ns); +  Documentation doc = e->parseClassBody(root, ns, 0, filename);    ns->documentation = doc; -  // if there was no documentation in the file whatsoever -  if (!doc && !sizeof(ns->docGroups) && !sizeof(ns->children)) -  return 0; -  return ns; +    }      //! Extract documentation for a Pike module.   //!   //! @seealso   //! @[extractNamespace()], @[extractClass()] - Module extractModule(string s, void|string filename, void|string moduleName, -  void|.Flags flags) { -  if (zero_type(flags)) flags = .FLAG_NORMAL; + void extractModule(AutoDoc root, Module parent, string s, void|string filename, +  void|string moduleName, void|.Flags flags) + { +  if (undefinedp(flags)) flags = .FLAG_NORMAL;    Extractor e = Extractor(s, filename, flags);    Module m = Module();    m->name = moduleName || filename; -  Documentation doc = e->parseClassBody(m, 0, filename); +  parent->addChild(m); +  Documentation doc = e->parseClassBody(root, m, 0, filename);    m->documentation = doc; -  // if there was no documentation in the file whatsoever -  if (!doc && !sizeof(m->docGroups) && !sizeof(m->children)) -  return 0; +        // If there's a _module_value it replaces the module itself.    PikeObject module_value = m->findChild("_module_value");    if (module_value) {    module_value->name = m->name; -  m = module_value; +  parent->children -= ({ m }); +  parent->addChild(module_value);    } -  return m; +    }      //! Extract documentation for a Pike class (aka program).   //!   //! @seealso   //! @[extractNamespace()], @[extractModule()] - Class extractClass(string s, void|string filename, void|string className, -  void|.Flags flags) { -  if (zero_type(flags)) flags = .FLAG_NORMAL; + void extractClass(AutoDoc root, Module parent, string s, void|string filename, +  void|string className, void|.Flags flags) + { +  if (undefinedp(flags)) flags = .FLAG_NORMAL;    Extractor e = Extractor(s, filename, flags);    Class c = Class();    c->name = className || filename; -  Documentation doc = e->parseClassBody(c, 0, filename); +  parent->addChild(c); +  Documentation doc = e->parseClassBody(root, c, 0, filename);    c->documentation = doc; -  // if there was no documentation in the file... -  if (!doc && !sizeof(c->docGroups) && !sizeof(c->children)) -  return 0; -  return c; +    }