Permalink
Browse files

use Cappuccino doxygen method to understand @accessors

  • Loading branch information...
1 parent 5577245 commit 5983e19b490d62ce4e87e45cc3b38993f707ef8f Antoine Mercadal committed Oct 18, 2010
Showing with 605 additions and 14 deletions.
  1. +4 −13 { → Doxygen}/StropheCappuccino.doxygen
  2. +2 −0 Doxygen/cleanup_headers
  3. +136 −0 Doxygen/make_headers
  4. +16 −0 Doxygen/make_headers.sh
  5. +39 −1 Jakefile
  6. +408 −0 common.jake
@@ -38,7 +38,7 @@ PROJECT_NUMBER = 1.0.0
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
-OUTPUT_DIRECTORY = Build/Documentation
+OUTPUT_DIRECTORY = Documentation
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
# 4096 sub-directories (in 2 levels) under the output directory of each output
@@ -303,15 +303,6 @@ SYMBOL_CACHE_SIZE = 0
# Build related configuration options
#---------------------------------------------------------------------------
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
-# style sheet that is used by each HTML page. It can be used to
-# fine-tune the look of the HTML output. If the tag is left blank doxygen
-# will generate a default style sheet. Note that doxygen will try to copy
-# the style sheet file to the HTML output directory, so don't put your own
-# stylesheet in the HTML output directory as well, or it will be erased!
-
-HTML_STYLESHEET = doxygen.css
-
# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
# documentation are documented, even if no documentation was available.
# Private class members and static file members will be hidden unless
@@ -599,7 +590,7 @@ WARN_LOGFILE = debug.txt
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
-INPUT = .
+INPUT = /tmp/tempDoc.doc
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
@@ -659,13 +650,13 @@ RECURSIVE = YES
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
-EXCLUDE = AppKit.doc/Themes
+EXCLUDE = /tmp/tempDoc.doc/Test
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
# directories that are symbolic links (a Unix filesystem feature) are excluded
# from the input.
-EXCLUDE_SYMLINKS = YES
+EXCLUDE_SYMLINKS = NO
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
View
@@ -0,0 +1,2 @@
+#! /bin/sh
+rm -rf /tmp/tempDoc.doc
View
@@ -0,0 +1,136 @@
+#! /usr/bin/env ruby
+
+ACCESSOR_GET_TEMPLATE = <<EOS
+/*!
+ Synthesized accessor method.
+*/
+- (\#{ivarType})\#{getter}
+{
+ return \#{ivar};
+}
+
+EOS
+
+ACCESSOR_SET_TEMPLATE = <<EOS
+/*!
+ Synthesized accessor method.
+*/
+- (void)\#{setter}:(\#{ivarType})aValue
+{
+ \#{ivar} = aValue;
+}
+
+EOS
+
+ACCESSORS_IMPLEMENTATION_TEMPLATE = <<EOS
+
+@implementation \#{className} (CPSynthesizedAccessors)
+
+\#{accessorsSource}@end
+EOS
+
+
+def makeHeaderFileFrom(fileName)
+ # Grab the entire file (text)
+ sourceFile = File.new(fileName, "r")
+ source = sourceFile.read
+ sourceFile.close()
+
+ # Remove @accessor declarations from ivars in the source file
+ sourceFile = File.new(fileName, "w")
+ sourceFile.write(source.gsub(/(\s*\w+\s+\w+)\s+@accessors(\(.+?\))?;/m, "\\1;"))
+
+ # Extract all the @implementations blocks. Note, there may be
+ # more than on in a given .j file.
+ m = source.scan(/^\s*(@implementation\s*(\w+)\s*:\s*\w+\s*\{(.*?)\}).*?^\s*@end\s*$/m)
+
+ return if m.length == 0
+
+ for i in 0...m.length
+ groups = m[i]
+ declaration = groups[0]
+ className = groups[1]
+ ivars = groups[2]
+
+ # Change "implementation" to "interface", create the .h file, and write the interface
+ newDeclaration = declaration.sub("@implementation", "@interface")
+ newFileName = File.dirname(fileName) + "/" + className + ".h"
+ f = File.new(newFileName, "a")
+
+ # Change @accessors declarations to a comment, doxygen chokes on them
+ f.write("\n" + newDeclaration.gsub(/(\s*\w+\s+\w+)\s+(@accessors.*?);/m, "\\1; // \\2") + "\n@end\n")
+ f.close()
+
+ # Skip @accessors parsing for private classes
+ next if className[0, 1] == "_"
+
+ # See if there are any @accessors in the ivars
+ accessorsMatches = ivars.scan(/\s*(\w+)\s+(\w+)\s+@accessors(\(.+?\))?;/m)
+ next if accessorsMatches.length == 0
+
+ accessorsSource = ""
+
+ # Create a CPSynthesizedAccessor category for the class with synthesized
+ # accessor methods for each @accessors declaration.
+ for accessorIndex in 0...accessorsMatches.length
+ ivarDeclaration = accessorsMatches[accessorIndex]
+ attributes = ivarDeclaration[2]
+ next if attributes.nil?
+ ivarType = ivarDeclaration[0];
+ ivar = ivarDeclaration[1];
+
+ attributesMatch = attributes.scan(/(\bproperty\s*=\s*(\w+)|\b(readonly)\b|\bgetter\s*=\s*(\w+)|\bsetter\s*=\s*(\w+))/m)
+ next if attributesMatch.length == 0
+
+ getter = nil
+ setter = nil
+ readonly = false
+
+ for attributeIndex in 0...attributesMatch.length
+ if not attributesMatch[attributeIndex][1].nil? # property
+ getter = attributesMatch[attributeIndex][1]
+ setter = readonly ? nil : "set#{getter[0,1].upcase}#{getter[1..-1]}"
+ elsif not attributesMatch[attributeIndex][2].nil? # readonly
+ readonly = true
+ setter = nil
+ elsif not attributesMatch[attributeIndex][3].nil? # getter
+ getter = attributesMatch[attributeIndex][3]
+ elsif not attributesMatch[attributeIndex][4].nil? and not readonly # setter
+ setter = attributesMatch[attributeIndex][4]
+ end
+ end
+
+ # Check for @accessors with no attributes
+ if getter.nil? and setter.nil?
+ getter = ivar
+ setter = "set#{getter[0,1].upcase}#{getter[1..-1]}"
+ end
+
+ accessorsSource += makeAccessors(getter, setter, ivar, ivarType)
+ end
+
+ sourceFile.write(eval('"' + ACCESSORS_IMPLEMENTATION_TEMPLATE + '"'))
+ end
+
+ sourceFile.close()
+end
+
+def makeAccessors(getter, setter, ivar, ivarType)
+ accessors = ""
+
+ if not getter.nil?
+ accessors += eval('"' + ACCESSOR_GET_TEMPLATE + '"')
+ end
+
+ if not setter.nil?
+ accessors += eval('"' + ACCESSOR_SET_TEMPLATE + '"')
+ end
+
+ return accessors
+end
+
+fileList = Dir["/tmp/tempDoc.doc/**/*.j"]
+
+for fileName in fileList
+ makeHeaderFileFrom(fileName)
+end
View
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# NOTE: The working directory should be the main capp directory when this script is run
+
+if [ -d /tmp/tempDoc.doc ]; then
+ rm -rf /tmp/tempDoc.doc
+fi
+
+echo "Copying source files..."
+cp -r . /tmp/tempDoc.doc
+rm -rf /tmp/tempDoc.doc/.git
+
+echo "Processing source files..."
+find /tmp/tempDoc.doc -name "*.j" -exec sed -e '/@import.*/ d' -i '' {} \;
+
+exec Doxygen/make_headers
View
@@ -17,6 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+require("./common.jake")
var ENV = require("system").env,
FILE = require("file"),
@@ -25,9 +26,12 @@ var ENV = require("system").env,
task = JAKE.task,
CLEAN = require("jake/clean").CLEAN,
FileList = JAKE.FileList,
+ stream = require("narwhal/term").stream,
framework = require("cappuccino/jake").framework,
configuration = ENV["CONFIG"] || ENV["CONFIGURATION"] || ENV["c"] || "Release";
+$DOCUMENTATION_BUILD = FILE.join("Build", "Documentation");
+
framework ("StropheCappuccino", function(task)
{
task.setBuildIntermediatesPath(FILE.join("Build", "StropheCappuccino.build", configuration));
@@ -65,7 +69,41 @@ task("release", function()
task ("documentation", function()
{
- OS.system("doxygen StropheCappuccino.doxygen")
+ // try to find a doxygen executable in the PATH;
+ var doxygen = executableExists("doxygen");
+
+ // If the Doxygen application is installed on Mac OS X, use that
+ if (!doxygen && executableExists("mdfind"))
+ {
+ var p = OS.popen(["mdfind", "kMDItemContentType == 'com.apple.application-bundle' && kMDItemCFBundleIdentifier == 'org.doxygen'"]);
+ if (p.wait() === 0)
+ {
+ var doxygenApps = p.stdout.read().split("\n");
+ if (doxygenApps[0])
+ doxygen = FILE.join(doxygenApps[0], "Contents/Resources/doxygen");
+ }
+ }
+
+ if (doxygen && FILE.exists(doxygen))
+ {
+ stream.print("\0green(Using " + doxygen + " for doxygen binary.\0)");
+
+ var documentationDir = FILE.join("Doxygen");
+
+ if (OS.system([FILE.join(documentationDir, "make_headers.sh")]))
+ OS.exit(1); //rake abort if ($? != 0)
+
+ if (!OS.system([doxygen, FILE.join(documentationDir, "StropheCappuccino.doxygen")]))
+ {
+ rm_rf($DOCUMENTATION_BUILD);
+ // mv("debug.txt", FILE.join("Documentation", "debug.txt"));
+ mv("Documentation", $DOCUMENTATION_BUILD);
+ }
+
+ OS.system(["ruby", FILE.join(documentationDir, "cleanup_headers")]);
+ }
+ else
+ stream.print("\0yellow(Doxygen not installed, skipping documentation generation.\0)");
});
task("test", function()
Oops, something went wrong.

0 comments on commit 5983e19

Please sign in to comment.