├── README.md ├── demo-build.html ├── demo-server.html ├── help.html ├── lib ├── css_inject.js ├── dep_tpl.js ├── modules.js ├── pkg_tpl.js └── pyjs.js ├── manifest.json ├── plugins ├── __init__.py ├── __init__.pyc ├── combo.py └── combo.pyc ├── pyjs.py ├── pyjs ├── __init__.py ├── __init__.pyc ├── localserver.py ├── localserver.pyc ├── parser.py ├── parser.pyc ├── utils.py └── utils.pyc ├── server.json ├── src ├── core │ ├── __init__.js │ ├── init.js │ └── prelude.js ├── increment.js ├── main │ ├── __init__.js │ ├── one.js │ └── two.js └── math.js ├── tools ├── .svn │ ├── all-wcprops │ └── entries ├── closure_linter │ ├── __init__.py │ ├── checker.py │ ├── checkerbase.py │ ├── closurizednamespacesinfo.py │ ├── closurizednamespacesinfo_test.py │ ├── common │ │ ├── __init__.py │ │ ├── error.py │ │ ├── erroraccumulator.py │ │ ├── errorhandler.py │ │ ├── errorprinter.py │ │ ├── filetestcase.py │ │ ├── htmlutil.py │ │ ├── lintrunner.py │ │ ├── matcher.py │ │ ├── position.py │ │ ├── simplefileflags.py │ │ ├── tokenizer.py │ │ └── tokens.py │ ├── ecmalintrules.py │ ├── ecmametadatapass.py │ ├── error_check.py │ ├── error_fixer.py │ ├── errorrules.py │ ├── errors.py │ ├── fixjsstyle.py │ ├── fixjsstyle_test.py │ ├── full_test.py │ ├── gjslint.py │ ├── indentation.py │ ├── javascriptlintrules.py │ ├── javascriptstatetracker.py │ ├── javascripttokenizer.py │ ├── javascripttokens.py │ ├── not_strict_test.py │ ├── requireprovidesorter.py │ ├── statetracker.py │ └── tokenutil.py └── jsdoc │ ├── README.txt │ ├── app │ ├── frame.js │ ├── frame │ │ ├── Chain.js │ │ ├── Dumper.js │ │ ├── Hash.js │ │ ├── Link.js │ │ ├── Namespace.js │ │ ├── Opt.js │ │ ├── Reflection.js │ │ ├── String.js │ │ └── Testrun.js │ ├── handlers │ │ ├── FOODOC.js │ │ ├── XMLDOC.js │ │ └── XMLDOC │ │ │ ├── DomReader.js │ │ │ ├── XMLDoc.js │ │ │ └── XMLParse.js │ ├── lib │ │ ├── JSDOC.js │ │ └── JSDOC │ │ │ ├── DocComment.js │ │ │ ├── DocTag.js │ │ │ ├── JsDoc.js │ │ │ ├── JsPlate.js │ │ │ ├── Lang.js │ │ │ ├── Parser.js │ │ │ ├── PluginManager.js │ │ │ ├── Symbol.js │ │ │ ├── SymbolSet.js │ │ │ ├── TextStream.js │ │ │ ├── Token.js │ │ │ ├── TokenReader.js │ │ │ ├── TokenStream.js │ │ │ ├── Util.js │ │ │ └── Walker.js │ ├── main.js │ ├── plugins │ │ ├── commentSrcJson.js │ │ ├── frameworkPrototype.js │ │ ├── functionCall.js │ │ ├── publishSrcHilite.js │ │ ├── symbolLink.js │ │ ├── tagParamConfig.js │ │ └── tagSynonyms.js │ ├── run.js │ ├── t │ │ ├── TestDoc.js │ │ └── runner.js │ ├── test.js │ └── test │ │ ├── addon.js │ │ ├── anon_inner.js │ │ ├── augments.js │ │ ├── augments2.js │ │ ├── borrows.js │ │ ├── borrows2.js │ │ ├── config.js │ │ ├── constructs.js │ │ ├── encoding.js │ │ ├── encoding_other.js │ │ ├── event.js │ │ ├── exports.js │ │ ├── functions_anon.js │ │ ├── functions_nested.js │ │ ├── global.js │ │ ├── globals.js │ │ ├── ignore.js │ │ ├── inner.js │ │ ├── jsdoc_test.js │ │ ├── lend.js │ │ ├── memberof.js │ │ ├── memberof2.js │ │ ├── memberof3.js │ │ ├── memberof_constructor.js │ │ ├── module.js │ │ ├── multi_methods.js │ │ ├── name.js │ │ ├── namespace_nested.js │ │ ├── nocode.js │ │ ├── oblit_anon.js │ │ ├── overview.js │ │ ├── param_inline.js │ │ ├── params_optional.js │ │ ├── prototype.js │ │ ├── prototype_nested.js │ │ ├── prototype_oblit.js │ │ ├── prototype_oblit_constructor.js │ │ ├── public.js │ │ ├── scripts │ │ ├── code.js │ │ └── notcode.txt │ │ ├── shared.js │ │ ├── shared2.js │ │ ├── shortcuts.js │ │ ├── static_this.js │ │ ├── synonyms.js │ │ ├── tosource.js │ │ └── variable_redefine.js │ ├── changes.txt │ ├── conf │ └── sample.conf │ ├── java │ ├── build.xml │ ├── build_1.4.xml │ ├── classes │ │ └── js.jar │ └── src │ │ ├── JsDebugRun.java │ │ └── JsRun.java │ ├── jsdebug.jar │ ├── jsrun.jar │ ├── jsrun.sh │ └── templates │ └── jsdoc │ ├── allclasses.tmpl │ ├── allfiles.tmpl │ ├── class.tmpl │ ├── index.tmpl │ ├── publish.js │ ├── static │ ├── default.css │ ├── header.html │ └── index.html │ └── symbol.tmpl └── utest ├── index.html ├── js └── pyjs.js ├── qunit.css └── qunit.js /README.md: -------------------------------------------------------------------------------- 1 | PyJs Javascript FrameWork 2 | ========================= 3 | 4 | A commonjs like js framework base on Python. 5 | 6 | See help.html for more information. 7 | 8 | [doc](http://demix.github.com/pyjs/) 9 | 10 | [intro](http://www.cnblogs.com/demix/tag/pyjs/) 11 | 12 | Full test under Python 2.7 13 | 14 | Python 3 seems not supported...... 15 | -------------------------------------------------------------------------------- /demo-build.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Test for connect sdk 6 | 7 | 8 | 9 | 10 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /demo-server.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Test for phoenix sdk 6 | 7 | 8 | 9 | 10 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /help.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Python JS Proxy Document 6 | 18 | 19 | 20 |

PyJs

21 |

demixcn@gmail.com

22 |
23 |

介绍

24 |

项目地址

25 |

PyJs是一种浏览器端的CommonJs实现

26 |

PyJs特别适用于一些只有静态文件构成的项目,最佳是只有js构成的项目,如baidu connect sdk.

27 | 28 |

使用

29 |
    30 |
  1. 31 |

    pyjsdir

    32 |

    pyjsdir是pyjs运行的核心文件夹,所有commonjs规范的js文件,必须放在pyjsdir中,默认为src,可在manifest.json中设置。

    33 |
  2. 34 |
  3. 35 |

    本地服务器中使用pyjs

    36 |

    使用 37 |

     38 | python pyjs.py runserver                        
     39 |                     
    40 | 启动本地服务器
    41 | 测试页面中引入lib/pyjs.js
    42 | 对于以.js结尾的文件,将查找相对路径,若相对路径下没有原文件,则搜索pyjsdir下文件或文件夹,若有文件与之相同,则编译包之后返回,replace为local。若有文件夹与去除.js部分相同,则查找文件夹下__init__.js文件,若有,按里面定义的__all__数据取出所有文件,编译之后返回。
    43 |
  4. 44 |
  5. 45 |

    编译

    46 |

    上线前,运行 47 |

     48 | python pyjs.py                        
     49 |                     
    50 | 会在build文件下生成所有commonjs模块文件。manifest中可以制定combo_url,若指定,运行编译后文件的require时,将通过combo请求文件。若没有指定,将同时加载多个js文件。
    51 | 文件同时会生成boot.js,里面有文件的依赖关系,线上html引用这个文件即可。 52 |
  6. 53 |
54 | 55 |

manifest.json声明属性

56 |
    57 |
  1. 58 |

    version

    59 |

    type:string

    60 |

    版本号

    61 |
  2. 62 |
  3. 63 |

    pyjsdir

    64 |

    type:string

    65 |

    pyjs包所在的文件夹,默认为src

    66 |
  4. 67 |
  5. 68 |

    combo

    69 |

    type:object

    70 |

    设置combo,属性combo_url标志combo目标url

    71 |
  6. 72 |
  7. 73 |

    replace

    74 |

    type:object

    75 |

    token: %#xxx#%,将替换文件中%##%中间的字符

    76 |
     77 |     "replace":{
     78 |         "replace_type":{
     79 |             "token1":"url1",
     80 |             "token2":"url2",
     81 |             "token3":"url3"
     82 |         }
     83 |     }                        
     84 |                     
    85 |
  8. 86 |
87 |

Local Transimission

88 |

本地server启动后,若配置server.json,会启用请求转发。

89 |

server.json声明分为两部分,key为正则,对应匹配url请求规则;value为映射

90 |
    91 |
  1. 92 |

    映射到线上请求

    93 |

    所有以http开头的都会映射到线上请求

    94 |

    这里不会做权限控制等,有复杂需求使用自定义插件

    95 |
  2. 96 |
  3. 97 |

    映射到本地插件

    98 |

    所有以plugins开头都会映射到本地插件,对应到plugins的相应module中。

    99 |

    module文件必须包含main函数,会将请求的search参数传入到main函数中。

    100 |

    返回值: content-type , body

    101 |
  4. 102 |
103 | 114 | 117 |
118 | 119 | 120 | -------------------------------------------------------------------------------- /lib/css_inject.js: -------------------------------------------------------------------------------- 1 | var baidu = baidu || {}; 2 | baidu.more = baidu.more || {}; 3 | 4 | /** 5 | * 使用 style 标签添加一段stylesheet 6 | * @function 7 | * @name baidu.more.addCssRules 8 | * @param styles {string} 样式 9 | * @param names {array} 样式的name值 10 | */ 11 | baidu.more.addCssRules = function(styles, names) { 12 | if (!baidu.more.addCssRules._cssRules) { 13 | baidu.more.addCssRules._cssRules = {}; 14 | } 15 | 16 | // note, we potentially re-include CSS if it comes with other CSS that we 17 | // have previously not included. 18 | var allIncluded = true; 19 | baidu.each(names, function(id) { 20 | if (!(id in baidu.more.addCssRules._cssRules)) { 21 | allIncluded = false; 22 | baidu.more.addCssRules._cssRules[id] = true; 23 | } 24 | }); 25 | 26 | if (allIncluded) { 27 | return; 28 | } 29 | 30 | if (!baidu.browser.ie) { 31 | var style = document.createElement('style'); 32 | style.type = 'text/css'; 33 | style.textContent = styles; 34 | document.getElementsByTagName('HEAD')[0].appendChild(style); 35 | } else { 36 | try { 37 | document.createStyleSheet().cssText = styles; 38 | } catch (exc) { 39 | // major problem on IE : You can only create 31 stylesheet objects with 40 | // this method. We will have to add the styles into an existing 41 | // stylesheet. 42 | if (document.styleSheets[0]) { 43 | document.styleSheets[0].cssText += styles; 44 | } 45 | } 46 | } 47 | }; 48 | 49 | -------------------------------------------------------------------------------- /lib/dep_tpl.js: -------------------------------------------------------------------------------- 1 | addDependence('##package##' , '##dependence##'); 2 | -------------------------------------------------------------------------------- /lib/modules.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | */ 4 | 5 | /** 6 | * 7 | */ 8 | 9 | 10 | define( "##package##" , function(require , exports , module){ 11 | 12 | ##file## 13 | 14 | } ); -------------------------------------------------------------------------------- /lib/pkg_tpl.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 3 | ##file## 4 | 5 | })(); -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"", 3 | "version":"0.1.1", 4 | "parent":"lib/modules.js", 5 | "pyjsdir": "src", 6 | 7 | "replace":{ 8 | "local":{ 9 | "js_url":"http://demix.baidu.com/PyJs/build/" 10 | }, 11 | "test":{ 12 | "js_url":"http://demix.baidu.com:8150/" 13 | }, 14 | "online":{ 15 | "js_url":"http://demix.baidu.com/PyJs/build/" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /plugins/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demix/PyJs/a95071c2ef6a3117e85b122ea6e781f0a35d6c8c/plugins/__init__.py -------------------------------------------------------------------------------- /plugins/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demix/PyJs/a95071c2ef6a3117e85b122ea6e781f0a35d6c8c/plugins/__init__.pyc -------------------------------------------------------------------------------- /plugins/combo.py: -------------------------------------------------------------------------------- 1 | def main(params): 2 | """ 3 | """ 4 | 5 | return ('text/html' , params) 6 | -------------------------------------------------------------------------------- /plugins/combo.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demix/PyJs/a95071c2ef6a3117e85b122ea6e781f0a35d6c8c/plugins/combo.pyc -------------------------------------------------------------------------------- /pyjs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | import json 5 | import pprint 6 | import sys 7 | import re 8 | import codecs 9 | import os 10 | 11 | 12 | import pyjs 13 | 14 | BASE_DIR = os.path.abspath(os.path.dirname(__file__)) + os.sep 15 | 16 | 17 | 18 | if __name__ == '__main__': 19 | args = sys.argv 20 | 21 | 22 | target = None 23 | 24 | 25 | if len(args) >1 and args[1] == 'runserver': 26 | pyjs.localserver.setpath(BASE_DIR) 27 | pyjs.localserver.setBaseDir(BASE_DIR) 28 | pyjs.localserver.run() 29 | else: 30 | if len(args) == 1: 31 | target = 'build' 32 | p = pyjs.parser.Parser(BASE_DIR ) 33 | elif len(args) == 2: 34 | target = 'build' 35 | p = pyjs.parser.Parser(BASE_DIR , '*' , args[1]) 36 | p.write(target) 37 | -------------------------------------------------------------------------------- /pyjs/__init__.py: -------------------------------------------------------------------------------- 1 | import parser 2 | import utils 3 | import localserver 4 | -------------------------------------------------------------------------------- /pyjs/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demix/PyJs/a95071c2ef6a3117e85b122ea6e781f0a35d6c8c/pyjs/__init__.pyc -------------------------------------------------------------------------------- /pyjs/localserver.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | import BaseHTTPServer 6 | import SimpleHTTPServer 7 | import socket 8 | import mimetypes 9 | import sys 10 | import os 11 | import re 12 | import codecs 13 | import json 14 | import urllib2 15 | import urllib 16 | 17 | import parser 18 | 19 | PATH = '' 20 | PORT = 8150 21 | baseDir = None 22 | encoding = 'utf-8' 23 | 24 | class PrHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): 25 | """ 26 | """ 27 | def sendResponseWithOutput(self, response, contentType, body): 28 | """ 29 | handles both str and unicode types 30 | """ 31 | self.send_response(response) 32 | self.send_header("Content-Type", contentType) 33 | self.send_header("Content-Length", len(body)) 34 | if response == 301: 35 | self.send_header("Location", body) 36 | self.end_headers() 37 | if response != 301: 38 | self.wfile.write(body) 39 | 40 | def getServerConfig(self , encoding , baseDir): 41 | path = baseDir + 'server.json' 42 | if os.path.exists(path): 43 | f = codecs.open(path , 'r' , encoding) 44 | serverConfig = f.read() 45 | f.close() 46 | return json.loads(serverConfig) 47 | 48 | 49 | def urlProxy(self , url): 50 | response = urllib2.urlopen(url) 51 | contentType = response.info()['Content-Type'] 52 | body = response.read() 53 | return (contentType,body) 54 | 55 | def pluginsProxy(self , plugins , params): 56 | try: 57 | exec("from " + plugins+" import main") 58 | return main(params) 59 | except: 60 | return ('text/html;charset=utf-8' , "Unexpected error:"+ str(sys.exc_info())) 61 | 62 | 63 | 64 | def do_GET(self): 65 | """ 66 | 67 | Arguments: 68 | - `self`: 69 | """ 70 | global encoding 71 | global baseDir 72 | truncate_path = self.path.split('?')[0].split('#')[0] 73 | path_items = self.path.split('?') 74 | response = 200 75 | 76 | 77 | serverConfig = self.getServerConfig(encoding , baseDir) 78 | 79 | isInServerConfig = False 80 | for reg,target in serverConfig.items(): 81 | if re.search(reg , truncate_path): 82 | isInServerConfig = True 83 | if target.startswith('http'):#http url 84 | contentType,body =self.urlProxy(target) 85 | elif target.startswith('plugins'):#local plugins 86 | path = '' 87 | if( len(path_items) >1 ): 88 | path = path_items[1] 89 | contentType , body = self.pluginsProxy(target , path) 90 | 91 | if not isInServerConfig: 92 | if truncate_path.endswith('.js'):#可能需要读取包内容 93 | if os.path.exists(baseDir + truncate_path): 94 | response, contentType, body = self.server_static(truncate_path) 95 | else: 96 | 97 | contentType = 'application/javascript; charset='+encoding 98 | package = re.search('\/(\w+?)\.js' , truncate_path) 99 | package = package.group(1) 100 | 101 | p = parser.Parser(baseDir , package , 'local') 102 | 103 | body = p.getFile(package).encode(encoding) 104 | else: 105 | response, contentType, body = self.server_static(truncate_path) 106 | self.sendResponseWithOutput(response , contentType , body) 107 | 108 | 109 | 110 | def server_static(self,file_path): 111 | file_path = '.' + file_path 112 | if not os.path.exists(file_path): 113 | return (404, 'text/html', 'no such file, may be your forget add /doc/, for example "/doc/' + file_path + '"') 114 | 115 | if os.path.isfile(file_path): 116 | stat_result = os.stat(file_path) 117 | mime_type, encoding = mimetypes.guess_type(file_path) 118 | 119 | file = open(file_path, "rb") 120 | try: 121 | return (200, mime_type, file.read()) 122 | finally: 123 | file.close() 124 | 125 | elif os.path.isdir(file_path): 126 | if file_path.endswith('/'): 127 | index_file = os.path.join(file_path, 'index.html') 128 | if os.path.exists(index_file): 129 | return (200, 'text/html', open(index_file).read()) 130 | else: 131 | return (200 , 'text/html; charset=utf-8' , self.list_directory(os.path.abspath(file_path)).read().encode('utf-8')[150:]) 132 | else: 133 | return (301, 'text/html', file_path + '/') 134 | else: 135 | pass 136 | 137 | 138 | 139 | 140 | 141 | def setpath(path): 142 | if os.path.exists(path): 143 | PATH = path 144 | 145 | def setBaseDir(m): 146 | global baseDir 147 | baseDir = m 148 | 149 | 150 | def run(handler_class = PrHandler): 151 | try: 152 | httpd = BaseHTTPServer.HTTPServer((PATH, PORT), handler_class) 153 | print 'server in http://localhost:' + str(PORT) 154 | httpd.serve_forever() 155 | except socket.error: 156 | print 'may be address already in use' 157 | print 'you can try another port by use "python localServer.py xxx"' 158 | sys.exit(1) 159 | 160 | 161 | 162 | if __name__ == '__main__': 163 | if (len(sys.argv) > 1): 164 | PORT = int(sys.argv[1]) 165 | run() 166 | 167 | 168 | -------------------------------------------------------------------------------- /pyjs/localserver.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demix/PyJs/a95071c2ef6a3117e85b122ea6e781f0a35d6c8c/pyjs/localserver.pyc -------------------------------------------------------------------------------- /pyjs/parser.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demix/PyJs/a95071c2ef6a3117e85b122ea6e781f0a35d6c8c/pyjs/parser.pyc -------------------------------------------------------------------------------- /pyjs/utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | import os 5 | import shutil 6 | 7 | def rm(target): 8 | """ 9 | 10 | Arguments: 11 | - `target`: 12 | """ 13 | if os.path.exists(target): 14 | if os.path.isfile(target): 15 | os.remove(target) 16 | elif os.path.isdir(target): 17 | shutil.rmtree(target) 18 | 19 | return True 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /pyjs/utils.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demix/PyJs/a95071c2ef6a3117e85b122ea6e781f0a35d6c8c/pyjs/utils.pyc -------------------------------------------------------------------------------- /server.json: -------------------------------------------------------------------------------- 1 | { 2 | "baidu":"http://www.baidu.com", 3 | "combo":"plugins.combo" 4 | } 5 | -------------------------------------------------------------------------------- /src/core/__init__.js: -------------------------------------------------------------------------------- 1 | __all__ = ['prelude' , 'init'] 2 | 3 | -------------------------------------------------------------------------------- /src/core/init.js: -------------------------------------------------------------------------------- 1 | exports.init = function(){ 2 | alert(1); 3 | }; 4 | 5 | 6 | 7 | 8 | var name = require('main'); 9 | var name2 = require('main'); 10 | require('math') 11 | 12 | exports.VERSION = '2.0'; 13 | 14 | exports.main = name.two; 15 | -------------------------------------------------------------------------------- /src/core/prelude.js: -------------------------------------------------------------------------------- 1 | exports.VERSION = '2.0'; 2 | 3 | 4 | exports.name = 'PyJsProxy'; 5 | 6 | exports.url = '%#js_url#%'; -------------------------------------------------------------------------------- /src/increment.js: -------------------------------------------------------------------------------- 1 | //我们 2 | var add = require('math').add; 3 | exports.increment = function(val) { 4 | return add(val, 1); 5 | }; 6 | -------------------------------------------------------------------------------- /src/main/__init__.js: -------------------------------------------------------------------------------- 1 | __all__ = ['one' , 'two'] -------------------------------------------------------------------------------- /src/main/one.js: -------------------------------------------------------------------------------- 1 | exports.one = '111'; 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/main/two.js: -------------------------------------------------------------------------------- 1 | exports.two = 'twotwotwo.'; -------------------------------------------------------------------------------- /src/math.js: -------------------------------------------------------------------------------- 1 | exports.add = function() { 2 | var sum = 0, i = 0, args = arguments, l = args.length; 3 | while (i < l) { 4 | sum += args[i++]; 5 | } 6 | return sum; 7 | }; 8 | -------------------------------------------------------------------------------- /tools/.svn/all-wcprops: -------------------------------------------------------------------------------- 1 | K 25 2 | svn:wc:ra_dav:version-url 3 | V 46 4 | /repos/!svn/ver/78944/doc/zhengxin/proxy/tools 5 | END 6 | -------------------------------------------------------------------------------- /tools/.svn/entries: -------------------------------------------------------------------------------- 1 | 10 2 | 3 | dir 4 | 79675 5 | http://fe.baidu.com/repos/doc/zhengxin/proxy/tools 6 | http://fe.baidu.com/repos 7 | 8 | 9 | 10 | 2011-06-22T07:12:48.177099Z 11 | 78944 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 01db0846-df26-4232-8c27-33e78907c97d 28 | 29 | jsdoc-toolkit 30 | dir 31 | 32 | closure_linter 33 | dir 34 | 35 | -------------------------------------------------------------------------------- /tools/closure_linter/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | -------------------------------------------------------------------------------- /tools/closure_linter/checker.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2007 The Closure Linter Authors. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS-IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """Core methods for checking JS files for common style guide violations.""" 18 | 19 | __author__ = ('robbyw@google.com (Robert Walker)', 20 | 'ajp@google.com (Andy Perelson)') 21 | 22 | import gflags as flags 23 | 24 | from closure_linter import checkerbase 25 | from closure_linter import closurizednamespacesinfo 26 | from closure_linter import ecmametadatapass 27 | from closure_linter import errors 28 | from closure_linter import javascriptlintrules 29 | from closure_linter import javascriptstatetracker 30 | from closure_linter.common import errorprinter 31 | from closure_linter.common import lintrunner 32 | 33 | flags.DEFINE_list('limited_doc_files', ['dummy.js', 'externs.js'], 34 | 'List of files with relaxed documentation checks. Will not ' 35 | 'report errors for missing documentation, some missing ' 36 | 'descriptions, or methods whose @return tags don\'t have a ' 37 | 'matching return statement.') 38 | flags.DEFINE_list('closurized_namespaces', '', 39 | 'Namespace prefixes, used for testing of' 40 | 'goog.provide/require') 41 | flags.DEFINE_list('ignored_extra_namespaces', '', 42 | 'Fully qualified namespaces that should be not be reported ' 43 | 'as extra by the linter.') 44 | 45 | 46 | class JavaScriptStyleChecker(checkerbase.CheckerBase): 47 | """Checker that applies JavaScriptLintRules.""" 48 | 49 | def __init__(self, error_handler): 50 | """Initialize an JavaScriptStyleChecker object. 51 | 52 | Args: 53 | error_handler: Error handler to pass all errors to 54 | """ 55 | self._namespaces_info = None 56 | if flags.FLAGS.closurized_namespaces: 57 | self._namespaces_info = ( 58 | closurizednamespacesinfo.ClosurizedNamespacesInfo( 59 | flags.FLAGS.closurized_namespaces, 60 | flags.FLAGS.ignored_extra_namespaces)) 61 | 62 | checkerbase.CheckerBase.__init__( 63 | self, 64 | error_handler=error_handler, 65 | lint_rules=javascriptlintrules.JavaScriptLintRules( 66 | self._namespaces_info), 67 | state_tracker=javascriptstatetracker.JavaScriptStateTracker(), 68 | metadata_pass=ecmametadatapass.EcmaMetaDataPass(), 69 | limited_doc_files=flags.FLAGS.limited_doc_files) 70 | 71 | def _CheckTokens(self, token, parse_error, debug_tokens): 72 | """Checks a token stream for lint warnings/errors. 73 | 74 | Adds a separate pass for computing dependency information based on 75 | goog.require and goog.provide statements prior to the main linting pass. 76 | 77 | Args: 78 | token: The first token in the token stream. 79 | parse_error: A ParseError if any errors occurred. 80 | debug_tokens: Whether every token should be printed as it is encountered 81 | during the pass. 82 | 83 | Returns: 84 | A boolean indicating whether the full token stream could be checked or if 85 | checking failed prematurely. 86 | """ 87 | # To maximize the amount of errors that get reported before a parse error 88 | # is displayed, don't run the dependency pass if a parse error exists. 89 | if self._namespaces_info and not parse_error: 90 | self._namespaces_info.Reset() 91 | result = (self._ExecutePass(token, self._DependencyPass) and 92 | self._ExecutePass(token, self._LintPass, 93 | debug_tokens=debug_tokens)) 94 | else: 95 | result = self._ExecutePass(token, self._LintPass, parse_error, 96 | debug_tokens) 97 | 98 | if not result: 99 | return False 100 | 101 | self._lint_rules.Finalize(self._state_tracker, self._tokenizer.mode) 102 | 103 | self._error_handler.FinishFile() 104 | return True 105 | 106 | def _DependencyPass(self, token): 107 | """Processes an invidual token for dependency information. 108 | 109 | Used to encapsulate the logic needed to process an individual token so that 110 | it can be passed to _ExecutePass. 111 | 112 | Args: 113 | token: The token to process. 114 | """ 115 | self._namespaces_info.ProcessToken(token, self._state_tracker) 116 | 117 | 118 | class GJsLintRunner(lintrunner.LintRunner): 119 | """Wrapper class to run GJsLint.""" 120 | 121 | def Run(self, filenames, error_handler=None): 122 | """Run GJsLint on the given filenames. 123 | 124 | Args: 125 | filenames: The filenames to check 126 | error_handler: An optional ErrorHandler object, an ErrorPrinter is used if 127 | none is specified. 128 | 129 | Returns: 130 | error_count, file_count: The number of errors and the number of files that 131 | contain errors. 132 | """ 133 | if not error_handler: 134 | error_handler = errorprinter.ErrorPrinter(errors.NEW_ERRORS) 135 | 136 | checker = JavaScriptStyleChecker(error_handler) 137 | 138 | # Check the list of files. 139 | for filename in filenames: 140 | checker.Check(filename) 141 | 142 | return error_handler 143 | -------------------------------------------------------------------------------- /tools/closure_linter/closurizednamespacesinfo_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2010 The Closure Linter Authors. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS-IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """Unit tests for ClosurizedNamespacesInfo.""" 18 | 19 | 20 | 21 | import unittest as googletest 22 | from closure_linter import closurizednamespacesinfo 23 | from closure_linter import javascripttokenizer 24 | from closure_linter import javascripttokens 25 | 26 | # Shorthand 27 | Token = javascripttokens.JavaScriptToken 28 | Type = javascripttokens.JavaScriptTokenType 29 | 30 | 31 | class ClosurizedNamespacesInfoTest(googletest.TestCase): 32 | """Tests for ClosurizedNamespacesInfo.""" 33 | 34 | __test_cases = { 35 | 'package.CONSTANT': 'package', 36 | 'package.methodName': 'package', 37 | 'package.subpackage.methodName': 'package.subpackage', 38 | 'package.subpackage.methodName.apply': 'package.subpackage', 39 | 'package.ClassName.something': 'package.ClassName', 40 | 'package.ClassName.Enum.VALUE.methodName': 'package.ClassName.Enum', 41 | 'package.ClassName.CONSTANT': 'package.ClassName', 42 | 'package.namespace.CONSTANT.methodName': 'package.namespace', 43 | 'package.ClassName.inherits': 'package.ClassName', 44 | 'package.ClassName.apply': 'package.ClassName', 45 | 'package.ClassName.methodName.apply': 'package.ClassName', 46 | 'package.ClassName.methodName.call': 'package.ClassName', 47 | 'package.ClassName.prototype.methodName': 'package.ClassName', 48 | 'package.ClassName.privateMethod_': 'package.ClassName', 49 | 'package.className.privateProperty_': 'package.className', 50 | 'package.className.privateProperty_.methodName': 'package.className', 51 | 'package.ClassName.PrivateEnum_': 'package.ClassName.PrivateEnum_', 52 | 'package.ClassName.prototype.methodName.apply': 'package.ClassName', 53 | 'package.ClassName.property.subProperty': 'package.ClassName', 54 | 'package.className.prototype.something.somethingElse': 'package.className' 55 | } 56 | 57 | def testGetClosurizedNamespace(self): 58 | """Tests that the correct namespace is returned for various identifiers.""" 59 | namespaces_info = closurizednamespacesinfo.ClosurizedNamespacesInfo( 60 | closurized_namespaces=['package'], ignored_extra_namespaces=[]) 61 | for identifier, expected_namespace in self.__test_cases.items(): 62 | actual_namespace = namespaces_info.GetClosurizedNamespace(identifier) 63 | self.assertEqual( 64 | expected_namespace, 65 | actual_namespace, 66 | 'expected namespace "' + str(expected_namespace) + 67 | '" for identifier "' + str(identifier) + '" but was "' + 68 | str(actual_namespace) + '"') 69 | 70 | def testIgnoredExtraNamespaces(self): 71 | """Tests that ignored_extra_namespaces are ignored.""" 72 | token = self._GetRequireTokens('package.Something') 73 | namespaces_info = closurizednamespacesinfo.ClosurizedNamespacesInfo( 74 | closurized_namespaces=['package'], 75 | ignored_extra_namespaces=['package.Something']) 76 | 77 | self.assertFalse(namespaces_info.IsExtraRequire(token), 78 | 'Should be valid since it is in ignored namespaces.') 79 | 80 | namespaces_info = closurizednamespacesinfo.ClosurizedNamespacesInfo( 81 | ['package'], []) 82 | 83 | self.assertTrue(namespaces_info.IsExtraRequire(token), 84 | 'Should be invalid since it is not in ignored namespaces.') 85 | 86 | def _GetRequireTokens(self, namespace): 87 | """Returns a list of tokens for a goog.require of the given namespace.""" 88 | line_text = 'goog.require(\'' + namespace + '\');\n' 89 | return javascripttokenizer.JavaScriptTokenizer().TokenizeFile([line_text]) 90 | 91 | if __name__ == '__main__': 92 | googletest.main() 93 | 94 | -------------------------------------------------------------------------------- /tools/closure_linter/common/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | -------------------------------------------------------------------------------- /tools/closure_linter/common/error.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2007 The Closure Linter Authors. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS-IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """Error object commonly used in linters.""" 18 | 19 | __author__ = ('robbyw@google.com (Robert Walker)', 20 | 'ajp@google.com (Andy Perelson)') 21 | 22 | 23 | class Error(object): 24 | """Object representing a style error.""" 25 | 26 | def __init__(self, code, message, token, position, fix_data): 27 | """Initialize the error object. 28 | 29 | Args: 30 | code: The numeric error code. 31 | message: The error message string. 32 | token: The tokens.Token where the error occurred. 33 | position: The position of the error within the token. 34 | fix_data: Data to be used in autofixing. Codes with fix_data are: 35 | GOOG_REQUIRES_NOT_ALPHABETIZED - List of string value tokens that are 36 | class names in goog.requires calls. 37 | """ 38 | self.code = code 39 | self.message = message 40 | self.token = token 41 | self.position = position 42 | if token: 43 | self.start_index = token.start_index 44 | else: 45 | self.start_index = 0 46 | self.fix_data = fix_data 47 | if self.position: 48 | self.start_index += self.position.start 49 | 50 | def Compare(a, b): 51 | """Compare two error objects, by source code order. 52 | 53 | Args: 54 | a: First error object. 55 | b: Second error object. 56 | 57 | Returns: 58 | A Negative/0/Positive number when a is before/the same as/after b. 59 | """ 60 | line_diff = a.token.line_number - b.token.line_number 61 | if line_diff: 62 | return line_diff 63 | 64 | return a.start_index - b.start_index 65 | Compare = staticmethod(Compare) 66 | -------------------------------------------------------------------------------- /tools/closure_linter/common/erroraccumulator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2008 The Closure Linter Authors. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS-IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """Linter error handler class that accumulates an array of errors.""" 18 | 19 | __author__ = ('robbyw@google.com (Robert Walker)', 20 | 'ajp@google.com (Andy Perelson)') 21 | 22 | 23 | from closure_linter.common import errorhandler 24 | 25 | 26 | class ErrorAccumulator(errorhandler.ErrorHandler): 27 | """Error handler object that accumulates errors in a list.""" 28 | 29 | def __init__(self): 30 | self._errors = [] 31 | 32 | def HandleError(self, error): 33 | """Append the error to the list. 34 | 35 | Args: 36 | error: The error object 37 | """ 38 | self._errors.append((error.token.line_number, error.code)) 39 | 40 | def GetErrors(self): 41 | """Returns the accumulated errors. 42 | 43 | Returns: 44 | A sequence of errors. 45 | """ 46 | return self._errors 47 | -------------------------------------------------------------------------------- /tools/closure_linter/common/errorhandler.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2008 The Closure Linter Authors. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS-IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """Interface for a linter error handler. 18 | 19 | Error handlers aggregate a set of errors from multiple files and can optionally 20 | perform some action based on the reported errors, for example, logging the error 21 | or automatically fixing it. 22 | """ 23 | 24 | __author__ = ('robbyw@google.com (Robert Walker)', 25 | 'ajp@google.com (Andy Perelson)') 26 | 27 | 28 | class ErrorHandler(object): 29 | """Error handler interface.""" 30 | 31 | def __init__(self): 32 | if self.__class__ == ErrorHandler: 33 | raise NotImplementedError('class ErrorHandler is abstract') 34 | 35 | def HandleFile(self, filename, first_token): 36 | """Notifies this ErrorHandler that subsequent errors are in filename. 37 | 38 | Args: 39 | filename: The file being linted. 40 | first_token: The first token of the file. 41 | """ 42 | 43 | def HandleError(self, error): 44 | """Append the error to the list. 45 | 46 | Args: 47 | error: The error object 48 | """ 49 | 50 | def FinishFile(self): 51 | """Finishes handling the current file. 52 | 53 | Should be called after all errors in a file have been handled. 54 | """ 55 | 56 | def GetErrors(self): 57 | """Returns the accumulated errors. 58 | 59 | Returns: 60 | A sequence of errors. 61 | """ 62 | -------------------------------------------------------------------------------- /tools/closure_linter/common/filetestcase.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2007 The Closure Linter Authors. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS-IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """Test case that runs a checker on a file, matching errors against annotations. 18 | 19 | Runs the given checker on the given file, accumulating all errors. The list 20 | of errors is then matched against those annotated in the file. Based heavily 21 | on devtools/javascript/gpylint/full_test.py. 22 | """ 23 | 24 | __author__ = ('robbyw@google.com (Robert Walker)', 25 | 'ajp@google.com (Andy Perelson)') 26 | 27 | import re 28 | 29 | import unittest as googletest 30 | from closure_linter.common import erroraccumulator 31 | 32 | 33 | class AnnotatedFileTestCase(googletest.TestCase): 34 | """Test case to run a linter against a single file.""" 35 | 36 | # Matches an all caps letters + underscores error identifer 37 | _MESSAGE = {'msg': '[A-Z][A-Z_]+'} 38 | # Matches a //, followed by an optional line number with a +/-, followed by a 39 | # list of message IDs. Used to extract expected messages from testdata files. 40 | # TODO(robbyw): Generalize to use different commenting patterns. 41 | _EXPECTED_RE = re.compile(r'\s*//\s*(?:(?P[+-]?[0-9]+):)?' 42 | r'\s*(?P%(msg)s(?:,\s*%(msg)s)*)' % _MESSAGE) 43 | 44 | def __init__(self, filename, runner, converter): 45 | """Create a single file lint test case. 46 | 47 | Args: 48 | filename: Filename to test. 49 | runner: Object implementing the LintRunner interface that lints a file. 50 | converter: Function taking an error string and returning an error code. 51 | """ 52 | 53 | googletest.TestCase.__init__(self, 'runTest') 54 | self._filename = filename 55 | self._messages = [] 56 | self._runner = runner 57 | self._converter = converter 58 | 59 | def shortDescription(self): 60 | """Provides a description for the test.""" 61 | return 'Run linter on %s' % self._filename 62 | 63 | def runTest(self): 64 | """Runs the test.""" 65 | try: 66 | filename = self._filename 67 | stream = open(filename) 68 | except IOError, ex: 69 | raise IOError('Could not find testdata resource for %s: %s' % 70 | (self._filename, ex)) 71 | 72 | expected = self._GetExpectedMessages(stream) 73 | got = self._ProcessFileAndGetMessages(filename) 74 | self.assertEqual(expected, got) 75 | 76 | def _GetExpectedMessages(self, stream): 77 | """Parse a file and get a sorted list of expected messages.""" 78 | messages = [] 79 | for i, line in enumerate(stream): 80 | match = self._EXPECTED_RE.search(line) 81 | if match: 82 | line = match.group('line') 83 | msg_ids = match.group('msgs') 84 | if line is None: 85 | line = i + 1 86 | elif line.startswith('+') or line.startswith('-'): 87 | line = i + 1 + int(line) 88 | else: 89 | line = int(line) 90 | for msg_id in msg_ids.split(','): 91 | # Ignore a spurious message from the license preamble. 92 | if msg_id != 'WITHOUT': 93 | messages.append((line, self._converter(msg_id.strip()))) 94 | stream.seek(0) 95 | messages.sort() 96 | return messages 97 | 98 | def _ProcessFileAndGetMessages(self, filename): 99 | """Trap gpylint's output parse it to get messages added.""" 100 | errors = erroraccumulator.ErrorAccumulator() 101 | self._runner.Run([filename], errors) 102 | 103 | errors = errors.GetErrors() 104 | errors.sort() 105 | return errors 106 | -------------------------------------------------------------------------------- /tools/closure_linter/common/htmlutil.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2007 The Closure Linter Authors. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS-IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """Utilities for dealing with HTML.""" 18 | 19 | __author__ = ('robbyw@google.com (Robert Walker)') 20 | 21 | import cStringIO 22 | import formatter 23 | import htmllib 24 | import HTMLParser 25 | import re 26 | 27 | 28 | class ScriptExtractor(htmllib.HTMLParser): 29 | """Subclass of HTMLParser that extracts script contents from an HTML file. 30 | 31 | Also inserts appropriate blank lines so that line numbers in the extracted 32 | code match the line numbers in the original HTML. 33 | """ 34 | 35 | def __init__(self): 36 | """Initialize a ScriptExtractor.""" 37 | htmllib.HTMLParser.__init__(self, formatter.NullFormatter()) 38 | self._in_script = False 39 | self._text = '' 40 | 41 | def start_script(self, attrs): 42 | """Internal handler for the start of a script tag. 43 | 44 | Args: 45 | attrs: The attributes of the script tag, as a list of tuples. 46 | """ 47 | for attribute in attrs: 48 | if attribute[0].lower() == 'src': 49 | # Skip script tags with a src specified. 50 | return 51 | self._in_script = True 52 | 53 | def end_script(self): 54 | """Internal handler for the end of a script tag.""" 55 | self._in_script = False 56 | 57 | def handle_data(self, data): 58 | """Internal handler for character data. 59 | 60 | Args: 61 | data: The character data from the HTML file. 62 | """ 63 | if self._in_script: 64 | # If the last line contains whitespace only, i.e. is just there to 65 | # properly align a tag, strip the whitespace. 66 | if data.rstrip(' \t') != data.rstrip(' \t\n\r\f'): 67 | data = data.rstrip(' \t') 68 | self._text += data 69 | else: 70 | self._AppendNewlines(data) 71 | 72 | def handle_comment(self, data): 73 | """Internal handler for HTML comments. 74 | 75 | Args: 76 | data: The text of the comment. 77 | """ 78 | self._AppendNewlines(data) 79 | 80 | def _AppendNewlines(self, data): 81 | """Count the number of newlines in the given string and append them. 82 | 83 | This ensures line numbers are correct for reported errors. 84 | 85 | Args: 86 | data: The data to count newlines in. 87 | """ 88 | # We append 'x' to both sides of the string to ensure that splitlines 89 | # gives us an accurate count. 90 | for i in xrange(len(('x' + data + 'x').splitlines()) - 1): 91 | self._text += '\n' 92 | 93 | def GetScriptLines(self): 94 | """Return the extracted script lines. 95 | 96 | Returns: 97 | The extracted script lines as a list of strings. 98 | """ 99 | return self._text.splitlines() 100 | 101 | 102 | def GetScriptLines(f): 103 | """Extract script tag contents from the given HTML file. 104 | 105 | Args: 106 | f: The HTML file. 107 | 108 | Returns: 109 | Lines in the HTML file that are from script tags. 110 | """ 111 | extractor = ScriptExtractor() 112 | 113 | # The HTML parser chokes on text like Array., so we patch 114 | # that bug by replacing the < with < - escaping all text inside script 115 | # tags would be better but it's a bit of a catch 22. 116 | contents = f.read() 117 | contents = re.sub(r'<([^\s\w/])', 118 | lambda x: '<%s' % x.group(1), 119 | contents) 120 | 121 | extractor.feed(contents) 122 | extractor.close() 123 | return extractor.GetScriptLines() 124 | 125 | 126 | def StripTags(str): 127 | """Returns the string with HTML tags stripped. 128 | 129 | Args: 130 | str: An html string. 131 | 132 | Returns: 133 | The html string with all tags stripped. If there was a parse error, returns 134 | the text successfully parsed so far. 135 | """ 136 | # Brute force approach to stripping as much HTML as possible. If there is a 137 | # parsing error, don't strip text before parse error position, and continue 138 | # trying from there. 139 | final_text = '' 140 | finished = False 141 | while not finished: 142 | try: 143 | strip = _HtmlStripper() 144 | strip.feed(str) 145 | strip.close() 146 | str = strip.get_output() 147 | final_text += str 148 | finished = True 149 | except HTMLParser.HTMLParseError, e: 150 | final_text += str[:e.offset] 151 | str = str[e.offset + 1:] 152 | 153 | return final_text 154 | 155 | 156 | class _HtmlStripper(HTMLParser.HTMLParser): 157 | """Simple class to strip tags from HTML. 158 | 159 | Does so by doing nothing when encountering tags, and appending character data 160 | to a buffer when that is encountered. 161 | """ 162 | def __init__(self): 163 | self.reset() 164 | self.__output = cStringIO.StringIO() 165 | 166 | def handle_data(self, d): 167 | self.__output.write(d) 168 | 169 | def get_output(self): 170 | return self.__output.getvalue() 171 | -------------------------------------------------------------------------------- /tools/closure_linter/common/lintrunner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2008 The Closure Linter Authors. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS-IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """Interface for a lint running wrapper.""" 18 | 19 | __author__ = ('robbyw@google.com (Robert Walker)', 20 | 'ajp@google.com (Andy Perelson)') 21 | 22 | 23 | class LintRunner(object): 24 | """Interface for a lint running wrapper.""" 25 | 26 | def __init__(self): 27 | if self.__class__ == LintRunner: 28 | raise NotImplementedError('class LintRunner is abstract') 29 | 30 | def Run(self, filenames, error_handler): 31 | """Run a linter on the given filenames. 32 | 33 | Args: 34 | filenames: The filenames to check 35 | error_handler: An ErrorHandler object 36 | 37 | Returns: 38 | The error handler, which may have been used to collect error info. 39 | """ 40 | -------------------------------------------------------------------------------- /tools/closure_linter/common/matcher.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2007 The Closure Linter Authors. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS-IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """Regular expression based JavaScript matcher classes.""" 18 | 19 | __author__ = ('robbyw@google.com (Robert Walker)', 20 | 'ajp@google.com (Andy Perelson)') 21 | 22 | from closure_linter.common import position 23 | from closure_linter.common import tokens 24 | 25 | # Shorthand 26 | Token = tokens.Token 27 | Position = position.Position 28 | 29 | 30 | class Matcher(object): 31 | """A token matcher. 32 | 33 | Specifies a pattern to match, the type of token it represents, what mode the 34 | token changes to, and what mode the token applies to. 35 | 36 | Modes allow more advanced grammars to be incorporated, and are also necessary 37 | to tokenize line by line. We can have different patterns apply to different 38 | modes - i.e. looking for documentation while in comment mode. 39 | 40 | Attributes: 41 | regex: The regular expression representing this matcher. 42 | type: The type of token indicated by a successful match. 43 | result_mode: The mode to move to after a successful match. 44 | """ 45 | 46 | def __init__(self, regex, token_type, result_mode=None, line_start=False): 47 | """Create a new matcher template. 48 | 49 | Args: 50 | regex: The regular expression to match. 51 | token_type: The type of token a successful match indicates. 52 | result_mode: What mode to change to after a successful match. Defaults to 53 | None, which means to not change the current mode. 54 | line_start: Whether this matcher should only match string at the start 55 | of a line. 56 | """ 57 | self.regex = regex 58 | self.type = token_type 59 | self.result_mode = result_mode 60 | self.line_start = line_start 61 | -------------------------------------------------------------------------------- /tools/closure_linter/common/position.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2008 The Closure Linter Authors. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS-IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """Classes to represent positions within strings.""" 18 | 19 | __author__ = ('robbyw@google.com (Robert Walker)', 20 | 'ajp@google.com (Andy Perelson)') 21 | 22 | 23 | class Position(object): 24 | """Object representing a segment of a string. 25 | 26 | Attributes: 27 | start: The index in to the string where the segment starts. 28 | length: The length of the string segment. 29 | """ 30 | 31 | def __init__(self, start, length): 32 | """Initialize the position object. 33 | 34 | Args: 35 | start: The start index. 36 | length: The number of characters to include. 37 | """ 38 | self.start = start 39 | self.length = length 40 | 41 | def Get(self, string): 42 | """Returns this range of the given string. 43 | 44 | Args: 45 | string: The string to slice. 46 | 47 | Returns: 48 | The string within the range specified by this object. 49 | """ 50 | return string[self.start:self.start + self.length] 51 | 52 | def Set(self, target, source): 53 | """Sets this range within the target string to the source string. 54 | 55 | Args: 56 | target: The target string. 57 | source: The source string. 58 | 59 | Returns: 60 | The resulting string 61 | """ 62 | return target[:self.start] + source + target[self.start + self.length:] 63 | 64 | def AtEnd(string): 65 | """Create a Position representing the end of the given string. 66 | 67 | Args: 68 | string: The string to represent the end of. 69 | 70 | Returns: 71 | The created Position object. 72 | """ 73 | return Position(len(string), 0) 74 | AtEnd = staticmethod(AtEnd) 75 | 76 | def IsAtEnd(self, string): 77 | """Returns whether this position is at the end of the given string. 78 | 79 | Args: 80 | string: The string to test for the end of. 81 | 82 | Returns: 83 | Whether this position is at the end of the given string. 84 | """ 85 | return self.start == len(string) and self.length == 0 86 | 87 | def AtBeginning(): 88 | """Create a Position representing the beginning of any string. 89 | 90 | Returns: 91 | The created Position object. 92 | """ 93 | return Position(0, 0) 94 | AtBeginning = staticmethod(AtBeginning) 95 | 96 | def IsAtBeginning(self): 97 | """Returns whether this position is at the beginning of any string. 98 | 99 | Returns: 100 | Whether this position is at the beginning of any string. 101 | """ 102 | return self.start == 0 and self.length == 0 103 | 104 | def All(string): 105 | """Create a Position representing the entire string. 106 | 107 | Args: 108 | string: The string to represent the entirety of. 109 | 110 | Returns: 111 | The created Position object. 112 | """ 113 | return Position(0, len(string)) 114 | All = staticmethod(All) 115 | 116 | def Index(index): 117 | """Returns a Position object for the specified index. 118 | 119 | Args: 120 | index: The index to select, inclusively. 121 | 122 | Returns: 123 | The created Position object. 124 | """ 125 | return Position(index, 1) 126 | Index = staticmethod(Index) 127 | -------------------------------------------------------------------------------- /tools/closure_linter/common/tokens.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2008 The Closure Linter Authors. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS-IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """Classes to represent tokens and positions within them.""" 18 | 19 | __author__ = ('robbyw@google.com (Robert Walker)', 20 | 'ajp@google.com (Andy Perelson)') 21 | 22 | 23 | class TokenType(object): 24 | """Token types common to all languages.""" 25 | NORMAL = 'normal' 26 | WHITESPACE = 'whitespace' 27 | BLANK_LINE = 'blank line' 28 | 29 | 30 | class Token(object): 31 | """Token class for intelligent text splitting. 32 | 33 | The token class represents a string of characters and an identifying type. 34 | 35 | Attributes: 36 | type: The type of token. 37 | string: The characters the token comprises. 38 | length: The length of the token. 39 | line: The text of the line the token is found in. 40 | line_number: The number of the line the token is found in. 41 | values: Dictionary of values returned from the tokens regex match. 42 | previous: The token before this one. 43 | next: The token after this one. 44 | start_index: The character index in the line where this token starts. 45 | attached_object: Object containing more information about this token. 46 | metadata: Object containing metadata about this token. Must be added by 47 | a separate metadata pass. 48 | """ 49 | 50 | def __init__(self, string, token_type, line, line_number, values=None): 51 | """Creates a new Token object. 52 | 53 | Args: 54 | string: The string of input the token contains. 55 | token_type: The type of token. 56 | line: The text of the line this token is in. 57 | line_number: The line number of the token. 58 | values: A dict of named values within the token. For instance, a 59 | function declaration may have a value called 'name' which captures the 60 | name of the function. 61 | """ 62 | self.type = token_type 63 | self.string = string 64 | self.length = len(string) 65 | self.line = line 66 | self.line_number = line_number 67 | self.values = values 68 | 69 | # These parts can only be computed when the file is fully tokenized 70 | self.previous = None 71 | self.next = None 72 | self.start_index = None 73 | 74 | # This part is set in statetracker.py 75 | # TODO(robbyw): Wrap this in to metadata 76 | self.attached_object = None 77 | 78 | # This part is set in *metadatapass.py 79 | self.metadata = None 80 | 81 | def IsFirstInLine(self): 82 | """Tests if this token is the first token in its line. 83 | 84 | Returns: 85 | Whether the token is the first token in its line. 86 | """ 87 | return not self.previous or self.previous.line_number != self.line_number 88 | 89 | def IsLastInLine(self): 90 | """Tests if this token is the last token in its line. 91 | 92 | Returns: 93 | Whether the token is the last token in its line. 94 | """ 95 | return not self.next or self.next.line_number != self.line_number 96 | 97 | def IsType(self, token_type): 98 | """Tests if this token is of the given type. 99 | 100 | Args: 101 | token_type: The type to test for. 102 | 103 | Returns: 104 | True if the type of this token matches the type passed in. 105 | """ 106 | return self.type == token_type 107 | 108 | def IsAnyType(self, *token_types): 109 | """Tests if this token is any of the given types. 110 | 111 | Args: 112 | token_types: The types to check. Also accepts a single array. 113 | 114 | Returns: 115 | True if the type of this token is any of the types passed in. 116 | """ 117 | if not isinstance(token_types[0], basestring): 118 | return self.type in token_types[0] 119 | else: 120 | return self.type in token_types 121 | 122 | def __repr__(self): 123 | return '' % (self.type, self.string, 124 | self.values, self.line_number, 125 | self.metadata) 126 | -------------------------------------------------------------------------------- /tools/closure_linter/error_check.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2011 The Closure Linter Authors. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS-IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | 18 | """Specific JSLint errors checker.""" 19 | 20 | 21 | 22 | import gflags as flags 23 | 24 | FLAGS = flags.FLAGS 25 | 26 | 27 | class Rule(object): 28 | """Different rules to check.""" 29 | 30 | # Documentations for specific rules goes in flag definition. 31 | BLANK_LINES_AT_TOP_LEVEL = 'blank_lines_at_top_level' 32 | INDENTATION = 'indentation' 33 | WELL_FORMED_AUTHOR = 'well_formed_author' 34 | NO_BRACES_AROUND_INHERIT_DOC = 'no_braces_around_inherit_doc' 35 | BRACES_AROUND_TYPE = 'braces_around_type' 36 | 37 | # Rule to raise all known errors. 38 | ALL = 'all' 39 | 40 | # All rules that are to be checked when using the strict flag. E.g. the rules 41 | # that are specific to the stricter Closure style. 42 | CLOSURE_RULES = frozenset([BLANK_LINES_AT_TOP_LEVEL, 43 | INDENTATION, 44 | WELL_FORMED_AUTHOR, 45 | NO_BRACES_AROUND_INHERIT_DOC, 46 | BRACES_AROUND_TYPE]) 47 | 48 | 49 | flags.DEFINE_boolean('strict', False, 50 | 'Whether to validate against the stricter Closure style. ' 51 | 'This includes ' + (', '.join(Rule.CLOSURE_RULES)) + '.') 52 | flags.DEFINE_multistring('jslint_error', [], 53 | 'List of specific lint errors to check. Here is a list' 54 | ' of accepted values:\n' 55 | ' - ' + Rule.ALL + ': enables all following errors.\n' 56 | ' - ' + Rule.BLANK_LINES_AT_TOP_LEVEL + ': validates' 57 | 'number of blank lines between blocks at top level.\n' 58 | ' - ' + Rule.INDENTATION + ': checks correct ' 59 | 'indentation of code.\n' 60 | ' - ' + Rule.WELL_FORMED_AUTHOR + ': validates the ' 61 | '@author JsDoc tags.\n' 62 | ' - ' + Rule.NO_BRACES_AROUND_INHERIT_DOC + ': ' 63 | 'forbids braces around @inheritdoc JsDoc tags.\n' 64 | ' - ' + Rule.BRACES_AROUND_TYPE + ': enforces braces ' 65 | 'around types in JsDoc tags.\n') 66 | 67 | 68 | def ShouldCheck(rule): 69 | """Returns whether the optional rule should be checked. 70 | 71 | Computes different flags (strict, jslint_error, jslint_noerror) to find out if 72 | this specific rule should be checked. 73 | 74 | Args: 75 | rule: Name of the rule (see Rule). 76 | 77 | Returns: 78 | True if the rule should be checked according to the flags, otherwise False. 79 | """ 80 | if rule in FLAGS.jslint_error or Rule.ALL in FLAGS.jslint_error: 81 | return True 82 | # Checks strict rules. 83 | return FLAGS.strict and rule in Rule.CLOSURE_RULES 84 | -------------------------------------------------------------------------------- /tools/closure_linter/errorrules.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2010 The Closure Linter Authors. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS-IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """Linter error rules class for Closure Linter.""" 18 | 19 | __author__ = 'robbyw@google.com (Robert Walker)' 20 | 21 | import gflags as flags 22 | from closure_linter import errors 23 | 24 | 25 | FLAGS = flags.FLAGS 26 | flags.DEFINE_boolean('jsdoc', True, 27 | 'Whether to report errors for missing JsDoc.') 28 | 29 | 30 | def ShouldReportError(error): 31 | """Whether the given error should be reported. 32 | 33 | Returns: 34 | True for all errors except missing documentation errors. For these, 35 | it returns the value of the jsdoc flag. 36 | """ 37 | return FLAGS.jsdoc or error not in ( 38 | errors.MISSING_PARAMETER_DOCUMENTATION, 39 | errors.MISSING_RETURN_DOCUMENTATION, 40 | errors.MISSING_MEMBER_DOCUMENTATION, 41 | errors.MISSING_PRIVATE, 42 | errors.MISSING_JSDOC_TAG_THIS) 43 | -------------------------------------------------------------------------------- /tools/closure_linter/errors.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2007 The Closure Linter Authors. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS-IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """Error codes for JavaScript style checker.""" 18 | 19 | __author__ = ('robbyw@google.com (Robert Walker)', 20 | 'ajp@google.com (Andy Perelson)') 21 | 22 | 23 | def ByName(name): 24 | """Get the error code for the given error name. 25 | 26 | Args: 27 | name: The name of the error 28 | 29 | Returns: 30 | The error code 31 | """ 32 | return globals()[name] 33 | 34 | 35 | # "File-fatal" errors - these errors stop further parsing of a single file 36 | FILE_NOT_FOUND = -1 37 | FILE_DOES_NOT_PARSE = -2 38 | 39 | # Spacing 40 | EXTRA_SPACE = 1 41 | MISSING_SPACE = 2 42 | EXTRA_LINE = 3 43 | MISSING_LINE = 4 44 | ILLEGAL_TAB = 5 45 | WRONG_INDENTATION = 6 46 | WRONG_BLANK_LINE_COUNT = 7 47 | 48 | # Semicolons 49 | MISSING_SEMICOLON = 10 50 | MISSING_SEMICOLON_AFTER_FUNCTION = 11 51 | ILLEGAL_SEMICOLON_AFTER_FUNCTION = 12 52 | REDUNDANT_SEMICOLON = 13 53 | 54 | # Miscellaneous 55 | ILLEGAL_PROTOTYPE_MEMBER_VALUE = 100 56 | LINE_TOO_LONG = 110 57 | LINE_STARTS_WITH_OPERATOR = 120 58 | COMMA_AT_END_OF_LITERAL = 121 59 | MULTI_LINE_STRING = 130 60 | UNNECESSARY_DOUBLE_QUOTED_STRING = 131 61 | 62 | # Requires, provides 63 | GOOG_REQUIRES_NOT_ALPHABETIZED = 140 64 | GOOG_PROVIDES_NOT_ALPHABETIZED = 141 65 | MISSING_GOOG_REQUIRE = 142 66 | MISSING_GOOG_PROVIDE = 143 67 | EXTRA_GOOG_REQUIRE = 144 68 | EXTRA_GOOG_PROVIDE = 145 69 | 70 | # JsDoc 71 | INVALID_JSDOC_TAG = 200 72 | INVALID_USE_OF_DESC_TAG = 201 73 | NO_BUG_NUMBER_AFTER_BUG_TAG = 202 74 | MISSING_PARAMETER_DOCUMENTATION = 210 75 | EXTRA_PARAMETER_DOCUMENTATION = 211 76 | WRONG_PARAMETER_DOCUMENTATION = 212 77 | MISSING_JSDOC_TAG_TYPE = 213 78 | MISSING_JSDOC_TAG_DESCRIPTION = 214 79 | MISSING_JSDOC_PARAM_NAME = 215 80 | OUT_OF_ORDER_JSDOC_TAG_TYPE = 216 81 | MISSING_RETURN_DOCUMENTATION = 217 82 | UNNECESSARY_RETURN_DOCUMENTATION = 218 83 | MISSING_BRACES_AROUND_TYPE = 219 84 | MISSING_MEMBER_DOCUMENTATION = 220 85 | MISSING_PRIVATE = 221 86 | EXTRA_PRIVATE = 222 87 | INVALID_OVERRIDE_PRIVATE = 223 88 | INVALID_INHERIT_DOC_PRIVATE = 224 89 | MISSING_JSDOC_TAG_THIS = 225 90 | UNNECESSARY_BRACES_AROUND_INHERIT_DOC = 226 91 | INVALID_AUTHOR_TAG_DESCRIPTION = 227 92 | JSDOC_PREFER_QUESTION_TO_PIPE_NULL = 230 93 | JSDOC_ILLEGAL_QUESTION_WITH_PIPE = 231 94 | JSDOC_TAG_DESCRIPTION_ENDS_WITH_INVALID_CHARACTER = 240 95 | # TODO(robbyw): Split this in to more specific syntax problems. 96 | INCORRECT_SUPPRESS_SYNTAX = 250 97 | INVALID_SUPPRESS_TYPE = 251 98 | UNNECESSARY_SUPPRESS = 252 99 | 100 | # File ending 101 | FILE_MISSING_NEWLINE = 300 102 | FILE_IN_BLOCK = 301 103 | 104 | # Interfaces 105 | INTERFACE_CONSTRUCTOR_CANNOT_HAVE_PARAMS = 400 106 | INTERFACE_METHOD_CANNOT_HAVE_CODE = 401 107 | 108 | # ActionScript specific errors: 109 | # TODO(user): move these errors to their own file and move all JavaScript 110 | # specific errors to their own file as well. 111 | # All ActionScript specific errors should have error number at least 1000. 112 | FUNCTION_MISSING_RETURN_TYPE = 1132 113 | PARAMETER_MISSING_TYPE = 1133 114 | VAR_MISSING_TYPE = 1134 115 | PARAMETER_MISSING_DEFAULT_VALUE = 1135 116 | IMPORTS_NOT_ALPHABETIZED = 1140 117 | IMPORT_CONTAINS_WILDCARD = 1141 118 | UNUSED_IMPORT = 1142 119 | INVALID_TRACE_SEVERITY_LEVEL = 1250 120 | MISSING_TRACE_SEVERITY_LEVEL = 1251 121 | MISSING_TRACE_MESSAGE = 1252 122 | REMOVE_TRACE_BEFORE_SUBMIT = 1253 123 | REMOVE_COMMENT_BEFORE_SUBMIT = 1254 124 | # End of list of ActionScript specific errors. 125 | 126 | NEW_ERRORS = frozenset([ 127 | # Errors added after 2.0.2: 128 | WRONG_INDENTATION, 129 | MISSING_SEMICOLON, 130 | # Errors added after 2.2.5: 131 | EXTRA_GOOG_REQUIRE, 132 | # Errors added after 2.2.7: 133 | EXTRA_GOOG_PROVIDE, 134 | # Errors added after 2.3: 135 | ]) 136 | -------------------------------------------------------------------------------- /tools/closure_linter/fixjsstyle.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2007 The Closure Linter Authors. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS-IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """Automatically fix simple style guide violations.""" 18 | 19 | __author__ = 'robbyw@google.com (Robert Walker)' 20 | 21 | import sys 22 | 23 | import gflags as flags 24 | from closure_linter import checker 25 | from closure_linter import error_fixer 26 | from closure_linter.common import simplefileflags as fileflags 27 | 28 | FLAGS = flags.FLAGS 29 | flags.DEFINE_list('additional_extensions', None, 'List of additional file ' 30 | 'extensions (not js) that should be treated as ' 31 | 'JavaScript files.') 32 | 33 | 34 | def main(argv = None): 35 | """Main function. 36 | 37 | Args: 38 | argv: Sequence of command line arguments. 39 | """ 40 | if argv is None: 41 | argv = flags.FLAGS(sys.argv) 42 | 43 | suffixes = ['.js'] 44 | if FLAGS.additional_extensions: 45 | suffixes += ['.%s' % ext for ext in FLAGS.additional_extensions] 46 | 47 | files = fileflags.GetFileList(argv, 'JavaScript', suffixes) 48 | 49 | style_checker = checker.JavaScriptStyleChecker(error_fixer.ErrorFixer()) 50 | 51 | # Check the list of files. 52 | for filename in files: 53 | style_checker.Check(filename) 54 | 55 | if __name__ == '__main__': 56 | main() 57 | -------------------------------------------------------------------------------- /tools/closure_linter/full_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2007 The Closure Linter Authors. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS-IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """Full regression-type (Medium) tests for gjslint. 18 | 19 | Tests every error that can be thrown by gjslint. Based heavily on 20 | devtools/javascript/gpylint/full_test.py 21 | """ 22 | 23 | __author__ = ('robbyw@google.com (Robert Walker)', 24 | 'ajp@google.com (Andy Perelson)') 25 | 26 | import re 27 | import os 28 | import sys 29 | import unittest 30 | 31 | import gflags as flags 32 | import unittest as googletest 33 | 34 | from closure_linter import checker 35 | from closure_linter import errors 36 | from closure_linter.common import filetestcase 37 | 38 | _RESOURCE_PREFIX = 'closure_linter/testdata' 39 | 40 | flags.FLAGS.strict = True 41 | flags.FLAGS.custom_jsdoc_tags = ('customtag', 'requires') 42 | flags.FLAGS.closurized_namespaces = ('goog', 'dummy') 43 | flags.FLAGS.limited_doc_files = ('externs.js', 'dummy.js', 44 | 'limited_doc_checks.js') 45 | 46 | # List of files under testdata to test. 47 | # We need to list files explicitly since pyglib can't list directories. 48 | # TODO(user): Figure out how to list the directory. 49 | _TEST_FILES = [ 50 | 'all_js_wrapped.js', 51 | 'blank_lines.js', 52 | 'ends_with_block.js', 53 | 'externs.js', 54 | 'html_parse_error.html', 55 | 'indentation.js', 56 | 'interface.js', 57 | 'jsdoc.js', 58 | 'limited_doc_checks.js', 59 | 'minimal.js', 60 | 'other.js', 61 | 'provide_blank.js', 62 | 'provide_extra.js', 63 | 'provide_missing.js', 64 | 'require_all_caps.js', 65 | 'require_blank.js', 66 | 'require_extra.js', 67 | 'require_function.js', 68 | 'require_function_missing.js', 69 | 'require_function_through_both.js', 70 | 'require_function_through_namespace.js', 71 | 'require_interface.js', 72 | 'require_lower_case.js', 73 | 'require_missing.js', 74 | 'require_numeric.js', 75 | 'require_provide_blank.js', 76 | 'require_provide_ok.js', 77 | 'require_provide_missing.js', 78 | 'simple.html', 79 | 'spaces.js', 80 | 'tokenizer.js', 81 | 'unparseable.js', 82 | 'utf8.html' 83 | ] 84 | 85 | 86 | class GJsLintTestSuite(unittest.TestSuite): 87 | """Test suite to run a GJsLintTest for each of several files. 88 | 89 | If sys.argv[1:] is non-empty, it is interpreted as a list of filenames in 90 | testdata to test. Otherwise, _TEST_FILES is used. 91 | """ 92 | 93 | def __init__(self, tests=()): 94 | unittest.TestSuite.__init__(self, tests) 95 | 96 | argv = sys.argv and sys.argv[1:] or [] 97 | if argv: 98 | test_files = argv 99 | else: 100 | test_files = _TEST_FILES 101 | for test_file in test_files: 102 | resource_path = os.path.join(_RESOURCE_PREFIX, test_file) 103 | self.addTest(filetestcase.AnnotatedFileTestCase(resource_path, 104 | checker.GJsLintRunner(), errors.ByName)) 105 | 106 | if __name__ == '__main__': 107 | # Don't let main parse args; it happens in the TestSuite. 108 | googletest.main(argv=sys.argv[0:1], defaultTest='GJsLintTestSuite') 109 | -------------------------------------------------------------------------------- /tools/closure_linter/gjslint.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2007 The Closure Linter Authors. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS-IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """Checks JavaScript files for common style guide violations. 18 | 19 | gjslint.py is designed to be used as a PRESUBMIT script to check for javascript 20 | style guide violations. As of now, it checks for the following violations: 21 | 22 | * Missing and extra spaces 23 | * Lines longer than 80 characters 24 | * Missing newline at end of file 25 | * Missing semicolon after function declaration 26 | * Valid JsDoc including parameter matching 27 | 28 | Someday it will validate to the best of its ability against the entirety of the 29 | JavaScript style guide. 30 | 31 | This file is a front end that parses arguments and flags. The core of the code 32 | is in tokenizer.py and checker.py. 33 | """ 34 | 35 | __author__ = ('robbyw@google.com (Robert Walker)', 36 | 'ajp@google.com (Andy Perelson)') 37 | 38 | import sys 39 | import time 40 | 41 | from closure_linter import checker 42 | from closure_linter import errors 43 | from closure_linter.common import errorprinter 44 | from closure_linter.common import simplefileflags as fileflags 45 | import gflags as flags 46 | 47 | 48 | FLAGS = flags.FLAGS 49 | flags.DEFINE_boolean('unix_mode', False, 50 | 'Whether to emit warnings in standard unix format.') 51 | flags.DEFINE_boolean('beep', True, 'Whether to beep when errors are found.') 52 | flags.DEFINE_boolean('time', False, 'Whether to emit timing statistics.') 53 | flags.DEFINE_boolean('check_html', False, 54 | 'Whether to check javascript in html files.') 55 | flags.DEFINE_boolean('summary', False, 56 | 'Whether to show an error count summary.') 57 | flags.DEFINE_list('additional_extensions', None, 'List of additional file ' 58 | 'extensions (not js) that should be treated as ' 59 | 'JavaScript files.') 60 | 61 | 62 | GJSLINT_ONLY_FLAGS = ['--unix_mode', '--beep', '--nobeep', '--time', 63 | '--check_html', '--summary'] 64 | 65 | 66 | def FormatTime(t): 67 | """Formats a duration as a human-readable string. 68 | 69 | Args: 70 | t: A duration in seconds. 71 | 72 | Returns: 73 | A formatted duration string. 74 | """ 75 | if t < 1: 76 | return '%dms' % round(t * 1000) 77 | else: 78 | return '%.2fs' % t 79 | 80 | 81 | def main(argv = None): 82 | """Main function. 83 | 84 | Args: 85 | argv: Sequence of command line arguments. 86 | """ 87 | if argv is None: 88 | argv = flags.FLAGS(sys.argv) 89 | 90 | if FLAGS.time: 91 | start_time = time.time() 92 | 93 | suffixes = ['.js'] 94 | if FLAGS.additional_extensions: 95 | suffixes += ['.%s' % ext for ext in FLAGS.additional_extensions] 96 | if FLAGS.check_html: 97 | suffixes += ['.html', '.htm'] 98 | files = fileflags.GetFileList(argv, 'JavaScript', suffixes) 99 | 100 | error_handler = None 101 | if FLAGS.unix_mode: 102 | error_handler = errorprinter.ErrorPrinter(errors.NEW_ERRORS) 103 | error_handler.SetFormat(errorprinter.UNIX_FORMAT) 104 | 105 | runner = checker.GJsLintRunner() 106 | result = runner.Run(files, error_handler) 107 | result.PrintSummary() 108 | 109 | exit_code = 0 110 | if result.HasOldErrors(): 111 | exit_code += 1 112 | if result.HasNewErrors(): 113 | exit_code += 2 114 | 115 | if exit_code: 116 | if FLAGS.summary: 117 | result.PrintFileSummary() 118 | 119 | if FLAGS.beep: 120 | # Make a beep noise. 121 | sys.stdout.write(chr(7)) 122 | 123 | # Write out instructions for using fixjsstyle script to fix some of the 124 | # reported errors. 125 | fix_args = [] 126 | for flag in sys.argv[1:]: 127 | for f in GJSLINT_ONLY_FLAGS: 128 | if flag.startswith(f): 129 | break 130 | else: 131 | fix_args.append(flag) 132 | 133 | print """ 134 | Some of the errors reported by GJsLint may be auto-fixable using the script 135 | fixjsstyle. Please double check any changes it makes and report any bugs. The 136 | script can be run by executing: 137 | 138 | fixjsstyle %s """ % ' '.join(fix_args) 139 | 140 | if FLAGS.time: 141 | print 'Done in %s.' % FormatTime(time.time() - start_time) 142 | 143 | sys.exit(exit_code) 144 | 145 | 146 | if __name__ == '__main__': 147 | main() 148 | -------------------------------------------------------------------------------- /tools/closure_linter/javascriptstatetracker.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2008 The Closure Linter Authors. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS-IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """Parser for JavaScript files.""" 18 | 19 | 20 | 21 | from closure_linter import javascripttokens 22 | from closure_linter import statetracker 23 | from closure_linter import tokenutil 24 | 25 | # Shorthand 26 | Type = javascripttokens.JavaScriptTokenType 27 | 28 | 29 | class JsDocFlag(statetracker.DocFlag): 30 | """Javascript doc flag object. 31 | 32 | Attribute: 33 | flag_type: param, return, define, type, etc. 34 | flag_token: The flag token. 35 | type_start_token: The first token specifying the flag JS type, 36 | including braces. 37 | type_end_token: The last token specifying the flag JS type, 38 | including braces. 39 | type: The JavaScript type spec. 40 | name_token: The token specifying the flag name. 41 | name: The flag name 42 | description_start_token: The first token in the description. 43 | description_end_token: The end token in the description. 44 | description: The description. 45 | """ 46 | 47 | # Please keep these lists alphabetized. 48 | 49 | # Some projects use the following extensions to JsDoc. 50 | # TODO(robbyw): determine which of these, if any, should be illegal. 51 | EXTENDED_DOC = frozenset([ 52 | 'class', 'code', 'desc', 'final', 'hidden', 'inheritDoc', 'link', 53 | 'protected', 'notypecheck', 'throws']) 54 | 55 | LEGAL_DOC = EXTENDED_DOC | statetracker.DocFlag.LEGAL_DOC 56 | 57 | def __init__(self, flag_token): 58 | """Creates the JsDocFlag object and attaches it to the given start token. 59 | 60 | Args: 61 | flag_token: The starting token of the flag. 62 | """ 63 | statetracker.DocFlag.__init__(self, flag_token) 64 | 65 | 66 | class JavaScriptStateTracker(statetracker.StateTracker): 67 | """JavaScript state tracker. 68 | 69 | Inherits from the core EcmaScript StateTracker adding extra state tracking 70 | functionality needed for JavaScript. 71 | """ 72 | 73 | def __init__(self): 74 | """Initializes a JavaScript token stream state tracker.""" 75 | statetracker.StateTracker.__init__(self, JsDocFlag) 76 | 77 | def InTopLevel(self): 78 | """Compute whether we are at the top level in the class. 79 | 80 | This function call is language specific. In some languages like 81 | JavaScript, a function is top level if it is not inside any parenthesis. 82 | In languages such as ActionScript, a function is top level if it is directly 83 | within a class. 84 | 85 | Returns: 86 | Whether we are at the top level in the class. 87 | """ 88 | return not self.InParentheses() 89 | 90 | def GetBlockType(self, token): 91 | """Determine the block type given a START_BLOCK token. 92 | 93 | Code blocks come after parameters, keywords like else, and closing parens. 94 | 95 | Args: 96 | token: The current token. Can be assumed to be type START_BLOCK 97 | Returns: 98 | Code block type for current token. 99 | """ 100 | last_code = tokenutil.SearchExcept(token, Type.NON_CODE_TYPES, None, 101 | True) 102 | if last_code.type in (Type.END_PARAMETERS, Type.END_PAREN, 103 | Type.KEYWORD) and not last_code.IsKeyword('return'): 104 | return self.CODE 105 | else: 106 | return self.OBJECT_LITERAL 107 | 108 | def HandleToken(self, token, last_non_space_token): 109 | """Handles the given token and updates state. 110 | 111 | Args: 112 | token: The token to handle. 113 | last_non_space_token: 114 | """ 115 | super(JavaScriptStateTracker, self).HandleToken(token, 116 | last_non_space_token) 117 | -------------------------------------------------------------------------------- /tools/closure_linter/javascripttokens.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2008 The Closure Linter Authors. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS-IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """Classes to represent JavaScript tokens.""" 18 | 19 | __author__ = ('robbyw@google.com (Robert Walker)', 20 | 'ajp@google.com (Andy Perelson)') 21 | 22 | from closure_linter.common import tokens 23 | 24 | class JavaScriptTokenType(tokens.TokenType): 25 | """Enumeration of JavaScript token types, and useful sets of token types.""" 26 | NUMBER = 'number' 27 | START_SINGLE_LINE_COMMENT = '//' 28 | START_BLOCK_COMMENT = '/*' 29 | START_DOC_COMMENT = '/**' 30 | END_BLOCK_COMMENT = '*/' 31 | END_DOC_COMMENT = 'doc */' 32 | COMMENT = 'comment' 33 | SINGLE_QUOTE_STRING_START = "'string" 34 | SINGLE_QUOTE_STRING_END = "string'" 35 | DOUBLE_QUOTE_STRING_START = '"string' 36 | DOUBLE_QUOTE_STRING_END = 'string"' 37 | STRING_TEXT = 'string' 38 | START_BLOCK = '{' 39 | END_BLOCK = '}' 40 | START_PAREN = '(' 41 | END_PAREN = ')' 42 | START_BRACKET = '[' 43 | END_BRACKET = ']' 44 | REGEX = '/regex/' 45 | FUNCTION_DECLARATION = 'function(...)' 46 | FUNCTION_NAME = 'function functionName(...)' 47 | START_PARAMETERS = 'startparams(' 48 | PARAMETERS = 'pa,ra,ms' 49 | END_PARAMETERS = ')endparams' 50 | SEMICOLON = ';' 51 | DOC_FLAG = '@flag' 52 | DOC_INLINE_FLAG = '{@flag ...}' 53 | DOC_START_BRACE = 'doc {' 54 | DOC_END_BRACE = 'doc }' 55 | DOC_PREFIX = 'comment prefix: * ' 56 | SIMPLE_LVALUE = 'lvalue=' 57 | KEYWORD = 'keyword' 58 | OPERATOR = 'operator' 59 | IDENTIFIER = 'identifier' 60 | 61 | STRING_TYPES = frozenset([ 62 | SINGLE_QUOTE_STRING_START, SINGLE_QUOTE_STRING_END, 63 | DOUBLE_QUOTE_STRING_START, DOUBLE_QUOTE_STRING_END, STRING_TEXT]) 64 | 65 | COMMENT_TYPES = frozenset([START_SINGLE_LINE_COMMENT, COMMENT, 66 | START_BLOCK_COMMENT, START_DOC_COMMENT, 67 | END_BLOCK_COMMENT, END_DOC_COMMENT, 68 | DOC_START_BRACE, DOC_END_BRACE, 69 | DOC_FLAG, DOC_INLINE_FLAG, DOC_PREFIX]) 70 | 71 | FLAG_DESCRIPTION_TYPES = frozenset([ 72 | DOC_INLINE_FLAG, COMMENT, DOC_START_BRACE, DOC_END_BRACE]) 73 | 74 | FLAG_ENDING_TYPES = frozenset([DOC_FLAG, END_DOC_COMMENT]) 75 | 76 | NON_CODE_TYPES = COMMENT_TYPES | frozenset([ 77 | tokens.TokenType.WHITESPACE, tokens.TokenType.BLANK_LINE]) 78 | 79 | UNARY_OPERATORS = ['!', 'new', 'delete', 'typeof', 'void'] 80 | 81 | UNARY_OK_OPERATORS = ['--', '++', '-', '+'] + UNARY_OPERATORS 82 | 83 | UNARY_POST_OPERATORS = ['--', '++'] 84 | 85 | # An expression ender is any token that can end an object - i.e. we could have 86 | # x.y or [1, 2], or (10 + 9) or {a: 10}. 87 | EXPRESSION_ENDER_TYPES = [tokens.TokenType.NORMAL, IDENTIFIER, NUMBER, 88 | SIMPLE_LVALUE, END_BRACKET, END_PAREN, END_BLOCK, 89 | SINGLE_QUOTE_STRING_END, DOUBLE_QUOTE_STRING_END] 90 | 91 | 92 | class JavaScriptToken(tokens.Token): 93 | """JavaScript token subclass of Token, provides extra instance checks. 94 | 95 | The following token types have data in attached_object: 96 | - All JsDoc flags: a parser.JsDocFlag object. 97 | """ 98 | 99 | def IsKeyword(self, keyword): 100 | """Tests if this token is the given keyword. 101 | 102 | Args: 103 | keyword: The keyword to compare to. 104 | 105 | Returns: 106 | True if this token is a keyword token with the given name. 107 | """ 108 | return self.type == JavaScriptTokenType.KEYWORD and self.string == keyword 109 | 110 | def IsOperator(self, operator): 111 | """Tests if this token is the given operator. 112 | 113 | Args: 114 | operator: The operator to compare to. 115 | 116 | Returns: 117 | True if this token is a operator token with the given name. 118 | """ 119 | return self.type == JavaScriptTokenType.OPERATOR and self.string == operator 120 | 121 | def IsAssignment(self): 122 | """Tests if this token is an assignment operator. 123 | 124 | Returns: 125 | True if this token is an assignment operator. 126 | """ 127 | return (self.type == JavaScriptTokenType.OPERATOR and 128 | self.string.endswith('=') and 129 | self.string not in ('==', '!=', '>=', '<=', '===', '!==')) 130 | 131 | def IsComment(self): 132 | """Tests if this token is any part of a comment. 133 | 134 | Returns: 135 | True if this token is any part of a comment. 136 | """ 137 | return self.type in JavaScriptTokenType.COMMENT_TYPES 138 | 139 | def IsCode(self): 140 | """Tests if this token is code, as opposed to a comment or whitespace.""" 141 | return self.type not in JavaScriptTokenType.NON_CODE_TYPES 142 | 143 | def __repr__(self): 144 | return '' % (self.line_number, 145 | self.type, self.string, 146 | self.values, 147 | self.metadata) 148 | -------------------------------------------------------------------------------- /tools/closure_linter/not_strict_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2011 The Closure Linter Authors. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS-IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """Tests for gjslint --nostrict. 18 | 19 | Tests errors that can be thrown by gjslint when not in strict mode. 20 | """ 21 | 22 | 23 | 24 | import os 25 | import sys 26 | import unittest 27 | 28 | import gflags as flags 29 | import unittest as googletest 30 | 31 | from closure_linter import checker 32 | from closure_linter import errors 33 | from closure_linter.common import filetestcase 34 | 35 | _RESOURCE_PREFIX = 'closure_linter/testdata' 36 | 37 | flags.FLAGS.strict = False 38 | flags.FLAGS.custom_jsdoc_tags = ('customtag', 'requires') 39 | flags.FLAGS.closurized_namespaces = ('goog', 'dummy') 40 | flags.FLAGS.limited_doc_files = ('externs.js', 'dummy.js', 41 | 'limited_doc_checks.js') 42 | 43 | 44 | # List of files under testdata to test. 45 | # We need to list files explicitly since pyglib can't list directories. 46 | _TEST_FILES = [ 47 | 'not_strict.js' 48 | ] 49 | 50 | 51 | class GJsLintTestSuite(unittest.TestSuite): 52 | """Test suite to run a GJsLintTest for each of several files. 53 | 54 | If sys.argv[1:] is non-empty, it is interpreted as a list of filenames in 55 | testdata to test. Otherwise, _TEST_FILES is used. 56 | """ 57 | 58 | def __init__(self, tests=()): 59 | unittest.TestSuite.__init__(self, tests) 60 | 61 | argv = sys.argv and sys.argv[1:] or [] 62 | if argv: 63 | test_files = argv 64 | else: 65 | test_files = _TEST_FILES 66 | for test_file in test_files: 67 | resource_path = os.path.join(_RESOURCE_PREFIX, test_file) 68 | self.addTest(filetestcase.AnnotatedFileTestCase(resource_path, 69 | checker.GJsLintRunner(), 70 | errors.ByName)) 71 | 72 | if __name__ == '__main__': 73 | # Don't let main parse args; it happens in the TestSuite. 74 | googletest.main(argv=sys.argv[0:1], defaultTest='GJsLintTestSuite') 75 | -------------------------------------------------------------------------------- /tools/jsdoc/app/frame.js: -------------------------------------------------------------------------------- 1 | IO.include("frame/Opt.js"); 2 | IO.include("frame/Chain.js"); 3 | IO.include("frame/Link.js"); 4 | IO.include("frame/String.js"); 5 | IO.include("frame/Hash.js"); 6 | IO.include("frame/Namespace.js"); 7 | //IO.include("frame/Reflection.js"); 8 | 9 | /** A few helper functions to make life a little easier. */ 10 | 11 | function defined(o) { 12 | return (o !== undefined); 13 | } 14 | 15 | function copy(o) { // todo check for circular refs 16 | if (o == null || typeof(o) != 'object') return o; 17 | var c = new o.constructor(); 18 | for(var p in o) c[p] = copy(o[p]); 19 | return c; 20 | } 21 | 22 | function isUnique(arr) { 23 | var l = arr.length; 24 | for(var i = 0; i < l; i++ ) { 25 | if (arr.lastIndexOf(arr[i]) > i) return false; 26 | } 27 | return true; 28 | } 29 | 30 | /** Returns the given string with all regex meta characters backslashed. */ 31 | RegExp.escapeMeta = function(str) { 32 | return str.replace(/([$^\\\/()|?+*\[\]{}.-])/g, "\\$1"); 33 | } 34 | -------------------------------------------------------------------------------- /tools/jsdoc/app/frame/Chain.js: -------------------------------------------------------------------------------- 1 | /**@constructor*/ 2 | function ChainNode(object, link) { 3 | this.value = object; 4 | this.link = link; // describes this node's relationship to the previous node 5 | } 6 | 7 | /**@constructor*/ 8 | function Chain(valueLinks) { 9 | this.nodes = []; 10 | this.cursor = -1; 11 | 12 | if (valueLinks && valueLinks.length > 0) { 13 | this.push(valueLinks[0], "//"); 14 | for (var i = 1, l = valueLinks.length; i < l; i+=2) { 15 | this.push(valueLinks[i+1], valueLinks[i]); 16 | } 17 | } 18 | } 19 | 20 | Chain.prototype.push = function(o, link) { 21 | if (this.nodes.length > 0 && link) this.nodes.push(new ChainNode(o, link)); 22 | else this.nodes.push(new ChainNode(o)); 23 | } 24 | 25 | Chain.prototype.unshift = function(o, link) { 26 | if (this.nodes.length > 0 && link) this.nodes[0].link = link; 27 | this.nodes.unshift(new ChainNode(o)); 28 | this.cursor++; 29 | } 30 | 31 | Chain.prototype.get = function() { 32 | if (this.cursor < 0 || this.cursor > this.nodes.length-1) return null; 33 | return this.nodes[this.cursor]; 34 | } 35 | 36 | Chain.prototype.first = function() { 37 | this.cursor = 0; 38 | return this.get(); 39 | } 40 | 41 | Chain.prototype.last = function() { 42 | this.cursor = this.nodes.length-1; 43 | return this.get(); 44 | } 45 | 46 | Chain.prototype.next = function() { 47 | this.cursor++; 48 | return this.get(); 49 | } 50 | 51 | Chain.prototype.prev = function() { 52 | this.cursor--; 53 | return this.get(); 54 | } 55 | 56 | Chain.prototype.toString = function() { 57 | var string = ""; 58 | for (var i = 0, l = this.nodes.length; i < l; i++) { 59 | if (this.nodes[i].link) string += " -("+this.nodes[i].link+")-> "; 60 | string += this.nodes[i].value.toString(); 61 | } 62 | return string; 63 | } 64 | 65 | Chain.prototype.joinLeft = function() { 66 | var result = ""; 67 | for (var i = 0, l = this.cursor; i < l; i++) { 68 | if (result && this.nodes[i].link) result += this.nodes[i].link; 69 | result += this.nodes[i].value.toString(); 70 | } 71 | return result; 72 | } 73 | 74 | 75 | /* USAGE: 76 | 77 | var path = "one/two/three.four/five-six"; 78 | var pathChain = new Chain(path.split(/([\/.-])/)); 79 | print(pathChain); 80 | 81 | var lineage = new Chain(); 82 | lineage.push("Port"); 83 | lineage.push("Les", "son"); 84 | lineage.push("Dawn", "daughter"); 85 | lineage.unshift("Purdie", "son"); 86 | 87 | print(lineage); 88 | 89 | // walk left 90 | for (var node = lineage.last(); node !== null; node = lineage.prev()) { 91 | print("< "+node.value); 92 | } 93 | 94 | // walk right 95 | var node = lineage.first() 96 | while (node !== null) { 97 | print(node.value); 98 | node = lineage.next(); 99 | if (node && node.link) print("had a "+node.link+" named"); 100 | } 101 | 102 | */ -------------------------------------------------------------------------------- /tools/jsdoc/app/frame/Dumper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @class 3 |
  4 | This is a lightly modified version of Kevin Jones' JavaScript
  5 | library Data.Dump. To download the original visit:
  6 |     http://openjsan.org/doc/k/ke/kevinj/Data/Dump/
  7 | 
  8 | AUTHORS
  9 | 
 10 | The Data.Dump JavaScript module is written by Kevin Jones 
 11 | (kevinj@cpan.org), based on Data::Dump by Gisle Aas (gisle@aas.no),
 12 | based on Data::Dumper by Gurusamy Sarathy (gsar@umich.edu).
 13 | 
 14 | COPYRIGHT
 15 | 
 16 | Copyright 2007 Kevin Jones. Copyright 1998-2000,2003-2004 Gisle Aas.
 17 | Copyright 1996-1998 Gurusamy Sarathy.
 18 | 
 19 | This program is free software; you can redistribute it and/or modify
 20 | it under the terms of the Perl Artistic License
 21 | 
 22 | See http://www.perl.com/perl/misc/Artistic.html
 23 | 
24 | * @static 25 | */ 26 | Dumper = { 27 | /** @param [...] The objects to dump. */ 28 | dump: function () { 29 | if (arguments.length > 1) 30 | return this._dump(arguments); 31 | else if (arguments.length == 1) 32 | return this._dump(arguments[0]); 33 | else 34 | return "()"; 35 | }, 36 | 37 | _dump: function (obj) { 38 | if (typeof obj == 'undefined') return 'undefined'; 39 | var out; 40 | if (obj.serialize) { return obj.serialize(); } 41 | var type = this._typeof(obj); 42 | if (obj.circularReference) obj.circularReference++; 43 | switch (type) { 44 | case 'circular': 45 | out = "{ //circularReference\n}"; 46 | break; 47 | case 'object': 48 | var pairs = new Array; 49 | 50 | for (var prop in obj) { 51 | if (prop != "circularReference" && obj.hasOwnProperty(prop)) { //hide inherited properties 52 | pairs.push(prop + ': ' + this._dump(obj[prop])); 53 | } 54 | } 55 | 56 | out = '{' + this._format_list(pairs) + '}'; 57 | break; 58 | 59 | case 'string': 60 | for (var prop in Dumper.ESC) { 61 | if (Dumper.ESC.hasOwnProperty(prop)) { 62 | obj = obj.replace(prop, Dumper.ESC[prop]); 63 | } 64 | } 65 | 66 | // Escape UTF-8 Strings 67 | if (obj.match(/^[\x00-\x7f]*$/)) { 68 | out = '"' + obj.replace(/\"/g, "\\\"").replace(/([\n\r]+)/g, "\\$1") + '"'; 69 | } 70 | else { 71 | out = "unescape('"+escape(obj)+"')"; 72 | } 73 | break; 74 | 75 | case 'array': 76 | var elems = new Array; 77 | 78 | for (var i=0; i 60 ? '\n' : ' '; 109 | return nl + list.join(',' + nl) + nl; 110 | }, 111 | 112 | _typeof: function (obj) { 113 | if (obj && obj.circularReference && obj.circularReference > 1) return 'circular'; 114 | if (Array.prototype.isPrototypeOf(obj)) return 'array'; 115 | if (Date.prototype.isPrototypeOf(obj)) return 'date'; 116 | if (typeof obj.nodeType != 'undefined') return 'element'; 117 | return typeof(obj); 118 | }, 119 | 120 | _dump_dom: function (obj) { 121 | return '"' + Dumper.nodeTypes[obj.nodeType] + '"'; 122 | } 123 | }; 124 | 125 | Dumper.ESC = { 126 | "\t": "\\t", 127 | "\n": "\\n", 128 | "\f": "\\f" 129 | }; 130 | 131 | Dumper.nodeTypes = { 132 | 1: "ELEMENT_NODE", 133 | 2: "ATTRIBUTE_NODE", 134 | 3: "TEXT_NODE", 135 | 4: "CDATA_SECTION_NODE", 136 | 5: "ENTITY_REFERENCE_NODE", 137 | 6: "ENTITY_NODE", 138 | 7: "PROCESSING_INSTRUCTION_NODE", 139 | 8: "COMMENT_NODE", 140 | 9: "DOCUMENT_NODE", 141 | 10: "DOCUMENT_TYPE_NODE", 142 | 11: "DOCUMENT_FRAGMENT_NODE", 143 | 12: "NOTATION_NODE" 144 | }; -------------------------------------------------------------------------------- /tools/jsdoc/app/frame/Hash.js: -------------------------------------------------------------------------------- 1 | /** 2 | @constructor 3 | @example 4 | var _index = new Hash(); 5 | _index.set("a", "apple"); 6 | _index.set("b", "blue"); 7 | _index.set("c", "coffee"); 8 | 9 | for (var p = _index.first(); p; p = _index.next()) { 10 | print(p.key+" is for "+p.value); 11 | } 12 | 13 | */ 14 | var Hash = function() { 15 | this._map = {}; 16 | this._keys = []; 17 | this._vals = []; 18 | this.reset(); 19 | } 20 | 21 | Hash.prototype.set = function(k, v) { 22 | if (k != "") { 23 | this._keys.push(k); 24 | this._map["="+k] = this._vals.length; 25 | this._vals.push(v); 26 | } 27 | } 28 | 29 | Hash.prototype.replace = function(k, k2, v) { 30 | if (k == k2) return; 31 | 32 | var offset = this._map["="+k]; 33 | this._keys[offset] = k2; 34 | if (typeof v != "undefined") this._vals[offset] = v; 35 | this._map["="+k2] = offset; 36 | delete(this._map["="+k]); 37 | } 38 | 39 | Hash.prototype.drop = function(k) { 40 | if (k != "") { 41 | var offset = this._map["="+k]; 42 | this._keys.splice(offset, 1); 43 | this._vals.splice(offset, 1); 44 | delete(this._map["="+k]); 45 | for (var p in this._map) { 46 | if (this._map[p] >= offset) this._map[p]--; 47 | } 48 | if (this._cursor >= offset && this._cursor > 0) this._cursor--; 49 | } 50 | } 51 | 52 | Hash.prototype.get = function(k) { 53 | if (k != "") { 54 | return this._vals[this._map["="+k]]; 55 | } 56 | } 57 | 58 | Hash.prototype.keys = function() { 59 | return this._keys; 60 | } 61 | 62 | Hash.prototype.hasKey = function(k) { 63 | if (k != "") { 64 | return (typeof this._map["="+k] != "undefined"); 65 | } 66 | } 67 | 68 | Hash.prototype.values = function() { 69 | return this._vals; 70 | } 71 | 72 | Hash.prototype.reset = function() { 73 | this._cursor = 0; 74 | } 75 | 76 | Hash.prototype.first = function() { 77 | this.reset(); 78 | return this.next(); 79 | } 80 | 81 | Hash.prototype.next = function() { 82 | if (this._cursor++ < this._keys.length) 83 | return {key: this._keys[this._cursor-1], value: this._vals[this._cursor-1]}; 84 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/frame/Link.js: -------------------------------------------------------------------------------- 1 | /** Handle the creation of HTML links to documented symbols. 2 | @constructor 3 | */ 4 | function Link() { 5 | this.alias = ""; 6 | this.src = ""; 7 | this.file = ""; 8 | this.text = ""; 9 | this.innerName = ""; 10 | this.classLink = false; 11 | this.targetName = ""; 12 | 13 | this.target = function(targetName) { 14 | if (defined(targetName)) this.targetName = targetName; 15 | return this; 16 | } 17 | this.inner = function(inner) { 18 | if (defined(inner)) this.innerName = inner; 19 | return this; 20 | } 21 | this.withText = function(text) { 22 | if (defined(text)) this.text = text; 23 | return this; 24 | } 25 | this.toSrc = function(filename) { 26 | if (defined(filename)) this.src = filename; 27 | return this; 28 | } 29 | this.toSymbol = function(alias) { 30 | if (defined(alias)) this.alias = new String(alias); 31 | return this; 32 | } 33 | this.toClass = function(alias) { 34 | this.classLink = true; 35 | return this.toSymbol(alias); 36 | } 37 | this.toFile = function(file) { 38 | if (defined(file)) this.file = file; 39 | return this; 40 | } 41 | 42 | this.toString = function() { 43 | var linkString; 44 | var thisLink = this; 45 | 46 | if (this.alias) { 47 | linkString = this.alias.replace(/(^|[^a-z$0-9_#.:^-])([|a-z$0-9_#.:^-]+)($|[^a-z$0-9_#.:^-])/i, 48 | function(match, prematch, symbolName, postmatch) { 49 | var symbolNames = symbolName.split("|"); 50 | var links = []; 51 | for (var i = 0, l = symbolNames.length; i < l; i++) { 52 | thisLink.alias = symbolNames[i]; 53 | links.push(thisLink._makeSymbolLink(symbolNames[i])); 54 | } 55 | return prematch+links.join("|")+postmatch; 56 | } 57 | ); 58 | } 59 | else if (this.src) { 60 | linkString = thisLink._makeSrcLink(this.src); 61 | } 62 | else if (this.file) { 63 | linkString = thisLink._makeFileLink(this.file); 64 | } 65 | 66 | return linkString; 67 | } 68 | } 69 | 70 | /** prefixed for hashes */ 71 | Link.hashPrefix = ""; 72 | 73 | /** Appended to the front of relative link paths. */ 74 | Link.base = ""; 75 | 76 | Link.symbolNameToLinkName = function(symbol) { 77 | var linker = "", 78 | ns = ""; 79 | 80 | if (symbol.isStatic) linker = "."; 81 | else if (symbol.isInner) linker = "-"; 82 | 83 | if (symbol.isEvent && !/^event:/.test(symbol.name)) { 84 | ns = "event:"; 85 | } 86 | return Link.hashPrefix+linker+ns+symbol.name; 87 | } 88 | 89 | Link.getSymbol= function(alias) { 90 | var symbol= Link.symbolSet.getSymbol(alias); 91 | 92 | if (symbol) 93 | return symbol; 94 | 95 | if ('#'!==alias.charAt(0) || !Link.currentSymbol) 96 | return null; 97 | 98 | // resolve relative name 99 | var container= Link.currentSymbol; 100 | 101 | while (container) 102 | { 103 | symbol= Link.symbolSet.getSymbol(container.alias + alias); 104 | if (symbol) 105 | return symbol; 106 | 107 | // No superclass 108 | if (!container.augments.length) 109 | return null; 110 | 111 | container= Link.symbolSet.getSymbol(container.augments[0].desc); 112 | } 113 | 114 | return null; 115 | } 116 | 117 | /** Create a link to another symbol. */ 118 | Link.prototype._makeSymbolLink = function(alias) { 119 | var linkBase = Link.base+publish.conf.symbolsDir; 120 | var linkTo = Link.getSymbol(alias); 121 | var linkPath; 122 | var target = (this.targetName)? " target=\""+this.targetName+"\"" : ""; 123 | 124 | // if there is no symbol by that name just return the name unaltered 125 | if (!linkTo) 126 | return this.text || alias; 127 | 128 | // it's a symbol in another file 129 | else { 130 | if (!linkTo.is("CONSTRUCTOR") && !linkTo.isNamespace) { // it's a method or property 131 | linkPath= (Link.filemap) ? Link.filemap[linkTo.memberOf] : 132 | escape(linkTo.memberOf) || "_global_"; 133 | linkPath += publish.conf.ext + "#" + Link.symbolNameToLinkName(linkTo); 134 | } 135 | else { 136 | linkPath = (Link.filemap)? Link.filemap[linkTo.alias] : escape(linkTo.alias); 137 | linkPath += publish.conf.ext;// + (this.classLink? "":"#" + Link.hashPrefix + "constructor"); 138 | } 139 | linkPath = linkBase + linkPath 140 | } 141 | 142 | var linkText= this.text || alias; 143 | 144 | var link = {linkPath: linkPath, linkText: linkText, linkInner: (this.innerName? "#"+this.innerName : "")}; 145 | 146 | if (typeof JSDOC.PluginManager != "undefined") { 147 | JSDOC.PluginManager.run("onSymbolLink", link); 148 | } 149 | 150 | return ""+link.linkText+""; 151 | } 152 | 153 | /** Create a link to a source file. */ 154 | Link.prototype._makeSrcLink = function(srcFilePath) { 155 | var target = (this.targetName)? " target=\""+this.targetName+"\"" : ""; 156 | 157 | // transform filepath into a filename 158 | var srcFile = srcFilePath.replace(/\.\.?[\\\/]/g, "").replace(/[:\\\/]/g, "_"); 159 | var outFilePath = Link.base + publish.conf.srcDir + srcFile + publish.conf.ext; 160 | 161 | if (!this.text) this.text = FilePath.fileName(srcFilePath); 162 | return ""+this.text+""; 163 | } 164 | 165 | /** Create a link to a source file. */ 166 | Link.prototype._makeFileLink = function(filePath) { 167 | var target = (this.targetName)? " target=\""+this.targetName+"\"" : ""; 168 | 169 | var outFilePath = Link.base + filePath; 170 | 171 | if (!this.text) this.text = filePath; 172 | return ""+this.text+""; 173 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/frame/Namespace.js: -------------------------------------------------------------------------------- 1 | _global_ = this; 2 | 3 | function Namespace(name, f) { 4 | var n = name.split("."); 5 | for (var o = _global_, i = 0, l = n.length; i < l; i++) { 6 | o = o[n[i]] = o[n[i]] || {}; 7 | } 8 | 9 | if (f) f(); 10 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/frame/Opt.js: -------------------------------------------------------------------------------- 1 | /** @namespace */ 2 | Opt = { 3 | /** 4 | * Get commandline option values. 5 | * @param {Array} args Commandline arguments. Like ["-a=xml", "-b", "--class=new", "--debug"] 6 | * @param {object} optNames Map short names to long names. Like {a:"accept", b:"backtrace", c:"class", d:"debug"}. 7 | * @return {object} Short names and values. Like {a:"xml", b:true, c:"new", d:true} 8 | */ 9 | get: function(args, optNames) { 10 | var opt = {"_": []}; // the unnamed option allows multiple values 11 | for (var i = 0; i < args.length; i++) { 12 | var arg = new String(args[i]); 13 | var name; 14 | var value; 15 | if (arg.charAt(0) == "-") { 16 | if (arg.charAt(1) == "-") { // it's a longname like --foo 17 | arg = arg.substring(2); 18 | var m = arg.split("="); 19 | name = m.shift(); 20 | value = m.shift(); 21 | if (typeof value == "undefined") value = true; 22 | 23 | for (var n in optNames) { // convert it to a shortname 24 | if (name == optNames[n]) { 25 | name = n; 26 | } 27 | } 28 | } 29 | else { // it's a shortname like -f 30 | arg = arg.substring(1); 31 | var m = arg.split("="); 32 | name = m.shift(); 33 | value = m.shift(); 34 | if (typeof value == "undefined") value = true; 35 | 36 | for (var n in optNames) { // find the matching key 37 | if (name == n || name+'[]' == n) { 38 | name = n; 39 | break; 40 | } 41 | } 42 | } 43 | if (name.match(/(.+)\[\]$/)) { // it's an array type like n[] 44 | name = RegExp.$1; 45 | if (!opt[name]) opt[name] = []; 46 | } 47 | 48 | if (opt[name] && opt[name].push) { 49 | opt[name].push(value); 50 | } 51 | else { 52 | opt[name] = value; 53 | } 54 | } 55 | else { // not associated with any optname 56 | opt._.push(args[i]); 57 | } 58 | } 59 | return opt; 60 | } 61 | } 62 | 63 | /*t: 64 | plan(11, "Testing Opt."); 65 | 66 | is( 67 | typeof Opt, 68 | "object", 69 | "Opt is an object." 70 | ); 71 | 72 | is( 73 | typeof Opt.get, 74 | "function", 75 | "Opt.get is a function." 76 | ); 77 | 78 | var optNames = {a:"accept", b:"backtrace", c:"class", d:"debug", "e[]":"exceptions"}; 79 | var t_options = Opt.get(["-a=xml", "-b", "--class=new", "--debug", "-e=one", "-e=two", "foo", "bar"], optNames); 80 | 81 | is( 82 | t_options.a, 83 | "xml", 84 | "an option defined with a short name can be accessed by its short name." 85 | ); 86 | 87 | is( 88 | t_options.b, 89 | true, 90 | "an option defined with a short name and no value are true." 91 | ); 92 | 93 | is( 94 | t_options.c, 95 | "new", 96 | "an option defined with a long name can be accessed by its short name." 97 | ); 98 | 99 | is( 100 | t_options.d, 101 | true, 102 | "an option defined with a long name and no value are true." 103 | ); 104 | 105 | is( 106 | typeof t_options.e, 107 | "object", 108 | "an option that can accept multiple values is defined." 109 | ); 110 | 111 | is( 112 | t_options.e.length, 113 | 2, 114 | "an option that can accept multiple values can have more than one value." 115 | ); 116 | 117 | is( 118 | t_options.e[1], 119 | "two", 120 | "an option that can accept multiple values can be accessed as an array." 121 | ); 122 | 123 | is( 124 | typeof t_options._, 125 | "object", 126 | "the property '_' is defined for unnamed options." 127 | ); 128 | 129 | is( 130 | t_options._[0], 131 | "foo", 132 | "the property '_' can be accessed as an array." 133 | ); 134 | */ -------------------------------------------------------------------------------- /tools/jsdoc/app/frame/Reflection.js: -------------------------------------------------------------------------------- 1 | /**@constructor*/ 2 | function Reflection(obj) { 3 | this.obj = obj; 4 | } 5 | 6 | Reflection.prototype.getConstructorName = function() { 7 | if (this.obj.constructor.name) return this.obj.constructor.name; 8 | var src = this.obj.constructor.toSource(); 9 | var name = src.substring(name.indexOf("function")+8, src.indexOf('(')).replace(/ /g,''); 10 | return name; 11 | } 12 | 13 | Reflection.prototype.getMethod = function(name) { 14 | for (var p in this.obj) { 15 | if (p == name && typeof(this.obj[p]) == "function") return this.obj[p]; 16 | } 17 | return null; 18 | } 19 | 20 | Reflection.prototype.getParameterNames = function() { 21 | var src = this.obj.toSource(); 22 | src = src.substring( 23 | src.indexOf("(", 8)+1, src.indexOf(")") 24 | ); 25 | return src.split(/, ?/); 26 | } 27 | -------------------------------------------------------------------------------- /tools/jsdoc/app/frame/String.js: -------------------------------------------------------------------------------- 1 | /** 2 | @name String 3 | @class Additions to the core string object. 4 | */ 5 | 6 | /** @author Steven Levithan, released as public domain. */ 7 | String.prototype.trim = function() { 8 | var str = this.replace(/^\s+/, ''); 9 | for (var i = str.length - 1; i >= 0; i--) { 10 | if (/\S/.test(str.charAt(i))) { 11 | str = str.substring(0, i + 1); 12 | break; 13 | } 14 | } 15 | return str; 16 | } 17 | /*t: 18 | plan(6, "Testing String.prototype.trim."); 19 | 20 | var s = " a bc ".trim(); 21 | is(s, "a bc", "multiple spaces front and back are trimmed."); 22 | 23 | s = "a bc\n\n".trim(); 24 | is(s, "a bc", "newlines only in back are trimmed."); 25 | 26 | s = "\ta bc".trim(); 27 | is(s, "a bc", "tabs only in front are trimmed."); 28 | 29 | s = "\n \t".trim(); 30 | is(s, "", "an all-space string is trimmed to empty."); 31 | 32 | s = "a b\nc".trim(); 33 | is(s, "a b\nc", "a string with no spaces in front or back is trimmed to itself."); 34 | 35 | s = "".trim(); 36 | is(s, "", "an empty string is trimmed to empty."); 37 | 38 | */ 39 | 40 | String.prototype.balance = function(open, close) { 41 | var i = 0; 42 | while (this.charAt(i) != open) { 43 | if (i == this.length) return [-1, -1]; 44 | i++; 45 | } 46 | 47 | var j = i+1; 48 | var balance = 1; 49 | while (j < this.length) { 50 | if (this.charAt(j) == open) balance++; 51 | if (this.charAt(j) == close) balance--; 52 | if (balance == 0) break; 53 | j++; 54 | if (j == this.length) return [-1, -1]; 55 | } 56 | 57 | return [i, j]; 58 | } 59 | /*t: 60 | plan(16, "Testing String.prototype.balance."); 61 | 62 | var s = "{abc}".balance("{","}"); 63 | is(s[0], 0, "opener in first is found."); 64 | is(s[1], 4, "closer in last is found."); 65 | 66 | s = "ab{c}de".balance("{","}"); 67 | is(s[0], 2, "opener in middle is found."); 68 | is(s[1], 4, "closer in middle is found."); 69 | 70 | s = "a{b{c}de}f".balance("{","}"); 71 | is(s[0], 1, "nested opener is found."); 72 | is(s[1], 8, "nested closer is found."); 73 | 74 | s = "{}".balance("{","}"); 75 | is(s[0], 0, "opener with no content is found."); 76 | is(s[1], 1, "closer with no content is found."); 77 | 78 | s = "".balance("{","}"); 79 | is(s[0], -1, "empty string opener is -1."); 80 | is(s[1], -1, "empty string closer is -1."); 81 | 82 | s = "{abc".balance("{","}"); 83 | is(s[0], -1, "opener with no closer returns -1."); 84 | is(s[1], -1, "no closer returns -1."); 85 | 86 | s = "abc".balance("{","}"); 87 | is(s[0], -1, "no opener or closer returns -1 for opener."); 88 | is(s[1], -1, "no opener or closer returns -1 for closer."); 89 | 90 | s = "aX11/MIT License 8 | * (See the accompanying README file for full details.) 9 | */ 10 | 11 | /** 12 | Yet another unit testing tool for JavaScript. 13 | @author Michael Mathews micmath@gmail.com 14 | @param {object} testCases Properties are testcase names, values are functions to execute as tests. 15 | */ 16 | function testrun(testCases) { 17 | var ran = 0; 18 | for (t in testCases) { 19 | var result = testCases[t](); 20 | ran++; 21 | } 22 | 23 | return testrun.reportOut+"-------------------------------\n"+((testrun.fails>0)? ":( Failed "+testrun.fails+"/" : ":) Passed all ")+testrun.count+" test"+((testrun.count == 1)? "":"s")+".\n"; 24 | } 25 | 26 | 27 | testrun.count = 0; 28 | testrun.current = null; 29 | testrun.passes = 0; 30 | testrun.fails = 0; 31 | testrun.reportOut = ""; 32 | 33 | /** @private */ 34 | testrun.report = function(text) { 35 | testrun.reportOut += text+"\n"; 36 | } 37 | 38 | /** 39 | Check if test evaluates to true. 40 | @param {string} test To be evaluated. 41 | @param {string} message Optional. To be displayed in the report. 42 | @return {boolean} True if the string test evaluates to true. 43 | */ 44 | ok = function(test, message) { 45 | testrun.count++; 46 | 47 | var result; 48 | try { 49 | result = eval(test); 50 | 51 | if (result) { 52 | testrun.passes++; 53 | testrun.report(" OK "+testrun.count+" - "+((message != null)? message : "")); 54 | } 55 | else { 56 | testrun.fails++; 57 | testrun.report("NOT OK "+testrun.count+" - "+((message != null)? message : "")); 58 | } 59 | } 60 | catch(e) { 61 | testrun.fails++ 62 | testrun.report("NOT OK "+testrun.count+" - "+((message != null)? message : "")); 63 | 64 | } 65 | } 66 | 67 | /** 68 | Check if test is same as expected. 69 | @param {string} test To be evaluated. 70 | @param {string} expected 71 | @param {string} message Optional. To be displayed in the report. 72 | @return {boolean} True if (test == expected). Note that the comparison is not a strict equality check. 73 | */ 74 | is = function(test, expected, message) { 75 | testrun.count++; 76 | 77 | var result; 78 | try { 79 | result = eval(test); 80 | 81 | if (result == expected) { 82 | testrun.passes++ 83 | testrun.report(" OK "+testrun.count+" - "+((message != null)? message : "")); 84 | } 85 | else { 86 | testrun.fails++ 87 | testrun.report("NOT OK "+testrun.count+" - "+((message != null)? message : "")); 88 | testrun.report("expected: "+expected); 89 | testrun.report(" got: "+result); 90 | } 91 | } 92 | catch(e) { 93 | testrun.fails++ 94 | testrun.report("NOT OK "+testrun.count+" - "+((message != null)? message : "")); 95 | testrun.report("expected: "+expected); 96 | testrun.report(" got: "+result);} 97 | } 98 | 99 | /** 100 | Check if test matches pattern. 101 | @param {string} test To be evaluated. 102 | @param {string} pattern Used to create a RegExp. 103 | @param {string} message Optional. To be displayed in the report. 104 | @return {boolean} True if test matches pattern. 105 | */ 106 | like = function(test, pattern, message) { 107 | testrun.count++; 108 | 109 | var result; 110 | try { 111 | result = eval(test); 112 | var rgx = new RegExp(pattern); 113 | 114 | if (rgx.test(result)) { 115 | testrun.passes++ 116 | testrun.report(" OK "+testrun.count+" - "+((message != null)? message : "")); 117 | } 118 | else { 119 | testrun.fails++ 120 | testrun.report("NOT OK "+testrun.count+" - "+((message != null)? message : "")); 121 | testrun.report(" this: "+result); 122 | testrun.report("is not like: "+pattern); 123 | } 124 | } 125 | catch(e) { 126 | testrun.fails++ 127 | testrun.report("NOT OK "+testrun.count+" - "+((message != null)? message : "")); 128 | } 129 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/handlers/FOODOC.js: -------------------------------------------------------------------------------- 1 | /** 2 | This is the main container for the FOODOC handler. 3 | @namespace 4 | */ 5 | FOODOC = { 6 | }; 7 | 8 | /** The current version string of this application. */ 9 | FOODOC.VERSION = "1.0"; 10 | 11 | FOODOC.handle = function(srcFile, src) { 12 | LOG.inform("Handling file '" + srcFile + "'"); 13 | 14 | return [ 15 | new JSDOC.Symbol( 16 | "foo", 17 | [], 18 | "VIRTUAL", 19 | new JSDOC.DocComment("/** This is a foo. */") 20 | ) 21 | ]; 22 | }; 23 | 24 | FOODOC.publish = function(symbolgroup) { 25 | LOG.inform("Publishing symbolgroup."); 26 | }; 27 | -------------------------------------------------------------------------------- /tools/jsdoc/app/handlers/XMLDOC.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This is the main container for the XMLDOC handler. 3 | * @namespace 4 | * @author Brett Fattori (bfattori@fry.com) 5 | * @version $Revision: 498 $ 6 | */ 7 | XMLDOC = { 8 | 9 | }; 10 | 11 | /** The current version string of this application. */ 12 | XMLDOC.VERSION = "1.0"; 13 | 14 | /** Include the library necessary to handle XML files */ 15 | IO.includeDir("handlers/XMLDOC/"); 16 | 17 | /** 18 | * @type Symbol[] 19 | */ 20 | XMLDOC.handle = function(srcFile, src) { 21 | 22 | }; 23 | 24 | XMLDOC.publish = function(symbolgroup) { 25 | 26 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/handlers/XMLDOC/DomReader.js: -------------------------------------------------------------------------------- 1 | LOG.inform("XMLDOC.DomReader loaded"); 2 | 3 | XMLDOC.DomReader = function(root) { 4 | 5 | this.dom = root; 6 | 7 | /** 8 | * The current node the reader is on 9 | */ 10 | this.node = root; 11 | 12 | /** 13 | * Get the current node the reader is on 14 | * @type XMLDOC.Parser.node 15 | */ 16 | XMLDOC.DomReader.prototype.getNode = function() { 17 | return this.node; 18 | }; 19 | 20 | /** 21 | * Set the node the reader should be positioned on. 22 | * @param node {XMLDOC.Parser.node} 23 | */ 24 | XMLDOC.DomReader.prototype.setNode = function(node) { 25 | this.node = node; 26 | }; 27 | 28 | /** 29 | * A helper method to make sure the current node will 30 | * never return null, unless null is passed as the root. 31 | * @param step {String} An expression to evaluate - should return a node or null 32 | */ 33 | XMLDOC.DomReader.prototype.navigate = function(step) { 34 | var n; 35 | if ((n = step) != null) 36 | { 37 | this.node = n; 38 | return this.node; 39 | } 40 | return null; 41 | }; 42 | 43 | /** 44 | * Get the root node of the current node's document. 45 | */ 46 | XMLDOC.DomReader.prototype.root = function() { 47 | this.navigate(this.dom); 48 | }; 49 | 50 | /** 51 | * Get the parent of the current node. 52 | */ 53 | XMLDOC.DomReader.prototype.parent = function() { 54 | return this.navigate(this.node.parentNode()); 55 | }; 56 | 57 | /** 58 | * Get the first child of the current node. 59 | */ 60 | XMLDOC.DomReader.prototype.firstChild = function() { 61 | return this.navigate(this.node.firstChild()); 62 | }; 63 | 64 | /** 65 | * Get the last child of the current node. 66 | */ 67 | XMLDOC.DomReader.prototype.lastChild = function() { 68 | return this.navigate(this.node.lastChild()); 69 | }; 70 | 71 | /** 72 | * Get the next sibling of the current node. 73 | */ 74 | XMLDOC.DomReader.prototype.nextSibling = function() { 75 | return this.navigate(this.node.nextSibling()); 76 | }; 77 | 78 | /** 79 | * Get the previous sibling of the current node. 80 | */ 81 | XMLDOC.DomReader.prototype.prevSibling = function() { 82 | return this.navigate(this.node.prevSibling()); 83 | }; 84 | 85 | //=============================================================================================== 86 | // Support methods 87 | 88 | /** 89 | * Walk the tree starting with the current node, calling the plug-in for 90 | * each node visited. Each time the plug-in is called, the DomReader 91 | * is passed as the only parameter. Use the {@link XMLDOC.DomReader#getNode} method 92 | * to access the current node. This method uses a depth first traversal pattern. 93 | * 94 | * @param srcFile {String} The source file being evaluated 95 | */ 96 | XMLDOC.DomReader.prototype.getSymbols = function(srcFile) 97 | { 98 | XMLDOC.DomReader.symbols = []; 99 | XMLDOC.DomReader.currentFile = srcFile; 100 | JSDOC.Symbol.srcFile = (srcFile || ""); 101 | 102 | if (defined(JSDOC.PluginManager)) { 103 | JSDOC.PluginManager.run("onDomGetSymbols", this); 104 | } 105 | 106 | return XMLDOC.DomReader.symbols; 107 | }; 108 | 109 | /** 110 | * Find the node with the given name using a depth first traversal. 111 | * Does not modify the DomReader's current node. 112 | * 113 | * @param name {String} The name of the node to find 114 | * @return the node that was found, or null if not found 115 | */ 116 | XMLDOC.DomReader.prototype.findNode = function(name) 117 | { 118 | var findNode = null; 119 | 120 | // Start at the current node and move into the subtree, 121 | // looking for the node with the given name 122 | function deeper(node, find) 123 | { 124 | var look = null; 125 | 126 | if (node) { 127 | if (node.name == find) 128 | { 129 | return node; 130 | } 131 | 132 | if (node.firstChild()) 133 | { 134 | look = deeper(node.firstChild(), find); 135 | } 136 | 137 | if (!look && node.nextSibling()) 138 | { 139 | look = deeper(node.nextSibling(), find); 140 | } 141 | } 142 | 143 | return look; 144 | } 145 | 146 | return deeper(this.getNode().firstChild(), name); 147 | }; 148 | 149 | /** 150 | * Find the next node with the given name using a depth first traversal. 151 | * 152 | * @param name {String} The name of the node to find 153 | */ 154 | XMLDOC.DomReader.prototype.findPreviousNode = function(name) 155 | { 156 | }; 157 | 158 | }; 159 | 160 | -------------------------------------------------------------------------------- /tools/jsdoc/app/handlers/XMLDOC/XMLDoc.js: -------------------------------------------------------------------------------- 1 | LOG.inform("XMLDOC.symbolize loaded"); 2 | 3 | /** 4 | * Convert the source file to a set of symbols 5 | */ 6 | XMLDOC.symbolize = function(srcFile, src) { 7 | 8 | LOG.inform("Symbolizing file '" + srcFile + "'"); 9 | 10 | // XML files already have a defined structure, so we don't need to 11 | // do anything but parse them. The DOM reader can create a symbol 12 | // table from the parsed XML. 13 | var dr = new XMLDOC.DomReader(XMLDOC.Parser.parse(src)); 14 | return dr.getSymbols(srcFile); 15 | 16 | }; 17 | -------------------------------------------------------------------------------- /tools/jsdoc/app/lib/JSDOC.js: -------------------------------------------------------------------------------- 1 | /** 2 | @overview 3 | @date $Date: 2010-06-13 22:02:44 +0100 (Sun, 13 Jun 2010) $ 4 | @version $Revision: 837 $ 5 | @location $HeadURL: https://jsdoc-toolkit.googlecode.com/svn/tags/jsdoc_toolkit-2.4.0/jsdoc-toolkit/app/lib/JSDOC.js $ 6 | @name JSDOC.js 7 | */ 8 | 9 | /** 10 | This is the main container for the JSDOC application. 11 | @namespace 12 | */ 13 | JSDOC = { 14 | }; 15 | 16 | /** 17 | @requires Opt 18 | */ 19 | if (typeof arguments == "undefined") arguments = []; 20 | JSDOC.opt = Opt.get( 21 | arguments, 22 | { 23 | a: "allfunctions", 24 | c: "conf", 25 | d: "directory", 26 | "D[]": "define", 27 | e: "encoding", 28 | "E[]": "exclude", 29 | h: "help", 30 | m: "multiple", 31 | n: "nocode", 32 | o: "out", 33 | p: "private", 34 | q: "quiet", 35 | r: "recurse", 36 | S: "securemodules", 37 | s: "suppress", 38 | t: "template", 39 | T: "testmode", 40 | u: "unique", 41 | v: "verbose", 42 | x: "ext" 43 | } 44 | ); 45 | 46 | /** The current version string of this application. */ 47 | JSDOC.VERSION = "2.4.0"; 48 | 49 | /** Print out usage information and quit. */ 50 | JSDOC.usage = function() { 51 | print("USAGE: java -jar jsrun.jar app/run.js [OPTIONS] ..."); 52 | print(""); 53 | print("OPTIONS:"); 54 | print(" -a or --allfunctions\n Include all functions, even undocumented ones.\n"); 55 | print(" -c or --conf\n Load a configuration file.\n"); 56 | print(" -d= or --directory=\n Output to this directory (defaults to \"out\").\n"); 57 | print(" -D=\"myVar:My value\" or --define=\"myVar:My value\"\n Multiple. Define a variable, available in JsDoc as JSDOC.opt.D.myVar.\n"); 58 | print(" -e= or --encoding=\n Use this encoding to read and write files.\n"); 59 | print(" -E=\"REGEX\" or --exclude=\"REGEX\"\n Multiple. Exclude files based on the supplied regex.\n"); 60 | print(" -h or --help\n Show this message and exit.\n"); 61 | print(" -m or --multiples\n Don't warn about symbols being documented more than once.\n"); 62 | print(" -n or --nocode\n Ignore all code, only document comments with @name tags.\n"); 63 | print(" -o= or --out=\n Print log messages to a file (defaults to stdout).\n"); 64 | print(" -p or --private\n Include symbols tagged as private, underscored and inner symbols.\n"); 65 | print(" -q or --quiet\n Do not output any messages, not even warnings.\n"); 66 | print(" -r= or --recurse=\n Descend into src directories.\n"); 67 | print(" -s or --suppress\n Suppress source code output.\n"); 68 | print(" -S or --securemodules\n Use Secure Modules mode to parse source code.\n"); 69 | print(" -t= or --template=\n Required. Use this template to format the output.\n"); 70 | print(" -T or --test\n Run all unit tests and exit.\n"); 71 | print(" -u or --unique\n Force file names to be unique, but not based on symbol names.\n"); 72 | print(" -v or --verbose\n Provide verbose feedback about what is happening.\n"); 73 | print(" -x=[,EXT]... or --ext=[,EXT]...\n Scan source files with the given extension/s (defaults to js).\n"); 74 | 75 | quit(); 76 | } 77 | 78 | /*t: 79 | plan(4, "Testing JSDOC namespace."); 80 | 81 | is( 82 | typeof JSDOC, 83 | "object", 84 | "JSDOC.usage is a function." 85 | ); 86 | 87 | is( 88 | typeof JSDOC.VERSION, 89 | "string", 90 | "JSDOC.VERSION is a string." 91 | ); 92 | 93 | is( 94 | typeof JSDOC.usage, 95 | "function", 96 | "JSDOC.usage is a function." 97 | ); 98 | 99 | is( 100 | typeof JSDOC.opt, 101 | "object", 102 | "JSDOC.opt is a object." 103 | ); 104 | */ 105 | 106 | if (this.IO) IO.includeDir("lib/JSDOC/"); 107 | -------------------------------------------------------------------------------- /tools/jsdoc/app/lib/JSDOC/JsDoc.js: -------------------------------------------------------------------------------- 1 | /** 2 | @constructor 3 | @param [opt] Used to override the commandline options. Useful for testing. 4 | @version $Id: JsDoc.js 831 2010-03-09 14:24:56Z micmath $ 5 | */ 6 | JSDOC.JsDoc = function(/**object*/ opt) { 7 | if (opt) { 8 | JSDOC.opt = opt; 9 | } 10 | 11 | if (JSDOC.opt.h) { 12 | JSDOC.usage(); 13 | quit(); 14 | } 15 | 16 | // defend against options that are not sane 17 | if (JSDOC.opt._.length == 0) { 18 | LOG.warn("No source files to work on. Nothing to do."); 19 | quit(); 20 | } 21 | if (JSDOC.opt.t === true || JSDOC.opt.d === true) { 22 | JSDOC.usage(); 23 | } 24 | 25 | if (typeof JSDOC.opt.d == "string") { 26 | if (!JSDOC.opt.d.charAt(JSDOC.opt.d.length-1).match(/[\\\/]/)) { 27 | JSDOC.opt.d = JSDOC.opt.d+"/"; 28 | } 29 | LOG.inform("Output directory set to '"+JSDOC.opt.d+"'."); 30 | IO.mkPath(JSDOC.opt.d); 31 | } 32 | if (JSDOC.opt.e) IO.setEncoding(JSDOC.opt.e); 33 | 34 | // the -r option: scan source directories recursively 35 | if (typeof JSDOC.opt.r == "boolean") JSDOC.opt.r = 10; 36 | else if (!isNaN(parseInt(JSDOC.opt.r))) JSDOC.opt.r = parseInt(JSDOC.opt.r); 37 | else JSDOC.opt.r = 1; 38 | 39 | // the -D option: define user variables 40 | var D = {}; 41 | if (JSDOC.opt.D) { 42 | for (var i = 0; i < JSDOC.opt.D.length; i++) { 43 | var param = JSDOC.opt.D[i]; 44 | // remove first and last character if both == " 45 | if ( 46 | param.length > 1 47 | && param.charAt(0) == '"' 48 | && param.charAt(param.length-1) == '"' 49 | ) { 50 | param = param.substr(1, param.length-2); 51 | } 52 | var defineParts = param.split(":"); 53 | if (defineParts && defineParts.length > 1) { 54 | for ( var dpIdx = 2; dpIdx < defineParts.length; dpIdx++ ) { 55 | defineParts[1] += ':' + defineParts[dpIdx]; 56 | } 57 | D[defineParts[0]] = defineParts[1]; 58 | } 59 | } 60 | } 61 | JSDOC.opt.D = D; 62 | // combine any conf file D options with the commandline D options 63 | if (defined(JSDOC.conf)) for (var c in JSDOC.conf.D) { 64 | if (!defined(JSDOC.opt.D[c])) { 65 | JSDOC.opt.D[c] = JSDOC.conf.D[c]; 66 | } 67 | } 68 | 69 | // Give plugins a chance to initialize 70 | if (defined(JSDOC.PluginManager)) { 71 | JSDOC.PluginManager.run("onInit", JSDOC.opt); 72 | } 73 | 74 | JSDOC.opt.srcFiles = JSDOC.JsDoc._getSrcFiles(); 75 | JSDOC.JsDoc._parseSrcFiles(); 76 | JSDOC.JsDoc.symbolSet = JSDOC.Parser.symbols; 77 | } 78 | 79 | /** 80 | Retrieve source file list. 81 | @returns {String[]} The pathnames of the files to be parsed. 82 | */ 83 | JSDOC.JsDoc._getSrcFiles = function() { 84 | JSDOC.JsDoc.srcFiles = []; 85 | 86 | var ext = ["js"]; 87 | if (JSDOC.opt.x) { 88 | ext = JSDOC.opt.x.split(",").map(function($) {return $.toLowerCase()}); 89 | } 90 | 91 | for (var i = 0; i < JSDOC.opt._.length; i++) { 92 | JSDOC.JsDoc.srcFiles = JSDOC.JsDoc.srcFiles.concat( 93 | IO.ls(JSDOC.opt._[i], JSDOC.opt.r).filter( 94 | function($) { 95 | var thisExt = $.split(".").pop().toLowerCase(); 96 | 97 | if (JSDOC.opt.E) { 98 | for(var n = 0; n < JSDOC.opt.E.length; n++) { 99 | if ($.match(new RegExp(JSDOC.opt.E[n]))) { 100 | LOG.inform("Excluding " + $); 101 | return false; // if the file matches the regex then it's excluded. 102 | } 103 | } 104 | } 105 | 106 | return (ext.indexOf(thisExt) > -1); // we're only interested in files with certain extensions 107 | } 108 | ) 109 | ); 110 | } 111 | 112 | return JSDOC.JsDoc.srcFiles; 113 | } 114 | 115 | JSDOC.JsDoc._parseSrcFiles = function() { 116 | JSDOC.Parser.init(); 117 | for (var i = 0, l = JSDOC.JsDoc.srcFiles.length; i < l; i++) { 118 | var srcFile = JSDOC.JsDoc.srcFiles[i]; 119 | 120 | if (JSDOC.opt.v) LOG.inform("Parsing file: " + srcFile); 121 | 122 | try { 123 | var src = IO.readFile(srcFile); 124 | } 125 | catch(e) { 126 | LOG.warn("Can't read source file '"+srcFile+"': "+e.message); 127 | } 128 | 129 | var tr = new JSDOC.TokenReader(); 130 | var ts = new JSDOC.TokenStream(tr.tokenize(new JSDOC.TextStream(src))); 131 | 132 | JSDOC.Parser.parse(ts, srcFile); 133 | 134 | } 135 | JSDOC.Parser.finish(); 136 | 137 | if (JSDOC.PluginManager) { 138 | JSDOC.PluginManager.run("onFinishedParsing", JSDOC.Parser.symbols); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /tools/jsdoc/app/lib/JSDOC/JsPlate.js: -------------------------------------------------------------------------------- 1 | /** 2 | @constructor 3 | */ 4 | JSDOC.JsPlate = function(templateFile) { 5 | if (templateFile) this.template = IO.readFile(templateFile); 6 | 7 | this.templateFile = templateFile; 8 | this.code = ""; 9 | this.parse(); 10 | } 11 | 12 | JSDOC.JsPlate.prototype.parse = function() { 13 | this.template = this.template.replace(/\{#[\s\S]+?#\}/gi, ""); 14 | this.code = "var output=\u001e"+this.template; 15 | 16 | this.code = this.code.replace( 17 | //gi, 18 | function (match, eachName, inName) { 19 | return "\u001e;\rvar $"+eachName+"_keys = keys("+inName+");\rfor(var $"+eachName+"_i = 0; $"+eachName+"_i < $"+eachName+"_keys.length; $"+eachName+"_i++) {\rvar $"+eachName+"_last = ($"+eachName+"_i == $"+eachName+"_keys.length-1);\rvar $"+eachName+"_key = $"+eachName+"_keys[$"+eachName+"_i];\rvar "+eachName+" = "+inName+"[$"+eachName+"_key];\routput+=\u001e"; 20 | } 21 | ); 22 | this.code = this.code.replace(//g, "\u001e;\rif ($1) { output+=\u001e"); 23 | this.code = this.code.replace(//g, "\u001e;}\relse if ($1) { output+=\u001e"); 24 | this.code = this.code.replace(//g, "\u001e;}\relse { output+=\u001e"); 25 | this.code = this.code.replace(/<\/(if|for)>/g, "\u001e;\r};\routput+=\u001e"); 26 | this.code = this.code.replace( 27 | /\{\+\s*([\s\S]+?)\s*\+\}/gi, 28 | function (match, code) { 29 | code = code.replace(/"/g, "\u001e"); // prevent qoute-escaping of inline code 30 | code = code.replace(/(\r?\n)/g, " "); 31 | return "\u001e+ ("+code+") +\u001e"; 32 | } 33 | ); 34 | this.code = this.code.replace( 35 | /\{!\s*([\s\S]+?)\s*!\}/gi, 36 | function (match, code) { 37 | code = code.replace(/"/g, "\u001e"); // prevent qoute-escaping of inline code 38 | code = code.replace(/(\n)/g, " "); 39 | return "\u001e; "+code+";\routput+=\u001e"; 40 | } 41 | ); 42 | this.code = this.code+"\u001e;"; 43 | 44 | this.code = this.code.replace(/(\r?\n)/g, "\\n"); 45 | this.code = this.code.replace(/"/g, "\\\""); 46 | this.code = this.code.replace(/\u001e/g, "\""); 47 | } 48 | 49 | JSDOC.JsPlate.prototype.toCode = function() { 50 | return this.code; 51 | } 52 | 53 | JSDOC.JsPlate.keys = function(obj) { 54 | var keys = []; 55 | if (obj.constructor.toString().indexOf("Array") > -1) { 56 | for (var i = 0; i < obj.length; i++) { 57 | keys.push(i); 58 | } 59 | } 60 | else { 61 | for (var i in obj) { 62 | keys.push(i); 63 | } 64 | } 65 | return keys; 66 | }; 67 | 68 | JSDOC.JsPlate.values = function(obj) { 69 | var values = []; 70 | if (obj.constructor.toString().indexOf("Array") > -1) { 71 | for (var i = 0; i < obj.length; i++) { 72 | values.push(obj[i]); 73 | } 74 | } 75 | else { 76 | for (var i in obj) { 77 | values.push(obj[i]); 78 | } 79 | } 80 | return values; 81 | }; 82 | 83 | JSDOC.JsPlate.prototype.process = function(data, compact) { 84 | var keys = JSDOC.JsPlate.keys; 85 | var values = JSDOC.JsPlate.values; 86 | 87 | try { 88 | eval(this.code); 89 | } 90 | catch (e) { 91 | print(">> There was an error evaluating the compiled code from template: "+this.templateFile); 92 | print(" The error was on line "+e.lineNumber+" "+e.name+": "+e.message); 93 | var lines = this.code.split("\r"); 94 | if (e.lineNumber-2 >= 0) print("line "+(e.lineNumber-1)+": "+lines[e.lineNumber-2]); 95 | print("line "+e.lineNumber+": "+lines[e.lineNumber-1]); 96 | print(""); 97 | } 98 | 99 | if (compact) { // patch by mcbain.asm 100 | // Remove lines that contain only space-characters, usually left by lines in the template 101 | // which originally only contained JSPlate tags or code. This makes it easier to write 102 | // non-tricky templates which still put out nice code (not bloated with extra lines). 103 | // Lines purposely left blank (just a line ending) are left alone. 104 | output = output.replace(/\s+?(\r?)\n/g, "$1\n"); 105 | } 106 | 107 | /*debug*///print(this.code); 108 | return output; 109 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/lib/JSDOC/Lang.js: -------------------------------------------------------------------------------- 1 | /** 2 | @namespace 3 | */ 4 | JSDOC.Lang = { 5 | } 6 | 7 | JSDOC.Lang.isBuiltin = function(name) { 8 | return (JSDOC.Lang.isBuiltin.coreObjects.indexOf(name) > -1); 9 | } 10 | JSDOC.Lang.isBuiltin.coreObjects = ['_global_', 'Array', 'Boolean', 'Date', 'Error', 'Function', 'Math', 'Number', 'Object', 'RegExp', 'String']; 11 | 12 | JSDOC.Lang.whitespace = function(ch) { 13 | return JSDOC.Lang.whitespace.names[ch]; 14 | } 15 | JSDOC.Lang.whitespace.names = { 16 | " ": "SPACE", 17 | "\f": "FORMFEED", 18 | "\t": "TAB", 19 | "\u0009": "UNICODE_TAB", 20 | "\u000A": "UNICODE_NBR", 21 | "\u0008": "VERTICAL_TAB" 22 | }; 23 | 24 | JSDOC.Lang.newline = function(ch) { 25 | return JSDOC.Lang.newline.names[ch]; 26 | } 27 | JSDOC.Lang.newline.names = { 28 | "\n": "NEWLINE", 29 | "\r": "RETURN", 30 | "\u000A": "UNICODE_LF", 31 | "\u000D": "UNICODE_CR", 32 | "\u2029": "UNICODE_PS", 33 | "\u2028": "UNICODE_LS" 34 | }; 35 | 36 | JSDOC.Lang.keyword = function(word) { 37 | return JSDOC.Lang.keyword.names["="+word]; 38 | } 39 | JSDOC.Lang.keyword.names = { 40 | "=break": "BREAK", 41 | "=case": "CASE", 42 | "=catch": "CATCH", 43 | "=const": "VAR", 44 | "=continue": "CONTINUE", 45 | "=default": "DEFAULT", 46 | "=delete": "DELETE", 47 | "=do": "DO", 48 | "=else": "ELSE", 49 | "=false": "FALSE", 50 | "=finally": "FINALLY", 51 | "=for": "FOR", 52 | "=function": "FUNCTION", 53 | "=if": "IF", 54 | "=in": "IN", 55 | "=instanceof": "INSTANCEOF", 56 | "=new": "NEW", 57 | "=null": "NULL", 58 | "=return": "RETURN", 59 | "=switch": "SWITCH", 60 | "=this": "THIS", 61 | "=throw": "THROW", 62 | "=true": "TRUE", 63 | "=try": "TRY", 64 | "=typeof": "TYPEOF", 65 | "=void": "VOID", 66 | "=while": "WHILE", 67 | "=with": "WITH", 68 | "=var": "VAR" 69 | }; 70 | 71 | JSDOC.Lang.punc = function(ch) { 72 | return JSDOC.Lang.punc.names[ch]; 73 | } 74 | JSDOC.Lang.punc.names = { 75 | ";": "SEMICOLON", 76 | ",": "COMMA", 77 | "?": "HOOK", 78 | ":": "COLON", 79 | "||": "OR", 80 | "&&": "AND", 81 | "|": "BITWISE_OR", 82 | "^": "BITWISE_XOR", 83 | "&": "BITWISE_AND", 84 | "===": "STRICT_EQ", 85 | "==": "EQ", 86 | "=": "ASSIGN", 87 | "!==": "STRICT_NE", 88 | "!=": "NE", 89 | "<<": "LSH", 90 | "<=": "LE", 91 | "<": "LT", 92 | ">>>": "URSH", 93 | ">>": "RSH", 94 | ">=": "GE", 95 | ">": "GT", 96 | "++": "INCREMENT", 97 | "--": "DECREMENT", 98 | "+": "PLUS", 99 | "-": "MINUS", 100 | "*": "MUL", 101 | "/": "DIV", 102 | "%": "MOD", 103 | "!": "NOT", 104 | "~": "BITWISE_NOT", 105 | ".": "DOT", 106 | "[": "LEFT_BRACKET", 107 | "]": "RIGHT_BRACKET", 108 | "{": "LEFT_CURLY", 109 | "}": "RIGHT_CURLY", 110 | "(": "LEFT_PAREN", 111 | ")": "RIGHT_PAREN" 112 | }; 113 | 114 | JSDOC.Lang.matching = function(name) { 115 | return JSDOC.Lang.matching.names[name]; 116 | } 117 | JSDOC.Lang.matching.names = { 118 | "LEFT_PAREN": "RIGHT_PAREN", 119 | "RIGHT_PAREN": "LEFT_PAREN", 120 | "LEFT_CURLY": "RIGHT_CURLY", 121 | "RIGHT_CURLY": "LEFT_CURLY", 122 | "LEFT_BRACE": "RIGHT_BRACE", 123 | "RIGHT_BRACE": "LEFT_BRACE" 124 | } 125 | 126 | JSDOC.Lang.isNumber = function(str) { 127 | return /^(\.[0-9]|[0-9]+\.|[0-9])[0-9]*([eE][+-][0-9]+)?$/i.test(str); 128 | } 129 | 130 | JSDOC.Lang.isHexDec = function(str) { 131 | return /^0x[0-9A-F]+$/i.test(str); 132 | } 133 | 134 | JSDOC.Lang.isWordChar = function(str) { 135 | return /^[a-zA-Z0-9$_.]+$/.test(str); 136 | } 137 | 138 | JSDOC.Lang.isSpace = function(str) { 139 | return (typeof JSDOC.Lang.whitespace(str) != "undefined"); 140 | } 141 | 142 | JSDOC.Lang.isNewline = function(str) { 143 | return (typeof JSDOC.Lang.newline(str) != "undefined"); 144 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/lib/JSDOC/Parser.js: -------------------------------------------------------------------------------- 1 | if (typeof JSDOC == "undefined") JSDOC = {}; 2 | 3 | /** 4 | @namespace 5 | @requires JSDOC.Walker 6 | @requires JSDOC.Symbol 7 | @requires JSDOC.DocComment 8 | */ 9 | JSDOC.Parser = { 10 | conf: { 11 | ignoreCode: JSDOC.opt.n, 12 | ignoreAnonymous: true, // factory: true 13 | treatUnderscoredAsPrivate: true, // factory: true 14 | explain: false // factory: false 15 | }, 16 | 17 | addSymbol: function(symbol) { 18 | 19 | if (JSDOC.Parser.rename) { 20 | for (var n in JSDOC.Parser.rename) { 21 | if (symbol.alias.indexOf(n) == 0) { 22 | if (symbol.name == symbol.alias) { 23 | symbol.name = symbol.name.replace(n, JSDOC.Parser.rename[n]); 24 | } 25 | symbol.alias = symbol.alias.replace(n, JSDOC.Parser.rename[n]); 26 | } 27 | } 28 | } 29 | 30 | if (JSDOC.opt.S) { 31 | if (typeof JSDOC.Parser.secureModules == "undefined") JSDOC.Parser.secureModules = {}; 32 | if (/^exports\./.test(symbol.alias)) { 33 | symbol.srcFile.match(/(^|[\\\/])([^\\\/]+)\.js/i); 34 | var fileNS = RegExp.$2; 35 | 36 | // need to create the namespace associated with this file first 37 | if (!JSDOC.Parser.secureModules[fileNS]) { 38 | JSDOC.Parser.secureModules[fileNS] = 1; 39 | var nsSymbol = new JSDOC.Symbol(fileNS, [], "GLOBAL", new JSDOC.DocComment("")); 40 | nsSymbol.isNamespace = true; 41 | nsSymbol.srcFile = ""; 42 | nsSymbol.isPrivate = false; 43 | nsSymbol.srcFile = symbol.srcFile; 44 | nsSymbol.desc = (JSDOC.Parser.symbols.getSymbol(symbol.srcFile) || {desc: ""}).desc; 45 | JSDOC.Parser.addSymbol(nsSymbol); 46 | } 47 | 48 | symbol.alias = symbol.alias.replace(/^exports\./, fileNS + '.'); 49 | symbol.name = symbol.name.replace(/^exports\./, ''); 50 | symbol.memberOf = fileNS; 51 | symbol.isStatic = true; 52 | } 53 | } 54 | 55 | // if a symbol alias is documented more than once the first one with the user docs wins 56 | if (JSDOC.Parser.symbols.hasSymbol(symbol.alias)) { 57 | var oldSymbol = JSDOC.Parser.symbols.getSymbol(symbol.alias); 58 | if (oldSymbol.comment.isUserComment) { 59 | if (JSDOC.opt.m) return; 60 | if (symbol.comment.isUserComment) { // old and new are both documented 61 | LOG.warn("The symbol '"+symbol.alias+"' is documented more than once."); 62 | return; 63 | } 64 | else { // old is documented but new isn't 65 | return; 66 | } 67 | } 68 | } 69 | 70 | // we don't document anonymous things 71 | if (JSDOC.Parser.conf.ignoreAnonymous && symbol.name.match(/\$anonymous\b/)) return; 72 | 73 | // uderscored things may be treated as if they were marked private, this cascades 74 | if (JSDOC.Parser.conf.treatUnderscoredAsPrivate && symbol.name.match(/[.#-]_[^.#-]+$/)) { 75 | if (!symbol.comment.getTag("public").length > 0) symbol.isPrivate = true; 76 | } 77 | 78 | // -p flag is required to document private things 79 | if (!JSDOC.opt.p && symbol.isPrivate) return; // issue #161 fixed by mcbain.asm 80 | 81 | // ignored things are not documented, this doesn't cascade 82 | if (symbol.isIgnored) return; 83 | JSDOC.Parser.symbols.addSymbol(symbol); 84 | }, 85 | 86 | addBuiltin: function(name) { 87 | var builtin = new JSDOC.Symbol(name, [], "CONSTRUCTOR", new JSDOC.DocComment("")); 88 | builtin.isNamespace = true; 89 | builtin.srcFile = ""; 90 | builtin.isPrivate = false; 91 | JSDOC.Parser.addSymbol(builtin); 92 | return builtin; 93 | }, 94 | 95 | init: function() { 96 | JSDOC.Parser.symbols = new JSDOC.SymbolSet(); 97 | JSDOC.Parser.walker = new JSDOC.Walker(); 98 | }, 99 | 100 | finish: function() { 101 | JSDOC.Parser.symbols.relate(); 102 | 103 | // make a litle report about what was found 104 | if (JSDOC.Parser.conf.explain) { 105 | var symbols = JSDOC.Parser.symbols.toArray(); 106 | var srcFile = ""; 107 | for (var i = 0, l = symbols.length; i < l; i++) { 108 | var symbol = symbols[i]; 109 | if (srcFile != symbol.srcFile) { 110 | srcFile = symbol.srcFile; 111 | print("\n"+srcFile+"\n-------------------"); 112 | } 113 | print(i+":\n alias => "+symbol.alias + "\n name => "+symbol.name+ "\n isa => "+symbol.isa + "\n memberOf => " + symbol.memberOf + "\n isStatic => " + symbol.isStatic + ", isInner => " + symbol.isInner+ ", isPrivate => " + symbol.isPrivate); 114 | } 115 | print("-------------------\n"); 116 | } 117 | } 118 | } 119 | 120 | JSDOC.Parser.parse = function(/**JSDOC.TokenStream*/ts, /**String*/srcFile) { 121 | JSDOC.Symbol.srcFile = (srcFile || ""); 122 | JSDOC.DocComment.shared = ""; // shared comments don't cross file boundaries 123 | 124 | if (!JSDOC.Parser.walker) JSDOC.Parser.init(); 125 | JSDOC.Parser.walker.walk(ts); // adds to our symbols 126 | 127 | // filter symbols by option 128 | for (var p = JSDOC.Parser.symbols._index.first(); p; p = JSDOC.Parser.symbols._index.next()) { 129 | var symbol = p.value; 130 | 131 | if (!symbol) continue; 132 | 133 | if (symbol.is("FILE") || symbol.is("GLOBAL")) { 134 | continue; 135 | } 136 | else if (!JSDOC.opt.a && !symbol.comment.isUserComment) { 137 | JSDOC.Parser.symbols.deleteSymbol(symbol.alias); 138 | } 139 | 140 | if (/#$/.test(symbol.alias)) { // we don't document prototypes 141 | JSDOC.Parser.symbols.deleteSymbol(symbol.alias); 142 | } 143 | } 144 | 145 | return JSDOC.Parser.symbols.toArray(); 146 | } 147 | -------------------------------------------------------------------------------- /tools/jsdoc/app/lib/JSDOC/PluginManager.js: -------------------------------------------------------------------------------- 1 | /** 2 | @namespace Holds functionality related to running plugins. 3 | */ 4 | JSDOC.PluginManager = { 5 | } 6 | 7 | /** 8 | @param name A unique name that identifies that plugin. 9 | @param handlers A collection of named functions. The names correspond to hooks in the core code. 10 | */ 11 | JSDOC.PluginManager.registerPlugin = function(/**String*/name, /**Object*/handlers) { 12 | if (!defined(JSDOC.PluginManager.plugins)) 13 | /** The collection of all plugins. Requires a unique name for each. 14 | */ 15 | JSDOC.PluginManager.plugins = {}; 16 | 17 | 18 | JSDOC.PluginManager.plugins[name] = handlers; 19 | } 20 | 21 | /** 22 | @param hook The name of the hook that is being caught. 23 | @param target Any object. This will be passed as the only argument to the handler whose 24 | name matches the hook name. Handlers cannot return a value, so must modify the target 25 | object to have an effect. 26 | */ 27 | JSDOC.PluginManager.run = function(/**String*/hook, /**Mixed*/target) { 28 | for (var name in JSDOC.PluginManager.plugins) { 29 | if (defined(JSDOC.PluginManager.plugins[name][hook])) { 30 | JSDOC.PluginManager.plugins[name][hook](target); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tools/jsdoc/app/lib/JSDOC/TextStream.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | @constructor 4 | */ 5 | JSDOC.TextStream = function(text) { 6 | if (typeof(text) == "undefined") text = ""; 7 | text = ""+text; 8 | this.text = text; 9 | this.cursor = 0; 10 | } 11 | 12 | JSDOC.TextStream.prototype.look = function(n) { 13 | if (typeof n == "undefined") n = 0; 14 | 15 | if (this.cursor+n < 0 || this.cursor+n >= this.text.length) { 16 | var result = new String(""); 17 | result.eof = true; 18 | return result; 19 | } 20 | return this.text.charAt(this.cursor+n); 21 | } 22 | 23 | JSDOC.TextStream.prototype.next = function(n) { 24 | if (typeof n == "undefined") n = 1; 25 | if (n < 1) return null; 26 | 27 | var pulled = ""; 28 | for (var i = 0; i < n; i++) { 29 | if (this.cursor+i < this.text.length) { 30 | pulled += this.text.charAt(this.cursor+i); 31 | } 32 | else { 33 | var result = new String(""); 34 | result.eof = true; 35 | return result; 36 | } 37 | } 38 | 39 | this.cursor += n; 40 | return pulled; 41 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/lib/JSDOC/Token.js: -------------------------------------------------------------------------------- 1 | if (typeof JSDOC == "undefined") JSDOC = {}; 2 | 3 | /** 4 | @constructor 5 | */ 6 | JSDOC.Token = function(data, type, name) { 7 | this.data = data; 8 | this.type = type; 9 | this.name = name; 10 | } 11 | 12 | JSDOC.Token.prototype.toString = function() { 13 | return "<"+this.type+" name=\""+this.name+"\">"+this.data+""; 14 | } 15 | 16 | JSDOC.Token.prototype.is = function(what) { 17 | return this.name === what || this.type === what; 18 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/lib/JSDOC/TokenStream.js: -------------------------------------------------------------------------------- 1 | if (typeof JSDOC == "undefined") JSDOC = {}; 2 | 3 | /** 4 | @constructor 5 | */ 6 | JSDOC.TokenStream = function(tokens) { 7 | this.tokens = (tokens || []); 8 | this.rewind(); 9 | } 10 | 11 | /** 12 | @constructor 13 | @private 14 | */ 15 | function VoidToken(/**String*/type) { 16 | this.toString = function() {return ""}; 17 | this.is = function(){return false;} 18 | } 19 | 20 | JSDOC.TokenStream.prototype.rewind = function() { 21 | this.cursor = -1; 22 | } 23 | 24 | /** 25 | @type JSDOC.Token 26 | */ 27 | JSDOC.TokenStream.prototype.look = function(/**Number*/n, /**Boolean*/considerWhitespace) { 28 | if (typeof n == "undefined") n = 0; 29 | 30 | if (considerWhitespace == true) { 31 | if (this.cursor+n < 0 || this.cursor+n > this.tokens.length) return {}; 32 | return this.tokens[this.cursor+n]; 33 | } 34 | else { 35 | var count = 0; 36 | var i = this.cursor; 37 | 38 | while (true) { 39 | if (i < 0) return new JSDOC.Token("", "VOID", "START_OF_STREAM"); 40 | else if (i > this.tokens.length) return new JSDOC.Token("", "VOID", "END_OF_STREAM"); 41 | 42 | if (i != this.cursor && (this.tokens[i] === undefined || this.tokens[i].is("WHIT"))) { 43 | if (n < 0) i--; else i++; 44 | continue; 45 | } 46 | 47 | if (count == Math.abs(n)) { 48 | return this.tokens[i]; 49 | } 50 | count++; 51 | (n < 0)? i-- : i++; 52 | } 53 | 54 | return new JSDOC.Token("", "VOID", "STREAM_ERROR"); // because null isn't an object and caller always expects an object 55 | } 56 | } 57 | 58 | /** 59 | @type JSDOC.Token|JSDOC.Token[] 60 | */ 61 | JSDOC.TokenStream.prototype.next = function(/**Number*/howMany) { 62 | if (typeof howMany == "undefined") howMany = 1; 63 | if (howMany < 1) return null; 64 | var got = []; 65 | 66 | for (var i = 1; i <= howMany; i++) { 67 | if (this.cursor+i >= this.tokens.length) { 68 | return null; 69 | } 70 | got.push(this.tokens[this.cursor+i]); 71 | } 72 | this.cursor += howMany; 73 | 74 | if (howMany == 1) { 75 | return got[0]; 76 | } 77 | else return got; 78 | } 79 | 80 | /** 81 | @type JSDOC.Token[] 82 | */ 83 | JSDOC.TokenStream.prototype.balance = function(/**String*/start, /**String*/stop) { 84 | if (!stop) stop = JSDOC.Lang.matching(start); 85 | 86 | var depth = 0; 87 | var got = []; 88 | var started = false; 89 | 90 | while ((token = this.look())) { 91 | if (token.is(start)) { 92 | depth++; 93 | started = true; 94 | } 95 | 96 | if (started) { 97 | got.push(token); 98 | } 99 | 100 | if (token.is(stop)) { 101 | depth--; 102 | if (depth == 0) return got; 103 | } 104 | if (!this.next()) break; 105 | } 106 | } 107 | 108 | JSDOC.TokenStream.prototype.getMatchingToken = function(/**String*/start, /**String*/stop) { 109 | var depth = 0; 110 | var cursor = this.cursor; 111 | 112 | if (!start) { 113 | start = JSDOC.Lang.matching(stop); 114 | depth = 1; 115 | } 116 | if (!stop) stop = JSDOC.Lang.matching(start); 117 | 118 | while ((token = this.tokens[cursor])) { 119 | if (token.is(start)) { 120 | depth++; 121 | } 122 | 123 | if (token.is(stop) && cursor) { 124 | depth--; 125 | if (depth == 0) return this.tokens[cursor]; 126 | } 127 | cursor++; 128 | } 129 | } 130 | 131 | JSDOC.TokenStream.prototype.insertAhead = function(/**JSDOC.Token*/token) { 132 | this.tokens.splice(this.cursor+1, 0, token); 133 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/lib/JSDOC/Util.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @namespace 3 | * @deprecated Use {@link FilePath} instead. 4 | */ 5 | JSDOC.Util = { 6 | } 7 | 8 | /** 9 | * @deprecated Use {@link FilePath.fileName} instead. 10 | */ 11 | JSDOC.Util.fileName = function(path) { 12 | LOG.warn("JSDOC.Util.fileName is deprecated. Use FilePath.fileName instead."); 13 | var nameStart = Math.max(path.lastIndexOf("/")+1, path.lastIndexOf("\\")+1, 0); 14 | return path.substring(nameStart); 15 | } 16 | 17 | /** 18 | * @deprecated Use {@link FilePath.fileExtension} instead. 19 | */ 20 | JSDOC.Util.fileExtension = function(filename) { 21 | LOG.warn("JSDOC.Util.fileExtension is deprecated. Use FilePath.fileExtension instead."); 22 | return filename.split(".").pop().toLowerCase(); 23 | }; 24 | 25 | /** 26 | * @deprecated Use {@link FilePath.dir} instead. 27 | */ 28 | JSDOC.Util.dir = function(path) { 29 | LOG.warn("JSDOC.Util.dir is deprecated. Use FilePath.dir instead."); 30 | var nameStart = Math.max(path.lastIndexOf("/")+1, path.lastIndexOf("\\")+1, 0); 31 | return path.substring(0, nameStart-1); 32 | } 33 | -------------------------------------------------------------------------------- /tools/jsdoc/app/main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @version $Id: main.js 818 2009-11-08 14:51:41Z micmath $ 3 | */ 4 | 5 | function main() { 6 | IO.include("lib/JSDOC.js"); 7 | IO.includeDir("plugins/"); 8 | 9 | // process the options 10 | 11 | // the -c option: options are defined in a configuration file 12 | if (JSDOC.opt.c) { 13 | eval("JSDOC.conf = " + IO.readFile(JSDOC.opt.c)); 14 | 15 | LOG.inform("Using configuration file at '"+JSDOC.opt.c+"'."); 16 | 17 | for (var c in JSDOC.conf) { 18 | if (c !== "D" && !defined(JSDOC.opt[c])) { // commandline overrules config file 19 | JSDOC.opt[c] = JSDOC.conf[c]; 20 | } 21 | } 22 | 23 | if (typeof JSDOC.conf["_"] != "undefined") { 24 | JSDOC.opt["_"] = JSDOC.opt["_"].concat(JSDOC.conf["_"]); 25 | } 26 | 27 | LOG.inform("With configuration: "); 28 | for (var o in JSDOC.opt) { 29 | LOG.inform(" "+o+": "+JSDOC.opt[o]); 30 | } 31 | } 32 | 33 | // be verbose 34 | if (JSDOC.opt.v) LOG.verbose = true; 35 | 36 | // send log messages to a file 37 | if (JSDOC.opt.o) LOG.out = IO.open(JSDOC.opt.o); 38 | 39 | // run the unit tests 40 | if (JSDOC.opt.T) { 41 | LOG.inform("JsDoc Toolkit running in test mode at "+new Date()+"."); 42 | IO.include("frame/Testrun.js"); 43 | IO.include("test.js"); 44 | } 45 | else { 46 | // a template must be defined and must be a directory path 47 | if (!JSDOC.opt.t && System.getProperty("jsdoc.template.dir")) { 48 | JSDOC.opt.t = System.getProperty("jsdoc.template.dir"); 49 | } 50 | if (JSDOC.opt.t && SYS.slash != JSDOC.opt.t.slice(-1)) { 51 | JSDOC.opt.t += SYS.slash; 52 | } 53 | 54 | // verbose messages about the options we were given 55 | LOG.inform("JsDoc Toolkit main() running at "+new Date()+"."); 56 | LOG.inform("With options: "); 57 | for (var o in JSDOC.opt) { 58 | LOG.inform(" "+o+": "+JSDOC.opt[o]); 59 | } 60 | 61 | // initialize and build a symbolSet from your code 62 | JSDOC.JsDoc(); 63 | 64 | // debugger's option: dump the entire symbolSet produced from your code 65 | if (JSDOC.opt.Z) { 66 | LOG.warn("So you want to see the data structure, eh? This might hang if you have circular refs..."); 67 | IO.include("frame/Dumper.js"); 68 | var symbols = JSDOC.JsDoc.symbolSet.toArray(); 69 | for (var i = 0, l = symbols.length; i < l; i++) { 70 | var symbol = symbols[i]; 71 | print("// symbol: " + symbol.alias); 72 | print(symbol.serialize()); 73 | } 74 | } 75 | else { 76 | if (typeof JSDOC.opt.t != "undefined") { 77 | try { 78 | // a file named "publish.js" must exist in the template directory 79 | load(JSDOC.opt.t+"publish.js"); 80 | 81 | // and must define a function named "publish" 82 | if (!publish) { 83 | LOG.warn("No publish() function is defined in that template so nothing to do."); 84 | } 85 | else { 86 | // which will be called with the symbolSet produced from your code 87 | publish(JSDOC.JsDoc.symbolSet); 88 | } 89 | } 90 | catch(e) { 91 | LOG.warn("Sorry, that doesn't seem to be a valid template: "+JSDOC.opt.t+"publish.js : "+e); 92 | } 93 | } 94 | else { 95 | LOG.warn("No template given. Might as well read the usage notes."); 96 | JSDOC.usage(); 97 | } 98 | } 99 | } 100 | 101 | // notify of any warnings 102 | if (!JSDOC.opt.q && LOG.warnings.length) { 103 | print(LOG.warnings.length+" warning"+(LOG.warnings.length != 1? "s":"")+"."); 104 | } 105 | 106 | // stop sending log messages to a file 107 | if (LOG.out) { 108 | LOG.out.flush(); 109 | LOG.out.close(); 110 | } 111 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/plugins/commentSrcJson.js: -------------------------------------------------------------------------------- 1 | JSDOC.PluginManager.registerPlugin( 2 | "JSDOC.commentSrcJson", 3 | { 4 | onDocCommentSrc: function(comment) { 5 | var json; 6 | if (/^\s*@json\b/.test(comment)) { 7 | comment.src = new String(comment.src).replace("@json", ""); 8 | 9 | eval("json = "+comment.src); 10 | var tagged = ""; 11 | for (var i in json) { 12 | var tag = json[i]; 13 | // todo handle cases where tag is an object 14 | tagged += "@"+i+" "+tag+"\n"; 15 | } 16 | comment.src = tagged; 17 | } 18 | } 19 | } 20 | ); -------------------------------------------------------------------------------- /tools/jsdoc/app/plugins/frameworkPrototype.js: -------------------------------------------------------------------------------- 1 | JSDOC.PluginManager.registerPlugin( 2 | "JSDOC.frameworkPrototype", 3 | { 4 | onPrototypeClassCreate: function(classCreator) { 5 | var desc = ""; 6 | if (classCreator.comment) { 7 | desc = classCreator.comment; 8 | } 9 | var insert = desc+"/** @name "+classCreator.name+"\n@constructor\n@scope "+classCreator.name+".prototype */" 10 | 11 | insert = insert.replace(/\*\/\/\*\*/g, "\n"); 12 | /*DEBUG*///print("insert is "+insert); 13 | classCreator.addComment.data = insert; 14 | } 15 | } 16 | ); 17 | -------------------------------------------------------------------------------- /tools/jsdoc/app/plugins/functionCall.js: -------------------------------------------------------------------------------- 1 | JSDOC.PluginManager.registerPlugin( 2 | "JSDOC.functionCall", 3 | { 4 | onFunctionCall: function(functionCall) { 5 | if (functionCall.name == "dojo.define" && functionCall.arg1) { 6 | functionCall.doc = "/** @lends "+eval(functionCall.arg1)+".prototype */"; 7 | } 8 | } 9 | } 10 | ); -------------------------------------------------------------------------------- /tools/jsdoc/app/plugins/publishSrcHilite.js: -------------------------------------------------------------------------------- 1 | JSDOC.PluginManager.registerPlugin( 2 | "JSDOC.publishSrcHilite", 3 | { 4 | onPublishSrc: function(src) { 5 | if (src.path in JsHilite.cache) { 6 | return; // already generated src code 7 | } 8 | else JsHilite.cache[src.path] = true; 9 | 10 | try { 11 | var sourceCode = IO.readFile(src.path); 12 | } 13 | catch(e) { 14 | print(e.message); 15 | quit(); 16 | } 17 | 18 | var hiliter = new JsHilite(sourceCode, src.charset); 19 | src.hilited = hiliter.hilite(); 20 | } 21 | } 22 | ); 23 | 24 | function JsHilite(src, charset) { 25 | 26 | var tr = new JSDOC.TokenReader(); 27 | 28 | tr.keepComments = true; 29 | tr.keepDocs = true; 30 | tr.keepWhite = true; 31 | 32 | this.tokens = tr.tokenize(new JSDOC.TextStream(src)); 33 | 34 | // TODO is redefining toString() the best way? 35 | JSDOC.Token.prototype.toString = function() { 36 | return ""+this.data.replace(/"; 37 | } 38 | 39 | if (!charset) charset = "utf-8"; 40 | 41 | this.header = ' '+ 42 | "
";
50 | 	this.footer = "
"; 51 | this.showLinenumbers = true; 52 | } 53 | 54 | JsHilite.cache = {}; 55 | 56 | JsHilite.prototype.hilite = function() { 57 | var hilited = this.tokens.join(""); 58 | var line = 1; 59 | if (this.showLinenumbers) hilited = hilited.replace(/(^|\n)/g, function(m){return m+""+((line<10)? " ":"")+((line<100)? " ":"")+(line++)+" "}); 60 | 61 | return this.header+hilited+this.footer; 62 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/plugins/symbolLink.js: -------------------------------------------------------------------------------- 1 | JSDOC.PluginManager.registerPlugin( 2 | "JSDOC.symbolLink", 3 | { 4 | onSymbolLink: function(link) { 5 | // modify link.linkPath (the href part of the link) 6 | // or link.linkText (the text displayed) 7 | // or link.linkInner (the #name part of the link) 8 | } 9 | } 10 | ); -------------------------------------------------------------------------------- /tools/jsdoc/app/plugins/tagParamConfig.js: -------------------------------------------------------------------------------- 1 | JSDOC.PluginManager.registerPlugin( 2 | "JSDOC.tagParamConfig", 3 | { 4 | onDocCommentTags: function(comment) { 5 | var currentParam = null; 6 | var tags = comment.tags; 7 | for (var i = 0, l = tags.length; i < l; i++) { 8 | 9 | if (tags[i].title == "param") { 10 | if (tags[i].name.indexOf(".") == -1) { 11 | currentParam = i; 12 | } 13 | } 14 | else if (tags[i].title == "config") { 15 | tags[i].title = "param"; 16 | if (currentParam == null) { 17 | tags[i].name = "arguments"+"."+tags[i].name; 18 | } 19 | else if (tags[i].name.indexOf(tags[currentParam].name+".") != 0) { 20 | tags[i].name = tags[currentParam].name+"."+tags[i].name; 21 | } 22 | currentParam != null 23 | //tags[currentParam].properties.push(tags[i]); 24 | } 25 | else { 26 | currentParam = null; 27 | } 28 | } 29 | } 30 | } 31 | ); 32 | -------------------------------------------------------------------------------- /tools/jsdoc/app/plugins/tagSynonyms.js: -------------------------------------------------------------------------------- 1 | JSDOC.PluginManager.registerPlugin( 2 | "JSDOC.tagSynonyms", 3 | { 4 | onDocCommentSrc: function(comment) { 5 | comment.src = comment.src.replace(/@methodOf\b/i, "@function\n@memberOf"); 6 | comment.src = comment.src.replace(/@fieldOf\b/i, "@field\n@memberOf"); 7 | }, 8 | 9 | onDocCommentTags: function(comment) { 10 | for (var i = 0, l = comment.tags.length; i < l; i++) { 11 | var title = comment.tags[i].title.toLowerCase(); 12 | var syn; 13 | if ((syn = JSDOC.tagSynonyms.synonyms["="+title])) { 14 | comment.tags[i].title = syn; 15 | } 16 | } 17 | } 18 | } 19 | ); 20 | 21 | new Namespace( 22 | "JSDOC.tagSynonyms", 23 | function() { 24 | JSDOC.tagSynonyms.synonyms = { 25 | "=member": "memberOf", 26 | "=memberof": "memberOf", 27 | "=description": "desc", 28 | "=exception": "throws", 29 | "=argument": "param", 30 | "=returns": "return", 31 | "=classdescription": "class", 32 | "=fileoverview": "overview", 33 | "=extends": "augments", 34 | "=base": "augments", 35 | "=projectdescription": "overview", 36 | "=classdescription": "class", 37 | "=link": "see", 38 | "=borrows": "inherits", 39 | "=scope": "lends", 40 | "=construct": "constructor" 41 | } 42 | } 43 | ); -------------------------------------------------------------------------------- /tools/jsdoc/app/t/TestDoc.js: -------------------------------------------------------------------------------- 1 | var TestDoc = { 2 | fails: 0, 3 | plans: 0, 4 | passes: 0, 5 | results: [] 6 | }; 7 | 8 | TestDoc.record = function(result) { 9 | TestDoc.results.push(result); 10 | if (typeof result.verdict == "boolean") { 11 | if (result.verdict === false) TestDoc.fails++; 12 | if (result.verdict === true) TestDoc.passes++; 13 | } 14 | } 15 | 16 | TestDoc.prove = function(filePath) { 17 | if (typeof document != "undefined" && typeof document.write != "undefined") { 18 | if (TestDoc.console) print = function(s) { TestDoc.console.appendChild(document.createTextNode(s+"\n")); } 19 | else print = function(s) { document.write(s+"
"); } 20 | } 21 | TestDoc.run(TestDoc.readFile(filePath)); 22 | } 23 | 24 | TestDoc.run = function(src) { 25 | try { eval(src); } catch(e) { print("# ERROR! "+e); } 26 | 27 | var chunks = src.split(/\/\*t:/); 28 | 29 | var run = function(chunk) { 30 | // local shortcuts 31 | var is = TestDoc.assertEquals; 32 | var isnt = TestDoc.assertNotEquals; 33 | var plan = TestDoc.plan; 34 | var requires = TestDoc.requires; 35 | 36 | try { eval(chunk); } catch(e) { print("# ERROR! "+e); } 37 | } 38 | for (var start = -1, end = 0; (start = src.indexOf("/*t:", end)) > end; start = end) { 39 | run( 40 | src.substring( 41 | start+4, 42 | (end = src.indexOf("*/", start)) 43 | ) 44 | ); 45 | } 46 | } 47 | 48 | TestDoc.Result = function(verdict, message) { 49 | this.verdict = verdict; 50 | this.message = message; 51 | } 52 | 53 | TestDoc.Result.prototype.toString = function() { 54 | if (typeof this.verdict == "boolean") { 55 | return (this.verdict? "ok" : "not ok") + " " + (++TestDoc.report.counter) + " - " + this.message; 56 | } 57 | 58 | return "# " + this.message; 59 | } 60 | 61 | TestDoc.requires = function(file) { 62 | if (!TestDoc.requires.loaded[file]) { 63 | load(file); 64 | TestDoc.requires.loaded[file] = true; 65 | } 66 | } 67 | TestDoc.requires.loaded = {}; 68 | 69 | TestDoc.report = function() { 70 | TestDoc.report.counter = 0; 71 | print("1.."+TestDoc.plans); 72 | for (var i = 0; i < TestDoc.results.length; i++) { 73 | print(TestDoc.results[i]); 74 | } 75 | print("----------------------------------------"); 76 | if (TestDoc.fails == 0 && TestDoc.passes == TestDoc.plans) { 77 | print("All tests successful."); 78 | } 79 | else { 80 | print("Failed " + TestDoc.fails + "/" + TestDoc.plans + " tests, "+((TestDoc.plans == 0)? 0 : Math.round(TestDoc.passes/(TestDoc.passes+TestDoc.fails)*10000)/100)+"% okay. Planned to run "+TestDoc.plans+", did run "+(TestDoc.passes+TestDoc.fails)+".") 81 | } 82 | } 83 | 84 | TestDoc.plan = function(n, message) { 85 | TestDoc.plans += n; 86 | TestDoc.record(new TestDoc.Result(null, message+" ("+n+" tests)")); 87 | } 88 | 89 | TestDoc.assertEquals = function(a, b, message) { 90 | var result = (a == b); 91 | if (!result) message += "\n#\n# " + a + " does not equal " + b + "\n#"; 92 | TestDoc.record(new TestDoc.Result(result, message)); 93 | } 94 | 95 | TestDoc.assertNotEquals = function(a, b, message) { 96 | var result = (a != b); 97 | if (!result) message += "\n#\n# " + a + " equals " + b + "\n#"; 98 | TestDoc.record(new TestDoc.Result(result, message)); 99 | } 100 | 101 | TestDoc.readFile = (function(){ 102 | // rhino 103 | if (typeof readFile == "function") { 104 | return function(url) { 105 | var text = readFile(url); 106 | return text || ""; 107 | } 108 | } 109 | 110 | // a web browser 111 | else { 112 | return function(url) { 113 | var httpRequest; 114 | 115 | if (window.XMLHttpRequest) { // Mozilla, Safari, etc 116 | httpRequest = new XMLHttpRequest(); 117 | } 118 | else if (window.ActiveXObject) { // IE 119 | try { 120 | httpRequest = new ActiveXObject("Msxml2.XMLHTTP"); 121 | } 122 | catch (e) { 123 | try { 124 | httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); 125 | } 126 | catch (e) { 127 | } 128 | } 129 | } 130 | 131 | if (!httpRequest) { throw "Cannot create HTTP Request."; } 132 | 133 | httpRequest.open('GET', url, false); 134 | httpRequest.send(''); 135 | if (httpRequest.readyState == 4) { 136 | if (httpRequest.status >= 400) { 137 | throw "The HTTP Request returned an error code: "+httpRequest.status; 138 | } 139 | } 140 | 141 | return httpRequest.responseText || ""; 142 | } 143 | } 144 | })(); 145 | -------------------------------------------------------------------------------- /tools/jsdoc/app/t/runner.js: -------------------------------------------------------------------------------- 1 | // try: java -jar ../../jsrun.jar runner.js 2 | 3 | load("TestDoc.js"); 4 | 5 | TestDoc.prove("../frame/Opt.js"); 6 | TestDoc.prove("../lib/JSDOC.js"); 7 | TestDoc.prove("../frame/String.js"); 8 | TestDoc.prove("../lib/JSDOC/DocTag.js"); 9 | TestDoc.prove("../lib/JSDOC/DocComment.js"); 10 | TestDoc.prove("../lib/JSDOC/TokenReader.js"); 11 | TestDoc.prove("../lib/JSDOC/Symbol.js"); 12 | 13 | TestDoc.report(); 14 | -------------------------------------------------------------------------------- /tools/jsdoc/app/test/addon.js: -------------------------------------------------------------------------------- 1 | String.prototype.reverse = function() { 2 | } 3 | 4 | String.prototype.reverse.utf8 = function() { 5 | } 6 | 7 | Function.count = function() { 8 | } 9 | 10 | /** @memberOf Function */ 11 | Function.count.reset = function() { 12 | } 13 | 14 | /** @memberOf Function */ 15 | count.getValue = function() { 16 | } 17 | 18 | /** @memberOf Function.prototype */ 19 | getSig = function() { 20 | } 21 | 22 | /** @memberOf Function.prototype */ 23 | Function.prototype.getProps = function() { 24 | } 25 | -------------------------------------------------------------------------------- /tools/jsdoc/app/test/anon_inner.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @name bar 3 | * @namespace 4 | */ 5 | 6 | new function() { 7 | /** 8 | * @name bar-foo 9 | * @function 10 | * @param {number} x 11 | */ 12 | function foo(x) { 13 | } 14 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/test/augments.js: -------------------------------------------------------------------------------- 1 | /** 2 | @constructor 3 | */ 4 | function Layout(p) { 5 | this.init = function(p) { 6 | } 7 | 8 | this.getId = function() { 9 | } 10 | 11 | /** @type Page */ 12 | this.orientation = "landscape"; 13 | } 14 | 15 | /** 16 | @constructor 17 | @augments Layout 18 | */ 19 | function Page() { 20 | this.reset = function(b) { 21 | } 22 | } 23 | 24 | /** 25 | @extends Page 26 | @constructor 27 | */ 28 | function ThreeColumnPage() { 29 | this.init = function(resetCode) { 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tools/jsdoc/app/test/augments2.js: -------------------------------------------------------------------------------- 1 | /** 2 | @constructor 3 | */ 4 | function LibraryItem() { 5 | this.reserve = function() { 6 | } 7 | } 8 | 9 | /** 10 | @constructor 11 | */ 12 | function Junkmail() { 13 | this.annoy = function() { 14 | } 15 | } 16 | 17 | /** 18 | @inherits Junkmail.prototype.annoy as pester 19 | @augments ThreeColumnPage 20 | @augments LibraryItem 21 | @constructor 22 | */ 23 | function NewsletterPage() { 24 | this.getHeadline = function() { 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tools/jsdoc/app/test/borrows.js: -------------------------------------------------------------------------------- 1 | /** 2 | @constructor 3 | */ 4 | function Layout(p) { 5 | /** initilize 1 */ 6 | this.init = function(p) { 7 | } 8 | 9 | /** get the id */ 10 | this.getId = function() { 11 | } 12 | 13 | /** @type string */ 14 | this.orientation = "landscape"; 15 | 16 | function getInnerElements(elementSecretId){ 17 | } 18 | } 19 | 20 | /** A static method. */ 21 | Layout.units = function() { 22 | } 23 | 24 | /** 25 | @constructor 26 | @borrows Layout#orientation 27 | @borrows Layout-getInnerElements 28 | @borrows Layout.units 29 | */ 30 | function Page() { 31 | /** reset the page */ 32 | this.reset = function(b) { 33 | } 34 | } 35 | 36 | /** 37 | @constructor 38 | @borrows Layout.prototype.orientation as this.orientation 39 | @borrows Layout.prototype.init as #init 40 | @inherits Page.prototype.reset as #reset 41 | */ 42 | function ThreeColumnPage() { 43 | /** initilize 2 */ 44 | this.init = function(p) { 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /tools/jsdoc/app/test/borrows2.js: -------------------------------------------------------------------------------- 1 | // testing circular borrows 2 | 3 | /** 4 | @class 5 | @borrows Bar#zop as this.my_zop 6 | */ 7 | function Foo() { 8 | /** this is a zip. */ 9 | this.zip = function() {} 10 | 11 | this.my_zop = new Bar().zop; 12 | } 13 | 14 | /** 15 | @class 16 | @borrows Foo#zip as this.my_zip 17 | */ 18 | function Bar() { 19 | /** this is a zop. */ 20 | this.zop = function() {} 21 | 22 | this.my_zip = new Foo().zip; 23 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/test/config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @constructor 3 | * @param person The person. 4 | * @param {string} person.name The person's name. 5 | * @config {integer} age The person's age. 6 | * @config [id=1] Optional id number to use. 7 | * @param connection 8 | */ 9 | function Contact(person, connection) { 10 | 11 | } 12 | 13 | /** 14 | * @constructor 15 | * @param persons 16 | * @config {string} Father The paternal person. 17 | * @config {string} Mother The maternal person. 18 | * @config {string[]} Children And the rest. 19 | */ 20 | function Family(/**Object*/persons) { 21 | 22 | } 23 | -------------------------------------------------------------------------------- /tools/jsdoc/app/test/constructs.js: -------------------------------------------------------------------------------- 1 | var Person = makeClass( 2 | /** 3 | @scope Person 4 | */ 5 | { 6 | /** 7 | This is just another way to define a constructor. 8 | @constructs 9 | @param {string} name The name of the person. 10 | */ 11 | initialize: function(name) { 12 | this.name = name; 13 | }, 14 | say: function(message) { 15 | return this.name + " says: " + message; 16 | } 17 | } 18 | ); -------------------------------------------------------------------------------- /tools/jsdoc/app/test/encoding.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @Constructor 4 | * @desc 配置文件 5 | * @class 什么也不返回 6 | */ 7 | function Test(conf) { 8 | // do something; 9 | } 10 | 11 | -------------------------------------------------------------------------------- /tools/jsdoc/app/test/encoding_other.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demix/PyJs/a95071c2ef6a3117e85b122ea6e781f0a35d6c8c/tools/jsdoc/app/test/encoding_other.js -------------------------------------------------------------------------------- /tools/jsdoc/app/test/event.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @name Kitchen 3 | * @constructor 4 | * @fires Bakery#event:donutOrdered 5 | */ 6 | 7 | /** 8 | * Fired when some cake is eaten. 9 | * @name Kitchen#event:cakeEaten 10 | * @function 11 | * @param {Number} pieces The number of pieces eaten. 12 | */ 13 | 14 | /** 15 | * Find out if cake was eaten. 16 | * @name Kitchen#cakeEaten 17 | * @function 18 | * @param {Boolean} wasEaten 19 | */ 20 | 21 | /** 22 | * @name getDesert 23 | * @function 24 | * @fires Kitchen#event:cakeEaten 25 | */ 26 | 27 | /** 28 | * @name Bakery 29 | * @constructor 30 | * @extends Kitchen 31 | */ 32 | 33 | /** 34 | * Fired when a donut order is made. 35 | * @name Bakery#event:donutOrdered 36 | * @event 37 | * @param {Event} e The event object. 38 | * @param {String} [e.topping] Optional sprinkles. 39 | */ 40 | 41 | /** 42 | * @constructor 43 | * @borrows Bakery#event:donutOrdered as this.event:cakeOrdered 44 | */ 45 | function CakeShop() { 46 | } 47 | 48 | /** @event */ 49 | CakeShop.prototype.icingReady = function(isPink) { 50 | } 51 | 52 | /** @event */ 53 | function amHungry(/**Boolean*/enoughToEatAHorse) { 54 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/test/exports.js: -------------------------------------------------------------------------------- 1 | /** @namespace */ 2 | var mxn = {}; 3 | 4 | (function(){ 5 | /** @exports Map as mxn.Map */ 6 | var Map = 7 | /** @constructor */ 8 | mxn.Map = function() { 9 | }; 10 | 11 | /** A method. */ 12 | Map.prototype.doThings = function() { 13 | }; 14 | })(); -------------------------------------------------------------------------------- /tools/jsdoc/app/test/functions_anon.js: -------------------------------------------------------------------------------- 1 | /** an anonymous constructor executed inline */ 2 | a = new function() { 3 | /** a.b*/ 4 | this.b = 1; 5 | /** a.f */ 6 | this.f = function() { 7 | /** a.c */ 8 | this.c = 2; 9 | } 10 | } 11 | 12 | 13 | /** 14 | named function executed inline 15 | */ 16 | bar1 = function Zoola1() { 17 | /** property of global */ 18 | this.g = 1; 19 | }(); 20 | 21 | /** 22 | named constructor executed inline 23 | */ 24 | bar2 = new function Zoola2() { 25 | /** property of bar */ 26 | this.p = 1; 27 | }; 28 | 29 | /** module pattern */ 30 | module = (function () { 31 | /** won't appear in documentation */ 32 | var priv = 1; 33 | 34 | /** @scope module */ 35 | return { 36 | /** will appear as a property of module */ 37 | pub: 1 38 | } 39 | })(); 40 | -------------------------------------------------------------------------------- /tools/jsdoc/app/test/functions_nested.js: -------------------------------------------------------------------------------- 1 | /** @constructor */ 2 | function Zop() { 3 | } 4 | 5 | /** 6 | @class 7 | */ 8 | Foo = function(id) { 9 | // this is a bit twisted, but if you call Foo() you will then 10 | // modify Foo(). This is kinda, sorta non-insane, because you 11 | // would have to call Foo() 100% of the time to use Foo's methods 12 | Foo.prototype.methodOne = function(bar) { 13 | alert(bar); 14 | }; 15 | 16 | // same again 17 | Foo.prototype.methodTwo = function(bar2) { 18 | alert(bar2); 19 | }; 20 | 21 | // and these are only executed if the enclosing function is actually called 22 | // and who knows if that will ever happen? 23 | Bar = function(pez) { 24 | alert(pez); 25 | }; 26 | Zop.prototype.zap = function(p){ 27 | alert(p); 28 | }; 29 | 30 | // but this is only visible inside Foo 31 | function inner() { 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /tools/jsdoc/app/test/global.js: -------------------------------------------------------------------------------- 1 | /** ecks */ 2 | var x = [1, 2, 4]; 3 | 4 | var y = { 5 | foo: function(){ 6 | } 7 | } 8 | 9 | bar = function() { 10 | } 11 | 12 | function zop() { 13 | } 14 | -------------------------------------------------------------------------------- /tools/jsdoc/app/test/globals.js: -------------------------------------------------------------------------------- 1 | function example(/**Circle*/a, b) { 2 | /** a global defined in function */ 3 | var number = a; 4 | 5 | var hideNumber = function(){ 6 | } 7 | 8 | setNumber = function(){ 9 | } 10 | alert('You have chosen: ' + b); 11 | } 12 | 13 | function initPage() { 14 | var supported = document.createElement && document.getElementsByTagName; 15 | if (!supported) return; 16 | // start of DOM script 17 | var x = document.getElementById('writeroot'); 18 | // etc. 19 | } 20 | 21 | /** an example var */ 22 | var document = new Document(x, y); 23 | 24 | var getNumber = function(){ 25 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/test/ignore.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A test constructor. 3 | * @constructor 4 | * @ignore 5 | */ 6 | function Ignored() { 7 | /** a method */ 8 | this.bar = function() { 9 | } 10 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/test/inner.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @constructor 3 | */ 4 | function Outer() { 5 | /** 6 | * @constructor 7 | */ 8 | function Inner(name) { 9 | /** The name of this. */ 10 | this.name = name; 11 | } 12 | 13 | this.open = function(name) { 14 | return (new Inner(name)); 15 | } 16 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/test/lend.js: -------------------------------------------------------------------------------- 1 | /** @class */ 2 | var Person = Class.create( 3 | /** 4 | @lends Person.prototype 5 | */ 6 | { 7 | initialize: function(name) { 8 | this.name = name; 9 | }, 10 | say: function(message) { 11 | return this.name + ': ' + message; 12 | } 13 | } 14 | ); 15 | 16 | /** @lends Person.prototype */ 17 | { 18 | /** like say but more musical */ 19 | sing: function(song) { 20 | } 21 | } 22 | 23 | /** @lends Person */ 24 | { 25 | getCount: function() { 26 | } 27 | } 28 | 29 | /** @lends Unknown.prototype */ 30 | { 31 | notok: function() { 32 | } 33 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/test/memberof.js: -------------------------------------------------------------------------------- 1 | /** @constructor */ 2 | pack = function() { 3 | this.init = function(){} 4 | function config(){} 5 | } 6 | 7 | pack.build = function(task) {}; 8 | 9 | /** @memberOf pack */ 10 | pack.install = function() {} 11 | 12 | /** @memberOf pack */ 13 | pack.install.overwrite = function() {} 14 | 15 | /** @memberOf pack */ 16 | clean = function() {} 17 | 18 | /** @memberOf pack-config */ 19 | install = function() {}; 20 | -------------------------------------------------------------------------------- /tools/jsdoc/app/test/memberof2.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @constructor 3 | */ 4 | function Foo() { 5 | /** 6 | @memberOf Foo.prototype 7 | */ 8 | function bar(a, b) { 9 | } 10 | 11 | /** 12 | @memberOf Foo 13 | */ 14 | var zip = function(p, q) { 15 | } 16 | 17 | /** 18 | @memberOf Foo 19 | */ 20 | function zop( x,y ) { 21 | } 22 | 23 | /** 24 | @memberOf Foo 25 | @constructor 26 | */ 27 | function Fiz() { 28 | /** A method of Foo#Fiz. */ 29 | this.fipple = function(fop){} 30 | } 31 | } 32 | 33 | /** 34 | @memberOf Foo# 35 | */ 36 | var blat = function() { 37 | 38 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/test/memberof3.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @name Foo 3 | * @class 4 | */ 5 | 6 | /**#@+ 7 | * @memberOf Foo# 8 | * @field 9 | */ 10 | 11 | /** 12 | * @name bar 13 | * @type Object[] 14 | */ 15 | 16 | /**#@-*/ 17 | 18 | /** 19 | * @name Foo2 20 | * @class 21 | */ 22 | 23 | /**#@+ 24 | * @memberOf Foo2# 25 | * @field 26 | */ 27 | 28 | /** 29 | * @name bar 30 | * @type Object[] 31 | */ 32 | 33 | /**#@-*/ -------------------------------------------------------------------------------- /tools/jsdoc/app/test/memberof_constructor.js: -------------------------------------------------------------------------------- 1 | /** @constructor */ 2 | function Circle(){} 3 | 4 | /** 5 | @constructor 6 | @memberOf Circle# 7 | */ 8 | Circle.prototype.Tangent = function(){}; 9 | 10 | // renaming Circle#Tangent to Circle#Circle#Tangent 11 | 12 | /** 13 | @memberOf Circle#Tangent# 14 | */ 15 | Circle.prototype.Tangent.prototype.getDiameter = function(){}; 16 | 17 | 18 | -------------------------------------------------------------------------------- /tools/jsdoc/app/test/module.js: -------------------------------------------------------------------------------- 1 | /** @namespace */ 2 | myProject = myProject || {}; 3 | 4 | /** @namespace */ 5 | myProject.myModule = (function () { 6 | /** describe myPrivateVar here */ 7 | var myPrivateVar = ""; 8 | 9 | var myPrivateMethod = function () { 10 | } 11 | 12 | /** @scope myProject.myModule */ 13 | return { 14 | myPublicMethod: function () { 15 | } 16 | }; 17 | })(); -------------------------------------------------------------------------------- /tools/jsdoc/app/test/multi_methods.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | Get the entire flavor. 4 | @name flavor^3 5 | @function 6 | @returns {Object} The entire flavor hash. 7 | */ 8 | /** 9 | Get a named flavor. 10 | @name flavor^2 11 | @function 12 | @param {String} name The name of the flavor to get. 13 | @returns {String} The value of that flavor. 14 | */ 15 | /** 16 | Set the flavor. 17 | @param {String} name The name of the flavor to set. 18 | @param {String} value The value of the flavor. 19 | @returns {String} The value of that flavor. 20 | */ 21 | function flavor(name, value) { 22 | if (arguments.length > 1) flavor[name] = value; 23 | else if (arguments.length == 1) return flavor[name]; 24 | else return flavor; 25 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/test/name.js: -------------------------------------------------------------------------------- 1 | /** 2 | @name Response 3 | @class 4 | */ 5 | 6 | Response.prototype = { 7 | /** 8 | @name Response#text 9 | @function 10 | @description 11 | Gets the body of the response as plain text 12 | @returns {String} 13 | Response as text 14 | */ 15 | 16 | text: function() { 17 | return this.nativeResponse.responseText; 18 | } 19 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/test/namespace_nested.js: -------------------------------------------------------------------------------- 1 | /** 2 | @namespace This is the first namespace. 3 | */ 4 | ns1 = {}; 5 | 6 | /** 7 | This is the second namespace. 8 | @namespace 9 | */ 10 | ns1.ns2 = {}; 11 | 12 | /** 13 | This part of ns1.ns2 14 | @constructor 15 | */ 16 | ns1.ns2.Function1 = function() { 17 | }; 18 | 19 | ns1.staticFunction = function() { 20 | }; 21 | 22 | /** A static field in a namespace. */ 23 | ns1.ns2.staticField = 1; 24 | -------------------------------------------------------------------------------- /tools/jsdoc/app/test/nocode.js: -------------------------------------------------------------------------------- 1 | /**#nocode+*/ 2 | /** 3 | @name star 4 | @function 5 | */ 6 | function blahblah() { 7 | 8 | } 9 | /**#nocode-*/ 10 | 11 | function yaddayadda() { 12 | 13 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/test/oblit_anon.js: -------------------------------------------------------------------------------- 1 | /** the options */ 2 | opt = Opt.get( 3 | arguments, 4 | { 5 | d: "directory", 6 | c: "conf", 7 | "D[]": "define" 8 | } 9 | ); 10 | 11 | /** configuration */ 12 | opt.conf = { 13 | /** keep */ 14 | keep: true, 15 | /** base */ 16 | base: getBase(this, {p: properties}) 17 | } 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /tools/jsdoc/app/test/overview.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @overview This "library" contains a 3 | * lot of classes and functions. 4 | * @example 5 |
 6 | 	var x (x < 1);
 7 | 	alert("This 'is' \"code\"");
 8 |  
9 | * @name My Cool Library 10 | * @author Joe Smith jsmith@company.com 11 | * @version 0.1 12 | */ 13 | 14 | /** 15 | * Gets the current foo 16 | * @param {String} fooId The unique identifier for the foo. 17 | * @return {Object} Returns the current foo. 18 | */ 19 | function getFoo(fooID){ 20 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/test/param_inline.js: -------------------------------------------------------------------------------- 1 | /** 2 | @constructor 3 | @param columns The number of columns. 4 | */ 5 | function Layout(/**int*/columns){ 6 | /** 7 | @param [id] The id of the element. 8 | @param elName The name of the element. 9 | */ 10 | this.getElement = function( 11 | /** string */ elName, 12 | /** number|string */ id 13 | ) { 14 | }; 15 | 16 | /** 17 | @constructor 18 | */ 19 | this.Canvas = function(top, left, /**int*/width, height) { 20 | /** Is it initiated yet? */ 21 | this.initiated = true; 22 | } 23 | 24 | this.rotate = function(/**nothing*/) { 25 | } 26 | 27 | /** 28 | @param x 29 | @param y 30 | @param {zoppler} z*/ 31 | this.init = function(x, y, /**abbler*/z) { 32 | /** The xyz. */ 33 | this.xyz = x+y+z; 34 | this.getXyz = function() { 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tools/jsdoc/app/test/params_optional.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @param {Page[]} pages 4 | * @param {number} [id] Specifies the id, if applicable. 5 | * @param {String} [title = This is untitled.] Specifies the title. 6 | */ 7 | function Document(pages, id, title){ 8 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/test/prototype.js: -------------------------------------------------------------------------------- 1 | /** @constructor */ 2 | function Article() { 3 | } 4 | 5 | Article.prototype.init = function(title) { 6 | /** the instance title */ 7 | this.title = title; 8 | 9 | /** the static counter */ 10 | Article.counter = 1; 11 | } 12 | 13 | a = new Article(); 14 | a.Init("my title"); 15 | 16 | print(a.title); 17 | print(Article.counter); -------------------------------------------------------------------------------- /tools/jsdoc/app/test/prototype_nested.js: -------------------------------------------------------------------------------- 1 | /** @constructor */ 2 | function Word() { 3 | } 4 | 5 | Word.prototype.reverse = function() { 6 | } 7 | 8 | Word.prototype.reverse.utf8 = function() { 9 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/test/prototype_oblit.js: -------------------------------------------------------------------------------- 1 | /** @constructor */ 2 | function Article() { 3 | } 4 | 5 | Article.prototype = { 6 | /** instance get title */ 7 | getTitle: function(){ 8 | } 9 | } 10 | 11 | /** static get title */ 12 | Article.getTitle = function(){ 13 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/test/prototype_oblit_constructor.js: -------------------------------------------------------------------------------- 1 | /** @constructor */ 2 | function Article() { 3 | } 4 | 5 | Article.prototype = { 6 | /** @constructor */ 7 | Title: function(title) { 8 | /** the value of the Title instance */ 9 | this.title = title; 10 | }, 11 | 12 | init: function(pages) { 13 | /** the value of the pages of the Article instance */ 14 | this.pages = pages; 15 | } 16 | } 17 | 18 | f = new Article(); 19 | f.init("one two three"); 20 | 21 | t = new f.Title("my title"); 22 | 23 | print(f.pages); 24 | print(t.title); -------------------------------------------------------------------------------- /tools/jsdoc/app/test/public.js: -------------------------------------------------------------------------------- 1 | /**@constructor*/ 2 | function Foo() { 3 | /** 4 | @public 5 | @static 6 | @field 7 | */ 8 | var bar = function(x) { 9 | } 10 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/test/scripts/code.js: -------------------------------------------------------------------------------- 1 | /** 2 | @class 3 | */ 4 | function thisiscode() { 5 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/test/scripts/notcode.txt: -------------------------------------------------------------------------------- 1 | (This is not code) 2 | function foo(){{{{ 3 | ( 4 | ! 5 | @ -------------------------------------------------------------------------------- /tools/jsdoc/app/test/shared.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Builtin object. 4 | * @class 5 | * @name Array 6 | */ 7 | 8 | /**#@+ 9 | * Extension to builtin array. 10 | * @memberOf Array 11 | * @method 12 | */ 13 | 14 | /** 15 | * @returns Boolen if some array members... 16 | */ 17 | Array.prototype.some = function(){}; 18 | 19 | /** 20 | * Change every element of an array. 21 | * @returns Filtered array copy. 22 | */ 23 | Array.prototype.filter = function(){}; 24 | 25 | /**#@-*/ 26 | 27 | 28 | /** 29 | * A first in, first out data structure. 30 | * @constructor 31 | */ 32 | Queue = function(){}; 33 | 34 | /**#@+ 35 | * Extension to Queue. 36 | * @memberOf Queue 37 | */ 38 | 39 | rewind = function(){ 40 | } 41 | 42 | // should close automatically here. -------------------------------------------------------------------------------- /tools/jsdoc/app/test/shared2.js: -------------------------------------------------------------------------------- 1 | startOver = function(){ 2 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/test/shortcuts.js: -------------------------------------------------------------------------------- 1 | // /**#=+ 2 | // * { 3 | // * 'D': 'Date.prototype', 4 | // * '$N': 'Number' 5 | // * } 6 | // */ 7 | // var D = Date.prototype, 8 | // $N = Number; 9 | // 10 | // D.locale = function(){ 11 | // }; 12 | // 13 | // /** 14 | // @return {string} The cardinal number string. 15 | // */ 16 | // $N.nth = function(n){ 17 | // }; 18 | // 19 | // LOAD.file = function(){ 20 | // } 21 | // 22 | // /**#=-*/ -------------------------------------------------------------------------------- /tools/jsdoc/app/test/static_this.js: -------------------------------------------------------------------------------- 1 | /** the parent */ 2 | var box = {}; 3 | 4 | /** @namespace */ 5 | box.holder = {} 6 | 7 | box.holder.foo = function() { 8 | /** the counter */ 9 | this.counter = 1; 10 | } 11 | 12 | box.holder.foo(); 13 | print(box.holder.counter); 14 | -------------------------------------------------------------------------------- /tools/jsdoc/app/test/synonyms.js: -------------------------------------------------------------------------------- 1 | /** 2 | @class 3 | @inherits Bar#zop as #my_zop 4 | */ 5 | function Foo() { 6 | /** this is a zip. */ 7 | this.zip = function() {} 8 | 9 | /** from Bar */ 10 | this.my_zop = new Bar().zop; 11 | } 12 | 13 | /** 14 | @class 15 | @borrows Foo#zip as this.my_zip 16 | */ 17 | function Bar() { 18 | /** this is a zop. */ 19 | this.zop = function() {} 20 | 21 | /** from Foo */ 22 | this.my_zip = new Foo().zip; 23 | } 24 | 25 | /** @namespace */ 26 | var myObject = { 27 | /** 28 | @type function 29 | */ 30 | myFunc: getFunction() 31 | } -------------------------------------------------------------------------------- /tools/jsdoc/app/test/tosource.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {Object} object 3 | * @return {string} 4 | */ 5 | function valueOf(object) {} 6 | 7 | /** 8 | * @param {Object} object 9 | * @return {string} 10 | */ 11 | function toString(object) {} 12 | 13 | /** 14 | * @param {Object} object 15 | * @return {string} 16 | */ 17 | function toSource(object) {} 18 | 19 | /** 20 | * @param {Object} object 21 | * @return {string} 22 | */ 23 | function constructor(object) {} -------------------------------------------------------------------------------- /tools/jsdoc/app/test/variable_redefine.js: -------------------------------------------------------------------------------- 1 | /** @constructor */ 2 | function Foo() { 3 | var bar = 1; 4 | bar = 2; // redefining a private 5 | 6 | this.baz = 1; 7 | baz = 2; // global 8 | 9 | /** a private */ 10 | var blap = { 11 | /** in here */ 12 | tada: 1 13 | } 14 | } -------------------------------------------------------------------------------- /tools/jsdoc/conf/sample.conf: -------------------------------------------------------------------------------- 1 | /* 2 | This is an example of one way you could set up a configuration file to more 3 | conveniently define some commandline options. You might like to do this if 4 | you frequently reuse the same options. Note that you don't need to define 5 | every option in this file, you can combine a configuration file with 6 | additional options on the commandline if your wish. 7 | 8 | You would include this configuration file by running JsDoc Toolkit like so: 9 | java -jar jsrun.jar app/run.js -c=conf/sample.conf 10 | 11 | */ 12 | 13 | { 14 | // source files to use 15 | _: ['app/test/jsdoc_test.js'], 16 | 17 | // document all functions, even uncommented ones 18 | a: true, 19 | 20 | // including those marked @private 21 | p: true, 22 | 23 | // some extra variables I want to include 24 | D: {generatedBy: "Michael Mathews", copyright: "2008"}, 25 | 26 | // use this directory as the output directory 27 | d: "docs", 28 | 29 | // use this template 30 | t: "templates/jsdoc" 31 | } -------------------------------------------------------------------------------- /tools/jsdoc/java/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /tools/jsdoc/java/build_1.4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /tools/jsdoc/java/classes/js.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demix/PyJs/a95071c2ef6a3117e85b122ea6e781f0a35d6c8c/tools/jsdoc/java/classes/js.jar -------------------------------------------------------------------------------- /tools/jsdoc/java/src/JsDebugRun.java: -------------------------------------------------------------------------------- 1 | /** 2 | * A trivial bootstrap class that simply adds the path to the 3 | * .js file as an argument to the Rhino call. This little hack 4 | * allows the code in the .js file to have access to it's own 5 | * path via the Rhino arguments object. This is necessary to 6 | * allow the .js code to find resource files in a location 7 | * relative to itself. 8 | * 9 | * USAGE: java -jar jsdebug.jar path/to/file.js 10 | */ 11 | public class JsDebugRun { 12 | public static void main(String[] args) { 13 | String[] jsargs = {"-j="+args[0]}; 14 | 15 | String[] allArgs = new String[jsargs.length + args.length]; 16 | System.arraycopy(args, 0, allArgs, 0, args.length); 17 | System.arraycopy(jsargs, 0, allArgs, args.length ,jsargs.length); 18 | 19 | org.mozilla.javascript.tools.debugger.Main.main(allArgs); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tools/jsdoc/java/src/JsRun.java: -------------------------------------------------------------------------------- 1 | /** 2 | * A trivial bootstrap class that simply adds the path to the 3 | * .js file as an argument to the Rhino call. This little hack 4 | * allows the code in the .js file to have access to it's own 5 | * path via the Rhino arguments object. This is necessary to 6 | * allow the .js code to find resource files in a location 7 | * relative to itself. 8 | * 9 | * USAGE: java -jar jsrun.jar path/to/file.js 10 | */ 11 | public class JsRun { 12 | public static void main(String[] args) { 13 | String[] jsargs = {"-j="+args[0]}; 14 | 15 | String[] allArgs = new String[jsargs.length + args.length]; 16 | System.arraycopy(args, 0, allArgs, 0, args.length); 17 | System.arraycopy(jsargs, 0, allArgs, args.length ,jsargs.length); 18 | 19 | org.mozilla.javascript.tools.shell.Main.main(allArgs); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tools/jsdoc/jsdebug.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demix/PyJs/a95071c2ef6a3117e85b122ea6e781f0a35d6c8c/tools/jsdoc/jsdebug.jar -------------------------------------------------------------------------------- /tools/jsdoc/jsrun.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/demix/PyJs/a95071c2ef6a3117e85b122ea6e781f0a35d6c8c/tools/jsdoc/jsrun.jar -------------------------------------------------------------------------------- /tools/jsdoc/jsrun.sh: -------------------------------------------------------------------------------- 1 | #!/bin/ksh 2 | 3 | # launcher script for jsdoc 4 | # Author: Avi Deitcher 5 | # 6 | # This program is released under the MIT License as follows: 7 | 8 | # Copyright (c) 2008-2009 Atomic Inc 9 | # 10 | #Permission is hereby granted, free of charge, to any person 11 | #obtaining a copy of this software and associated documentation 12 | #files (the "Software"), to deal in the Software without 13 | #restriction, including without limitation the rights to use, 14 | #copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | #copies of the Software, and to permit persons to whom the 16 | #Software is furnished to do so, subject to the following 17 | #conditions: 18 | ## 19 | #The above copyright notice and this permission notice shall be 20 | #included in all copies or substantial portions of the Software. 21 | # 22 | #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 | #EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 24 | #OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 25 | #NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 26 | #HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 27 | #WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 28 | #FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 29 | #OTHER DEALINGS IN THE SOFTWARE. 30 | # 31 | 32 | 33 | if [[ -n "$JSDOCDIR" ]]; then 34 | _DOCDIR="-Djsdoc.dir=$JSDOCDIR" 35 | _APPDIR="$JSDOCDIR/app" 36 | _BASEDIR="$JSDOCDIR" 37 | else 38 | _DOCDIR="" 39 | _APPDIR="./app" 40 | _BASEDIR="." 41 | fi 42 | 43 | if [[ -n "$JSDOCTEMPLATEDIR" ]]; then 44 | _TDIR="-Djsdoc.template.dir=$JSDOCTEMPLATEDIR" 45 | else 46 | _TDIR="" 47 | fi 48 | 49 | CMD="java $_DOCDIR $_TDIR -jar $_BASEDIR/jsrun.jar $_APPDIR/run.js $@" 50 | echo $CMD 51 | $CMD 52 | 53 | -------------------------------------------------------------------------------- /tools/jsdoc/templates/jsdoc/allclasses.tmpl: -------------------------------------------------------------------------------- 1 |
{+new Link().toFile("index.html").withText("Class Index")+} 2 | | {+new Link().toFile("files.html").withText("File Index")+}
3 |
4 |

Classes

5 |
    6 | 7 |
  • {! 8 | if (thisClass.alias == "_global_") { 9 | output += ""+new Link().toClass(thisClass.alias)+""; 10 | } 11 | else { 12 | output += new Link().toClass(thisClass.alias); 13 | } 14 | !}
  • 15 |
    16 |
17 |
-------------------------------------------------------------------------------- /tools/jsdoc/templates/jsdoc/allfiles.tmpl: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | {! Link.base = ""; /* all generated links will be relative to this */ !} 7 | JsDoc Reference - File Index 8 | 9 | 10 | 13 | 14 | 15 | 16 | {+include("static/header.html")+} 17 | 18 |
19 | {+publish.classesIndex+} 20 |
21 | 22 |
23 |

File Index

24 | 25 | 26 |
27 |

{+new Link().toSrc(item.alias).withText(item.name)+}

28 | {+resolveLinks(item.desc)+} 29 |
30 | 31 |
Author:
32 |
{+item.author+}
33 |
34 | 35 |
Version:
36 |
{+item.version+}
37 |
38 | {! var locations = item.comment.getTag('location').map(function($){return $.toString().replace(/(^\$ ?| ?\$$)/g, '').replace(/^HeadURL: https:/g, 'http:');}) !} 39 | 40 |
Location:
41 | 42 |
{+location+}
43 |
44 |
45 |
46 |
47 |
48 |
49 | 50 |
51 |
52 | ©{+JSDOC.opt.D.copyright+}
53 | Documentation generated by JsDoc Toolkit {+JSDOC.VERSION+} on {+new Date()+} 54 |
55 | 56 | -------------------------------------------------------------------------------- /tools/jsdoc/templates/jsdoc/index.tmpl: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | JsDoc Reference - Index 8 | 9 | 10 | 13 | 14 | 15 | 16 | {+include("static/header.html")+} 17 | 18 |
19 | {+publish.classesIndex+} 20 |
21 | 22 |
23 |

Class Index

24 | 25 | 26 |
27 |

{+(new Link().toSymbol(thisClass.alias))+}

28 | {+resolveLinks(summarize(thisClass.classDesc))+} 29 |
30 |
31 |
32 | 33 |
34 |
35 | ©{+JSDOC.opt.D.copyright+}
36 | Documentation generated by JsDoc Toolkit {+JSDOC.VERSION+} on {+new Date()+} 37 |
38 | 39 | -------------------------------------------------------------------------------- /tools/jsdoc/templates/jsdoc/static/default.css: -------------------------------------------------------------------------------- 1 | /* default.css */ 2 | body 3 | { 4 | font: 12px "Lucida Grande", Tahoma, Arial, Helvetica, sans-serif; 5 | width: 800px; 6 | } 7 | 8 | .header 9 | { 10 | clear: both; 11 | background-color: #ccc; 12 | padding: 8px; 13 | } 14 | 15 | h1 16 | { 17 | font-size: 150%; 18 | font-weight: bold; 19 | padding: 0; 20 | margin: 1em 0 0 .3em; 21 | } 22 | 23 | hr 24 | { 25 | border: none 0; 26 | border-top: 1px solid #7F8FB1; 27 | height: 1px; 28 | } 29 | 30 | pre.code 31 | { 32 | display: block; 33 | padding: 8px; 34 | border: 1px dashed #ccc; 35 | } 36 | 37 | #index 38 | { 39 | margin-top: 24px; 40 | float: left; 41 | width: 160px; 42 | position: absolute; 43 | left: 8px; 44 | background-color: #F3F3F3; 45 | padding: 8px; 46 | } 47 | 48 | #content 49 | { 50 | margin-left: 190px; 51 | width: 600px; 52 | } 53 | 54 | .classList 55 | { 56 | list-style-type: none; 57 | padding: 0; 58 | margin: 0 0 0 8px; 59 | font-family: arial, sans-serif; 60 | font-size: 1em; 61 | overflow: auto; 62 | } 63 | 64 | .classList li 65 | { 66 | padding: 0; 67 | margin: 0 0 8px 0; 68 | } 69 | 70 | .summaryTable { width: 100%; } 71 | 72 | h1.classTitle 73 | { 74 | font-size:170%; 75 | line-height:130%; 76 | } 77 | 78 | h2 { font-size: 110%; } 79 | caption, div.sectionTitle 80 | { 81 | background-color: #7F8FB1; 82 | color: #fff; 83 | font-size:130%; 84 | text-align: left; 85 | padding: 2px 6px 2px 6px; 86 | border: 1px #7F8FB1 solid; 87 | } 88 | 89 | div.sectionTitle { margin-bottom: 8px; } 90 | .summaryTable thead { display: none; } 91 | 92 | .summaryTable td 93 | { 94 | vertical-align: top; 95 | padding: 4px; 96 | border-bottom: 1px #7F8FB1 solid; 97 | border-right: 1px #7F8FB1 solid; 98 | } 99 | 100 | /*col#summaryAttributes {}*/ 101 | .summaryTable td.attributes 102 | { 103 | border-left: 1px #7F8FB1 solid; 104 | width: 140px; 105 | text-align: right; 106 | } 107 | 108 | td.attributes, .fixedFont 109 | { 110 | line-height: 15px; 111 | color: #002EBE; 112 | font-family: "Courier New",Courier,monospace; 113 | font-size: 13px; 114 | } 115 | 116 | .summaryTable td.nameDescription 117 | { 118 | text-align: left; 119 | font-size: 13px; 120 | line-height: 15px; 121 | } 122 | 123 | .summaryTable td.nameDescription, .description 124 | { 125 | line-height: 15px; 126 | padding: 4px; 127 | padding-left: 4px; 128 | } 129 | 130 | .summaryTable { margin-bottom: 8px; } 131 | 132 | ul.inheritsList 133 | { 134 | list-style: square; 135 | margin-left: 20px; 136 | padding-left: 0; 137 | } 138 | 139 | .detailList { 140 | margin-left: 20px; 141 | line-height: 15px; 142 | } 143 | .detailList dt { margin-left: 20px; } 144 | 145 | .detailList .heading 146 | { 147 | font-weight: bold; 148 | padding-bottom: 6px; 149 | margin-left: 0; 150 | } 151 | 152 | .light, td.attributes, .light a:link, .light a:visited 153 | { 154 | color: #777; 155 | font-style: italic; 156 | } 157 | 158 | .fineprint 159 | { 160 | text-align: right; 161 | font-size: 10px; 162 | } -------------------------------------------------------------------------------- /tools/jsdoc/templates/jsdoc/static/header.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/jsdoc/templates/jsdoc/static/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Generated Javascript Documentation 7 | 8 | 9 | 10 | 11 | 12 | <body> 13 | <p> 14 | This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. 15 | </p> 16 | </body> 17 | 18 | 19 | -------------------------------------------------------------------------------- /tools/jsdoc/templates/jsdoc/symbol.tmpl: -------------------------------------------------------------------------------- 1 | 2 | {+data.name+} 3 | {+data.memberOf+} 4 | {+data.isStatic+} 5 | {+data.isa+} 6 | {+data.desc+} 7 | {+data.classDesc+} 8 | 9 | 10 | 11 | {+method.name+} 12 | {+method.memberOf+} 13 | {+method.isStatic+} 14 | {+method.desc+} 15 | 16 | 17 | {+param.type+} 18 | {+param.name+} 19 | {+param.desc+} 20 | {+param.defaultValue+} 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | {+property.name+} 29 | {+property.memberOf+} 30 | {+property.isStatic+} 31 | {+property.desc+} 32 | {+property.type+} 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /utest/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Baidu Connect SDK Unit Test 6 | 7 | 8 | 9 | 10 | 11 | 12 |

QUnit example

13 |

14 |
15 |

16 |
    17 |
    test markup, will be hidden
    18 | 19 | 20 |
    21 | 22 |
    23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /utest/js/pyjs.js: -------------------------------------------------------------------------------- 1 | module('pyjs'); 2 | 3 | 4 | test('get dependency' , function(){ 5 | addDependence('main' , ''); 6 | addDependence('core' , ''); 7 | addDependence('string' , 'main,core'); 8 | addDependence('do' , 'main'); 9 | addDependence('final' , 'do,string'); 10 | var rs = ['core' , 'main' , 'do', 'string' , 'final']; 11 | 12 | deepEqual( getDependence('final') , rs , 'getDependence works right.'); 13 | }); 14 | 15 | -------------------------------------------------------------------------------- /utest/qunit.css: -------------------------------------------------------------------------------- 1 | /** 2 | * QUnit - A JavaScript Unit Testing Framework 3 | * 4 | * http://docs.jquery.com/QUnit 5 | * 6 | * Copyright (c) 2011 John Resig, Jörn Zaefferer 7 | * Dual licensed under the MIT (MIT-LICENSE.txt) 8 | * or GPL (GPL-LICENSE.txt) licenses. 9 | * Pulled Live from Git Mon Jun 13 12:10:01 UTC 2011 10 | * Last Commit: d4f23f8a882d13b71768503e2db9fa33ef169ba0 11 | */ 12 | 13 | /** Font Family and Sizes */ 14 | 15 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { 16 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; 17 | } 18 | 19 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } 20 | #qunit-tests { font-size: smaller; } 21 | 22 | 23 | /** Resets */ 24 | 25 | #qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult { 26 | margin: 0; 27 | padding: 0; 28 | } 29 | 30 | 31 | /** Header */ 32 | 33 | #qunit-header { 34 | padding: 0.5em 0 0.5em 1em; 35 | 36 | color: #8699a4; 37 | background-color: #0d3349; 38 | 39 | font-size: 1.5em; 40 | line-height: 1em; 41 | font-weight: normal; 42 | 43 | border-radius: 15px 15px 0 0; 44 | -moz-border-radius: 15px 15px 0 0; 45 | -webkit-border-top-right-radius: 15px; 46 | -webkit-border-top-left-radius: 15px; 47 | } 48 | 49 | #qunit-header a { 50 | text-decoration: none; 51 | color: #c2ccd1; 52 | } 53 | 54 | #qunit-header a:hover, 55 | #qunit-header a:focus { 56 | color: #fff; 57 | } 58 | 59 | #qunit-banner { 60 | height: 5px; 61 | } 62 | 63 | #qunit-testrunner-toolbar { 64 | padding: 0.5em 0 0.5em 2em; 65 | color: #5E740B; 66 | background-color: #eee; 67 | } 68 | 69 | #qunit-userAgent { 70 | padding: 0.5em 0 0.5em 2.5em; 71 | background-color: #2b81af; 72 | color: #fff; 73 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; 74 | } 75 | 76 | 77 | /** Tests: Pass/Fail */ 78 | 79 | #qunit-tests { 80 | list-style-position: inside; 81 | } 82 | 83 | #qunit-tests li { 84 | padding: 0.4em 0.5em 0.4em 2.5em; 85 | border-bottom: 1px solid #fff; 86 | list-style-position: inside; 87 | } 88 | 89 | #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running { 90 | display: none; 91 | } 92 | 93 | #qunit-tests li strong { 94 | cursor: pointer; 95 | } 96 | 97 | #qunit-tests li a { 98 | padding: 0.5em; 99 | color: #c2ccd1; 100 | text-decoration: none; 101 | } 102 | #qunit-tests li a:hover, 103 | #qunit-tests li a:focus { 104 | color: #000; 105 | } 106 | 107 | #qunit-tests ol { 108 | margin-top: 0.5em; 109 | padding: 0.5em; 110 | 111 | background-color: #fff; 112 | 113 | border-radius: 15px; 114 | -moz-border-radius: 15px; 115 | -webkit-border-radius: 15px; 116 | 117 | box-shadow: inset 0px 2px 13px #999; 118 | -moz-box-shadow: inset 0px 2px 13px #999; 119 | -webkit-box-shadow: inset 0px 2px 13px #999; 120 | } 121 | 122 | #qunit-tests table { 123 | border-collapse: collapse; 124 | margin-top: .2em; 125 | } 126 | 127 | #qunit-tests th { 128 | text-align: right; 129 | vertical-align: top; 130 | padding: 0 .5em 0 0; 131 | } 132 | 133 | #qunit-tests td { 134 | vertical-align: top; 135 | } 136 | 137 | #qunit-tests pre { 138 | margin: 0; 139 | white-space: pre-wrap; 140 | word-wrap: break-word; 141 | } 142 | 143 | #qunit-tests del { 144 | background-color: #e0f2be; 145 | color: #374e0c; 146 | text-decoration: none; 147 | } 148 | 149 | #qunit-tests ins { 150 | background-color: #ffcaca; 151 | color: #500; 152 | text-decoration: none; 153 | } 154 | 155 | /*** Test Counts */ 156 | 157 | #qunit-tests b.counts { color: black; } 158 | #qunit-tests b.passed { color: #5E740B; } 159 | #qunit-tests b.failed { color: #710909; } 160 | 161 | #qunit-tests li li { 162 | margin: 0.5em; 163 | padding: 0.4em 0.5em 0.4em 0.5em; 164 | background-color: #fff; 165 | border-bottom: none; 166 | list-style-position: inside; 167 | } 168 | 169 | /*** Passing Styles */ 170 | 171 | #qunit-tests li li.pass { 172 | color: #5E740B; 173 | background-color: #fff; 174 | border-left: 26px solid #C6E746; 175 | } 176 | 177 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } 178 | #qunit-tests .pass .test-name { color: #366097; } 179 | 180 | #qunit-tests .pass .test-actual, 181 | #qunit-tests .pass .test-expected { color: #999999; } 182 | 183 | #qunit-banner.qunit-pass { background-color: #C6E746; } 184 | 185 | /*** Failing Styles */ 186 | 187 | #qunit-tests li li.fail { 188 | color: #710909; 189 | background-color: #fff; 190 | border-left: 26px solid #EE5757; 191 | } 192 | 193 | #qunit-tests > li:last-child { 194 | border-radius: 0 0 15px 15px; 195 | -moz-border-radius: 0 0 15px 15px; 196 | -webkit-border-bottom-right-radius: 15px; 197 | -webkit-border-bottom-left-radius: 15px; 198 | } 199 | 200 | #qunit-tests .fail { color: #000000; background-color: #EE5757; } 201 | #qunit-tests .fail .test-name, 202 | #qunit-tests .fail .module-name { color: #000000; } 203 | 204 | #qunit-tests .fail .test-actual { color: #EE5757; } 205 | #qunit-tests .fail .test-expected { color: green; } 206 | 207 | #qunit-banner.qunit-fail { background-color: #EE5757; } 208 | 209 | 210 | /** Result */ 211 | 212 | #qunit-testresult { 213 | padding: 0.5em 0.5em 0.5em 2.5em; 214 | 215 | color: #2b81af; 216 | background-color: #D2E0E6; 217 | 218 | border-bottom: 1px solid white; 219 | } 220 | 221 | /** Fixture */ 222 | 223 | #qunit-fixture { 224 | position: absolute; 225 | top: -10000px; 226 | left: -10000px; 227 | } 228 | --------------------------------------------------------------------------------