<html>
<head>
<style><!--
body {background-color:#ffffff;}
.file {border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;}
.pathname {font-family:monospace; float:right;}
.fileheader {margin-bottom:.5em;}
.diff {margin:0;}
.tasklist {padding:4px;border:1px dashed #000000;margin-top:1em;}
.tasklist ul {margin-top:0;margin-bottom:0;}
tr.alt {background-color:#eeeeee}
#added {background-color:#ddffdd;}
#addedchars {background-color:#99ff99;font-weight:bolder;}
tr.alt #added {background-color:#ccf7cc;}
#removed {background-color:#ffdddd;}
#removedchars {background-color:#ff9999;font-weight:bolder;}
tr.alt #removed {background-color:#f7cccc;}
#copied {background-color:#ccccff;}
tr.alt #copied {background-color:#bbbbf7;}
#info {color:#888888;}
#context {background-color:#eeeeee;}
td {padding-left:.3em;padding-right:.3em;}
tr.head {border-bottom-width:1px;border-bottom-style:solid;}
tr.head td {padding:0;padding-top:.2em;}
.task {background-color:#ffff00;}
.comment {white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;padding:4px;border:1px dashed #000000;background-color:#ffffdd}
.error {color:red;}
hr {border-width:0px;height:2px;background:black;}
--></style>
</head>
<body>
<table cellspacing="0" cellpadding="0" border="0" rules="cols">
<tr class="head"><td colspan="5">Commit in <b><tt>as2api/trunk/as2api</tt></b></td></tr>
<tr><td><tt><a href="#file1"><span id="removed">api_diff.rb</span></a></tt> </td><td></td><td></td><td align="right" id="removed">-294</td><td nowrap="nowrap">332 removed</td></tr>
<tr class="alt"><td><tt><a href="#file2"><span id="removed">api_loader.rb</span></a></tt> </td><td></td><td></td><td align="right" id="removed">-602</td><td nowrap="nowrap">332 removed</td></tr>
<tr><td><tt><a href="#file3"><span id="removed">api_model.rb</span></a></tt> </td><td></td><td></td><td align="right" id="removed">-471</td><td nowrap="nowrap">332 removed</td></tr>
<tr class="alt"><td><tt><a href="#file4"><span id="removed">doc_comment.rb</span></a></tt> </td><td></td><td></td><td align="right" id="removed">-599</td><td nowrap="nowrap">332 removed</td></tr>
<tr><td><tt><a href="#file5"><span id="removed">documenter.rb</span></a></tt> </td><td></td><td></td><td align="right" id="removed">-67</td><td nowrap="nowrap">332 removed</td></tr>
<tr class="alt"><td><tt>lib/<a href="#file6"><span id="copied">api_diff.rb</span></a></tt> </td><td colspan="3" align="center"><small id="info">[copied]</small></td><td nowrap="nowrap" align="center">as2api/trunk/as2api/api_diff.rb:332 -> 333</td></tr>
<tr><td><tt> /<a href="#file7"><span id="copied">api_loader.rb</span></a></tt> </td><td colspan="3" align="center"><small id="info">[copied]</small></td><td nowrap="nowrap" align="center">as2api/trunk/as2api/api_loader.rb:332 -> 333</td></tr>
<tr class="alt"><td><tt> /<a href="#file8"><span id="copied">api_model.rb</span></a></tt> </td><td colspan="3" align="center"><small id="info">[copied]</small></td><td nowrap="nowrap" align="center">as2api/trunk/as2api/api_model.rb:332 -> 333</td></tr>
<tr><td><tt> /<a href="#file9"><span id="copied">doc_comment.rb</span></a></tt> </td><td colspan="3" align="center"><small id="info">[copied]</small></td><td nowrap="nowrap" align="center">as2api/trunk/as2api/doc_comment.rb:332 -> 333</td></tr>
<tr class="alt"><td><tt> /<a href="#file10"><span id="copied">documenter.rb</span></a></tt> </td><td colspan="3" align="center"><small id="info">[copied]</small></td><td nowrap="nowrap" align="center">as2api/trunk/as2api/documenter.rb:332 -> 333</td></tr>
<tr><td><tt> /<a href="#file11"><span id="copied">localisation</span></a></tt> </td><td colspan="3" align="center"><small id="info">[copied]</small></td><td nowrap="nowrap" align="center">as2api/trunk/as2api/localisation:332 -> 333</td></tr>
<tr class="alt"><td><tt>lib/localisation/<a href="#file12"><span id="copied">xliff</span></a></tt> </td><td colspan="3" align="center"><small id="info">[copied]</small></td><td nowrap="nowrap" align="center">as2api/trunk/as2api/localisation/xliff:332 -> 333</td></tr>
<tr><td><tt>lib/<a href="#file13"><span id="copied">output</span></a></tt> </td><td colspan="3" align="center"><small id="info">[copied]</small></td><td nowrap="nowrap" align="center">as2api/trunk/as2api/output:332 -> 333</td></tr>
<tr class="alt"><td><tt>lib/output/<a href="#file14"><span id="copied">diff</span></a></tt> </td><td colspan="3" align="center"><small id="info">[copied]</small></td><td nowrap="nowrap" align="center">as2api/trunk/as2api/output/diff:332 -> 333</td></tr>
<tr><td><tt> /<a href="#file15"><span id="copied">html</span></a></tt> </td><td colspan="3" align="center"><small id="info">[copied]</small></td><td nowrap="nowrap" align="center">as2api/trunk/as2api/output/html:332 -> 333</td></tr>
<tr class="alt"><td><tt> /<a href="#file16"><span id="removed">utils.rb</span></a></tt> </td><td></td><td></td><td align="right" id="removed">-48</td><td nowrap="nowrap">330 removed</td></tr>
<tr><td><tt> /<a href="#file17"><span id="copied">utils.rb</span></a></tt> </td><td colspan="3" align="center"><small id="info">[copied]</small></td><td nowrap="nowrap" align="center">as2api/trunk/as2api/output/utils.rb:332 -> 333</td></tr>
<tr class="alt"><td><tt> /<a href="#file18"><span id="copied">xml</span></a></tt> </td><td colspan="3" align="center"><small id="info">[copied]</small></td><td nowrap="nowrap" align="center">as2api/trunk/as2api/output/xml:332 -> 333</td></tr>
<tr><td><tt>lib/<a href="#file19"><span id="copied">ui</span></a></tt> </td><td colspan="3" align="center"><small id="info">[copied]</small></td><td nowrap="nowrap" align="center">as2api/trunk/as2api/ui:332 -> 333</td></tr>
<tr class="alt"><td><tt>lib/ui/<a href="#file20"><span id="removed">cli.rb</span></a></tt> </td><td></td><td></td><td align="right" id="removed">-406</td><td nowrap="nowrap">330 removed</td></tr>
<tr><td><tt> /<a href="#file21"><span id="copied">cli.rb</span></a></tt> </td><td colspan="3" align="center"><small id="info">[copied]</small></td><td nowrap="nowrap" align="center">as2api/trunk/as2api/ui/cli.rb:332 -> 333</td></tr>
<tr class="alt"><td><tt>lib/<a href="#file22"><span id="copied">xhtmlwriter.rb</span></a></tt> </td><td colspan="3" align="center"><small id="info">[copied]</small></td><td nowrap="nowrap" align="center">as2api/trunk/as2api/xhtmlwriter.rb:332 -> 333</td></tr>
<tr><td><tt> /<a href="#file23"><span id="copied">xmlwriter.rb</span></a></tt> </td><td colspan="3" align="center"><small id="info">[copied]</small></td><td nowrap="nowrap" align="center">as2api/trunk/as2api/xmlwriter.rb:332 -> 333</td></tr>
<tr class="alt"><td><tt><a href="#file24"><span id="removed">xhtmlwriter.rb</span></a></tt> </td><td></td><td></td><td align="right" id="removed">-156</td><td nowrap="nowrap">332 removed</td></tr>
<tr><td><tt><a href="#file25"><span id="removed">xmlwriter.rb</span></a></tt> </td><td></td><td></td><td align="right" id="removed">-109</td><td nowrap="nowrap">332 removed</td></tr>
<tr><td></td><td></td><td></td><td align="right" id="removed">-2752</td><td></td></tr>
</table>
<small id="info">9 removed + 16 copied, total 25 files</small><br />
<pre class="comment">
Moving most of the code into a lib subdirectory, in accordance with normal Ruby practice
</pre>
<hr /><a name="file1" /><div class="file">
<span class="pathname" id="removed">as2api/trunk/as2api</span><br />
<div class="fileheader" id="removed"><big><b>api_diff.rb</b></big> <small id="info">removed after 332</small></div>
<pre class="diff"><small id="info">--- trunk/as2api/api_diff.rb        2006-03-23 20:31:08 UTC (rev 332)
+++ trunk/as2api/api_diff.rb        2006-03-23 21:23:41 UTC (rev 333)
@@ -1,294 +0,0 @@
</small></pre><pre class="diff" id="removed">-#
-# Part of as2api - http://www.badgers-in-foil.co.uk/projects/as2api/
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-
-
-class APIDiff
- def diff(old, new)
- added_packages, removed_packages, oldpkg_to_newpkg = diff_lists(old.packages, new.packages) {|old,new| old.name==new.name}
-
- modified_packages = diff_map(oldpkg_to_newpkg, :diff_package)
-
- if added_packages.empty? && removed_packages.empty? && modified_packages.empty?
- nil
- else
- APIChanges.new(added_packages, removed_packages, modified_packages)
- end
- end
-
- private
-
- def diff_lists(oldlist, newlist)
- removed = []
- matching = {}
-
- oldlist.each do |oldval|
- newval = newlist.detect {|a| yield oldval,a}
- if newval
-        matching[oldval] = newval
- else
-        removed << oldval
- end
- end
-
- added = newlist - matching.values
-
- [added, removed, matching]
- end
-
- def find_package(packages, name)
- packages.detect {|pkg| pkg.name == name}
- end
-
- def diff_map(old_to_new, diff_method_sym)
- result = []
- old_to_new.each do |oldval, newval|
- change = send(diff_method_sym, oldval, newval)
- result << change if change
- end
- result
- end
-
- def diff_package(oldpkg, newpkg)
- added_types, removed_types, old_to_new = diff_lists(oldpkg.types, newpkg.types) {|old,new| old.unqualified_name==new.unqualified_name}
-
- modified_types = diff_map(old_to_new, :diff_type)
- if added_types.empty? && removed_types.empty? && modified_types.empty?
- nil
- else
- PackageChanges.new(newpkg.name, added_types, removed_types, modified_types)
- end
- end
-
- def diff_type(old_type, new_type)
- # TODO: handle class>interface, interface>class changes
- if old_type.is_a?(ASClass) && new_type.is_a?(ASClass)
- added_fields, removed_fields, old_to_new_fields = diff_lists(old_type.fields, new_type.fields) {|old,new| old.name==new.name}
- modified_fields = diff_map(old_to_new_fields, :diff_field)
- else
- added_fields = removed_fields = modified_fields = nil
- end
-
- added_methods, removed_methods, old_to_new_methods = diff_lists(old_type.methods, new_type.methods) {|old,new| old.name==new.name}
- modified_methods = diff_map(old_to_new_methods, :diff_method)
-
- if added_methods.empty? && removed_methods.empty? && (new_type.is_a?(ASInterface) || new_type.is_a?(ASClass) && modified_methods.empty? && added_fields.empty? && removed_fields.empty? && modified_fields.empty?)
- nil
- else
- TypeChanges.new(new_type, added_methods, removed_methods, modified_methods, added_fields, removed_fields, modified_fields)
- end
- end
-
- def diff_field(old_field, new_field)
- visibility_change, static_change = diff_access(old_field.access, new_field.access)
- type_change = diff_typesig(old_field.field_type, new_field.field_type)
- readwrite_change = diff_field_readwrite(old_field, new_field)
-
- if visibility_change || static_change || type_change || readwrite_change
- FieldChange.new(new_field.name, visibility_change, static_change, type_change, readwrite_change)
- else
- nil
- end
- end
-
- def diff_method(old_method, new_method)
- visibility_change, static_change = diff_access(old_method.access, new_method.access)
- type_change = diff_typesig(old_method.return_type, new_method.return_type)
- args_change = diff_args(old_method.arguments, new_method.arguments)
- if visibility_change || static_change || type_change || args_change
- MethodChange.new(new_method.name, visibility_change, static_change, type_change, args_change)
- else
- nil
- end
- end
-
- def diff_access(old_access, new_access)
- visibility_change = diff_visibility(old_access.visibility, new_access.visibility)
- static_change = diff_static(old_access.static?, new_access.static?)
- [visibility_change, static_change]
- end
-
- def diff_visibility(old_visibility, new_visibility)
- if old_visibility != new_visibility
- VisibilityChange.new(old_visibility, new_visibility)
- else
- nil
- end
- end
-
- def diff_static(old_flag, new_flag)
- if old_flag != new_flag
- StaticChange.new(old_flag, new_flag)
- else
- nil
- end
- end
-
- def diff_field_readwrite(old_field, new_field)
- # TODO: smells like an enumeration (RO, WO, RW) is needed,
- if old_field.read? != new_field.read? || old_field.write? != new_field.write?
- ReadWriteChange.new(old_field.read?, new_field.read?, old_field.write?, new_field.write?)
- else
- nil
- end
- end
-
- def diff_typesig(old_type, new_type)
- if old_type.nil?
- old_type_name = nil
- else
- old_type_name = old_type.resolved? ? old_type.resolved_type.qualified_name : old_type.local_name
- end
- if new_type.nil?
- new_type_name = nil
- else
- new_type_name = new_type.resolved? ? new_type.resolved_type.qualified_name : new_type.local_name
- end
- if old_type_name != new_type_name
- TypeSigChange.new(old_type_name, new_type_name)
- end
- end
-
- def args_differ?(old_args, new_args)
- return true if old_args.length != new_args.length
-
- old_args.each_with_index do |arg, i|
- return true unless arg.name == new_args[i].name && arg_type_name(arg.arg_type) == arg_type_name(new_args[i].arg_type)
- end
-
- false
- end
-
- def arg_type_name(arg_type)
- return nil if arg_type.nil?
- arg_type.resolved? ? arg_type.resolved_type.qualified_name : arg_type.local_name
- end
-
- def diff_args(old_args, new_args)
- if args_differ?(old_args, new_args)
- ArgumentChange.new(old_args, new_args)
- else
- nil
- end
- end
-end
-
-
-class APIChanges
- def initialize(added_packages, removed_packages, modified_packages)
- @added_packages = added_packages
- @removed_packages = removed_packages
- @modified_packages = modified_packages
- end
-
- attr_accessor :added_packages, :removed_packages, :modified_packages
-end
-
-
-class PackageChanges
- def initialize(name, added_types, removed_types, modified_types)
- @name = name
- @added_types = added_types
- @removed_types = removed_types
- @modified_types = modified_types
- end
-
- attr_accessor :name, :added_types, :removed_types, :modified_types
-end
-
-class TypeChanges
- def initialize(new_type, added_methods, removed_methods, modified_methods, added_fields, removed_fields, modified_fields)
- @new_type = new_type
- @added_methods = added_methods
- @removed_methods = removed_methods
- @modified_methods = modified_methods
- @added_fields = added_fields
- @removed_fields = removed_fields
- @modified_fields = modified_fields
- end
-
- attr_accessor :new_type, :added_methods, :removed_methods, :modified_methods, :added_fields, :removed_fields, :modified_fields
-end
-
-class VisibilityChange
- def initialize(old_vis, new_vis)
- @old_vis = old_vis
- @new_vis = new_vis
- end
-
- attr_accessor :old_vis, :new_vis
-end
-
-
-class FieldChange
- def initialize(name, visibility_change, static_change, type_change, readwrite_change)
- @name = name
- @visibility_change = visibility_change
- @static_change = static_change
- @type_change = type_change
- @readwrite_change = readwrite_change
- end
-
- attr_accessor :name, :visibility_change, :static_change, :type_change, :readwrite_change
-end
-
-class MethodChange
- def initialize(name, visibility_change, static_change, type_change, args_change)
- @name = name
- @visibility_change = visibility_change
- @static_change = static_change
- @type_change = type_change
- @args_change = args_change
- end
-
- attr_accessor :name, :visibility_change, :static_change, :type_change, :args_change
-end
-
-class StaticChange
- def initialize(old_flag, new_flag)
- @old_flag = old_flag
- @new_flag = new_flag
- end
-
- attr_accessor :old_flag, :new_flag
-end
-
-
-class ReadWriteChange
- def initialize(old_read, new_read, old_write, new_write)
- @old_read = old_read
- @new_read = new_read
- @old_write = old_write
- @new_write = new_write
- end
-
- attr_accessor :old_read, :new_read, :old_write, :new_write
-end
-
-class TypeSigChange
- # TODO: pass the ASTypes instead
- def initialize(old_type_name, new_type_name)
- @old_type_name = old_type_name
- @new_type_name = new_type_name
- end
-
- attr_accessor :old_type_name, :new_type_name
-end
-
-ArgumentChange = Struct.new("ArgumentChange", :old_args, :new_args)
-
-# vim:shiftwidth=2:softtabstop=2
</pre></div>
<hr /><a name="file2" /><div class="file">
<span class="pathname" id="removed">as2api/trunk/as2api</span><br />
<div class="fileheader" id="removed"><big><b>api_loader.rb</b></big> <small id="info">removed after 332</small></div>
<pre class="diff"><small id="info">--- trunk/as2api/api_loader.rb        2006-03-23 20:31:08 UTC (rev 332)
+++ trunk/as2api/api_loader.rb        2006-03-23 21:23:41 UTC (rev 333)
@@ -1,602 +0,0 @@
</small></pre><pre class="diff" id="removed">-#
-# Part of as2api - http://www.badgers-in-foil.co.uk/projects/as2api/
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-
-
-require 'parse/aslexer'
-require 'parse/parser'
-require 'api_model'
-require 'doc_comment'
-require 'parse/doccomment_lexer'
-require 'stringio'
-
-# We used to just define the class again to add this attribute, but I want
-# to be compatable with Ruby1.6, which doesn' allow 'class ModName::ClassName'
-ActionScript::Parse::ASToken.module_eval("attr_accessor :last_comment")
-
-
-def simple_parse(input, source)
- as_io = ASIO.new(input)
- lex = ActionScript::Parse::ASLexer.new(as_io)
- lex.source = source
- skip = DocASLexer.new(lex)
- parse = DocASParser.new(skip)
- handler = DocASHandler.new(source)
- parse.handler = handler
- parse.parse_compilation_unit
- handler.defined_type
-end
-
-
-def parse_file(file)
- File.open(File.join(file.prefix, file.suffix)) do |io|
- begin
- is_utf8 = detect_bom?(io)
- astype = simple_parse(io, file.suffix)
- astype.input_file = file
- astype.source_utf8 = is_utf8
- return astype
- rescue =>e
- $stderr.puts "#{file.suffix}: #{e.message}\n#{e.backtrace.join("\n")}"
- end
- end
-end
-
-
-# Hacked subclass of SkipASLexer that remembers multiline comment tokens as
-# they're bing skipped over, and then pokes them into the next real token
-# that comes by
-class DocASLexer < ActionScript::Parse::SkipASLexer
- def initialize(io)
- super(io)
- @last_comment= nil
- end
-
- attr_accessor :last_comment
- protected
- def skip?(tok)
- if tok.instance_of?(ActionScript::Parse::MultiLineCommentToken) &&
- tok.body =~ /^\*/
- @last_comment = tok
- end
- result = super(tok)
- unless result
- if @last_comment
- tok.last_comment = @last_comment
-        @last_comment = nil
- end
- end
- result
- end
-end
-
-
-# Take the comment tokens stuffed into 'real' tokens by DocASLexer, and
-# pass these to our DocASHandler instance for parts of the grammar where
-# they might contain API docs
-class DocASParser < ActionScript::Parse::ASParser
- def parse_class_or_intrinsic_definition
- snarf_comment
- super()
- end
-
- def parse_interface_definition
- snarf_comment
- super()
- end
-
- def parse_class_member
- snarf_comment
- super()
- end
-
- def parse_interface_function
- snarf_comment
- super()
- end
-
- private
-
- def snarf_comment
- @handler.doc_comment @lex.peek_next.last_comment
- end
-end
-
-
-# Builds a model of the API being processed as ActionScript::Parse::Parser
-# recognises pieces of the ActionScript grammar
-class DocASHandler < ActionScript::Parse::ASHandler
- def initialize(source)
- @source = source
- parse_conf_build = ConfigBuilder.new
- @method_comment_config = parse_conf_build.build_method_config
- @field_comment_config = parse_conf_build.build_field_config
- @type_comment_config = parse_conf_build.build_type_config
- end
-
- def compilation_unit_start
- @import_list = ImportList.new
- @defined_type = nil
- end
-
- attr_accessor :defined_type
-
- def doc_comment(comment)
- @doc_comment = comment
- end
-
- def import(name)
- @import_list.add_import(name)
- end
-
- def start_class(dynamic, name, super_name, interfaces)
- pkg_name = name[0, name.length-1].join(".")
- cls_name = name.last.body
- @defined_type = ASClass.new(pkg_name, cls_name)
- @type_namespace = TypeLocalNamespace.new(@defined_type)
- if @doc_comment
- @defined_type.comment = parse_comment(@type_comment_config, @doc_comment)
- end
- @defined_type.dynamic = dynamic
- if super_name
- @defined_type.extends = @type_namespace.resolve(super_name)
- end
- if interfaces
- interfaces.each do |interface|
- @defined_type.add_interface(@type_namespace.resolve(interface))
- end
- end
- @defined_type.type_namespace = @type_namespace
- @defined_type.import_list = @import_list
- end
-
- def start_intrinsic_class(dynamic, name, super_name, interfaces)
- start_class(dynamic, name, super_name, interfaces)
- @defined_type.intrinsic = true
- end
-
- def start_interface(name, super_name)
- pkg_name = name[0, name.length-1].join(".")
- int_name = name.last.body
- @defined_type = ASInterface.new(pkg_name, int_name)
- @type_namespace = TypeLocalNamespace.new(@defined_type)
- if @doc_comment
- @defined_type.comment = parse_comment(@type_comment_config, @doc_comment)
- end
- if super_name
- @defined_type.extends = @type_namespace.resolve(super_name)
- end
- @defined_type.type_namespace = @type_namespace
- @defined_type.import_list = @import_list
- end
-
- def access_modifier(modifier)
- vis = case modifier.visibility
- when ActionScript::Parse::PublicToken
-        :public
- when ActionScript::Parse::PrivateToken
-        :private
- when nil
-        nil
- else
-        raise "unhandled visibility #{modifier.visibility.inspect}"
- end
- @last_modifier = ASAccess.new(vis, modifier.is_static)
- end
-
- def show_modifier
- visibility = @last_modifier.visibility
- if visibility.instance_of?(ActionScript::Parse::PublicToken)
- print "public "
- elsif visibility.instance_of?(ActionScript::Parse::PrivateToken)
- print "private "
- end
- if @last_modifier.is_static
- print "static "
- end
- end
-
- def start_member_field(name, astype)
- field = ASExplicitField.new(@defined_type, @last_modifier, name.body)
- unless astype.nil?
- field.field_type = @type_namespace.resolve(astype)
- end
- if @doc_comment
- field.comment = parse_comment(@field_comment_config, @doc_comment)
- end
- @defined_type.add_field(field)
- end
-
- def interface_function(name, sig)
- member_function(name, sig)
- end
-
- def intrinsic_member_function(name, sig)
- member_function(name, sig)
- end
-
- def member_function(name, sig)
- if sig.implicit_property_modifier.nil?
- real_member_function(name, sig)
- else
- implicit_property_function(name, sig)
- end
- end
-
- private
-
- def create_method(name, sig)
- method = ASMethod.new(@defined_type, @last_modifier, name.body)
- if sig.return_type
- method.return_type = @type_namespace.resolve(sig.return_type)
- end
- sig.arguments.each do |arg|
- argument = ASArg.new(arg.name.body)
- if arg.type
- argument.arg_type = @type_namespace.resolve(arg.type)
- end
- method.add_arg(argument)
- end
- if @doc_comment
- method.comment = parse_comment(@method_comment_config, @doc_comment)
- end
- method
- end
-
- def real_member_function(name, sig)
- method = create_method(name, sig)
- if name.body == @defined_type.unqualified_name
- @defined_type.constructor = method
- else
- @defined_type.add_method(method)
- end
- end
-
- def implicit_property_function(name, sig)
- field = @defined_type.get_field_called(name.body)
- if field.nil?
- field = ASImplicitField.new(@defined_type, name.body)
- @defined_type.add_field(field)
- end
- func = create_method(name, sig)
- if sig.implicit_property_modifier == "get"
- field.getter_method = func
- elsif sig.implicit_property_modifier == "set"
- field.setter_method = func
- else
- raise "unknown property-modifier #{sig.implicit_property_modifier.inspect}"
- end
- end
-
- def parse_comment(config, comment_token)
- comment_data = CommentData.new
-
- input = StringIO.new(comment_token.body)
- input.lineno = comment_token.lineno
- lexer = ActionScript::ParseDoc::DocCommentLexer.new(input)
- lexer.source = @source
- parser = ActionScript::ParseDoc::DocCommentParser.new(lexer)
- handler = OurDocCommentHandler.new(comment_data, config, @type_namespace)
- parser.handler = handler
-
- parser.parse_comment
-
- comment_data
- end
-end
-
-
-# The following classes could maybe be split into a different unit from those
-# above
-
-
-# Records the classes and packages imported into a compilation unit
-class ImportList
- def initialize
- @types = []
- @packages = []
- end
-
- def add_import(name)
- if name.last.instance_of?(ActionScript::Parse::StarToken)
- name.pop
- add_package_import(name)
- else
- add_type_import(name)
- end
- end
-
- def add_type_import(name)
- @types << name
- end
-
- def each_type
- @types.each do |type_name|
- yield type_name
- end
- end
-
- def add_package_import(name)
- @packages << name
- end
-
- def each_package
- @packages.each do |package_name|
- yield package_name
- end
- end
-end
-
-
-# A proxy for some type referred to by a particular name within a compilation
-# unit. After we've parsed all compilation units, we'll be able to resolve
-# what real type this proxy stands for (i.e. becase we'll have found the
-# types pulled into the compilation unit by 'import com.example.*')
-class TypeProxy
- # TODO: this should be in api_model.rb
- # TODO: this should be called TypeRef
-
- def initialize(containing_type, name)
- @name = name
- @containing_type = containing_type
- @resolved_type = nil
- @lineno = nil
- end
-
- attr_accessor :name, :containing_type, :resolved_type, :lineno
-
- def resolved?
- !@resolved_type.nil?
- end
-
- def local_name
- # TODO: come up with smarter representations for resolved vs. unresolved
- # types
- @name
- end
-
- def qualified?
- @name =~ /\./
- end
-
- def ==(o)
- # note that types are considered to be equal here if they have the same
- # name; we don't recursively compare their whole subgraphs
- name==o.name &&
- ((containing_type.nil? && o.containing_type.nil? ) || (containing_type.qualified_name == o.containing_type.qualified_name)) &&
- ((resolved_type.nil? && o.resolved_type.nil?) || (resolved_type.qualified_name == o.resolved_type.qualified_name)) &&
- lineno==o.lineno
- end
-
- def inspect
- "<#{self.class.name}:0x#{(object_id&0xffffffff).to_s(16)} @name=#{name.inspect} @containing_type=#{@containing_type ? @containing_type.qualified_name : "nil"} @resolved_type=#{@resolved_type ? @resolved_type.qualified_name : "nil"} @lineno=#{@lineno.inspect}>"
- end
-end
-
-
-# Resolves type names to instances of TypeProxy for a particular compilation
-# unit (the same name could refer to different types in different compilation
-# units).
-class TypeLocalNamespace
- def initialize(containing_type)
- @containing_type = containing_type
- @named_types = {}
- end
-
- def resolve(name, lineno=nil)
- raise "invalid name #{name.inspect}" if name.nil?
- if name.is_a?(Array)
- lineno = name.first.lineno
- name = name.join(".")
- end
- astype = @named_types[name]
- if astype.nil?
- astype = TypeProxy.new(@containing_type, name)
- astype.lineno = lineno
- @named_types[name] = astype
- end
- astype
- end
-
- def each
- @named_types.each_value do |astype|
- yield astype
- end
- end
-end
-
-
-# Collects types that are produced by parsing compilation units, building the
-# package list as types from different packages are added.
-class GlobalTypeAggregator
- def initialize()
- @types = []
- @packages = {}
- end
-
- def add_type(astype)
- @types << astype
- package_name = astype.package_name
- package = @packages[package_name]
- if package.nil?
- package = ASPackage.new(package_name)
- @packages[package_name] = package
- end
- astype.package = package
- package.add_type(astype)
- end
-
- def each_type
- @types.each do |astype|
- yield astype
- end
- end
-
- def types
- @types.dup
- end
-
- def each_package
- @packages.each_value do |package|
- yield package
- end
- end
-
- def packages
- @packages.values
- end
-
- def package(name)
- @packages[name]
- end
-end
-
-
-# Utility for resolving the TypeProxy objects created within each ASType of
-# a GlobalTypeAggregator.
-#
-# Once all types to be documented have been parsed, this class resolves the
-# inter-type references that the TypeProxy objects represent, possibly loading
-# and parsing further ActionScript files from the classpath as type-resolution
-# requires.
-class TypeResolver
- def initialize(classpath)
- @classpath = classpath
- @parsed_external_types = {}
- end
-
- def resolve_types(type_aggregator)
- global_ns = create_default_global_namespace
- add_fully_qualified_types_to_namespace(global_ns, type_aggregator)
- resolve_each_type(global_ns, type_aggregator)
- end
-
- private
-
- def create_default_global_namespace
- ns = {}
- ns[AS_VOID.qualified_name] = AS_VOID
- ns
- end
-
- def add_fully_qualified_types_to_namespace(ns, type_aggregator)
- type_aggregator.each_type do |astype|
- ns[astype.qualified_name] = astype
- end
- end
-
- def create_local_namespace(global_ns, type_aggregator, astype)
- ns = global_ns.dup
- ns[astype.unqualified_name] = astype
- import_types_into_namespace(astype, ns)
- import_packages_into_namespace(type_aggregator, astype, ns)
- ns
- end
-
- def resolve_each_type(global_ns, type_aggregator)
- type_aggregator.each_type do |astype|
- local_ns = create_local_namespace(global_ns, type_aggregator, astype)
- resolve_type_proxies(local_ns, astype)
- end
- end
-
- def resolve_type_proxies(local_ns, astype)
- astype.type_namespace.each do |type_proxy|
- real_type = local_ns[type_proxy.local_name]
- unless real_type
-        real_type = maybe_parse_external_definition(type_proxy)
- end
- if real_type
-        type_proxy.resolved_type = real_type
- else
-        $stderr.puts "#{astype.input_filename}:#{type_proxy.lineno}: Found no definition of type known locally as #{type_proxy.local_name.inspect}"
- end
- end
- end
-
- def import_types_into_namespace(astype, local_namespace)
- astype.import_list.each_type do |type_name|
- import_type = local_namespace[type_name.join(".")]
- import_type = maybe_parse_external_definition(TypeProxy.new(astype, type_name.join('.'))) unless import_type
- if import_type
-        local_namespace[type_name.last.body] = import_type
- else
-        $stderr.puts "#{astype.input_filename}:#{type_name.first.lineno}: Couldn't resolve import of #{type_name.join(".").inspect}"
- end
- end
- end
-
- def import_packages_into_namespace(type_aggregator, astype, local_namespace)
- astype.import_list.each_package do |package_name|
- pkg = type_aggregator.package(package_name.join("."))
- unless pkg
-        $stderr.puts "#{astype.input_filename}:#{package_name.first.lineno}: couldn't find package #{package_name.join(".").inspect}"
-        next
- end
- pkg.each_type do|package_type|
-        if local_namespace.has_key?(package_type.unqualified_name)
-         $stderr.puts "#{astype.input_filename}: #{package_type.unqualified_name} already refers to #{local_namespace[package_type.unqualified_name].qualified_name}"
-        end
-        local_namespace[package_type.unqualified_name] = package_type
- end
- end
- end
-
- def classname_to_filename(qualified_class_name)
- return qualified_class_name.gsub(/\./, File::SEPARATOR) + ".as"
- end
-
- def search_classpath_for(qualified_class_name)
- filename = classname_to_filename(qualified_class_name)
-
- @classpath.each do |path|
- if FileTest.exist?(File.join(path, filename))
-        return SourceFile.new(path, filename)
- end
- end
-
- nil
- end
-
- def find_file_matching(type_proxy)
- file_name = search_classpath_for(type_proxy.name)
- return file_name unless file_name.nil?
- return nil if type_proxy.qualified?
-
- type_proxy.containing_type.import_list.each_package do |package_name|
- candidate_name = package_name.join(".") + "." + type_proxy.name
- file_name = search_classpath_for(candidate_name)
- return file_name unless file_name.nil?
- end
-
- nil
- end
-
- def maybe_parse_external_definition(type_proxy)
- source_file = find_file_matching(type_proxy)
- return nil if source_file.nil?
- astype = @parsed_external_types[source_file.suffix]
- return astype unless astype.nil?
- astype = parse_file(source_file)
- astype.document = false
- @parsed_external_types[source_file.suffix] = astype
-
- astype
- end
-end
-
-# vim:softtabstop=2:shiftwidth=2
</pre></div>
<hr /><a name="file3" /><div class="file">
<span class="pathname" id="removed">as2api/trunk/as2api</span><br />
<div class="fileheader" id="removed"><big><b>api_model.rb</b></big> <small id="info">removed after 332</small></div>
<pre class="diff"><small id="info">--- trunk/as2api/api_model.rb        2006-03-23 20:31:08 UTC (rev 332)
+++ trunk/as2api/api_model.rb        2006-03-23 21:23:41 UTC (rev 333)
@@ -1,471 +0,0 @@
</small></pre><pre class="diff" id="removed">-#
-# Part of as2api - http://www.badgers-in-foil.co.uk/projects/as2api/
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-
-
-# These classes represent the data-model upon which as2api operates. The
-# class names are all prefixed with 'AS' becase many would otherwise clash
-# with Ruby's inbuilt classes with the same name.
-
-
-# TODO: The interfaces to these classes still, in places, make direct use of
-# types provided by ActionScript::Parse (i.e. methods expecting or
-# returning subclasses of ASToken). These classes should be refactored
-# to insulate the documentation-generating subsystem from those details
-
-
-# Describes what level of access a type allows to one of its members
-class ASAccess
- def initialize(visibility, static)
- @visibility = visibility
- @static = static
- end
-
- attr_accessor :visibility
-
- def static?; @static; end
- def private?; @visibility==:private; end
- attr_writer :static
-
- def ==(o)
- static? == o.static? && visibility == o.visibility
- end
-end
-
-# Superclass for ASClass and ASInterface, one instance of an ASType subclass
-# is created per compilation unit successfully parsed
-class ASType
- # give this ASType the given name (an array of IdentifierToken values
- # found by the parser)
- def initialize(package_name, type_name)
- @package_name = package_name # name[0, name.length-1].join(".")
- @name = type_name #name.last.body
- @source_utf8 = false
- @methods = []
- @constructor = nil
- @extends = nil
- @comment = nil
- @type_namespace = nil
- @import_list = nil
- @input_file = nil
- @document = true
- end
-
- attr_accessor :package, :extends, :comment, :source_utf8, :type_namespace, :import_list, :intrinsic, :constructor
-
- def input_filename
- @input_file && @input_file.suffix
- end
-
- def input_file=(file)
- @input_file = file
- sourcepath_location(File.dirname(file.suffix))
- end
-
- attr_reader :input_file
-
- def add_method(method)
- raise "nil not allowed" if method.nil?
- @methods << method
- end
-
- def each_method
- @methods.each do |meth|
- yield meth
- end
- end
-
- def methods
- @methods.dup
- end
-
- def methods?
- !@methods.empty?
- end
-
- def constructor?
- !@constructor.nil?
- end
-
- def get_method_called(name)
- each_method do |method|
- return method if method.name == name
- end
- nil
- end
-
- # The type's name, excluding its package-prefix
- def unqualified_name
- @name
- end
-
- # ascends the hierarchy of resolved supertypes of this type, passing
- # each ASType to the given block. Stops when a type does not extend
- # anything, or when the class it extends wasn't resolved.
- def each_ancestor
- parent = @extends
- while !parent.nil? && parent.resolved?
- yield parent.resolved_type
- parent = parent.resolved_type.extends
- end
- end
-
- def has_ancestor?
- !@extends.nil? && @extends.resolved?
- end
-
- # The whole type name, including package-prefix
- def qualified_name
- if @package_name.nil? || @package_name == ""
- @name
- else
- "#{@package_name}.#{@name}"
- end
- end
-
- # The package-prefix on this type's name
- def package_name
- @package_name
- end
-
- # This exists mostly as a hack to handle types that are declaired without
- # a package-prefix 'class SomeClass {', but shich are located in the
- # directory structure such that a package is implied (and indeed used by
- # Flash when the fileis found).
- #
- # When a type has no package-prefix, and this method is called on it with
- # an argument "com/foobar", we will 're-package' the type to subsequently
- # become 'com.foobar.SomeClass'
- def sourcepath_location(path)
- path = "" if path == "."
- if @package_name == "" and path != ""
- @package_name = path.gsub("/", ".")
- else
- if @package_name != path.gsub("/", ".")
-        $stderr.puts("package #{@package_name.inspect} doesn't match location #{path.inspect}")
- end
- end
- end
-
- # compare two types based on their qualified names
- def <=>(other)
- cmp = qualified_name.downcase <=> other.qualified_name.downcase
- return cmp unless cmp==0
- qualified_name <=> other.qualified_name
- end
-
- def document?
- @document
- end
-
- def document=(is_allowed_in_documentation)
- @document = is_allowed_in_documentation
- end
-end
-
-class ASVoidType < ASType
- def initialize
- @name = "Void"
- @package_name = ""
- @document = false
- end
-end
-
-AS_VOID = ASVoidType.new
-
-# Classes are types that (just for the perposes of API docs) have fields, and
-# implement interfaces
-class ASClass < ASType
- def initialize(package_name, class_name)
- @dynamic = false
- @interfaces = []
- @fields = []
- super(package_name, class_name)
- end
-
- attr_accessor :dynamic
-
- def implements_interfaces?
- !@interfaces.empty?
- end
-
- def add_interface(name)
- @interfaces << name
- end
-
- def each_interface
- @interfaces.each do |name|
- yield name
- end
- end
-
- def interfaces
- @interfaces.dup
- end
-
- # like #each_interface, but then also reports each_interface of each_ancestor
- def each_implemented_interface
- each_interface do |interface|
- yield interface.resolved_type if interface.resolved?
- end
- each_ancestor do |supertype|
- supertype.each_interface do |interface|
-        yield interface.resolved_type if interface.resolved?
- end
- end
- end
-
- def add_field(field)
- @fields << field
- end
-
- def fields?
- !@fields.empty?
- end
-
- # returns true if this class, or any superclass has fields
- def inherited_fields?
- return true if fields?
- each_ancestor do |supertype|
- return true if supertype.fields?
- end
- false
- end
-
- def each_field
- @fields.each do |field|
- yield field
- end
- end
-
- def fields
- @fields.dup
- end
-
- def get_field_called(name)
- each_field do |field|
- return field if field.name == name
- end
- nil
- end
-end
-
-# ASInterface doesn't add anything to the superclass, it just affirms that
-# the API only supported by ASClass will not be available here
-class ASInterface < ASType
- def initialize(package_name, interface_name)
- super(package_name, interface_name)
- end
-
- def implements_interfaces?
- false
- end
-
- def fields?
- false
- end
-end
-
-# A member in some type
-class ASMember
- def initialize(containing_type, access, name)
- @containing_type = containing_type
- @access = access
- @name = name
- @comment = nil
- end
-
- attr_accessor :containing_type, :access, :name, :comment
-
- # compares two members based on their names
- def <=>(other)
- cmp = name.downcase <=> other.name.downcase
- return cmp unless cmp==0
- name <=> other.name
- end
-end
-
-# A method member, which may appear in an ASClass or ASInterface
-class ASMethod < ASMember
- def initialize(containing_type, access, name)
- super(containing_type, access, name)
- @return_type = nil
- @args = []
- end
-
- attr_accessor :return_type
-
- def add_arg(arg)
- @args << arg
- end
-
- def arguments
- @args
- end
-
- def argument(index)
- @args[index]
- end
-
- def specified_by
- raise "not applicable to interface methods" unless containing_type.is_a?(ASClass)
- containing_type.each_implemented_interface do |interface|
- spec_method = interface.get_method_called(name)
- return spec_method unless spec_method.nil?
- end
- nil
- end
-
- def overrides
- containing_type.each_ancestor do |as_class|
- as_method = as_class.get_method_called(name)
- return as_method unless as_method.nil?
- end
- end
-
- def inherited_comment
- raise "method #{name.inspect} has a comment of its own" unless comment.nil?
- containing_type.each_ancestor do |as_class|
- as_method = as_class.get_method_called(name)
- return as_method unless as_method.nil? || as_method.comment.nil?
- end
- if containing_type.is_a?(ASClass)
- containing_type.each_implemented_interface do |as_interface|
- as_method = as_interface.get_method_called(name)
- return as_method unless as_method.nil? || as_method.comment.nil?
- end
- end
- end
-end
-
-# A field member, which may appear in an ASClass, but not an ASInterface
-class ASField < ASMember
-end
-
-class ASExplicitField < ASField
- def initialize(containing_tyye, access, name)
- super(containing_tyye, access, name)
- @field_type = nil
- end
-
- attr_accessor :field_type
-
- def readwrite?; true; end
-
- def read?; true; end
-
- def write?; true; end
-end
-
-# A field implied by the presence of "get" or "set" methods with this name
-class ASImplicitField < ASField
- def initialize(containing_tyye, name)
- super(containing_tyye, nil, name)
- @getter_method = nil
- @setter_method = nil
- end
-
- attr_accessor :getter_method, :setter_method
-
- def readwrite?
- !(@getter_method.nil? || @setter_method.nil?)
- end
-
- def read?
- !@getter_method.nil?
- end
-
- def write?
- !@setter_method.nil?
- end
-
- def access
- (@getter_method || @setter_method).access
- end
-
- def comment
- (@getter_method || @setter_method).comment
- end
-
- def field_type
- if read?
- return @getter_method.return_type
- else
- unless @setter_method.arguments.empty?
-        arg = @setter_method.arguments[0]
-        return arg.arg_type
- end
- end
- return nil
- end
-end
-
-# A formal function parameter, a list of which appear in an ASMethod
-class ASArg
- def initialize(name)
- @name = name
- @arg_type = nil
- end
-
- attr_accessor :name, :arg_type
-end
-
-# A simple aggregation of ASType objects
-class ASPackage
- def initialize(name)
- @name = name
- @types = []
- end
-
- attr_accessor :name
-
- def add_type(astype)
- @types << astype
- end
-
- def types
- @types
- end
-
- def each_type
- @types.each do |astype|
- yield astype
- end
- end
-
- def classes
- result = []
- each_type do |astype|
- result << astype if astype.instance_of?(ASClass)
- end
- result
- end
-
- def interfaces
- result = []
- each_type do |astype|
- result << astype if astype.instance_of?(ASInterface)
- end
- result
- end
-
- def <=>(other)
- cmp = name.downcase <=> other.name.downcase
- return cmp unless cmp==0
- name <=> other.name
- end
-end
</pre></div>
<hr /><a name="file4" /><div class="file">
<span class="pathname" id="removed">as2api/trunk/as2api</span><br />
<div class="fileheader" id="removed"><big><b>doc_comment.rb</b></big> <small id="info">removed after 332</small></div>
<pre class="diff"><small id="info">--- trunk/as2api/doc_comment.rb        2006-03-23 20:31:08 UTC (rev 332)
+++ trunk/as2api/doc_comment.rb        2006-03-23 21:23:41 UTC (rev 333)
@@ -1,599 +0,0 @@
</small></pre><pre class="diff" id="removed">-#
-# Part of as2api - http://www.badgers-in-foil.co.uk/projects/as2api/
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-
-
-require 'parse/doccomment_parser'
-
-class CommentData
- def initialize
- @blocks = []
- end
-
- def add_block(block)
- @blocks << block
- end
-
- def each_block
- @blocks.each do |block|
- yield block
- end
- end
-
- def [](i)
- @blocks[i]
- end
-
- def description
- @blocks[0]
- end
-
- def each_block_of_type(type)
- each_block do |block|
- yield block if block.is_a?(type)
- end
- end
-
- def has_blocktype?(type)
- each_block_of_type(type) do |block|
- return true
- end
- return false
- end
-
- def has_params?
- has_blocktype?(ParamBlockTag)
- end
-
- def has_exceptions?
- has_blocktype?(ThrowsBlockTag)
- end
-
- def has_seealso?
- has_blocktype?(SeeBlockTag)
- end
-
- def has_return?
- has_blocktype?(ReturnBlockTag)
- end
-
- def has_overload?
- has_blocktype?(OverloadBlockTag)
- end
-
- # Does the method comment include any info in addition to any basic
- # description block?
- def has_method_additional_info?
- has_params? || has_return? || has_exceptions? || has_seealso? || has_overload?
- end
-
- # Does the field comment include any info in addition to any basic description
- # block?
- def has_field_additional_info?
- has_seealso?
- end
-
- def each_exception
- each_block_of_type(ThrowsBlockTag) {|block| yield block }
- end
-
- def each_seealso
- each_block_of_type(SeeBlockTag) {|block| yield block }
- end
-
- def each_overload
- each_block_of_type(OverloadBlockTag) {|block| yield block }
- end
-
- def find_param(param_match)
- each_block_of_type(ParamBlockTag) do |block|
- return block if param_match === block.param_name
- end
- return nil
- end
-
- def find_return
- each_block_of_type(ReturnBlockTag) do |block|
- return block
- end
- return nil
- end
-
- def find_throws(exception_name)
- each_exception do |block|
- return block if block.exception_type.name == exception_name
- end
- nil
- end
-end
-
-class OurDocCommentHandler < ActionScript::ParseDoc::DocCommentHandler
- def initialize(comment_data, handler_config, type_namespace)
- @comment_data = comment_data
- @handler_config = handler_config
- @type_namespace = type_namespace
- end
-
- def comment_start(lineno)
- @block_handler = @handler_config.initial_block_handler
- @inline_handler = nil
- beginning_of_block(lineno)
- end
-
- def comment_end
- end_of_block
- end
-
- def text(text)
- if @inline_handler
- @inline_handler.text(text)
- else
- @block_handler.text(text)
- end
- end
-
- def start_paragraph_tag(tag)
- end_of_block
- @block_handler = @handler_config.handler_for(tag)
- beginning_of_block(tag.lineno)
- end
-
- def start_inline_tag(tag)
- @inline_handler = @block_handler.handler_for(tag)
- @inline_handler.start(@type_namespace, tag.lineno)
- end
-
- def end_inline_tag
- tag = @inline_handler.end
- @block_handler.add_inline(tag) if tag
- @inline_handler = nil
- end
-
- private
-
- def beginning_of_block(lineno)
- @block_handler.begin_block(@type_namespace, lineno)
- end
-
- def end_of_block
- block = @block_handler.end_block
- @comment_data.add_block(block) unless block.nil?
- end
-end
-
-class DocCommentParserConfig
- def initialize
- @initial_block_handler = nil
- @block_handlers = {}
- end
-
- attr_accessor :initial_block_handler
-
- def add_block_parser(name, handler)
- @block_handlers[name] = handler
- handler.handler = self
- end
-
- def handler_for(kind)
- handler = @block_handlers[kind.body]
- if handler.nil?
- parse_error("#{kind.source}:#{kind.lineno}: Unknown block tag @#{kind.body}")
- handler = NIL_HANDLER
- end
- handler
- end
-
- private
-
- def parse_error(msg)
- $stderr.puts(msg)
- end
-
-end
-
-
-class Tag
- def initialize(lineno)
- @lineno = lineno
- end
-
- attr_accessor :lineno
-
- def ==(o)
- lineno == o.lineno
- end
-end
-
-class LinkTag < Tag
- def initialize(lineno, target, member, text)
- super(lineno)
- @target = target
- @member = member
- @text = text
- end
-
- attr_accessor :target, :member, :text
-
- def ==(o)
- super(o) && member==o.member && text==o.text && target==o.target
- end
-end
-
-class CodeTag < Tag
- def initialize(lineno, text)
- super(lineno)
- @text = text
- end
-
- attr_accessor :text
-end
-
-
-class BlockTag
- def initialize
- @inlines = []
- end
-
- def add_inline(inline)
- # coalesce multiple consecutive strings,
- last_inline = @inlines.last
- if inline.is_a?(String) && last_inline.is_a?(String)
- last_inline << inline
- else
- @inlines << inline
- end
- end
-
- def each_inline
- @inlines.each do |inline|
- yield inline
- end
- end
-
- def inlines
- @inlines
- end
-
- def clear
- @inlines.clear
- end
-
- def ==(o)
- o.respond_to?(:inlines) && inlines==o.inlines
- end
-end
-
-
-class ParamBlockTag < BlockTag
- attr_accessor :param_name
-
- def ==(o)
- super(o) && param_name==o.param_name
- end
-end
-
-
-class ThrowsBlockTag < BlockTag
- attr_accessor :exception_type
-end
-
-
-class SeeBlockTag < BlockTag
-end
-
-
-class ReturnBlockTag < BlockTag
-end
-
-class OverloadBlockTag < BlockTag
-end
-
-
-class InlineParser
- def start(type_namespace, lineno)
- @type_namespace = type_namespace
- @lineno = lineno
- @text = ""
- end
-
- def text(text)
- @text << text.to_s
- end
-end
-
-
-# creates a LinkTag inline
-def create_link(type_namespace, text, lineno)
- if text =~ /^\s*([^\s]+(?:\([^\)]*\))?)\s*(.+)?/m
- target = $1
- text = $2
- # TODO: need a MemberProxy (and maybe Method+Field subclasses) with similar
- # role to TypeProxy, to simplify this, and output_doccomment_inlinetag
- if target =~ /([^#]*)#(.*)/
- type_name = $1
- member_name = $2
- else
- type_name = target
- member_name = nil
- end
- if type_name == ""
- type_proxy = nil
- else
- type_proxy = type_namespace.resolve(type_name, lineno)
- end
- return LinkTag.new(lineno, type_proxy, member_name, text)
- end
- return nil
-end
-
-
-# handle {@link ...} in comments
-class LinkInlineParser < InlineParser
- def end
- link = create_link(@type_namespace, @text, @lineno)
- if link.nil?
- "{@link #{@text}}"
- else
- link
- end
- end
-end
-
-# handle {@code ...} in comments
-class CodeInlineParser < InlineParser
- def end; CodeTag.new(@lineno, @text); end
-end
-
-
-class BlockParser
- def initialize
- @inline_parsers = {}
- @data = nil
- end
-
- attr_accessor :handler
-
- def begin_block(type_namespace, lineno)
- @type_namespace = type_namespace
- @lineno = lineno
- end
-
- def end_block
- @data
- end
-
- def add_inline_parser(tag_name, parser)
- @inline_parsers[tag_name] = parser
- end
-
- def handler_for(tag)
- inline_parser = @inline_parsers[tag.body]
- if inline_parser.nil?
- $stderr.puts("#{tag.lineno}: Unknown inline tag #{tag.body.inspect} for #{self.class.name}")
- NIL_INLINE_PARSER
- else
- inline_parser
- end
- end
-
- def text(text)
- add_text(text.to_s)
- end
-
- def add_inline(tag)
- @data.add_inline(tag)
- end
-
- def add_text(text)
- raise "#{self.class.name} has no @data" unless @data
- @data.add_inline(text)
- end
-end
-
-class NilBlockParser < BlockParser
- def add_text(text); end
- def handler_for(tag); NIL_INLINE_PARSER; end
-end
-
-NIL_HANDLER = NilBlockParser.new
-
-
-class NilInlineParser < InlineParser
- def end; nil; end
-end
-
-NIL_INLINE_PARSER = NilInlineParser.new
-
-class ParamParser < BlockParser
- def begin_block(type_namespace, lineno)
- super(type_namespace, lineno)
- @data = ParamBlockTag.new
- end
-
- def end_block
- first_inline = @data.inlines[0]
- if first_inline =~ /\s*([^\s]+)\s+/
- @data.inlines[0] = $'
- @data.param_name = $1
- end
- @data
- end
-end
-
-
-class ThrowsParser < BlockParser
- def begin_block(type_namespace, lineno)
- super(type_namespace, lineno)
- @data = ThrowsBlockTag.new
- end
-
- def end_block
- first_inline = @data.inlines[0]
- if first_inline =~ /\A\s*([^\s]+)\s+/
- @data.inlines[0] = $'
- @data.exception_type = @type_namespace.resolve($1)
- @data
- else
- nil
- end
- end
-end
-
-
-class ReturnParser < BlockParser
- def begin_block(type_namespace, lineno)
- super(type_namespace, lineno)
- @data = ReturnBlockTag.new
- end
-end
-
-
-class DescriptionParser < BlockParser
- def begin_block(type_namespace, lineno)
- super(type_namespace, lineno)
- @data = BlockTag.new
- end
-end
-
-
-class SeeParser < BlockParser
- def begin_block(type_namespace, lineno)
- super(type_namespace, lineno)
- @data = SeeBlockTag.new
- end
-
- def end_block
- @data.inlines.first =~ /\A\s*/
- case $'
- when /['"]/
-        # plain, 'string'-like see entry
- when /</
-        # HTML entry
- else
-        # 'link' entry
-        link = create_link(@type_namespace, @data.inlines.first, @lineno)
-        unless link.nil?
-         @data.inlines[0] = link
-        end
- end
- @data
- end
-end
-
-
-class OverloadParser < BlockParser
- def begin_block(type_namespace, lineno)
- super(type_namespace, lineno)
- @data = OverloadBlockTag.new
- end
-
- def end_block
- if @data.inlines.first =~ /\A\s*(#.*)/
- link = create_link(@type_namespace, $1, @lineno)
- unless link.nil?
-        @data.inlines[0] = link
- end
- end
- @data
- end
-end
-
-
-#############################################################################
-
-
-class ConfigBuilder
- def build_method_config
- config = build_config
- add_standard_block_parsers(config)
- config.add_block_parser("param", build_param_block_parser)
- config.add_block_parser("return", build_return_block_parser)
- config.add_block_parser("throws", build_throws_block_parser)
- config.add_block_parser("exception", build_throws_block_parser)
- config.add_block_parser("overload", build_overload_block_parser)
- return config
- end
-
- def build_field_config
- config = build_config
- add_standard_block_parsers(config)
- return config
- end
-
- def build_type_config
- config = build_config
- add_standard_block_parsers(config)
- config.add_block_parser("author", build_author_block_parser)
- return config
- end
-
- protected
-
- def build_config
- DocCommentParserConfig.new
- end
-
- def add_standard_block_parsers(config)
- config.initial_block_handler = build_description_block_parser
- config.add_block_parser("see", build_see_block_parser)
- end
-
- def add_common_inlines(block_parser)
- block_parser.add_inline_parser("link", LinkInlineParser.new)
- block_parser.add_inline_parser("code", CodeInlineParser.new)
- end
-
- def build_description_block_parser
- parser = DescriptionParser.new
- add_common_inlines(parser)
- parser
- end
-
- def build_param_block_parser
- parser = ParamParser.new
- add_common_inlines(parser)
- parser
- end
-
- def build_return_block_parser
- parser = ReturnParser.new
- add_common_inlines(parser)
- parser
- end
-
- def build_throws_block_parser
- parser = ThrowsParser.new
- add_common_inlines(parser)
- parser
- end
-
- def build_see_block_parser
- parser = SeeParser.new
- add_common_inlines(parser)
- parser
- end
-
- def build_author_block_parser
- NilBlockParser.new # ignore @author tags
- end
-
- def build_overload_block_parser
- OverloadParser.new
- end
-end
-
-# vim:softtabstop=2:shiftwidth=2
</pre></div>
<hr /><a name="file5" /><div class="file">
<span class="pathname" id="removed">as2api/trunk/as2api</span><br />
<div class="fileheader" id="removed"><big><b>documenter.rb</b></big> <small id="info">removed after 332</small></div>
<pre class="diff"><small id="info">--- trunk/as2api/documenter.rb        2006-03-23 20:31:08 UTC (rev 332)
+++ trunk/as2api/documenter.rb        2006-03-23 21:23:41 UTC (rev 333)
@@ -1,67 +0,0 @@
</small></pre><pre class="diff" id="removed">-#
-# Part of as2api - http://www.badgers-in-foil.co.uk/projects/as2api/
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-
-
-require 'find'
-require 'parse/lexer' # TODO: remove this requirement
-require 'parse/as_io'
-require 'api_loader'
-
-
-
-class NullProgressListener
- def parsing_sources(total_files)
- yield
- end
-
- def parse_source(file_number, file_name)
- end
-
- def generating_pages(total_pages)
- yield
- end
-
- def generate_page(file_number, file_name)
- end
-end
-
-BOM = "\357\273\277"
-
-# Look for a byte-order-marker in the first 3 bytes of io.
-# Eats the BOM and returns true on finding one; rewinds the stream to its
-# start and returns false if none is found.
-def detect_bom?(io)
- return true if io.read(3) == BOM
- io.seek(0)
- false
-end
-
-
-# lists the .as files in 'path', and it's subdirectories
-def each_source(path)
- path = path.sub(/\/+$/, "")
- Find.find(path) do |f|
- base = File.basename(f)
- # Ignore anything named 'CVS', or starting with a dot
- Find.prune if base =~ /^\./ || base == "CVS"
- if base =~ /\.as$/
- yield f[path.length+1, f.length]
- end
- end
-end
-
</pre></div>
<hr /><a name="file6" /><div class="file">
<span class="pathname" id="copied">as2api/trunk/as2api/lib</span><br />
<div class="fileheader" id="copied"><big><b>api_diff.rb</b></big> <small id="info">copied from as2api/trunk/as2api/api_diff.rb:332</small></div>
<pre class="diff"><small id="info">
Copied from as2api/trunk/as2api/api_diff.rb:330
</small></pre></div>
<hr /><a name="file7" /><div class="file">
<span class="pathname" id="copied">as2api/trunk/as2api/lib</span><br />
<div class="fileheader" id="copied"><big><b>api_loader.rb</b></big> <small id="info">copied from as2api/trunk/as2api/api_loader.rb:332</small></div>
<pre class="diff"><small id="info">
Copied from as2api/trunk/as2api/api_loader.rb:330
</small></pre></div>
<hr /><a name="file8" /><div class="file">
<span class="pathname" id="copied">as2api/trunk/as2api/lib</span><br />
<div class="fileheader" id="copied"><big><b>api_model.rb</b></big> <small id="info">copied from as2api/trunk/as2api/api_model.rb:332</small></div>
<pre class="diff"><small id="info">
Copied from as2api/trunk/as2api/api_model.rb:330
</small></pre></div>
<hr /><a name="file9" /><div class="file">
<span class="pathname" id="copied">as2api/trunk/as2api/lib</span><br />
<div class="fileheader" id="copied"><big><b>doc_comment.rb</b></big> <small id="info">copied from as2api/trunk/as2api/doc_comment.rb:332</small></div>
<pre class="diff"><small id="info">
Copied from as2api/trunk/as2api/doc_comment.rb:330
</small></pre></div>
<hr /><a name="file10" /><div class="file">
<span class="pathname" id="copied">as2api/trunk/as2api/lib</span><br />
<div class="fileheader" id="copied"><big><b>documenter.rb</b></big> <small id="info">copied from as2api/trunk/as2api/documenter.rb:332</small></div>
<pre class="diff"><small id="info">
Copied from as2api/trunk/as2api/documenter.rb:330
</small></pre></div>
<hr /><a name="file11" /><div class="file">
<span class="pathname" id="copied">as2api/trunk/as2api/lib</span><br />
<div class="fileheader" id="copied"><big><b>localisation</b></big> <small id="info">copied from as2api/trunk/as2api/localisation:332</small></div>
<pre class="diff"><small id="info">
Copied from as2api/trunk/as2api/localisation:330
</small></pre></div>
<hr /><a name="file12" /><div class="file">
<span class="pathname" id="copied">as2api/trunk/as2api/lib/localisation</span><br />
<div class="fileheader" id="copied"><big><b>xliff</b></big> <small id="info">copied from as2api/trunk/as2api/localisation/xliff:332</small></div>
<pre class="diff"><small id="info">
Copied from as2api/trunk/as2api/localisation/xliff:332
</small></pre></div>
<hr /><a name="file13" /><div class="file">
<span class="pathname" id="copied">as2api/trunk/as2api/lib</span><br />
<div class="fileheader" id="copied"><big><b>output</b></big> <small id="info">copied from as2api/trunk/as2api/output:332</small></div>
<pre class="diff"><small id="info">
Copied from as2api/trunk/as2api/output:330
</small></pre></div>
<hr /><a name="file14" /><div class="file">
<span class="pathname" id="copied">as2api/trunk/as2api/lib/output</span><br />
<div class="fileheader" id="copied"><big><b>diff</b></big> <small id="info">copied from as2api/trunk/as2api/output/diff:332</small></div>
<pre class="diff"><small id="info">
Copied from as2api/trunk/as2api/output/diff:332
</small></pre></div>
<hr /><a name="file15" /><div class="file">
<span class="pathname" id="copied">as2api/trunk/as2api/lib/output</span><br />
<div class="fileheader" id="copied"><big><b>html</b></big> <small id="info">copied from as2api/trunk/as2api/output/html:332</small></div>
<pre class="diff"><small id="info">
Copied from as2api/trunk/as2api/output/html:332
</small></pre></div>
<hr /><a name="file16" /><div class="file">
<span class="pathname" id="removed">as2api/trunk/as2api/lib/output</span><br />
<div class="fileheader" id="removed"><big><b>utils.rb</b></big> <small id="info">removed after 330</small&