From fe8858635137d15e55db56ae62988dc378631eb1 Mon Sep 17 00:00:00 2001 From: Richard Frith-Macdonald Date: Mon, 29 Mar 2004 03:44:10 +0000 Subject: [PATCH] Completed integration of Adrians patch. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@18944 72102866-910b-0410-8b05-ffd578937521 --- Tools/AGSHtml.h | 2 + Tools/AGSHtml.m | 75 ++++++++++++++++---- Tools/AGSParser.h | 2 + Tools/AGSParser.m | 20 ++++-- Tools/autogsdoc.m | 172 ++++++++++++++++++++++++++++++++-------------- 5 files changed, 201 insertions(+), 70 deletions(-) diff --git a/Tools/AGSHtml.h b/Tools/AGSHtml.h index e5666f0cc..7ee9e6630 100644 --- a/Tools/AGSHtml.h +++ b/Tools/AGSHtml.h @@ -43,6 +43,7 @@ unsigned ssect; unsigned sssect; BOOL isContentsDoc; + BOOL ivarsAtEnd; } - (void) decIndent; - (void) incIndent; @@ -69,6 +70,7 @@ - (void) setGlobalRefs: (AGSIndex*)r; - (void) setLocalRefs: (AGSIndex*)r; - (void) setProjectRefs: (AGSIndex*)r; +- (void) setInstanceVariablesAtEnd: (BOOL)val; - (NSString*) typeRef: (NSString*)t; @end #endif diff --git a/Tools/AGSHtml.m b/Tools/AGSHtml.m index 70c939dca..14a332c1a 100644 --- a/Tools/AGSHtml.m +++ b/Tools/AGSHtml.m @@ -45,6 +45,8 @@ static GSXMLNode *firstElement(GSXMLNode *nodes) @implementation AGSHtml static NSMutableSet *textNodes = nil; +static NSString *tocFont = nil; +static NSString *mainFont = nil; + (void) initialize { @@ -73,6 +75,10 @@ static NSMutableSet *textNodes = nil; [textNodes addObject: @"url"]; [textNodes addObject: @"var"]; [textNodes addObject: @"footnote"]; + + // default fonts + tocFont = @"sans"; + mainFont = @"palatino linotype"; // good on linux, elsewhere gets 'serif' } } @@ -580,13 +586,8 @@ static NSMutableSet *textNodes = nil; [self decIndent]; [buf appendString: indent]; - // special formatting for table-of-contents frames; ultimately - // this should be moved to stylesheet - if (isContentsDoc) - { - [buf appendString: indent]; - [buf appendString: @"\n"]; - } + [buf appendString: indent]; + [buf appendString: @"\n"]; [buf appendString: @"\n"]; } @@ -1077,7 +1078,12 @@ static NSMutableSet *textNodes = nil; if (isContentsDoc) { [buf appendString: indent]; - [buf appendString: @"\n"]; + [buf appendFormat: @"\n", tocFont]; + } + else + { + [buf appendString: indent]; + [buf appendFormat: @"\n", mainFont]; } if (prevFile != nil) @@ -1488,6 +1494,9 @@ static NSMutableSet *textNodes = nil; if (content == nil) content = @""; sel = [sel stringByAppendingString: content]; + // these nbsp added for readability, but must + // be removed below when making href link + sel = [sel stringByAppendingString: @" "]; if (hadArg == YES) { str = [str stringByAppendingString: @" "]; @@ -1537,13 +1546,19 @@ static NSMutableSet *textNodes = nil; if ([sel length] > 1) { NSString *s; + NSMutableString *linkRef; /* * Output selector heading. */ [buf appendString: indent]; [buf appendString: @"

"]; - s = [self makeLink: sel ofType: @"method" inUnit: nil isRef: NO]; + // get rid of nbsps put in for readability above + linkRef = [NSMutableString stringWithCapacity: [sel length]]; + [linkRef setString:sel]; + [linkRef replaceOccurrencesOfString:@" " withString:@"" + options: 0 range: NSMakeRange(0, [sel length])]; + s = [self makeLink: linkRef ofType: @"method" inUnit: nil isRef: NO]; if (s != nil) { [buf appendString: s]; @@ -2232,6 +2247,8 @@ static NSMutableSet *textNodes = nil; { GSXMLNode *t; NSArray *a; + NSMutableString *ivarBuf = ivarsAtEnd ? + [NSMutableString stringWithCapacity: 1024] : nil; node = [node firstChildElement]; if (node != nil && [[node name] isEqual: @"declared"] == YES) @@ -2312,15 +2329,34 @@ static NSMutableSet *textNodes = nil; if (node != nil && [[node name] isEqual: @"ivariable"] == YES) { - [buf appendString: indent]; - [buf appendString: @"
\n"]; - [buf appendString: indent]; - [buf appendString: @"

