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