0

This CL contains the the changes needed to build

an externs file for the JSCompiler as well as
the code to build a compiled verison of the o3djs
sample libs.

Review URL: http://codereview.chromium.org/147079

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@19659 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
gman@google.com
2009-06-30 21:44:39 +00:00
parent dc5b41997c
commit 07facf095e
9 changed files with 2343 additions and 125 deletions

Binary file not shown.

@ -28,7 +28,6 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import glob
import os.path
import subprocess
Import('env')
@ -38,11 +37,8 @@ Import('O3D_IDL_SOURCES')
Import('O3D_JS_SOURCES')
env.Replace(
EZT_FORMATTER = 'documentation/ezt_formatter.py',
CLASS_TREE_GEN = 'documentation/classtree.py',
JSDOC_DIR = '$SCONSTRUCT_DIR/documentation',
JSDOC_EZT_TEMPLATE_DIR = '$JSDOC_DIR/jsdoc-toolkit-templates/',
JSDOC_JAR = '$JSDOCTOOLKIT_DIR/jsrun.jar',
PYTHONPATH = ['$NIXYSA_DIR',
'$GFLAGS_DIR/python',
'$PLY_DIR']
@ -54,71 +50,14 @@ LOCAL_IDL_SOURCES = [IDL_DIR + i for i in O3D_IDL_SOURCES]
JS_DIR = '$SCONSTRUCT_DIR/samples/o3djs/'
LOCAL_JS_SOURCES = [JS_DIR + i for i in O3D_JS_SOURCES]
def IdlDocsEmitter(target, source, env):
bases = [os.path.splitext(s.name)[0] for s in source]
targets = [target[0].dir.abspath + "/%s.$IDL_GENERATE_EXT" % b for b in bases]
return targets, source
DOCSGEN_ARGS = ['$JSDOC_DIR/build_docs.py $JAVA_EXE']
AUTOGEN_ARGS = ['$NIXYSA_DIR/codegen.py',
'--binding-module=o3d:plugin/o3d_binding.py',
'--generate=$IDL_GENERATE',
'--output-dir=${TARGET.dir}']
if ARGUMENTS.get('force-docs', False):
AUTOGEN_ARGS += ['--force-docs']
AUTOGEN_ARGS += ['$SOURCES']
JSDOCS_CMD = ' '.join([
'$JAVA_EXE',
'-Djsdoc.dir=$JSDOCTOOLKIT_DIR',
'-jar $JSDOC_JAR',
'$JSDOCTOOLKIT_DIR/app/run.js',
'-v',
'-t=$JSDOC_EZT_TEMPLATE_DIR/',
'-d=${TARGET.dir}',
' '.join(LOCAL_JS_SOURCES)])
def TouchAll(target=None, source=None, env=None):
for i in target:
if not os.path.exists(i.path):
open(i.path, 'wb').close()
env["BUILDERS"]["IdlDocs"] = Builder(action=[env.Python(AUTOGEN_ARGS),
Action(TouchAll)],
emitter=IdlDocsEmitter)
doxy_inputs = []
doxy_inputs += env.IdlDocs(
'dummy', LOCAL_IDL_SOURCES,
IDL_GENERATE='cppheader',
IDL_GENERATE_EXT='h')
def EZTStep(target=None, source=None, env=None):
dir = env.Dir('$OBJ_ROOT/documentation/html')
html_files = glob.glob(dir.path + os.sep + '*.html')
for file in html_files:
ret = env.Execute(env.Python(['$EZT_FORMATTER', file]))
if ret > 0:
return ret
return 0
def ClassTreeStep(target=None, source=None, env=None):
dir = env.Dir('$OBJ_ROOT/documentation/html')
return env.Execute(env.Python(['$CLASS_TREE_GEN', dir.path]))
env.Command(
'html/doxygen.png', doxy_inputs,
['$DOXYGEN documentation/Doxyfile',
Action(EZTStep),
Action(ClassTreeStep),
Touch('$TARGET')],
)
env["BUILDERS"]["JSDocs"] = Builder(action=JSDOCS_CMD)
env["BUILDERS"]["JSDocs"] = Builder(action=env.Python(DOCSGEN_ARGS))
# index.ezt is a file that the jsdoctoolkit happens to build.
# Putting it in jsdocs means that will be our target dir for the rest
# of the files.
env.JSDocs('html/jsdocs/classtree.html', LOCAL_JS_SOURCES +
env.JSDocs('base.js', LOCAL_JS_SOURCES + LOCAL_IDL_SOURCES +
['$JSDOC_EZT_TEMPLATE_DIR/annotated.tmpl',
'$JSDOC_EZT_TEMPLATE_DIR/class.tmpl',
'$JSDOC_EZT_TEMPLATE_DIR/classtree.tmpl',

@ -0,0 +1,33 @@
@echo OFF
REM Copyright 2009, Google Inc.
REM All rights reserved.
REM
REM Redistribution and use in source and binary forms, with or without
REM modification, are permitted provided that the following conditions are
REM met:
REM
REM * Redistributions of source code must retain the above copyright
REM notice, this list of conditions and the following disclaimer.
REM * Redistributions in binary form must reproduce the above
REM copyright notice, this list of conditions and the following disclaimer
REM in the documentation and/or other materials provided with the
REM distribution.
REM * Neither the name of Google Inc. nor the names of its
REM contributors may be used to endorse or promote products derived from
REM this software without specific prior written permission.
REM
REM THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
REM "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
REM LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
REM A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
REM OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
REM SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
REM LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
REM DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
REM THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
REM (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
REM OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
set PYTHONDIR=%~dp0..\..\third_party\python_24
call %PYTHONDIR%\setup_env.bat
%PYTHONDIR%\python.exe %~dp0\build_docs.py %*

253
o3d/documentation/build_docs.py Executable file

@ -0,0 +1,253 @@
#!/usr/bin/python2.4
# Copyright 2009, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Docbuilder for O3D and o3djs."""
import os
import os.path
import sys
import imp
import types
import glob
import subprocess
_java_exe = ''
_script_path = os.path.dirname(os.path.realpath(__file__))
GlobalsDict = { }
def MakePath(file_path):
"""Makes a path absolute given a path relativel to this script."""
return os.path.join(_script_path, file_path)
def UpdateGlobals(dict):
"""Copies pairs from dict into GlobalDict."""
for i, v in dict.items():
GlobalsDict.__setitem__(i, v)
def GetCallingNamespaces():
"""Return the locals and globals for the function that called
into this module in the current call stack."""
try: 1/0
except ZeroDivisionError:
# Don't start iterating with the current stack-frame to
# prevent creating reference cycles (f_back is safe).
frame = sys.exc_info()[2].tb_frame.f_back
# Find the first frame that *isn't* from this file
while frame.f_globals.get("__name__") == __name__:
frame = frame.f_back
return frame.f_locals, frame.f_globals
def ComputeExports(exports):
"""Compute a dictionary of exports given one of the parameters
to the Export() function or the exports argument to SConscript()."""
loc, glob = GetCallingNamespaces()
retval = {}
try:
for export in exports:
if isinstance(export, types.DictType):
retval.update(export)
else:
try:
retval[export] = loc[export]
except KeyError:
retval[export] = glob[export]
except KeyError, x:
raise Error, "Export of non-existent variable '%s'"%x
return retval
def Export(*vars):
"""Copies the named variables to GlobalDict."""
for var in vars:
UpdateGlobals(ComputeExports(vars))
def Import(filename):
"""Imports a python file in a scope with 'Export' defined."""
scope = {'__builtins__': globals()['__builtins__'],
'Export': Export}
file = open(filename, 'r')
exec file in scope
file.close()
def Execute(args):
"""Executes an external program."""
# Comment the next line in for debugging.
# print "Execute: ", ' '.join(args)
if subprocess.call(args) > 0:
raise RuntimeError('FAILED: ' + ' '.join(args))
def AppendBasePath(folder, filenames):
"""Appends a base path to a ist of files"""
return [os.path.join(folder, filename) for filename in filenames]
def RunNixysa(idl_files, generate, output_dir, nixysa_options):
"""Executes Nixysa."""
python_exe = 'python'
Execute([
python_exe,
MakePath('../third_party/nixysa/files/codegen.py'),
'--binding-module=o3d:%s' % MakePath('../plugin/o3d_binding.py'),
'--generate=' + generate,
'--force',
'--output-dir=' + output_dir] +
nixysa_options +
idl_files)
def RunJSDocToolkit(js_files, output_dir, prefix):
"""Executes the JSDocToolkit."""
list_filename = MakePath('../scons-out/docs/obj/doclist.conf')
f = open(list_filename, 'w')
f.write('{\n_: [\n')
for filename in js_files:
f.write('"%s",\n' % filename.replace('\\', '/'))
f.write(']\n}\n')
f.close()
Execute([
_java_exe,
'-Djsdoc.dir=%s' % MakePath('../third_party/jsdoctoolkit/files'),
'-jar',
MakePath('../third_party/jsdoctoolkit/files/jsrun.jar'),
MakePath('../third_party/jsdoctoolkit/files/app/run.js'),
'-D="prefix:%s"' % prefix,
'-v',
'-t=%s' % MakePath('./jsdoc-toolkit-templates//'),
'-d=' + output_dir,
'-c=' + list_filename])
def BuildJavaScriptForDocsFromIDLs(idl_files, output_dir):
RunNixysa(idl_files, 'jsheader', output_dir, [])
def BuildJavaScriptForExternsFromIDLs(idl_files, output_dir):
if (os.path.exists(output_dir)):
for filename in glob.glob(os.path.join(output_dir, '*.js')):
os.unlink(filename)
RunNixysa(idl_files, 'jsheader', output_dir, ['--no-return-docs'])
def BuildO3DDocsFromJavaScript(js_files, output_dir):
RunJSDocToolkit(js_files, output_dir, 'classo3d_1_1_')
def BuildO3DExternsFile(js_files_dir, extra_externs_file, externs_file):
outfile = open(externs_file, 'w')
filenames = (glob.glob(os.path.join(js_files_dir, '*.js')) +
[extra_externs_file])
for filename in filenames:
infile = open(filename, 'r')
outfile.write(infile.read())
infile.close()
outfile.close()
def BuildCompiledO3DJS(o3djs_files,
externs_path,
o3d_externs_js_path,
compiled_o3djs_outpath):
Execute([
_java_exe,
'-jar',
MakePath('JSCompiler_deploy.jar'),
'--externs=%s' % externs_path,
('--externs=%s' % o3d_externs_js_path),
('--js_output_file=%s' % compiled_o3djs_outpath)] +
['-js=%s' % (x, ) for x in o3djs_files]);
def main():
"""Builds the O3D API docs and externs and the o3djs docs."""
global _java_exe
_java_exe = sys.argv[1]
js_list_filename = MakePath('../samples/o3djs/js_list.scons')
idl_list_filename = MakePath('../plugin/idl_list.scons')
js_list_basepath = os.path.dirname(js_list_filename)
idl_list_basepath = os.path.dirname(idl_list_filename)
docs_js_outpath = MakePath('../scons-out/docs/obj/documentation/apijs')
externs_js_outpath = MakePath('../scons-out/docs/obj/externs')
o3d_docs_html_outpath = MakePath('../scons-out/docs/obj/documentation/html')
o3d_externs_path = MakePath('../scons-out/docs/obj/o3d-externs.js')
compiled_o3djs_outpath = MakePath(
'../scons-out/docs/obj/documentation/base.js')
externs_path = MakePath('externs/externs.js')
o3d_extra_externs_path = MakePath('externs/o3d-extra-externs.js')
Import(js_list_filename)
Import(idl_list_filename)
idl_files = AppendBasePath(idl_list_basepath, GlobalsDict['O3D_IDL_SOURCES'])
o3djs_files = AppendBasePath(js_list_basepath, GlobalsDict['O3D_JS_SOURCES'])
# we need to put base.js first?
o3djs_files = (
filter(lambda x: x.endswith('base.js'), o3djs_files) +
filter(lambda x: not x.endswith('base.js'), o3djs_files))
docs_js_files = [os.path.join(
docs_js_outpath,
os.path.splitext(os.path.basename(f))[0] + '.js')
for f in GlobalsDict['O3D_IDL_SOURCES']]
BuildJavaScriptForDocsFromIDLs(idl_files, docs_js_outpath)
BuildO3DDocsFromJavaScript([o3d_extra_externs_path] + docs_js_files,
o3d_docs_html_outpath)
BuildJavaScriptForExternsFromIDLs(idl_files, externs_js_outpath)
BuildO3DExternsFile(externs_js_outpath,
o3d_extra_externs_path,
o3d_externs_path)
BuildCompiledO3DJS(o3djs_files,
externs_path,
o3d_externs_path,
compiled_o3djs_outpath)
if __name__ == '__main__':
main()

File diff suppressed because it is too large Load Diff

@ -0,0 +1,48 @@
/**
* Special global variable for V8 instances.
*/
var plugin;
/**
* The main namespace for the o3d plugin.
* @namespace
*/
var o3d;
/**
* @type {!Object}
*/
var Exception = goog.typedef;
/**
* A namespace for the Cursor.
* @namespace
*/
o3d.Cursor = o3d.Cursor || { };
/**
* A namespace for the VectorMath.
* @namespace
*/
var Vectormath;
/**
* A namespace for the VectorMath.Aos
* @namespace
*/
Vectormath.Aos = Vectormath.Aos || { };
/**
* A 4x4 Matrix of floats
* @type {!Array.<!Array.<number>>}
*/
o3d.Matrix4 = goog.typedef;
/**
* RangeError.
* why is this sometimes needed and sometimes not?
* @exception
*/
var RangeError;

@ -39,7 +39,7 @@ thisClass = data;
<ul>
<for each="seeAlso" in="data.see">
<li>
{+linkifyTypeSpec(seeAlso)+}
{+linkifyTypeSpec(makeName('[Class See Also]', thisClass.alias), seeAlso)+}
</li>
</for>
</ul>
@ -65,7 +65,7 @@ thisClass = data;
<if test="!method.isPrivate">
<li>
<if test="method.isStatic||!method.memberOf">&lt;static&gt; </if>
<if test="method.type.length">{+linkifyTypeSpec(method.type)+}&nbsp;</if>
<if test="method.type.length">{+linkifyTypeSpec(makeName('[Method Summary]', thisClass.alias, method.name), method.type)+}&nbsp;</if>
<a class="el" href="#{+method.name+}">{+method.name+}</a>{+makeSignature(method.params)+}
</li>
</if>
@ -84,7 +84,7 @@ thisClass = data;
<if test="!property.isPrivate">
<li>
<if test="property.isStatic||!property.memberOf">&lt;static&gt;&nbsp;</if>
{+linkifyTypeSpec(getPropertyType(property))+}
{+linkifyTypeSpec(makeName('[Property Summary]', thisClass.alias, property.name), getPropertyType(property))+}
<a class="el" href="#{+property.name+}">{+property.name+}</a>
</li>
</if>
@ -114,7 +114,7 @@ thisClass = data;
<tr>
<td class="{+tempCSS+}">{+tempName+}</td>
<td>{+tempParen+}</td>
<td class="paramtype">{+linkifyTypeSpec(param.type)+}</td>
<td class="paramtype">{+linkifyTypeSpec(makeName('[Constructor Param]', thisClass.alias, param.name), param.type)+}</td>
<td class="paramname"><em>{+param.name+}</em></td>
<td><if test="$param_last">)</if></td>
<td></td>
@ -172,7 +172,7 @@ thisClass = data;
<if test="member.params && member.params.length">
{!
var tempCSS = "memname";
var tempName = linkifyTypeSpec(member.type)+" "+member.memberOf+"."+member.name;
var tempName = linkifyTypeSpecForReturn(makeName('[Method Detail]', thisClass.alias, member.name), member.type)+" "+member.memberOf+"."+member.name;
var tempParen = "(";
var tempEnd = member.params.length > 1 ? "" : ")"
!}
@ -180,7 +180,7 @@ thisClass = data;
<tr>
<td class="{+tempCSS+}">{+tempName+}</td>
<td>{+tempParen+}</td>
<td class="paramtype">{+linkifyTypeSpec(param.type)+}</td>
<td class="paramtype">{+linkifyTypeSpec(makeName('[Param Detail]', thisClass.alias, member.name, param.name), param.type)+}</td>
<td class="paramname"><em>{+param.name+}</em></td>
<td><if test="$param_last">)</if></td>
<td><if test="$param_last">{+tempInherited+}</if></td>
@ -222,7 +222,7 @@ thisClass = data;
<if test="member.type && member.type.length">
<dl class="return" compact><dt><b>Returns:</b></dt>
<dd>
{+linkifyTypeSpec(member.type)+}.<if test="member.returns && member.returns.length">{+sanitizeForEZT(member.returns[0].desc)+}</if>
{+linkifyTypeSpec(makeName('[Return detail]', thisClass.alias, member.name), member.type)+}.<if test="member.returns && member.returns.length">{+sanitizeForEZT(member.returns[0].desc)+}</if>
</dd>
</if>
</div>
@ -232,7 +232,7 @@ thisClass = data;
<dd><ul>
<for each="seeAlso" in="member.see">
<li>
{+linkifyTypeSpec(seeAlso)+}
{+linkifyTypeSpec(makeName('[Method See Also]', thisClass.alias, '[See Also]'), seeAlso)+}
</li>
</for>
</ul></dd>
@ -256,7 +256,7 @@ thisClass = data;
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">{+linkifyTypeSpec(getPropertyType(property))+} {+property.memberOf+"."+property.name+}</td>
<td class="memname">{+linkifyTypeSpec(makeName('[Property Detail]', thisClass.alias, property.name), getPropertyType(property))+} {+property.memberOf+"."+property.name+}</td>
</tr>
</table>
</div>
@ -271,7 +271,7 @@ thisClass = data;
<dd><ul>
<for each="seeAlso" in="property.see">
<li>
{+linkifyTypeSpec(seeAlso)+}
{+linkifyTypeSpec(makeName('[Property See Also]', thisClass.alias), seeAlso)+}
</li>
</for>
</ul></dd>

@ -49,6 +49,7 @@ var g_validJSDOCTypes = {
'void': true,
'undefined': true};
var g_unknownTypes = { };
var g_numErrors = 0;
/**
* Called automatically by JsDoc Toolkit.
@ -60,7 +61,7 @@ function publish(symbolSet) {
outDir: JSDOC.opt.d || SYS.pwd + '../out/jsdoc/',
templatesDir: JSDOC.opt.t || SYS.pwd + '../templates/jsdoc/',
symbolsDir: '',
prefix: 'js_1_0_'};
prefix: JSDOC.opt.D.prefix || 'js_1_0_'};
publish.conf.srcDir = publish.conf.outDir + 'src/'
publish.conf.htmlDir = publish.conf.outDir + 'original_html/'
@ -94,8 +95,8 @@ function publish(symbolSet) {
var namespacesTemplate = new JSDOC.JsPlate(templatesDir +
'namespaces.tmpl');
} catch(e) {
print('Couldn\'t create the required templates: ' + e);
quit();
generateError('Couldn\'t create the required templates: ' + e);
System.exit(1);
}
// some ustility filters
@ -172,6 +173,11 @@ function publish(symbolSet) {
var namespaces = namespacesTemplate.process(classes);
IO.saveFile(publish.conf.outDir, 'namespaces' + publish.conf.ext, namespaces);
IO.saveFile(publish.conf.htmlDir, 'namespaces.html', namespaces);
if (g_numErrors > 0) {
print('Num Errors: ' + g_numErrors);
System.exit(1);
}
}
@ -437,12 +443,13 @@ function camelCaseToUnderscore(str) {
/**
* Prints a warning about an unknown type only once.
* @param {string} place Use to print error message if type not found.
* @param {string} type Type specification.
*/
function reportUnknownType(type) {
function reportUnknownType(place, type) {
if (!g_unknownTypes[type]) {
g_unknownTypes[type] = true;
print ('WARNING: reference to unknown type: "' + type + '"');
generatePlaceError (place, 'reference to unknown type: "' + type + '"');
}
}
@ -492,12 +499,47 @@ function getIndexOfClosingCharacter(str, startIndex) {
return -1;
}
/**
* Make's a name by concatenating strings.
* @param {...[string]} strings to concatenate.
* @return {string} Concatenated string.
*/
function makeName() {
var str = '';
for (var ii = 0; ii < arguments.length; ++ii) {
if (str) {
str += '.';
}
str += arguments[ii];
}
return str;
}
/**
* Generates an error msg.
* @param {string} msg.
*/
function generateError(msg) {
++g_numErrors;
print('ERROR: ' + msg);
}
/**
* Generates an error msg.
* @param {string} place Use to print error message.
* @param {string} msg.
*/
function generatePlaceError(place, msg) {
generateError(place + ': ' + msg);
}
/**
* Converts a reference to a single JSDOC type specification to an html link.
* @param {string} place Use to print error message if type not found.
* @param {string} str to linkify.
* @return {string} linkified string.
*/
function linkifySingleType(type) {
function linkifySingleType(place, type) {
var not = '';
var equals = '';
// Remove ! if it exists.
@ -516,65 +558,69 @@ function linkifySingleType(type) {
if (startsWith(type, 'Array.<')) {
var closingAngle = getIndexOfClosingCharacter(type, 6);
if (closingAngle < 0) {
print ('WARNING: Unmatched "<" in Array type : ' + type);
generatePlaceError(place, 'Unmatched "<" in Array type : ' + type);
} else {
link = 'Array.&lt;' +
linkifySingleType(type.substring(7, closingAngle)) + '>';
linkifySingleType(place, type.substring(7, closingAngle)) + '>';
}
} else if (startsWith(type, 'function(')) {
var closingParen = getIndexOfClosingCharacter(type, 8);
if (closingParen < 0) {
print ('WARNING: Unmatched "(" in function type : ' + type);
generatePlaceError(place, 'Unmatched "(" in function type : ' + type);
} else {
var end = type.substring(closingParen + 1);
if (!startsWith(end, ': ')) {
print ('WARNING: Malformed return specification on function. Must be' +
' "function(args): type" including the space after the colon.');
generatePlaceError(place,
'Malformed return specification on function. Must be' +
' "function(args): type" including the space after the colon.');
} else {
var args = type.substring(9, closingParen).split(/ *, */);
var output = '';
for (var ii = 0; ii < args.length; ++ii) {
if (ii > 0) {
output += ', ';
var argsStr = type.substring(9, closingParen);
if (argsStr) {
var args = argsStr.split(/ *, */);
for (var ii = 0; ii < args.length; ++ii) {
if (ii > 0) {
output += ', ';
}
output += linkifyTypeSpec(place, args[ii]);
}
output += linkifyTypeSpec(args[ii]);
}
link = 'function(' + output + '): ' + linkifyTypeSpec(end.substring(2));
link = 'function(' + output + '): ' +
linkifyTypeSpec(place, end.substring(2));
}
}
} else if (type.indexOf(':') >= 0) { // check for records.
var elements = type.split(/\s*,\s*/);
var output = '{';
for (var ii = 0; ii < elements.length; ++ii) {
if (ii > 0) {
output += ', ';
}
var element = elements[ii];
var colon = element.indexOf(': ');
if (colon < 0) {
print ("WARNING: Malformed record specification. Format must be " +
"{id1: type1, id2: type2, ...}.");
output += element;
} else {
var name = element.substring(0, colon);
var subType = element.substring(colon + 2);
output += name + ':&nbsp;' + linkifyTypeSpec(subType)
if (type.indexOf('::') >= 0) { // check for CPP scope
generatePlaceError(place,
'CPP "::" scope operator found for type "' + type +
'" must be Javascript "." scope operator.');
} else {
var elements = type.split(/\s*,\s*/);
var output = '{';
for (var ii = 0; ii < elements.length; ++ii) {
if (ii > 0) {
output += ', ';
}
var element = elements[ii];
var colon = element.indexOf(': ');
if (colon < 0) {
generatePlaceError(place,
'Malformed record specification. Format must be ' +
'{id1: type1, id2: type2, ...}.');
output += element;
} else {
var name = element.substring(0, colon);
var subType = element.substring(colon + 2);
output += name + ':&nbsp;' + linkifyTypeSpec(place, subType)
}
}
link = output + '}';
}
link = output + '}';
} else {
var symbol = getSymbol(type);
if (symbol) {
link = '<a class="el" href="' + getLinkToSymbol(symbol) + '">' +
type + '</a>';
} else if (startsWith(type, 'o3d.')) {
// TODO: remove this hack, make nixysa generate JSDOC js
// files instead of C++ headers and pass those into
// jsdoctoolkit.
reportUnknownType(type);
link = '<a class="el" href="../classo3d_1_1_' +
camelCaseToUnderscore(type.substring(4)) + '.html">' +
type + '</a>';
} else {
// See if the symbol is a property or field.
var period = type.lastIndexOf('.');
@ -586,11 +632,21 @@ function linkifySingleType(type) {
link = '<a class="el" href="' + getLinkToSymbol(symbol) + '#' +
field + '">' + type + '</a>';
} else {
if (subType[0] == '?') {
subType = subType.substring(1);
}
if (!g_validJSDOCTypes[subType]) {
reportUnknownType(type);
if (startsWith(type, 'o3d.')) {
// TODO(gman): remove this hack, make nixysa generate JSDOC js
// files instead of C++ headers and pass those into
// jsdoctoolkit.
reportUnknownType(place, type);
link = '<a class="el" href="../classo3d_1_1_' +
camelCaseToUnderscore(type.substring(4)) + '.html">' +
type + '</a>';
} else {
if (subType[0] == '?') {
subType = subType.substring(1);
}
if (!g_validJSDOCTypes[subType]) {
reportUnknownType(place, type);
}
}
}
}
@ -627,10 +683,11 @@ function fixSpecCommas(str) {
* '(!o3djs.math.Vector3|!O3D.math.Vector4)' would change to
* '(!<a href="??">o3djs.math.Vector3</a>
* |!<a href="??">o3djs.math.Vector4</a>)'.
* @param {string} place Use to print error message if type not found.
* @param {string} str to linkify.
* @return {string} linkified string.
*/
function linkifyTypeSpec(str) {
function linkifyTypeSpec(place, str) {
var output = '';
if (str) {
var fixed = fixSpecCommas(str);
@ -642,16 +699,31 @@ function linkifyTypeSpec(str) {
if (tt > 0) {
output += '|';
}
output += linkifySingleType(types[tt]);
output += linkifySingleType(place, types[tt]);
}
output += ')';
} else {
output += linkifySingleType(fixed);
output += linkifySingleType(place, fixed);
}
} else {
generatePlaceError(place, 'missing type specification (' + str + ')');
}
return output;
}
/**
* Same as linkifyTypeSpec but allows str to be undefined or ''.
* @param {string} place Use to print error message if type not found.
* @param {string} str to linkify.
* @return {string} linkified string.
*/
function linkifyTypeSpecForReturn(place, str) {
if (str) {
return linkifyTypeSpec(place, str);
}
return '';
}
/**
* Gets a symbol for a type.
* This is here mostly for debugging so you can insert a print before or after

@ -28,7 +28,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""o3d binding model module.
This module implements the glue functions for the o3d binding model, binding
@ -300,6 +299,21 @@ def CppGetStatic(scope, type_defn, field):
cpp_utils.GetGetterName(field))
def JSDocTypeString(type_defn):
"""Gets the representation of a type in JSDoc notation.
Args:
type_defn: a Definition for the type.
Returns:
a string that is the JSDoc notation of type_defn.
"""
type_defn = type_defn.GetFinalType()
type_stack = type_defn.GetParentScopeStack()
name = type_defn.name
return '!' + '.'.join([s.name for s in type_stack[1:]] + [name])
_binding_glue_header_template = string.Template('')