From fcc26990caddacf30dd15c7e58d3c150aa1e5dc7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Wrzeszcz?= <rafal.wrzeszcz@wrzasq.pl>
Date: Sat, 10 Dec 2011 10:27:33 +0100
Subject: [PATCH 1/6] @abstract/@virtual tag support.

---
 rhino_modules/jsdoc/schema.js                 |  5 +++++
 .../jsdoc/tag/dictionary/definitions.js       |  9 ++++++++
 templates/default/publish.js                  |  4 ++++
 templates/haruki/publish.js                   | 10 +++++++--
 test/cases/abstracttag.js                     | 17 ++++++++++++++
 test/runner.js                                |  1 +
 test/t/cases/abstracttag.js                   | 22 +++++++++++++++++++
 7 files changed, 66 insertions(+), 2 deletions(-)
 create mode 100644 test/cases/abstracttag.js
 create mode 100644 test/t/cases/abstracttag.js

diff --git a/rhino_modules/jsdoc/schema.js b/rhino_modules/jsdoc/schema.js
index 5cbc85e21..2e3b1e0b9 100644
--- a/rhino_modules/jsdoc/schema.js
+++ b/rhino_modules/jsdoc/schema.js
@@ -113,6 +113,11 @@ exports.jsdocSchema = {
                         "maxItems": 1,
                         "enum": ["private", "protected", "public"]
                     },
