jscs-jsdoc
Advanced tools
Comparing version 0.4.6 to 1.0.0
@@ -13,2 +13,3 @@ module.exports = { | ||
* Search for the closest scope node tree for Node | ||
* | ||
* @param {{type: string}} n | ||
@@ -15,0 +16,0 @@ * @returns {EsprimaNode} |
202
lib/jsdoc.js
var assert = require('assert'); | ||
var commentParser = require('comment-parser'); | ||
var TypeParser = require('jsdoctypeparser').Parser; | ||
@@ -10,2 +11,11 @@ var TypeBuilder = require('jsdoctypeparser').Builder; | ||
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers | ||
var PARSERS = { | ||
tag: commentParser.PARSERS.parse_tag, | ||
type: commentParser.PARSERS.parse_type, | ||
description: commentParser.PARSERS.parse_description, | ||
}; | ||
// jscs:enable | ||
var RE_SPACE = /\s/; | ||
module.exports = { | ||
@@ -35,2 +45,3 @@ | ||
* jsdoc comment object | ||
* | ||
* @param {string} value | ||
@@ -57,3 +68,5 @@ * @param {{start: DocLocation}} loc | ||
// doc parsed data | ||
this.description = _parsed.description || null; | ||
this.description = _parsed.source && _parsed.description ? | ||
_parsed.source.substr(0, _parsed.source.indexOf('\n@')) : null; | ||
this.tags = (_parsed.tags || []).map(function(tag) { | ||
@@ -63,2 +76,7 @@ return new DocTag(tag, new DocLocation(tag.line, 3, loc.start)); | ||
// calculate abstract flag | ||
this.abstract = this.tags.some(function(v) { | ||
return v.id === 'abstract' || v.id === 'virtual'; | ||
}); | ||
/** | ||
@@ -93,2 +111,3 @@ * @param {function(this: DocComment, DocTag): DocComment} fn | ||
* Simple jsdoc tag object | ||
* | ||
* @param {Object} tag object from comment parser, fields: tag, line, value, name, type, description | ||
@@ -102,2 +121,4 @@ * @param {DocLocation} loc | ||
this.value = tag.value; | ||
this.name = undefined; | ||
this.type = undefined; | ||
@@ -123,2 +144,3 @@ this.description = tag.description; | ||
* Parses jsdoctype string and provides several methods to work with it | ||
* | ||
* @param {string} type | ||
@@ -147,3 +169,4 @@ * @param {DocLocation} loc | ||
/** | ||
* match type | ||
* Match type | ||
* | ||
* @param {EsprimaNode} node | ||
@@ -170,2 +193,3 @@ * @returns {boolean} | ||
* DocLocation | ||
* | ||
* @constructor | ||
@@ -186,2 +210,3 @@ * @param {number} line | ||
* Shift location by line and column | ||
* | ||
* @param {number|Object} line | ||
@@ -201,2 +226,3 @@ * @param {number} [column] | ||
* Comment parsing helper | ||
* | ||
* @param {string} comment | ||
@@ -207,103 +233,111 @@ * @returns {Object} | ||
function _parseComment(comment) { | ||
var notCleanTagRe = /[^\w\d_]/i; | ||
var parsed = commentParser(comment, { | ||
'line_numbers': true, | ||
'raw_value': true | ||
return commentParser(comment, { | ||
parsers: [ | ||
// parse tag | ||
function(str) { | ||
var res = PARSERS.tag.call(this, str); | ||
res.data.value = str; | ||
return res; | ||
}, | ||
PARSERS.type, | ||
_parseName, | ||
PARSERS.description, | ||
] | ||
})[0]; | ||
if (parsed && Array.isArray(parsed.tags)) { | ||
// additional tag.name parsing logic | ||
parsed.tags = parsed.tags.map(function(tag) { | ||
if (!tag.name || !notCleanTagRe.test(tag.name)) { | ||
return tag; | ||
} | ||
var node = _parseNameAgain(tag.name); | ||
if (node.error) { | ||
tag.error = node.error; | ||
return tag; | ||
} | ||
if (node.ticked) { | ||
tag.ticked = node.ticked; | ||
} | ||
if (node.default) { | ||
tag.default = node.default; | ||
} | ||
if (node.required) { | ||
tag.required = node.required; | ||
} | ||
tag.name = node.name; | ||
return tag; | ||
}); | ||
} | ||
return parsed; | ||
} | ||
/** | ||
* Additional name parsing logic for our purposes | ||
* @param {string} str - unparsed name thing | ||
* @returns {Object} | ||
* analogue of str.match(/@(\S+)(?:\s+\{([^\}]+)\})?(?:\s+(\S+))?(?:\s+([^$]+))?/); | ||
* | ||
* @param {string} str raw jsdoc string | ||
* @returns {?Object} parsed tag node | ||
*/ | ||
function _parseNameAgain(str) { // (?:\s+(\S+))? | ||
var out = {}; | ||
// strip ticks (support for ticked variables) | ||
if (str[0] === '`' && str[str.length - 1] === '`') { | ||
out.ticked = true; | ||
str = str.substr(1, str.length - 2); | ||
function _parseName(str, data) { | ||
if (data.errors && data.errors.length) { | ||
return null; | ||
} | ||
// strip chevrons | ||
if (str[0] === '<' && str[str.length - 1] === '>') { | ||
out.required = true; | ||
str = str.substr(1, str.length - 2); | ||
if (str.replace(/[\s\w\d]+/ig, '') === '') { | ||
out.name = str.replace(/^\s+|\s+$/g, ''); | ||
return out; | ||
} else { | ||
out.error = 'Unknown name format'; | ||
return out; | ||
} | ||
} | ||
var l = str.length; | ||
var pos = _skipws(str); | ||
var ch = ''; | ||
var name = ''; | ||
var brackets = 0; | ||
var chevrons = 0; | ||
var ticks = 0; | ||
// parsing [name="mix"] | ||
var ch; | ||
var res = ''; | ||
var brackets = 0; | ||
var re = /\s/; | ||
var l = str.length; | ||
var pos = 0; | ||
while (pos < l) { | ||
ch = str[pos]; | ||
brackets += ch === '[' ? 1 : ch === ']' ? -1 : 0; | ||
res += ch; | ||
pos ++; | ||
if (brackets === 0 && re.test(str[pos])) { | ||
chevrons += ch === '<' ? 1 : ch === '>' ? -1 : 0; | ||
if (ch === '`') { | ||
ticks++; | ||
} | ||
if (ticks % 2 === 0 && chevrons === 0 && brackets === 0 && RE_SPACE.test(ch)) { | ||
break; | ||
} | ||
name += ch; | ||
pos ++; | ||
} | ||
if (brackets) { | ||
// throw new Error('Unpaired curly in type doc'); | ||
out.error = 'Unpaired brackets in type doc'; | ||
return out; | ||
if (brackets !== 0) { throw Error('Invalid `name`, unpaired brackets'); } | ||
if (chevrons !== 0) { throw Error('Invalid `name`, unpaired chevrons'); } | ||
if (ticks % 2 !== 0) { throw Error('Invalid `name`, unpaired ticks'); } | ||
var res = { | ||
name: name, | ||
default: undefined, | ||
optional: false, | ||
required: false, | ||
ticked: false | ||
}; | ||
// strip ticks (support for ticked variables) | ||
if (name[0] === '`' && name[name.length - 1] === '`') { | ||
res.ticked = true; | ||
name = name.slice(1, -1).trim(); | ||
} | ||
if (res[0] === '[' && res[res.length - 1] === ']') { | ||
out.optional = true; | ||
res = res.substr(1, res.length - 2); | ||
var eqPos = res.indexOf('='); | ||
// strip chevrons | ||
if (name[0] === '<' && name[name.length - 1] === '>') { | ||
res.required = true; | ||
name = name.slice(1, -1).trim(); | ||
} | ||
// strip brackets | ||
if (name[0] === '[' && name[name.length - 1] === ']') { | ||
res.optional = true; | ||
name = name.slice(1, -1).trim(); | ||
var eqPos = name.indexOf('='); | ||
if (eqPos !== -1) { | ||
out.name = res.substr(0, eqPos); | ||
out.default = res.substr(eqPos + 1).replace(/^(["'])(.+)(\1)$/, '$2'); | ||
} else { | ||
out.name = res; | ||
res.default = name.substr(eqPos + 1).trim().replace(/^(["'])(.+)(\1)$/, '$2'); | ||
name = name.substr(0, eqPos).trim(); | ||
} | ||
} else { | ||
out.name = res; | ||
} | ||
return out; | ||
res.name = name; | ||
return { | ||
source : str.substr(0, pos), | ||
data : res | ||
}; | ||
/** | ||
* Returns the next to whitespace char position in a string | ||
* | ||
* @param {string} str | ||
* @return {number} | ||
*/ | ||
function _skipws(str) { | ||
var i = 0; | ||
var l = str.length; | ||
var ch; | ||
do { | ||
ch = str[i]; | ||
if (ch !== ' ' && ch !== '\t') { | ||
break; | ||
} | ||
} while (++i < l); | ||
return i; | ||
} | ||
} | ||
@@ -433,2 +467,3 @@ | ||
* Converts AST jsDoc node to simple object | ||
* | ||
* @param {Object} node | ||
@@ -453,2 +488,3 @@ * @returns {!Array.<SimplifiedType>} | ||
* Compare parsed jsDocTypes with esprima node | ||
* | ||
* @param {SimplifiedType[]} variants - result of jsDocParseType | ||
@@ -455,0 +491,0 @@ * @param {Object} argument - esprima source code node |
@@ -9,2 +9,3 @@ var assert = require('assert'); | ||
* Rule constructor | ||
* | ||
* @this {module:jscs/Rule} | ||
@@ -19,2 +20,3 @@ * @constructor | ||
* Load all rules and init them | ||
* | ||
* @param {Object} options | ||
@@ -142,3 +144,4 @@ * @throws {Error} If options is not an Object | ||
/** | ||
* send error to jscs | ||
* Send error to jscs | ||
* | ||
* @param {string} text | ||
@@ -163,2 +166,3 @@ * @param {number|DocLocation} relLine | ||
* Generates function with location fixing logic to send error to jscs | ||
* | ||
* @param {function(string, number|Object, ?number)} err | ||
@@ -182,3 +186,4 @@ * @param {DocTag} tag | ||
/** | ||
* caching scope search. todo: move to patchNodesInFile | ||
* Caching scope search. todo: move to patchNodesInFile | ||
* | ||
* @param {Object} node | ||
@@ -207,2 +212,3 @@ */ | ||
* Extends each node with helper properties | ||
* | ||
* @param {Object} file | ||
@@ -227,2 +233,3 @@ */ | ||
* Fetchs jsdoc block for this | ||
* | ||
* @this {module:esprima/Node} | ||
@@ -241,2 +248,3 @@ * @returns {DocComment} | ||
* Finds DocComment in file before passed line number | ||
* | ||
* @param {number} line | ||
@@ -243,0 +251,0 @@ * @returns {?module:esprima/Node} |
@@ -68,3 +68,4 @@ var assert = require('assert'); | ||
/** | ||
* validator for annotations | ||
* Validator for annotations | ||
* | ||
* @param {JSCS.JSFile} file | ||
@@ -71,0 +72,0 @@ * @param {JSCS.Errors} errors |
@@ -8,3 +8,4 @@ module.exports = validateCheckParamNames; | ||
/** | ||
* validator for check-param-names | ||
* Validator for check-param-names | ||
* | ||
* @param {(FunctionDeclaration|FunctionExpression)} node | ||
@@ -35,3 +36,4 @@ * @param {Function} err | ||
/** | ||
* tag checker | ||
* Tag checker | ||
* | ||
* @param {DocType} tag | ||
@@ -41,3 +43,12 @@ * @param {number} i index | ||
function(tag, i) { | ||
// checking validity | ||
// There is no parameter name in destructuring assignments. | ||
if (node.params[i - skipped] && node.params[i - skipped].name === undefined) { | ||
// So if there is no tag name or the tag name does not contain '.', there is nothing to check. | ||
if (!tag.name || tag.name.value.indexOf('.') === -1) { | ||
lastRootParamTag = tag; | ||
return; | ||
} | ||
} | ||
// Сhecking validity | ||
if (!tag.name) { | ||
@@ -44,0 +55,0 @@ return err('Missing param name', tag.loc); |
@@ -9,3 +9,4 @@ module.exports = checkRedundantAccess; | ||
/** | ||
* validator for @access | ||
* Validator for @access | ||
* | ||
* @param {(FunctionDeclaration|FunctionExpression)} node | ||
@@ -12,0 +13,0 @@ * @param {Function} err |
@@ -8,3 +8,4 @@ module.exports = validateCheckParamNames; | ||
/** | ||
* validator for check-param-names | ||
* Validator for check-param-names | ||
* | ||
* @param {(FunctionDeclaration|FunctionExpression)} node | ||
@@ -22,3 +23,4 @@ * @param {Function} err | ||
/** | ||
* tag checker | ||
* Tag checker | ||
* | ||
* @param {DocType} tag | ||
@@ -25,0 +27,0 @@ * @param {number} i index |
@@ -9,3 +9,4 @@ module.exports = checkReturnTypes; | ||
/** | ||
* checking returns types | ||
* Checking returns types | ||
* | ||
* @param {(FunctionDeclaration|FunctionExpression)} node | ||
@@ -21,2 +22,7 @@ * @param {DocTag} tag | ||
// skip abstract methods | ||
if (node.jsdoc.abstract) { | ||
return; | ||
} | ||
// checking redundant: invalid or not return statements in code | ||
@@ -23,0 +29,0 @@ var redundant = !Boolean(this._getReturnStatementsForNode(node).length); |
@@ -9,3 +9,4 @@ module.exports = checkReturnTypes; | ||
/** | ||
* checking returns types | ||
* Checking returns types | ||
* | ||
* @param {(FunctionDeclaration|FunctionExpression)} node | ||
@@ -12,0 +13,0 @@ * @param {DocTag} tag |
@@ -49,3 +49,4 @@ var jsdoc = require('../../jsdoc'); | ||
/** | ||
* validator for types in tags | ||
* Validator for types in tags | ||
* | ||
* @param {JSCS.JSFile} file | ||
@@ -95,6 +96,6 @@ * @param {JSCS.Errors} errors | ||
var lowerType = type.toLowerCase(); | ||
//console.log(capitalizedNativeCase, type, lowerType, strictNatives.hasOwnProperty(type)); | ||
if (!strictNatives.hasOwnProperty(lowerType)) { | ||
return; | ||
} | ||
var normType = strictNatives[lowerType]; | ||
@@ -101,0 +102,0 @@ if (strictNativeCase && type !== normType || |
@@ -8,3 +8,4 @@ module.exports = enforceExistence; | ||
/** | ||
* validator for jsdoc data existance | ||
* Validator for jsdoc data existance | ||
* | ||
* @param {(FunctionDeclaration|FunctionExpression)} node | ||
@@ -11,0 +12,0 @@ * @param {Function} err |
@@ -17,2 +17,5 @@ var assert = require('assert'); | ||
requireNewlineAfterDescription: require('./require-newline-after-description'), | ||
disallowNewlineAfterDescription: require('./disallow-newline-after-description'), | ||
checkRedundantAccess: require('./check-redundant-access'), | ||
@@ -26,2 +29,3 @@ enforceExistence: require('./enforce-existence'), | ||
* loads and initializes existing and required validators | ||
* | ||
* @param {Object} passedOptions | ||
@@ -63,2 +67,3 @@ * @returns {Array.<Function>} | ||
* Validates passed options | ||
* | ||
* @param {Object} validator | ||
@@ -65,0 +70,0 @@ * @param {Object} options |
@@ -35,3 +35,4 @@ module.exports = validateLeadingUnderscoresAccess; | ||
/** | ||
* validator for jsdoc data existance | ||
* Validator for jsdoc data existance | ||
* | ||
* @param {(FunctionDeclaration|FunctionExpression)} node | ||
@@ -38,0 +39,0 @@ * @param {Function} err |
@@ -9,3 +9,4 @@ module.exports = requireHyphenBeforeDescription; | ||
/** | ||
* checking returns types | ||
* Checking returns types | ||
* | ||
* @param {(FunctionDeclaration|FunctionExpression)} node | ||
@@ -12,0 +13,0 @@ * @param {DocTag} tag |
@@ -9,3 +9,4 @@ module.exports = validateParamTag; | ||
/** | ||
* validator for @param | ||
* Validator for @param | ||
* | ||
* @param {(FunctionDeclaration|FunctionExpression)} node | ||
@@ -12,0 +13,0 @@ * @param {DocTag} tag |
@@ -9,3 +9,4 @@ module.exports = requireReturnTypes; | ||
/** | ||
* requiring returns types (?) | ||
* Requiring returns types (?) | ||
* | ||
* @param {(FunctionDeclaration|FunctionExpression)} node | ||
@@ -12,0 +13,0 @@ * @param {DocTag} tag |
@@ -5,3 +5,3 @@ { | ||
"description": "JSCS jsdoc plugin", | ||
"version": "0.4.6", | ||
"version": "1.0.0", | ||
"main": "lib/index", | ||
@@ -27,10 +27,10 @@ "homepage": "https://github.com/jscs-dev/jscs-jsdoc", | ||
"dependencies": { | ||
"comment-parser": "0.2.4", | ||
"comment-parser": "0.3.0", | ||
"jsdoctypeparser": "^1.1.4" | ||
}, | ||
"devDependencies": { | ||
"chai": "^2.2.0", | ||
"jscs": "^1.12.0", | ||
"jshint": "^2.6.3", | ||
"mocha": "^2.2.1" | ||
"chai": "^2.3.0", | ||
"jscs": "^1.13.1", | ||
"jshint": "^2.7.0", | ||
"mocha": "^2.2.4" | ||
}, | ||
@@ -37,0 +37,0 @@ "_peerDependencies": { |
115
README.md
# jscs-jsdoc | ||
[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/jscs-dev/jscs-jsdoc?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) | ||
[![Build Status](https://secure.travis-ci.org/jscs-dev/jscs-jsdoc.svg?branch=master)](http://travis-ci.org/jscs-dev/jscs-jsdoc) | ||
[![NPM version](https://badge.fury.io/js/jscs-jsdoc.png)](http://badge.fury.io/js/jscs-jsdoc) | ||
[![Dependency Status](https://david-dm.org/jscs-dev/jscs-jsdoc.png)](https://david-dm.org/jscs-dev/jscs-jsdoc) | ||
[![Gitter](https://img.shields.io/badge/GITTER-JOIN_CHAT_%E2%86%92-1dce73.svg)](https://gitter.im/jscs-dev/talks?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) | ||
[![Build Status](https://img.shields.io/travis/jscs-dev/jscs-jsdoc.svg)](http://travis-ci.org/jscs-dev/jscs-jsdoc?style=flat) | ||
[![Dependency Status](https://img.shields.io/david/jscs-dev/jscs-jsdoc.svg)](https://david-dm.org/jscs-dev/jscs-jsdoc) | ||
[![Coverage](https://img.shields.io/coveralls/jscs-dev/jscs-jsdoc.svg)](https://coveralls.io/r/jscs-dev/jscs-jsdoc) | ||
[![NPM version](https://img.shields.io/npm/v/jscs-jsdoc.svg)](https://www.npmjs.com/package/jscs-jsdoc) | ||
[![NPM downloads](https://img.shields.io/npm/dm/jscs-jsdoc.svg)](https://www.npmjs.com/package/jscs-jsdoc) | ||
[![MIT License](https://img.shields.io/npm/l/jscs-jsdoc.svg)](https://github.com/jscs-dev/jscs-jsdoc/blob/master/LICENSE) | ||
`jsdoc` plugin for [jscs](https://github.com/jscs-dev/node-jscs/). [Twitter](https://twitter.com/jscs_dev) | [Mailing List](https://groups.google.com/group/jscs-dev) | ||
@@ -91,3 +95,3 @@ | ||
See also [tag presets](https://github.com/jscs-dev/jscs-jsdoc/tree/hotfix/check-annotations-rework/lib/tags). | ||
See also [tag presets](https://github.com/jscs-dev/jscs-jsdoc/tree/master/lib/tags). | ||
@@ -616,2 +620,103 @@ #### Example | ||
### requireNewlineAfterDescription | ||
Ensures a doc comment description has padding newline | ||
Type: `Boolean` | ||
Values: `true` | ||
Context: `functions` | ||
Tags: `*` | ||
#### Example | ||
```js | ||
"requireNewlineAfterDescription": true | ||
``` | ||
##### Valid | ||
```js | ||
/** | ||
* @param {String} - message | ||
*/ | ||
function method() {} | ||
/** | ||
* Description | ||
*/ | ||
function method() {} | ||
/** | ||
* Description | ||
* | ||
* @param {String} - message | ||
*/ | ||
function method() {} | ||
``` | ||
##### Invalid | ||
```js | ||
/** | ||
* Description | ||
* @param {String} message | ||
*/ | ||
function method() {} | ||
``` | ||
### disallowNewlineAfterDescription | ||
Ensures a doc comment description has no padding newlines | ||
Type: `Boolean` | ||
Values: `true` | ||
Context: `functions` | ||
Tags: `*` | ||
#### Example | ||
```js | ||
"disallowNewlineAfterDescription": true | ||
``` | ||
##### Valid | ||
```js | ||
/** | ||
* @param {String} - message | ||
*/ | ||
function method() {} | ||
/** | ||
* Description | ||
*/ | ||
function method() {} | ||
/** | ||
* Description | ||
* @param {String} - message | ||
*/ | ||
function method() {} | ||
``` | ||
##### Invalid | ||
```js | ||
/** | ||
* Description | ||
* | ||
* @param {String} message | ||
*/ | ||
function method() {} | ||
``` | ||
## Browser Usage | ||
@@ -618,0 +723,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
89369
27
1667
0
741
+ Addedcomment-parser@0.3.0(transitive)
- Removedcomment-parser@0.2.4(transitive)
Updatedcomment-parser@0.3.0