Permalink
Browse files

feat(experimental): decorators

  • Loading branch information...
h13i32maru committed Nov 23, 2016
1 parent e694c2c commit c9419512b7dda5e8f0b906945fb2a91f0b4621b3
View
@@ -3,6 +3,7 @@ import ParamParser from '../Parser/ParamParser.js';
import ASTUtil from '../Util/ASTUtil.js';
import InvalidCodeLogger from '../Util/InvalidCodeLogger.js';
import ASTNodeContainer from '../Util/ASTNodeContainer.js';
+import babelGenerator from 'babel-generator';
/**
* Abstract Doc Class.
@@ -77,6 +78,7 @@ export default class AbstractDoc {
this._$throws();
this._$emits();
this._$listens();
+ this._$decorator();
}
/**
@@ -525,6 +527,31 @@ export default class AbstractDoc {
}
}
+ /**
+ * decide `decorator`.
+ */
+ _$decorator() {
+ if (!this._node.decorators) return;
+
+ this._value.decorators = [];
+ for (const decorator of this._node.decorators) {
+ const value = {};
+ switch (decorator.expression.type) {
+ case 'Identifier':
+ value.name = decorator.expression.name;
+ value.arguments = null;
+ break;
+ case 'CallExpression':
+ value.name = decorator.expression.callee.name;
+ value.arguments = babelGenerator(decorator.expression).code.replace(/^[^(]+/, '');
+ break;
+ default:
+ throw new Error(`unknown decorator expression type: ${decorator.expression.type}`);
+ }
+ this._value.decorators.push(value);
+ }
+ }
+
/**
* find all tags.
* @param {string[]} names - tag names.
@@ -291,6 +291,13 @@ export default class DocFactory {
Reflect.defineProperty(node, 'parent', {value: parentNode});
}
+ // if node has decorators, leading comments is attached to decorators.
+ if (node.decorators && node.decorators[0].leadingComments) {
+ if (!node.leadingComments || !node.leadingComments.length) {
+ node.leadingComments = node.decorators[0].leadingComments;
+ }
+ }
+
let results;
results = this._traverseComments(parentNode, node, node.leadingComments);
this._results.push(...results);
View
@@ -66,6 +66,8 @@ export default class ESParser {
if (experimental.functionBind) option.plugins.push('functionBind');
if (experimental.functionSent) option.plugins.push('functionSent');
if (experimental.asyncGenerators) option.plugins.push('asyncGenerators');
+ if (experimental.asyncGenerators) option.plugins.push('asyncGenerators');
+ if (experimental.decorators) option.plugins.push('decorators');
}
return option;
@@ -74,6 +74,7 @@ export default class ClassDocBuilder extends DocBuilder {
ice.load('experimental', this._buildExperimentalHTML(doc));
ice.load('see', this._buildDocsLinkHTML(doc.see), 'append');
ice.load('todo', this._buildDocsLinkHTML(doc.todo), 'append');
+ ice.load('decorator', this._buildDecoratorHTML(doc), 'append');
ice.into('instanceDocs', instanceDocs, (instanceDocs, ice)=>{
ice.loop('instanceDoc', instanceDocs, (i, instanceDoc, ice)=>{
@@ -479,6 +479,7 @@ export default class DocBuilder {
ice.load('see', this._buildDocsLinkHTML(doc.see), 'append');
ice.load('todo', this._buildDocsLinkHTML(doc.todo), 'append');
ice.load('override', this._buildOverrideMethod(doc));
+ ice.load('decorator', this._buildDecoratorHTML(doc), 'append');
let isFunction = false;
if (['method', 'constructor', 'function'].indexOf(doc.kind) !== -1) isFunction = true;
@@ -1017,6 +1018,24 @@ export default class DocBuilder {
return '';
}
+ _buildDecoratorHTML(doc) {
+ if (!doc.decorators) return '';
+
+ const links = [];
+ for (const decorator of doc.decorators) {
+ const link = this._buildDocLinkHTML(decorator.name, decorator.name, false, 'function');
+ if (decorator.arguments) {
+ links.push(`<li>${link}${decorator.arguments}</li>`);
+ } else {
+ links.push(`<li>${link}</li>`);
+ }
+ }
+
+ if (!links.length) return '';
+
+ return `<ul>${links.join('\n')}</ul>`;
+ }
+
// _buildAuthorHTML(doc, separator = '\n') {
// if (!doc.author) return '';
//
@@ -29,6 +29,7 @@ <h1 data-ice="name"></h1>
<div class="deprecated" data-ice="deprecated"></div>
<div class="experimental" data-ice="experimental"></div>
<div class="description" data-ice="description"></div>
+ <div class="decorator" data-ice="decorator"><h4>Decorators:</h4></div>
<div data-ice="see"><h4>See:</h4></div>
@@ -73,6 +73,8 @@ <h4>Throw:</h4>
</table>
</div>
+ <div data-ice="decorator"><h4>Decorators:</h4></div>
+
<div data-ice="example">
<h4>Example:</h4>
<div class="example-doc" data-ice="exampleDoc">
View
@@ -35,6 +35,7 @@
* @property {boolean} experimentalProposal.functionBind
* @property {boolean} experimentalProposal.functionSent
* @property {boolean} experimentalProposal.asyncGenerators
+ * @property {boolean} experimentalProposal.decorators
* @see https://esdoc.org/config.html
*/
@@ -23,6 +23,7 @@
},
"experimentalProposal": {
"classProperties": true,
- "objectRestSpread": true
+ "objectRestSpread": true,
+ "decorators": true
}
}
@@ -0,0 +1,42 @@
+/**
+ * this is TestDecoratorDefinition.
+ */
+@testDecoratorAnnotation1
+export default class TestDecoratorDefinition {
+ /**
+ * this is static method1.
+ */
+ @testDecoratorAnnotation1
+ static method1(){}
+
+ /**
+ * this is get value1.
+ * @type {number}
+ */
+ @testDecoratorAnnotation1
+ get value1(){}
+
+ /**
+ * this is set value2.
+ * @type {number}
+ */
+ @testDecoratorAnnotation1
+ set value2(v){}
+
+ /**
+ * this is method1.
+ */
+ @testDecoratorAnnotation1
+ @testDecoratorAnnotation2(true)
+ method1(){}
+}
+
+/**
+ * this is testDecoratorAnnotation1.
+ */
+export function testDecoratorAnnotation1(){}
+
+/**
+ * this is testDecoratorAnnotation2.
+ */
+export function testDecoratorAnnotation2(){}
@@ -7,10 +7,10 @@ describe('test coverage', ()=> {
const badge = fs.readFileSync('./test/fixture/dest/esdoc/badge.svg', {encoding: 'utf8'}).toString();
it('has coverage summary', ()=> {
- assert(badge.includes('79%'));
+ assert(badge.includes('80%'));
assert.includes(doc, '[data-ice="coverageBadge"]', './badge.svg', 'src');
- assert.includes(doc, '[data-ice="totalCoverageCount"]', '267/335');
- assert.equal(doc.find('[data-ice="file"] [data-ice="coverage"]').length, 117);
+ assert.includes(doc, '[data-ice="totalCoverageCount"]', '274/342');
+ assert.equal(doc.find('[data-ice="file"] [data-ice="coverage"]').length, 118);
});
/* eslint-disable max-statements */
@@ -36,6 +36,7 @@ describe('test coverage', ()=> {
test('file/src/ClassProperty/Definition.js.html', '100 %3/3');
test('file/src/Computed/Method.js.html', '100 %11/11');
test('file/src/Computed/Property.js.html', '100 %12/12');
+ test('file/src/Decorator/Definition.js.html', '100 %7/7');
test('file/src/Deprecated/Class.js.html#errorLines=6', '75 %3/4');
test('file/src/Deprecated/Function.js.html', '100 %1/1');
test('file/src/Deprecated/Variable.js.html', '100 %1/1');
@@ -141,6 +142,6 @@ describe('test coverage', ()=> {
test('file/src/Version/Function.js.html', '100 %1/1');
test('file/src/Version/Variable.js.html', '100 %1/1');
- assert.equal(count, 117);
+ assert.equal(count, 118);
});
});
@@ -0,0 +1,40 @@
+import {readDoc, assert, find, findParent} from './../../../util.js';
+
+/**
+ * @test {ClassDocBuilder#_buildClassDoc}
+ * @test {DocBuilder#_buildDetailDocs}
+ */
+describe('TestDecoratorDefinition:', ()=> {
+ const doc = readDoc('class/src/Decorator/Definition.js~TestDecoratorDefinition.html');
+
+ it('has decorator at class.', ()=>{
+ find(doc, '[data-ice="content"] .self-detail', (doc)=>{
+ assert.includes(doc, '[data-ice="decorator"]', 'testDecoratorAnnotation1');
+ });
+ });
+
+ it('has decorator at static method.', ()=>{
+ findParent(doc, '[id="static-method-method1"]', '[data-ice="detail"]', (doc)=>{
+ assert.includes(doc, '[data-ice="decorator"]', 'testDecoratorAnnotation1');
+ });
+ });
+
+ it('has decorator at getter.', ()=>{
+ findParent(doc, '[id="instance-get-value1"]', '[data-ice="detail"]', (doc)=>{
+ assert.includes(doc, '[data-ice="decorator"]', 'testDecoratorAnnotation1');
+ });
+ });
+
+ it('has decorator at setter.', ()=>{
+ findParent(doc, '[id="instance-set-value2"]', '[data-ice="detail"]', (doc)=>{
+ assert.includes(doc, '[data-ice="decorator"]', 'testDecoratorAnnotation1');
+ });
+ });
+
+ it('has decorator at method.', ()=>{
+ findParent(doc, '[id="instance-method-method1"]', '[data-ice="detail"]', (doc)=>{
+ assert.includes(doc, '[data-ice="decorator"] li:nth-of-type(1)', 'testDecoratorAnnotation1');
+ assert.includes(doc, '[data-ice="decorator"] li:nth-of-type(2)', 'testDecoratorAnnotation2(true)');
+ });
+ });
+});

0 comments on commit c941951

Please sign in to comment.