5 public enum DocTagTitle
48 // these are some we have added for creating trees etc..
49 CHILDREN, // what classes can be added as child in a tree
50 PARENT, // restrict what the class can be added to.
51 ABSTRACT, // is the class abstract
52 BUILDER_TOP // can the element be used as a top level in the gui builder
57 errordomain DocTagException {
65 public class DocTag : Object
68 public DocTagTitle title = DocTagTitle.NO_VALUE;
69 public string type = ""; // eg.. boolean / string etc..., may be xxxx|bbbb - eg. optional types
70 public string name = ""; // eg. "title" << a property name etc...
71 public bool isOptional = false;
72 public string defaultValue = "";
73 public string desc = "";
74 public Gee.ArrayList<string> optvalues;
75 public string memberOf = ""; // set by add addMember..
77 public string asString()
79 return "DocTag: title=%s name=%s type=%s desc=%s".printf(
80 this.title.to_string(),
87 public Json.Object toJson()
89 var ret = new Json.Object();
90 ret.set_string_member("title", this.title.to_string());
91 ret.set_string_member("type", this.type);
92 ret.set_string_member("name", this.name);
93 ret.set_string_member("defaultValue", this.defaultValue);
94 ret.set_string_member("desc", this.desc);
95 ret.set_string_member("memberOf", this.memberOf);
96 ret.set_boolean_member("isOptional", this.isOptional);
97 var ar = new Json.Array();
98 foreach(var ov in this.optvalues) {
99 ar.add_string_element(ov);
101 ret.set_array_member("optvalues", ar);
106 public DocTag (string in_src)
109 GLib.debug("Parsing Tag: %s", in_src);
114 this.optvalues = new Gee.ArrayList<string>();
119 src = this.nibbleTitle(src);
121 src = this.nibbleType(src);
124 // only some tags are allowed to have names.
126 this.title == DocTagTitle.PARAM ||
127 this.title == DocTagTitle.PROPERTY ||
128 this.title == DocTagTitle.CFG) { // @config is deprecated << not really?
129 src = this.nibbleName(src);
132 catch(DocTagException e) {
133 GLib.debug("Failed to parse tag: '%s' = error = %s", in_src, e.message);
134 // only throw if in 'strict'??
139 // if type == @cfg, and matches (|....|...)
143 // our code uses (Optional) - but we really want to ignore this.
144 src = /\(Optional\)/.replace(src, src.length, 0, "").strip();
151 if (this.title == DocTagTitle.CFG && /^\([^)]+\)/.match_all(src, 0, out mi )) {
153 var ms = mi.fetch(0);
154 GLib.debug("Got Opt list: %s", ms);
156 ms = ms.substring(1,ms.length-2);
157 GLib.debug("clan to: %s", ms);
158 if (ms.contains("|")) {
159 var ar = ms.split("|");
160 GLib.debug("split to: %d", ar.length);
161 for (var i =0 ; i < ar.length;i++) {
162 GLib.debug("Add optvalue: %s",ar[i].strip());
163 this.optvalues.add(ar[i].strip());
165 src = src.substring(ms.length, src.length - (ms.length+2)).strip();
166 GLib.debug("SRC NOW: %s",src);
170 if (this.title == DocTagTitle.CFG && /\[required\]/.match(src)) {
171 this.isOptional = false;
172 src = /\[required\]/.replace(src, src.length, 0, "").strip();
174 this.desc = src; // whatever is left
176 // example tags need to have whitespace preserved
177 if (this.title != DocTagTitle.EXAMPLE) {
178 this.desc = this.desc.strip();
189 Find and shift off the title of a tag.
193 private string nibbleTitle (string src) throws DocTagException
195 //GLib.debug("nibbleTitle: %s", src);
198 if(! /^\s*(\S+)\s*(?:\s([\s\S]*))?$/.match_full(src, src.length, 0, 0, out mi) ||
199 mi.get_match_count() < 2) {
200 throw new DocTagException.NO_TITLE("missing title");
204 // convert the @xxx to a DocTagTitle
205 // wonder if caching this as a GeeHashmap would be quicker?
207 EnumClass enumc = (EnumClass) typeof (DocTagTitle).class_ref ();
209 unowned EnumValue? eval = enumc.get_value_by_name(
210 // "JSDOC_DOC_TAG_TITLE_"+ mi.fetch(1).up()
211 "JSDOC_DOC_TAG_TITLE_"+ mi.fetch(1).up().replace("-", "_")
214 throw new DocTagException.INVALID_TITLE("title not supported ??");
217 this.title = (DocTagTitle) eval.value;
218 return mi.get_match_count() > 2 ? mi.fetch(2) : "";
223 Find and shift off the type of a tag.
224 @requires frame/String.js
228 private string nibbleType(string src)
231 if(! /^\s*\{/.match_all(src, 0, out mi)) {
237 this.balance(src,'{', '}', out start, out stop);
238 //GLib.debug("nibble type: %s %d, %d", src, start,stop);
240 throw new DocTagException.INVALID_TYPE("Malformed comment tag ignored. Tag type requires an opening { and a closing }: ") ;
243 this.type = src.substring(start+1,stop-1).strip();
244 this.type = this.type.replace(",", "|"); // multiples can be separated by , or |
245 return src.substring(stop+1, -1);
252 Find and shift off the name of a tag.
253 @requires frame/String.js
257 private string nibbleName( string in_src) throws DocTagException
261 var src = in_src.strip();
262 //GLib.debug("nibbleName: %s", in_src);
265 if (src.get(0) == '[') {
267 this.balance(src,'[', ']', out start, out stop);
269 throw new DocTagException.INVALID_NAME("Malformed comment tag ignored. Tag optional name requires an opening [ and a closing ]: ");
272 this.name = src.substring(start+1, stop).strip();
273 this.isOptional = true;
275 src = src.substring(stop+1);
277 // has default value?
278 var nameAndValue = this.name.split("=");
279 if (nameAndValue.length > 1) {
280 var oname = this.name;
281 this.name = nameAndValue[0].strip();
283 this.defaultValue = oname.substring( nameAndValue[0].length + 1 , nameAndValue[0].length + 1 - oname.length); /// what about
285 GLib.debug("got name %s", this.name);
286 return src.substring(stop+1, stop+1-src.length);
288 // not encased with [ ]
292 if (/^(\S+)(?:\s([\s\S]*))?$/.match_full(src, src.length, 0, 0, out mi)) {
293 this.name = mi.fetch(1);
294 GLib.debug("got name %s", this.name);
295 return mi.get_match_count() > 2 ? mi.fetch(2) : "";
303 private void balance(string str, char open, char close, out int start, out int stop) {
306 while (str.get(start) != open) {
307 if (start == str.length) {
315 while (stop < str.length) {
316 if (str.get(stop) == open) balance++;
317 if (str.get(stop) == close) balance--;
318 if (balance == 0) break;
320 if (stop == str.length) {
329 public Json.Array optvalue_as_json_array()
331 var ret = new Json.Array();
332 foreach (var str in this.optvalues ) {
333 ret.add_string_element(str);
339 public Json.Object toPropertyJSON (Symbol parent)
342 var add = new Json.Object();
343 add.set_string_member("name",this.name);
344 add.set_string_member("type",this.type);
345 add.set_string_member("desc",this.desc);
346 add.set_string_member("memberOf", this.memberOf == parent.alias ? "" : this.memberOf);
347 add.set_boolean_member("isOptional", this.isOptional);
348 var ar = new Json.Array();
349 foreach(var ov in this.optvalues) {
350 ar.add_string_element(ov);
352 add.set_array_member("optvalues", ar);