Instance variables

\n"]; + /* + * If want instance variables at end, throw it all into an alternate + * buffer and just put a link here; later alt buf must be appended. + */ + NSMutableString *ibuf = buf; + if (ivarsAtEnd) { + ibuf = ivarBuf; + [buf appendString: indent]; + [buf appendString: @"
\n"]; + [buf appendString: indent]; + [buf appendFormat: @"Instance Variables\n", + classname]; + [buf appendString: indent]; + [buf appendString: @"

\n"]; + [ibuf appendFormat: @""]; + } + [ibuf appendString: indent]; + [ibuf appendString: @"

\n"]; + [ibuf appendString: indent]; + [ibuf appendFormat: @"

Instance Variables for %@ Class

\n", + classname]; while (node != nil && [[node name] isEqual: @"ivariable"] == YES) { - [self outputNode: node to: buf]; + [self outputNode: node to: ibuf]; node = [node nextElement]; } + [ibuf appendString: indent]; + [ibuf appendString: @"


\n"]; } a = [localRefs methodsInUnit: unit]; @@ -2343,6 +2379,12 @@ static NSMutableSet *textNodes = nil; node = [node nextElement]; } } + + // if had ivars docs, insert them now + if (ivarsAtEnd) + { + [buf appendString: ivarBuf]; + } } /** @@ -2379,6 +2421,11 @@ static NSMutableSet *textNodes = nil; ASSIGN(projectRefs, r); } +- (void) setInstanceVariablesAtEnd: (BOOL)val +{ + ivarsAtEnd = val; +} + /** * Assuming that the supplied string contains type information (as used * in a method declaration or type cast), we make an attempt at extracting diff --git a/Tools/AGSParser.h b/Tools/AGSParser.h index a08fc1e71..a432f153f 100644 --- a/Tools/AGSParser.h +++ b/Tools/AGSParser.h @@ -53,6 +53,7 @@ BOOL haveSource; BOOL inInstanceVariables; BOOL inArgList; + BOOL documentInstanceVariables; BOOL documentAllInstanceVariables; BOOL verbose; BOOL warn; @@ -91,6 +92,7 @@ - (unsigned) parseSpace; - (void) reset; - (void) setDeclared: (NSString*)name; +- (void) setDocumentInstanceVariables: (BOOL)flag; - (void) setDocumentAllInstanceVariables: (BOOL)flag; - (void) setGenerateStandards: (BOOL)flag; - (void) setStandards: (NSMutableDictionary*)dict; diff --git a/Tools/AGSParser.m b/Tools/AGSParser.m index 8a32ced5e..40705a1f9 100644 --- a/Tools/AGSParser.m +++ b/Tools/AGSParser.m @@ -155,6 +155,7 @@ source = [NSMutableArray new]; verbose = [[NSUserDefaults standardUserDefaults] boolForKey: @"Verbose"]; warn = [[NSUserDefaults standardUserDefaults] boolForKey: @"Warn"]; + documentInstanceVariables = YES; ifStack = [[NSMutableArray alloc] initWithCapacity: 4]; s = [NSMutableSet new]; [ifStack addObject: s]; @@ -2050,8 +2051,7 @@ try: { NSString *validity = @"private"; NSMutableDictionary *ivars; - BOOL shouldDocument = documentAllInstanceVariables; - + BOOL shouldDocument = documentInstanceVariables; DESTROY(comment); inInstanceVariables = YES; @@ -2074,17 +2074,18 @@ try: if ([token isEqual: @"private"] == YES) { ASSIGN(validity, token); - shouldDocument = documentAllInstanceVariables; + shouldDocument = documentInstanceVariables + && documentAllInstanceVariables; } else if ([token isEqual: @"protected"] == YES) { ASSIGN(validity, token); - shouldDocument = YES; + shouldDocument = documentInstanceVariables; } else if ([token isEqual: @"public"] == YES) { ASSIGN(validity, token); - shouldDocument = YES; + shouldDocument = documentInstanceVariables; } else { @@ -3204,6 +3205,15 @@ fail: documentAllInstanceVariables = flag; } +/** + * This method is used to enable (or disable) documentation of instance + * variables. If it is turned off, instance variables will not be documented. + */ +- (void) setDocumentInstanceVariables: (BOOL)flag +{ + documentInstanceVariables = flag; +} + /** * Turn on or off parsing of preprocessor conditional compilation info * indicating the standards complied with. When this is turned on, we diff --git a/Tools/autogsdoc.m b/Tools/autogsdoc.m index ddb23bb05..80101c753 100644 --- a/Tools/autogsdoc.m +++ b/Tools/autogsdoc.m @@ -324,6 +324,18 @@ variables. Normally, only those explicitly declared 'public' or 'protected' will be documented. + DocumentInstanceVariables + This flag permits you to turn off documentation for instance + variables completely. Normally, explicitly declared 'public' or + 'protected' instance variables will be documented. + + InstanceVariablesAtEnd + This flag, if set, directs the HTML generator to place instance + variable documentation at the end of the class, instead of the + beginning. This is useful if you use a lot of protected instance + variables which are only going to be of secondary interest to general + users of the class. + DocumentationDirectory May be used to specify the directory in which generated documentation is to be placed. If this is not set, output is placed in the current @@ -666,18 +678,18 @@ main(int argc, char **argv, char **env) 8) Build index references to external projects. - 8.5) Create HTML frames auxiliary files. + 9) Create HTML frames auxiliary files. - 9) If needed, re-pass through the "gsdoc files" to generate HTML. - 9a) Find files as before. - 9b) Parse as before. - 9c) Feed the DOM tree to an AGSHtml instance, and dump the result to - a file. + 10) If needed, re-pass through the "gsdoc files" to generate HTML. + 10a) Find files as before. + 10b) Parse as before. + 10c) Feed the DOM tree to an AGSHtml instance, and dump the result to + a file. - 10) For HTML files that were given on the command line, adjust all cross + 11) For HTML files that were given on the command line, adjust all cross reference HREFs to paths given in arguments. - 11) If MakeDependencies was requested, list all header and source files + 12) If MakeDependencies was requested, list all header and source files as colon-dependencies of the project name. */ @@ -723,6 +735,8 @@ main(int argc, char **argv, char **env) @"\t\t\tspecial\t(nil)\n\tdictionary used to preprocess (see docs)", @"WordMap", @"\t\t\tBOOL\t(NO)\n\twhether to insert information on standards compliance", @"Standards", @"BOOL\t(NO)\n\tdocument private instance variables", @"DocumentAllInstanceVariables", + @"\tBOOL\t(YES)\n\tdocument instance variables at all", @"DocumentInstanceVariables", + @"\tBOOL\t(YES)\n\tput instance variable docs at end of class", @"InstanceVariablesAtEnd", @"\t\tSTR\t(\"None\")\n\twhether to include other projects in index", @"LocalProjects", @"\t\tSTR\t(\"None\")\n\twhether to include system projects in index", @"SystemProjects", @"\t\t\tSTR\t(\"None\")\n\texplicit list of other projects to index", @"Projects", @@ -756,15 +770,14 @@ main(int argc, char **argv, char **env) GSPrintf(stderr, @"Usage:\n"); GSPrintf(stderr, [NSString stringWithFormat: - @" %@ [options] [files]\n", - [argsGiven objectAtIndex :0]]); + @" %@ [options] [files]\n", + [argsGiven objectAtIndex: 0]]); GSPrintf(stderr, @"\n Options:\n"); for (i=0; i<[args count]; i++) { arg = [args objectAtIndex: i]; - GSPrintf(stderr, [NSString stringWithFormat: - @" -%@\t%@\n\n", - arg, [argsRecognized objectForKey: - arg]]); + GSPrintf(stderr, + [NSString stringWithFormat: @" -%@\t%@\n\n", + arg, [argsRecognized objectForKey: arg]]); } GSPrintf(stderr, @"\n Files:\n"); @@ -1118,6 +1131,11 @@ main(int argc, char **argv, char **env) { [parser setDocumentAllInstanceVariables: YES]; } + if ([defs objectForKey: @"DocumentInstanceVariables"] != nil + && [defs boolForKey: @"DocumentInstanceVariables"] == NO) + { + [parser setDocumentInstanceVariables: NO]; + } for (i = 0; i < count; i++) { @@ -1657,29 +1675,32 @@ main(int argc, char **argv, char **env) } /* - * 8.5) If we are generating HTML frames, create the gsdoc files specifying + * 9) If we are generating HTML frames, create the gsdoc files specifying * indices that we will use. */ if ([defs boolForKey: @"MakeFrames"] == YES) { int i; int cap = 1360; - NSArray *idxTypes = [NSArray arrayWithObjects: - @"class", - @"constant", - @"function", - @"macro", - @"type", - @"variable", - @"tool", - nil]; - NSString *idxIndexFile; - NSMutableString *idxIndex = [NSMutableString stringWithCapacity: 5*cap]; - NSString *framesetFile; - NSMutableString *frameset = [NSMutableString stringWithCapacity: cap]; - NSMutableString *tocSkel = [NSMutableString stringWithCapacity: cap]; + NSArray *idxTypes = [NSArray arrayWithObjects: + @"class", + @"constant", + @"function", + @"macro", + @"type", + @"variable", + @"tool", + nil]; + NSString *idxIndexFile; + NSMutableString *idxIndex= [NSMutableString stringWithCapacity: 5*cap]; + NSString *framesetFile; + NSMutableString *frameset = [NSMutableString stringWithCapacity: cap]; + NSMutableString *tocSkel = [NSMutableString stringWithCapacity: cap]; + NSString *prjFile = + [NSString stringWithFormat: @"%@.gsdoc",project]; - [tocSkel setString :@"\n" + // skeleton for table of contents files + [tocSkel setString: @"\n" "\n" "\n" " \n" @@ -1693,14 +1714,16 @@ main(int argc, char **argv, char **env) " \n" "\n"]; [tocSkel replaceOccurrencesOfString: @"[prjName]" withString: project - options: 0 - range: NSMakeRange(0, [tocSkel length])]; + options: 0 + range: NSMakeRange(0, [tocSkel length])]; + // file for top-left frame (header only; rest appended below) idxIndexFile = [@"MainIndex" stringByAppendingPathExtension: @"html"]; [idxIndex setString: @"\n \n" " Index

\n" " "]; + // this becomes index.html framesetFile = [@"index" stringByAppendingPathExtension: @"html"]; [frameset setString: @"\n" "\n" @@ -1721,27 +1744,30 @@ main(int argc, char **argv, char **env) options: 0 range: NSMakeRange(0, [frameset length])]; + // generate the table of contents gsdoc files for (i=0; i<[idxTypes count]; i++) { - NSString *gsdocFile; - NSString *htmlFile; - NSMutableString *contents= [NSMutableString stringWithCapacity: cap]; + NSString *gsdocFile; + NSString *htmlFile; + NSMutableString *contents; + NSString *typeL = [idxTypes objectAtIndex: i]; + NSString *typeU = [typeL capitalizedString]; + + contents = [NSMutableString stringWithCapacity: cap]; [contents setString: tocSkel]; - NSString *typeL = [idxTypes objectAtIndex: i]; - NSString *typeU = [typeL capitalizedString]; typeU = [@"Class" isEqualToString: typeU] ? [typeU stringByAppendingString: @"es"] : [typeU stringByAppendingString: @"s"]; [contents replaceOccurrencesOfString: @"[typeL]" withString: typeL - options: 0 + options: 0 range: NSMakeRange(0,[contents length])]; [contents replaceOccurrencesOfString: @"[typeU]" withString: typeU - options: 0 - range: NSMakeRange(0, [contents length])]; + options: 0 + range: NSMakeRange(0,[contents length])]; gsdocFile = [[typeU stringByAppendingString: @"TOC"] - stringByAppendingPathExtension: @"gsdoc"]; + stringByAppendingPathExtension: @"gsdoc"]; htmlFile = [[typeU stringByAppendingString: @"TOC"] - stringByAppendingPathExtension: @"html"]; + stringByAppendingPathExtension: @"html"]; if ([[projectRefs refs] objectForKey: typeL] != nil) { @@ -1771,11 +1797,51 @@ main(int argc, char **argv, char **env) [frameset writeToFile: [documentationDirectory stringByAppendingPathComponent: framesetFile] atomically: YES]; + + // it is possible that .gsdoc does not exist; if that is the + // case, generate one now as a placeholder + for (i=0; i<[gFiles count]; i++) + { + NSString *fname = [gFiles objectAtIndex: i]; + if ([fname rangeOfString: prjFile].length > 0) + break; + } + if (i == [gFiles count]) + { + NSLog(@"\n\nNOTE: Generating a simple introductory page for your" +" project.\nTo replace this with a custom version, edit the gsdoc file \n" +"named %@ in the documentation output directory.\n" +"Then include this file in the arguments to autogsdoc.\n\n", prjFile); + NSMutableString *prjFileContents = + [NSMutableString stringWithCapacity: cap]; + [prjFileContents setString: @"\n" +"\n" +"\n" +" \n" +" The [prjName] Project\n" +" \n" +" \n" +" \n" +"

The index below lists the major components of the [prjName] \n" +" documentation.

\n" +" \n" +"
\n" +" \n" +"
\n"]; + [prjFileContents replaceOccurrencesOfString: @"[prjName]" + withString: project + options: 0 + range: NSMakeRange(0, [prjFileContents length])]; + [prjFileContents writeToFile: + [documentationDirectory stringByAppendingPathComponent: prjFile] + atomically: YES]; + [gFiles addObject: prjFile]; + } } /* - * 9) Next pass ... generate html output from gsdoc files if required. + * 10) Next pass ... generate html output from gsdoc files if required. */ count = [gFiles count]; if (generateHtml == YES && count > 0) @@ -1803,9 +1869,9 @@ main(int argc, char **argv, char **env) } #endif /* - * 9a) As before in connection with (6a), drop path information - * and look for gsdoc files in 'documentationDirectory' or - * CWD. + * 10a) As before in connection with (6a), drop path information + * and look for gsdoc files in 'documentationDirectory' or + * CWD. */ file = [[arg lastPathComponent] stringByDeletingPathExtension]; @@ -1854,7 +1920,7 @@ main(int argc, char **argv, char **env) NSLog(@"%@: gsdoc %@, html %@ ==> regenerate", file, gDate, hDate); } - // 9b) parse the .gsdoc file + // 10b) parse the .gsdoc file parser = [GSXMLParser parserWithContentsOfFile: gsdocfile]; [parser doValidityChecking: YES]; [parser keepBlanks: NO]; @@ -1875,13 +1941,15 @@ main(int argc, char **argv, char **env) [localRefs makeRefs: root]; /* - * 9c) Feed the XML tree to an AGSHtml instance, and dump - * the result to a file. + * 10c) Feed the XML tree to an AGSHtml instance, and dump + * the result to a file. */ html = AUTORELEASE([AGSHtml new]); [html setGlobalRefs: globalRefs]; [html setProjectRefs: projectRefs]; [html setLocalRefs: localRefs]; + [html setInstanceVariablesAtEnd: + [defs boolForKey: @"InstanceVariablesAtEnd"]]; generated = [html outputDocument: root]; if ([generated writeToFile: htmlfile atomically: YES] == NO) { @@ -1901,7 +1969,7 @@ main(int argc, char **argv, char **env) } /* - * 10) Relocate existing html documents if required ... adjust all cross + * 11) Relocate existing html documents if required ... adjust all cross * referencing within those documents. This entails searching for *
links, parsing the key, and replacing the * contents as per our current index info (which may have changed). @@ -1955,6 +2023,8 @@ main(int argc, char **argv, char **env) [html setGlobalRefs: globalRefs]; [html setProjectRefs: projectRefs]; [html setLocalRefs: nil]; + [html setInstanceVariablesAtEnd: + [defs boolForKey: @"InstanceVariablesAtEnd"]]; s = [NSMutableString stringWithContentsOfFile: src]; l = [s length]; @@ -2105,7 +2175,7 @@ main(int argc, char **argv, char **env) } /* - * 11) If MakeDependencies was requested, list all header and source files + * 12) If MakeDependencies was requested, list all header and source files * as colon-dependencies of the project name. */ if ([defs stringForKey: @"MakeDependencies"] != nil)