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