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