JSDOC/BuildDocs.js
[gnome.introspection-doc-generator] / JSDOC / DocTag.js
1 //<script  type="text/javascript">
2  
3  
4 XObject = imports.XObject.XObject;
5
6 Options = imports.Options.Options;
7
8  
9 /**
10  * DocTag - represents a single A=b tag.
11  * @class DocTag
12  */
13  
14  
15 DocTag = XObject.define(
16
17 /**
18  * @constructor
19  * @arg {String} src
20  */
21
22     function(src) {
23         this.title        = "";
24         this.type         = "";
25         this.name         = "";
26         this.isOptional   = false;
27         this.defaultValue = "";
28         this.desc         = "";
29         if (typeof src != "undefined") {
30             this.parse(src);
31         }
32     }, 
33     Object,
34     {
35         
36         title: '',
37         type: '',
38         name : '',
39         isOptional : false,
40         defaultValue : '',
41         desc : '',
42         /* qdump needed for cahcing?
43         toQDump  :function(t)
44         {
45             return JSDOC.toQDump(t, 'JSDOC.DocTag.fromDump({', '})', new JSDOC.DocTag());
46         } ,
47         */
48
49
50         /**
51             Populate the properties of this from the given tag src.
52             @param {string} src
53          */
54         parse : function(src) {
55             if (typeof src != "string") throw "src must be a string not "+(typeof src);
56
57             try {
58                 src = this.nibbleTitle(src);
59                 //if (JSDOC.PluginManager) {
60                 //    JSDOC.PluginManager.run("onDocTagSynonym", this);
61                // }
62                 
63                 src = this.nibbleType(src);
64                 
65                 // only some tags are allowed to have names.
66                 if (this.title == "param" || this.title == "property" || this.title == "cfg") { // @config is deprecated
67                     src = this.nibbleName(src);
68                 }
69             }
70             catch(e) {
71                 if (Options.LOG) Options.LOG.warn(e);
72                 else throw e;
73             }
74             this.desc = src; // whatever is left
75             
76             // example tags need to have whitespace preserved
77             if (this.title != "example") this.desc = this.desc.trim();
78             
79             //if (JSDOC.PluginManager) {
80             //    JSDOC.PluginManager.run("onDocTag", this);
81             //}
82         },
83
84         /**
85             Automatically called when this is stringified.
86          */
87         toString : function() {
88             return this.desc;
89         },
90          
91
92         /**
93             Find and shift off the title of a tag.
94             @param {string} src
95             @return src
96          */
97         nibbleTitle : function(src) {
98             if (typeof src != "string") throw "src must be a string not "+(typeof src);
99             
100             var parts = src.match(/^\s*(\S+)(?:\s([\s\S]*))?$/);
101
102             if (parts && parts[1]) this.title = parts[1];
103             if (parts && parts[2]) src = parts[2];
104             else src = "";
105             
106             return src;
107         },
108          
109         /**
110             Find and shift off the type of a tag.
111             @requires frame/String.js
112             @param {string} src
113             @return src
114          */
115         nibbleType : function(src) 
116         {
117             if (typeof src != "string") throw "src must be a string not "+(typeof src);
118             
119             if (src.match(/^\s*\{/)) {
120                 var typeRange = this.balance(src,"{", "}");
121                 if (typeRange[1] == -1) {
122                     throw "Malformed comment tag ignored. Tag type requires an opening { and a closing }: "+src;
123                 }
124                 this.type = src.substring(typeRange[0]+1, typeRange[1]).trim();
125                 this.type = this.type.replace(/\s*,\s*/g, "|"); // multiples can be separated by , or |
126                 src = src.substring(typeRange[1]+1);
127             }
128             
129             return src;
130         },
131          
132
133         /**
134             Find and shift off the name of a tag.
135             @requires frame/String.js
136             @param {string} src
137             @return src
138          */
139         nibbleName : function(src) {
140             if (typeof src != "string") throw "src must be a string not "+(typeof src);
141             
142             src = src.trim();
143             
144             // is optional?
145             if (src.charAt(0) == "[") {
146                 var nameRange = this.balance(src,"[", "]");
147                 if (nameRange[1] == -1) {
148                     throw "Malformed comment tag ignored. Tag optional name requires an opening [ and a closing ]: "+src;
149                 }
150                 this.name = src.substring(nameRange[0]+1, nameRange[1]).trim();
151                 this.isOptional = true;
152                 
153                 src = src.substring(nameRange[1]+1);
154                 
155                 // has default value?
156                 var nameAndValue = this.name.split("=");
157                 if (nameAndValue.length) {
158                     this.name = nameAndValue.shift().trim();
159                     this.defaultValue = nameAndValue.join("=");
160                 }
161             }
162             else {
163                 var parts = src.match(/^(\S+)(?:\s([\s\S]*))?$/);
164                 if (parts) {
165                     if (parts[1]) this.name = parts[1];
166                     if (parts[2]) src = parts[2].trim();
167                     else src = "";
168                 }
169             }   
170
171             return src;
172         },
173         
174         balance : function(str, open, close) {
175             var i = 0;
176             while (str.charAt(i) != open) {
177                 if (i == str.length) return [-1, -1];
178                 i++;
179             }
180             
181             var j = i+1;
182             var balance = 1;
183             while (j < str.length) {
184                 if (str.charAt(j) == open) balance++;
185                 if (str.charAt(j) == close) balance--;
186                 if (balance == 0) break;
187                 j++;
188                 if (j == str.length) return [-1, -1];
189             }
190             
191             return [i, j];
192 }
193
194         
195         
196 });
197
198 // cached support?
199 DocTag.fromDump = function(t)
200 {
201     var ns = new DocTag();
202     for (var i in t) {
203         if (typeof(ns[i]) == "undefined") {
204             println("ERR:no default for DocTag:"+ i);
205         }
206        ns[i] = t[i];
207     }
208     return ns;
209 }