Skip to content

Commit

Permalink
add dev docs with internal api for happy contributing
Browse files Browse the repository at this point in the history
Fixes #53
  • Loading branch information
Alexej Yaroshevich committed Nov 18, 2014
1 parent 4ba9648 commit dc6bf05
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CONTRIBUTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,7 @@ Features
It you've got an idea about a new feature, it's most likely that you'll have to implement it on your own.
If you cannot implement the feature, but it is very important, you can create an issue at GitHub,
but expect it to be declined by the maintainer.

Feel free to add your own rules. We really need to know your guide styles to write js documentation.

Please read [maintainers guide](./MAINTAIN.md) with inner API and some other things.
161 changes: 161 additions & 0 deletions MAINTAIN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
# README for contributors

## Naming convention

Rules should be placed as they are in configuration. Their names should be hyphenized (as well as in jscs).

Tests for them should be placed in the same manner in `./test` directory. For one rule file should be maked one test file with the same name.

## Rule formats

There are 3 rule formats atm to simplify developing:

- Classic (used in `jscs`) - function with JSFile and JSErrors objects
- Scope based - function with specified scope and 2 params: esprima node object and err callback
- Tag based - function with specified tags and 3 params: DocTag, esprima node object (if exists) and err callback

Scopes and tags are pretty fine for structurizing rules for jsdocs (at some pov) but also there are iterators in file and jsdoc blocks.

### Classic

Some times you need to have full data of file to check it. You can take a look at [checkTypes rule](https://github.com/jscs-dev/jscs-jsdoc/blob/master/lib/rules/validate-jsdoc/check-types.js)

```js
// passing a function
module.exports = ruleChecker;
// define a scope 'file'
module.exports.scopes = ['file'];
// define allowed options
module.exports.options = {
rule: {allowedValues: [true]}
};

/**
* @param {JSCS.JSFile} file
* @param {JSCS.Errors} errors
*/
function ruleChecker(file, errors) {
var comments = file.getComments();
comments.forEach(function(commentNode) {
if (commentNode.type !== 'Block' || commentNode.value[0] !== '*') {
return;
}

// trying to create DocComment object
var node = jsdoc.createDocCommentByCommentNode(commentNode);
if (!node.valid) {
errors.add('invalid doc comment block', node.loc.start);
}

node.iterate(function(tag) {
// test tags here
)}
});
}
```
### Scope based
For now it's only function scope. But it could be a variable, or some other important places. (need to know about it actually)
```js
module.exports = ruleChecker;
module.exports.scopes = ['function'];
module.exports.options = {
rule: {allowedValues: [true]}
};

/**
* @param {(FunctionDeclaration|FunctionExpression)} node
* @param {function(string,DocLocation|number,?number)} err
*/
function ruleChecker(node, err) {
if (!node.jsdoc) {
return;
}

// will check only `@nohugshere` tags in function jsdocs
node.jsdoc.iterateByType(['nohugshere'],
function (tag, i) {
if (tag.value.indexOf('hug')) {
err('hug found in tag ' + tag.id, tag.loc);
}
});
}
```
### Tag based
```js
module.exports = ruleChecker;
module.exports.tags = ['foo', 'bar', 'baz'];
module.exports.scopes = ['function'];
module.exports.options = {
rule: {allowedValues: [true]}
};

/**
* @param {(FunctionDeclaration|FunctionExpression)} node
* @param {DocTag} tag
* @param {Function} err
*/
function ruleChecker(node, tag, err) {
// etc.
}
```
## Tests
The root name of each test should be full path name of rule without `.js` suffix (to simplify debugging process).
Each section in test file could be splitted to several sections: allowed params tests, functional tests, and location tests.
Also there're [some helpers](./test/init.js) to simplify test development. Most important of them are global.checker, and chai's `.deep.similar` assertion.
### Tests checker
This object provides few methods to make tests much easier:
- __construct(opts) - makes checker wrapper object
- configure(opts) - to configure checker instantly
- check - to check case instantly
- rules - to configure checker before each case
- cases - to describe what cases it should check
```js
describe('lib/rules/validate-jsdoc/some-rule', function () {
var checker = global.checker({
additionalRules: ['lib/rules/validate-jsdoc.js']
});

checker.rules({commonRule: true});
checker.cases([
/* jshint ignore:start */
{
it: 'should not report',
code: function() {
// some code here
}
}, {
it: 'should report something',
errors: 1,
code: function () {}
}, {
it: 'should report something concrete',
errors: {loc: {line: 5, column:10}},
code: function () {}
}, {
it: 'should be called with additional rules',
rules: {additionalRule: 'orAnother'},
errors: {loc: {line: 5, column:10}},
code: function () {}
}
/* jshint ignore:end */
]);
});
```
## Another helpful things
There're pretty simple `Doc*` objects so please take a look at [their code](./lib/jsdoc.js).
Also we have some helpers in the [root rule file](./lib/rules/validate-jsdoc.js).

0 comments on commit dc6bf05

Please sign in to comment.