+                    "virtual": { // is a member left to be implemented during inheritance?
+                        "type": "boolean",
+                        "optional": true,
+                        "default": false
+                    },
                     "attrib": { // other attributes, like "readonly"
                         "type": "string",
                         "optional": true
diff --git a/rhino_modules/jsdoc/tag/dictionary/definitions.js b/rhino_modules/jsdoc/tag/dictionary/definitions.js
index 8f6d33ca2..190e6fb5f 100644
--- a/rhino_modules/jsdoc/tag/dictionary/definitions.js
+++ b/rhino_modules/jsdoc/tag/dictionary/definitions.js
@@ -11,6 +11,15 @@
 */
 exports.defineTags = function(dictionary) {
     
+    dictionary.defineTag('abstract', {
+        mustNotHaveValue: true,
+        onTagged: function(doclet, tag) {
+            // since "abstract" is reserved word in JavaScript let's use "virtual" in code
+            doclet.virtual = true;
+        }
+    })
+    .synonym('virtual');
+    
     dictionary.defineTag('access', {
         mustHaveValue: true,
         onTagged: function(doclet, tag) {
diff --git a/templates/default/publish.js b/templates/default/publish.js
index e5f98a884..ebdbbe6b8 100644
--- a/templates/default/publish.js
+++ b/templates/default/publish.js
@@ -102,6 +102,10 @@
         function addAttribs(f) {
             var attribs = [];
             
+            if (f.virtual) {
+                attribs.push('virtual');
+            }
+            
             if (f.access && f.access !== 'public') {
                 attribs.push(f.access);
             }
diff --git a/templates/haruki/publish.js b/templates/haruki/publish.js
index 1119d2f53..694ce6a49 100644
--- a/templates/haruki/publish.js
+++ b/templates/haruki/publish.js
@@ -51,7 +51,8 @@
                 var thisNamespace = parentNode.namespaces[element.name] = {
                     'name': element.name,
                     'description': element.description || '',
-                    'access': element.access || ''
+                    'access': element.access || '',
+                    'virtual': !!element.virtual
                 };
                 
                 graft(thisNamespace, childNodes, element.longname, element.name);
@@ -64,7 +65,8 @@
                 var thisMixin = parentNode.mixins[element.name] = {
                     'name': element.name,
                     'description': element.description || '',
-                    'access': element.access || ''
+                    'access': element.access || '',
+                    'virtual': !!element.virtual
                 };
                 
                 graft(thisMixin, childNodes, element.longname, element.name);
@@ -77,6 +79,7 @@
                 var thisFunction = parentNode.functions[element.name] = {
                     'name': element.name,
                     'access': element.access || '',
+                    'virtual': !!element.virtual,
                     'description': element.description || '',
                     'parameters': [ ]
                 };
@@ -108,6 +111,7 @@
                 parentNode.properties[element.name] = {
                     'name': element.name,
                     'access': element.access || '',
+                    'virtual': !!element.virtual,
                     'description': element.description || '',
                     'type': element.type? (element.type.length === 1? element.type[0] : element.type) : ''
                 };
@@ -121,6 +125,7 @@
                 var thisEvent = parentNode.events[element.name] = {
                     'name': element.name,
                     'access': element.access || '',
+                    'virtual': !!element.virtual,
                     'description': element.description || '',
                     'parameters': [
                     ]
@@ -156,6 +161,7 @@
                     'description': element.classdesc || '',
                     'extends': element.augments || [],
                     'access': element.access || '',
+                    'virtual': !!element.virtual,
                     'fires': element.fires || '',
                     'constructor': {
                         'name': element.name,
diff --git a/test/cases/abstracttag.js b/test/cases/abstracttag.js
new file mode 100644
index 000000000..07aeb9b74
--- /dev/null
+++ b/test/cases/abstracttag.js
@@ -0,0 +1,17 @@
+/** @constructor */
+function Thingy() {
+
+    /** @abstract */
+    this.pez = 2;
+    
+}
+
+// same as...
+
+/** @constructor */
+function OtherThingy() {
+
+    /** @virtual */
+    this.pez = 2;
+    
+}
\ No newline at end of file
diff --git a/test/runner.js b/test/runner.js
index ae341fedf..b37c9cd0f 100644
--- a/test/runner.js
+++ b/test/runner.js
@@ -103,6 +103,7 @@ testFile('test/t/cases/innerscope2.js');
 testFile('test/t/cases/modules/data/mod-1.js');
 testFile('test/t/cases/modules/data/mod-2.js');
 
+testFile('test/t/cases/abstracttag.js');
 testFile('test/t/cases/accesstag.js');
 testFile('test/t/cases/alias.js');
 testFile('test/t/cases/alias2.js');
diff --git a/test/t/cases/abstracttag.js b/test/t/cases/abstracttag.js
new file mode 100644
index 000000000..be9c66e36
--- /dev/null
+++ b/test/t/cases/abstracttag.js
@@ -0,0 +1,22 @@
+(function() {
+    var docSet = testhelpers.getDocSetFromFile('test/cases/abstracttag.js'),
+        type = docSet.getByLongname('Thingy')[0]
+        pez = docSet.getByLongname('Thingy#pez')[0];
+    
+    test('By default symbol has virtual=undefined property.', function() {
+        assert.equal(!!type.virtual, false);
+    });
+    
+    test('When a symbol has a @abstract tag, the doclet has a virtual=true property.', function() {
+        assert.equal(pez.virtual, true);
+    });
+    
+    // same as...
+    
+    pez = docSet.getByLongname('OtherThingy#pez')[0];
+    
+    test('When a symbol has a @virtual tag, the doclet has a virtual=true property.', function() {
+        assert.equal(pez.virtual, true);
+    });
+
+})();
\ No newline at end of file

From 03d9a9f16debe216cd911ca9429492f88df80b2d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Wrzeszcz?= <rafal.wrzeszcz@wrzasq.pl>
Date: Sat, 10 Dec 2011 23:02:47 +0100
Subject: [PATCH 2/6] Allow to define runtime options in configuration file.

---
 jsdoc.js | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/jsdoc.js b/jsdoc.js
index 4353576ba..beaf2b228 100644
--- a/jsdoc.js
+++ b/jsdoc.js
@@ -159,6 +159,16 @@ function main() {
         env.opts.query = require('query').toObject(env.opts.query);
     }
     
+    // allow to pass arguments from configuration file
+    if (env.conf.opts) {
+        for (var opt in env.conf.opts) {
+            // arguments passed in command are more important
+            if (!(opt in env.opts)) {
+                env.opts[opt] = env.conf.opts[opt];
+            }
+        }
+    }
+    
     // which version of javascript will be supported? (rhino only)
     if (typeof version === 'function') {
         version(env.conf.jsVersion || 180);
@@ -244,4 +254,4 @@ function main() {
         else { // TODO throw no publish warning?
         }
     }
-}
\ No newline at end of file
+}

From bcc5d5116ee218c7fd2d3d9af49fbdcd4d78b611 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Wrzeszcz?= <rafal.wrzeszcz@wrzasq.pl>
Date: Sat, 10 Dec 2011 23:10:08 +0100
Subject: [PATCH 3/6] Moved options merging before query parameter parsing.

---
 jsdoc.js | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/jsdoc.js b/jsdoc.js
index beaf2b228..28ceca8a5 100644
--- a/jsdoc.js
+++ b/jsdoc.js
@@ -155,10 +155,6 @@ function main() {
         throw('Configuration file cannot be evaluated. '+e);
     }
     
-    if (env.opts.query) {
-        env.opts.query = require('query').toObject(env.opts.query);
-    }
-    
     // allow to pass arguments from configuration file
     if (env.conf.opts) {
         for (var opt in env.conf.opts) {
@@ -169,6 +165,10 @@ function main() {
         }
     }
     
+    if (env.opts.query) {
+        env.opts.query = require('query').toObject(env.opts.query);
+    }
+    
     // which version of javascript will be supported? (rhino only)
     if (typeof version === 'function') {
         version(env.conf.jsVersion || 180);

From c48a69229a275256aa5c3cae5979d8ac9c98f3ea Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Wrzeszcz?= <rafal.wrzeszcz@wrzasq.pl>
Date: Sat, 10 Dec 2011 23:24:30 +0100
Subject: [PATCH 4/6] Made template parameter an entire path.

---
 jsdoc.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/jsdoc.js b/jsdoc.js
index 4353576ba..7c47411ed 100644
--- a/jsdoc.js
+++ b/jsdoc.js
@@ -230,10 +230,10 @@ function main() {
             exit(0);
         }
 
-        env.opts.template = env.opts.template || 'default';
+        env.opts.template = env.opts.template || 'templates/default';
         
         // should define a global "publish" function
-        include('templates/' + env.opts.template + '/publish.js');
+        include(env.opts.template + '/publish.js');
 
         if (typeof publish === 'function') {
             publish(

From fa7825a42b86701f6d36993ddd31891119ed3873 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Wrzeszcz?= <rafal.wrzeszcz@wrzasq.pl>
Date: Sat, 10 Dec 2011 23:29:17 +0100
Subject: [PATCH 5/6] Changed default parameter value.

---
 rhino_modules/jsdoc/opts/parser.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/rhino_modules/jsdoc/opts/parser.js b/rhino_modules/jsdoc/opts/parser.js
index f82e0f508..8ffead796 100644
--- a/rhino_modules/jsdoc/opts/parser.js
+++ b/rhino_modules/jsdoc/opts/parser.js
@@ -12,7 +12,7 @@ var common = {
 var argParser = new common.args.ArgParser(),
 	ourOptions,
 	defaults = {
-		template: 'default',
+		template: 'templates/default',
 		destination: './out/'
 	};
 

From 563dde0ae96e3afd2288e1a329408ca31d20462f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Wrzeszcz?= <rafal.wrzeszcz@wrzasq.pl>
Date: Sun, 11 Dec 2011 10:07:07 +0100
Subject: [PATCH 6/6] Fixed query.js inclusion path.

---
 jsdoc.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/jsdoc.js b/jsdoc.js
index 4353576ba..e955924ee 100644
--- a/jsdoc.js
+++ b/jsdoc.js
@@ -156,7 +156,7 @@ function main() {
     }
     
     if (env.opts.query) {
-        env.opts.query = require('query').toObject(env.opts.query);
+        env.opts.query = require('common/query').toObject(env.opts.query);
     }
     
     // which version of javascript will be supported? (rhino only)
@@ -244,4 +244,4 @@ function main() {
         else { // TODO throw no publish warning?
         }
     }
-}
\ No newline at end of file
+}