JSDOC/DocTag.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         /**
43          * serialize..
44          */
45         toObject :function(t)
46         {
47             
48             var ret = { };
49             for (var i in this) {
50                 if (Symbol.hide.indexOf(i) > -1) {
51                     continue;
52                 }
53                 switch (typeof(this[i])) {
54                     case 'function':
55                         continue;
56                     case 'object':
57                         switch(i) {
58                             //arrays..
59                             case 'params' : 
60                                 ret[i] = array2object(this[i],true); 
61                                 continue;
62                                 
63                             //objects..
64                             case 'augments' : 
65                                 ret[i] = this[i].toArray();
66                                 continue;
67                                 
68                             default:
69                                 print("object? :" + i);
70                                 Seed.quit();
71                         }
72                         
73                         
74                     case 'string':
75                     case 'number':
76                         ret[i] = this[i]; continue;
77                     default:
78                         print("unknown type:" + typeof(this[i]));
79                         Seed.quit();
80                    }
81             }
82             return ret;
83         },
84         
85
86
87         /**
88             Populate the properties of this from the given tag src.
89             @param {string} src
90          */
91         parse : function(src) {
92             if (typeof src != "string") throw "src must be a string not "+(typeof src);
93
94             try {
95                 src = this.nibbleTitle(src);
96                 //if (JSDOC.PluginManager) {
97                 //    JSDOC.PluginManager.run("onDocTagSynonym", this);
98                // }
99                 
100                 src = this.nibbleType(src);
101                 
102                 // only some tags are allowed to have names.
103                 if (this.title == "param" || this.title == "property" || this.title == "cfg") { // @config is deprecated
104                     src = this.nibbleName(src);
105                 }
106             }
107             catch(e) {
108                 if (Options.LOG) Options.LOG.warn(e);
109                 else throw e;
110             }
111             this.desc = src; // whatever is left
112             
113             // example tags need to have whitespace preserved
114             if (this.title != "example") this.desc = this.desc.trim();
115             
116             //if (JSDOC.PluginManager) {
117             //    JSDOC.PluginManager.run("onDocTag", this);
118             //}
119         },
120
121         /**
122             Automatically called when this is stringified.
123          */
124         toString : function() {
125             return this.desc;
126         },
127          
128
129         /**
130             Find and shift off the title of a tag.
131             @param {string} src
132             @return src
133          */
134         nibbleTitle : function(src) {
135             if (typeof src != "string") throw "src must be a string not "+(typeof src);
136             
137             var parts = src.match(/^\s*(\S+)(?:\s([\s\S]*))?$/);
138
139             if (parts && parts[1]) this.title = parts[1];
140             if (parts && parts[2]) src = parts[2];
141             else src = "";
142             
143             return src;
144         },
145          
146         /**
147             Find and shift off the type of a tag.
148             @requires frame/String.js
149             @param {string} src
150             @return src
151          */
152         nibbleType : function(src) 
153         {
154             if (typeof src != "string") throw "src must be a string not "+(typeof src);
155             
156             if (src.match(/^\s*\{/)) {
157                 var typeRange = this.balance(src,"{", "}");
158                 if (typeRange[1] == -1) {
159                     throw "Malformed comment tag ignored. Tag type requires an opening { and a closing }: "+src;
160                 }
161                 this.type = src.substring(typeRange[0]+1, typeRange[1]).trim();
162                 this.type = this.type.replace(/\s*,\s*/g, "|"); // multiples can be separated by , or |
163                 src = src.substring(typeRange[1]+1);
164             }
165             
166             return src;
167         },
168          
169
170         /**
171             Find and shift off the name of a tag.
172             @requires frame/String.js
173             @param {string} src
174             @return src
175          */
176         nibbleName : function(src) {
177             if (typeof src != "string") throw "src must be a string not "+(typeof src);
178             
179             src = src.trim();
180             
181             // is optional?
182             if (src.charAt(0) == "[") {
183                 var nameRange = this.balance(src,"[", "]");
184                 if (nameRange[1] == -1) {
185                     throw "Malformed comment tag ignored. Tag optional name requires an opening [ and a closing ]: "+src;
186                 }
187                 this.name = src.substring(nameRange[0]+1, nameRange[1]).trim();
188                 this.isOptional = true;
189                 
190                 src = src.substring(nameRange[1]+1);
191                 
192                 // has default value?
193                 var nameAndValue = this.name.split("=");
194                 if (nameAndValue.length) {
195                     this.name = nameAndValue.shift().trim();
196                     this.defaultValue = nameAndValue.join("=");
197                 }
198             }
199             else {
200                 var parts = src.match(/^(\S+)(?:\s([\s\S]*))?$/);
201                 if (parts) {
202                     if (parts[1]) this.name = parts[1];
203                     if (parts[2]) src = parts[2].trim();
204                     else src = "";
205                 }
206             }   
207
208             return src;
209         },
210         
211         balance : function(str, open, close) {
212             var i = 0;
213             while (str.charAt(i) != open) {
214                 if (i == str.length) return [-1, -1];
215                 i++;
216             }
217             
218             var j = i+1;
219             var balance = 1;
220             while (j < str.length) {
221                 if (str.charAt(j) == open) balance++;
222                 if (str.charAt(j) == close) balance--;
223                 if (balance == 0) break;
224                 j++;
225                 if (j == str.length) return [-1, -1];
226             }
227             
228             return [i, j];
229 }
230
231         
232         
233 });
234
235 // cached support?
236 DocTag.fromDump = function(t)
237 {
238     var ns = new DocTag();
239     for (var i in t) {
240         if (typeof(ns[i]) == "undefined") {
241             println("ERR:no default for DocTag:"+ i);
242         }
243        ns[i] = t[i];
244     }
245     return ns;
246 }