Implement documentation linter (#47)

This patch implements documentation linter, which leaves under `test/doclint`
folder.

The documentation linter works like this:
1. Parse javascript source code with esprima and construct a "documentation" out of source code
2. Generate HTML out of `api.md` and traverse the HTML with puppeteer.
3. Make sure javascript aligns nicely with HTML

The documentation linter adds the following commands:
- `yarn doc` - to test that documentation covers all the relevant apis
- `yarn generate-toc` - to update the table-of-contents for the `api.md`
This commit is contained in:
Andrey Lushnikov
2017-07-07 19:36:45 +03:00
committed by GitHub
parent 18b2a46a83
commit 62cacbe5f5
11 changed files with 1715 additions and 61 deletions

14
third_party/chromium/CHANGES.md vendored Normal file
View File

@@ -0,0 +1,14 @@
Short Name: Chromium
URL: https://chromium.org
Version: 484360
License: The Chromium License
License File: LICENSE
Security Critical: no
Description:
This package is used to get the ESTreeWalker file from Chrome DevTools frontend:
- ESTreeWalker.js
Local Modifications:
- The "formatterWorker" namespace was removed

135
third_party/chromium/ESTreeWalker.js vendored Normal file
View File

@@ -0,0 +1,135 @@
// Copyright (c) 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @unrestricted
*/
class ESTreeWalker {
/**
* @param {function(!ESTree.Node):(!Object|undefined)} beforeVisit
* @param {function(!ESTree.Node)=} afterVisit
*/
constructor(beforeVisit, afterVisit) {
this._beforeVisit = beforeVisit;
this._afterVisit = afterVisit || new Function();
}
/**
* @param {!ESTree.Node} ast
*/
walk(ast) {
this._innerWalk(ast, null);
}
/**
* @param {!ESTree.Node} node
* @param {?ESTree.Node} parent
*/
_innerWalk(node, parent) {
if (!node)
return;
node.parent = parent;
if (this._beforeVisit.call(null, node) === ESTreeWalker.SkipSubtree) {
this._afterVisit.call(null, node);
return;
}
let walkOrder = ESTreeWalker._walkOrder[node.type];
if (!walkOrder)
return;
if (node.type === 'TemplateLiteral') {
let templateLiteral = /** @type {!ESTree.TemplateLiteralNode} */ (node);
let expressionsLength = templateLiteral.expressions.length;
for (let i = 0; i < expressionsLength; ++i) {
this._innerWalk(templateLiteral.quasis[i], templateLiteral);
this._innerWalk(templateLiteral.expressions[i], templateLiteral);
}
this._innerWalk(templateLiteral.quasis[expressionsLength], templateLiteral);
} else {
for (let i = 0; i < walkOrder.length; ++i) {
let entity = node[walkOrder[i]];
if (Array.isArray(entity))
this._walkArray(entity, node);
else
this._innerWalk(entity, node);
}
}
this._afterVisit.call(null, node);
}
/**
* @param {!Array.<!ESTree.Node>} nodeArray
* @param {?ESTree.Node} parentNode
*/
_walkArray(nodeArray, parentNode) {
for (let i = 0; i < nodeArray.length; ++i)
this._innerWalk(nodeArray[i], parentNode);
}
}
/** @typedef {!Object} ESTreeWalker.SkipSubtree */
ESTreeWalker.SkipSubtree = {};
/** @enum {!Array.<string>} */
ESTreeWalker._walkOrder = {
'AwaitExpression': ['arguments'],
'ArrayExpression': ['elements'],
'ArrowFunctionExpression': ['params', 'body'],
'AssignmentExpression': ['left', 'right'],
'BinaryExpression': ['left', 'right'],
'BlockStatement': ['body'],
'BreakStatement': ['label'],
'CallExpression': ['callee', 'arguments'],
'CatchClause': ['param', 'body'],
'ClassBody': ['body'],
'ClassDeclaration': ['id', 'superClass', 'body'],
'ClassExpression': ['id', 'superClass', 'body'],
'ConditionalExpression': ['test', 'consequent', 'alternate'],
'ContinueStatement': ['label'],
'DebuggerStatement': [],
'DoWhileStatement': ['body', 'test'],
'EmptyStatement': [],
'ExpressionStatement': ['expression'],
'ForInStatement': ['left', 'right', 'body'],
'ForOfStatement': ['left', 'right', 'body'],
'ForStatement': ['init', 'test', 'update', 'body'],
'FunctionDeclaration': ['id', 'params', 'body'],
'FunctionExpression': ['id', 'params', 'body'],
'Identifier': [],
'IfStatement': ['test', 'consequent', 'alternate'],
'LabeledStatement': ['label', 'body'],
'Literal': [],
'LogicalExpression': ['left', 'right'],
'MemberExpression': ['object', 'property'],
'MethodDefinition': ['key', 'value'],
'NewExpression': ['callee', 'arguments'],
'ObjectExpression': ['properties'],
'ObjectPattern': ['properties'],
'ParenthesizedExpression': ['expression'],
'Program': ['body'],
'Property': ['key', 'value'],
'ReturnStatement': ['argument'],
'SequenceExpression': ['expressions'],
'Super': [],
'SwitchCase': ['test', 'consequent'],
'SwitchStatement': ['discriminant', 'cases'],
'TaggedTemplateExpression': ['tag', 'quasi'],
'TemplateElement': [],
'TemplateLiteral': ['quasis', 'expressions'],
'ThisExpression': [],
'ThrowStatement': ['argument'],
'TryStatement': ['block', 'handler', 'finalizer'],
'UnaryExpression': ['argument'],
'UpdateExpression': ['argument'],
'VariableDeclaration': ['declarations'],
'VariableDeclarator': ['id', 'init'],
'WhileStatement': ['test', 'body'],
'WithStatement': ['object', 'body'],
'YieldExpression': ['argument']
};
module.exports = ESTreeWalker;

27
third_party/chromium/LICENSE vendored Normal file
View File

@@ -0,0 +1,27 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.