mirror of
https://github.com/jsdoc/jsdoc.git
synced 2025-12-08 19:46:11 +00:00
refactor: move ast-builder and ast-node to @jsdoc/parse
BREAKING CHANGE: Modules no longer exist in jsdoc package.
This commit is contained in:
parent
86d18ff44a
commit
65e6db3ba4
@ -1,5 +1,9 @@
|
|||||||
|
const { AstBuilder } = require('./lib/ast-builder');
|
||||||
|
const astNode = require('./lib/ast-node');
|
||||||
const { Syntax } = require('./lib/syntax');
|
const { Syntax } = require('./lib/syntax');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
AstBuilder,
|
||||||
|
astNode,
|
||||||
Syntax
|
Syntax
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,7 +2,7 @@ const _ = require('lodash');
|
|||||||
const babelParser = require('@babel/parser');
|
const babelParser = require('@babel/parser');
|
||||||
const { log } = require('@jsdoc/util');
|
const { log } = require('@jsdoc/util');
|
||||||
|
|
||||||
// exported so we can use them in tests
|
// Exported so we can use them in tests.
|
||||||
const parserOptions = exports.parserOptions = {
|
const parserOptions = exports.parserOptions = {
|
||||||
allowAwaitOutsideFunction: true,
|
allowAwaitOutsideFunction: true,
|
||||||
allowImportExportEverywhere: true,
|
allowImportExportEverywhere: true,
|
||||||
@ -58,10 +58,8 @@ function parse(source, filename, sourceType) {
|
|||||||
// TODO: docs
|
// TODO: docs
|
||||||
class AstBuilder {
|
class AstBuilder {
|
||||||
// TODO: docs
|
// TODO: docs
|
||||||
/* eslint-disable class-methods-use-this */
|
static build(source, filename, sourceType) {
|
||||||
build(source, filename, sourceType) {
|
|
||||||
return parse(source, filename, sourceType);
|
return parse(source, filename, sourceType);
|
||||||
}
|
}
|
||||||
/* eslint-enable class-methods-use-this */
|
|
||||||
}
|
}
|
||||||
exports.AstBuilder = AstBuilder;
|
exports.AstBuilder = AstBuilder;
|
||||||
@ -1,9 +1,9 @@
|
|||||||
// TODO: docs
|
// TODO: docs
|
||||||
/** @module jsdoc/src/astnode */
|
/** @module @jsdoc/parse.astNode */
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const { cast } = require('@jsdoc/util');
|
const { cast } = require('@jsdoc/util');
|
||||||
const { SCOPE } = require('@jsdoc/core').name;
|
const { SCOPE } = require('@jsdoc/core').name;
|
||||||
const { Syntax } = require('@jsdoc/parse');
|
const { Syntax } = require('./syntax');
|
||||||
|
|
||||||
// Counter for generating unique node IDs.
|
// Counter for generating unique node IDs.
|
||||||
let uid = 100000000;
|
let uid = 100000000;
|
||||||
@ -11,7 +11,7 @@ let uid = 100000000;
|
|||||||
/**
|
/**
|
||||||
* Check whether an AST node represents a function.
|
* Check whether an AST node represents a function.
|
||||||
*
|
*
|
||||||
* @alias module:jsdoc/src/astnode.isFunction
|
* @alias module:@jsdoc/parse.astNode.isFunction
|
||||||
* @param {(Object|string)} node - The AST node to check, or the `type` property of a node.
|
* @param {(Object|string)} node - The AST node to check, or the `type` property of a node.
|
||||||
* @return {boolean} Set to `true` if the node is a function or `false` in all other cases.
|
* @return {boolean} Set to `true` if the node is a function or `false` in all other cases.
|
||||||
*/
|
*/
|
||||||
@ -36,7 +36,7 @@ const isFunction = exports.isFunction = node => {
|
|||||||
/**
|
/**
|
||||||
* Check whether an AST node creates a new scope.
|
* Check whether an AST node creates a new scope.
|
||||||
*
|
*
|
||||||
* @alias module:jsdoc/src/astnode.isScope
|
* @alias module:@jsdoc/parse.astNode.isScope
|
||||||
* @param {Object} node - The AST node to check.
|
* @param {Object} node - The AST node to check.
|
||||||
* @return {Boolean} Set to `true` if the node creates a new scope, or `false` in all other cases.
|
* @return {Boolean} Set to `true` if the node creates a new scope, or `false` in all other cases.
|
||||||
*/
|
*/
|
||||||
@ -5,6 +5,22 @@ describe('@jsdoc/parse', () => {
|
|||||||
expect(parse).toBeObject();
|
expect(parse).toBeObject();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('AstBuilder', () => {
|
||||||
|
it('is lib/ast-builder.AstBuilder', () => {
|
||||||
|
const { AstBuilder } = require('../../lib/ast-builder');
|
||||||
|
|
||||||
|
expect(parse.AstBuilder).toBe(AstBuilder);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('astNode', () => {
|
||||||
|
it('is lib/ast-node', () => {
|
||||||
|
const astNode = require('../../lib/ast-node');
|
||||||
|
|
||||||
|
expect(parse.astNode).toBe(astNode);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('Syntax', () => {
|
describe('Syntax', () => {
|
||||||
it('is lib/syntax.Syntax', () => {
|
it('is lib/syntax.Syntax', () => {
|
||||||
const { Syntax } = require('../../lib/syntax');
|
const { Syntax } = require('../../lib/syntax');
|
||||||
|
|||||||
41
packages/jsdoc-parse/test/specs/lib/ast-builder.js
Normal file
41
packages/jsdoc-parse/test/specs/lib/ast-builder.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/* global jsdoc */
|
||||||
|
describe('@jsdoc/parse/lib/ast-builder', () => {
|
||||||
|
const astBuilder = require('../../../lib/ast-builder');
|
||||||
|
|
||||||
|
it('is an object', () => {
|
||||||
|
expect(astBuilder).toBeObject();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('exports an AstBuilder class', () => {
|
||||||
|
expect(astBuilder.AstBuilder).toBeFunction();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('exports a parserOptions object', () => {
|
||||||
|
expect(astBuilder.parserOptions).toBeObject();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('AstBuilder', () => {
|
||||||
|
const { AstBuilder } = astBuilder;
|
||||||
|
|
||||||
|
// TODO: more tests
|
||||||
|
it('has a "build" static method', () => {
|
||||||
|
expect(AstBuilder.build).toBeFunction();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('build', () => {
|
||||||
|
// TODO: more tests
|
||||||
|
it('logs (not throws) an error when a file cannot be parsed', () => {
|
||||||
|
function parse() {
|
||||||
|
AstBuilder.build('qwerty!!!!!', 'bad.js');
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(parse).not.toThrow();
|
||||||
|
expect(jsdoc.didLog(parse, 'error')).toBeTrue();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('parserOptions', () => {
|
||||||
|
// TODO: tests
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -1,11 +1,11 @@
|
|||||||
describe('jsdoc/src/astNode', () => {
|
describe('@jsdoc/parse/lib/ast-node', () => {
|
||||||
const astBuilder = require('jsdoc/src/astbuilder');
|
const astNode = require('../../../lib/ast-node');
|
||||||
const astNode = require('jsdoc/src/astnode');
|
|
||||||
const babelParser = require('@babel/parser');
|
const babelParser = require('@babel/parser');
|
||||||
const { Syntax } = require('@jsdoc/parse');
|
const { parserOptions } = require('../../../lib/ast-builder');
|
||||||
|
const { Syntax } = require('../../../lib/syntax');
|
||||||
|
|
||||||
function parse(str) {
|
function parse(str) {
|
||||||
return babelParser.parse(str, astBuilder.parserOptions).program.body[0];
|
return babelParser.parse(str, parserOptions).program.body[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the AST nodes we'll be testing
|
// create the AST nodes we'll be testing
|
||||||
@ -526,8 +526,8 @@ describe('jsdoc/src/astNode', () => {
|
|||||||
|
|
||||||
// TODO: we can't test this here because JSDoc, not Babylon, adds the `parent` property to
|
// TODO: we can't test this here because JSDoc, not Babylon, adds the `parent` property to
|
||||||
// nodes. also, we currently return an empty string instead of `<anonymous>` in this case;
|
// nodes. also, we currently return an empty string instead of `<anonymous>` in this case;
|
||||||
// see `module:jsdoc/src/astnode.nodeToValue` and the comment on `Syntax.MethodDefinition`
|
// see `module:@jsdoc/parse.astNode.nodeToValue` and the comment on
|
||||||
// for details
|
// `Syntax.MethodDefinition` for details
|
||||||
xit('should return `<anonymous>` for method definitions inside classes that were ' +
|
xit('should return `<anonymous>` for method definitions inside classes that were ' +
|
||||||
'returned by an arrow function expression', () => {
|
'returned by an arrow function expression', () => {
|
||||||
expect( astNode.nodeToValue(methodDefinition2) ).toBe('<anonymous>');
|
expect( astNode.nodeToValue(methodDefinition2) ).toBe('<anonymous>');
|
||||||
@ -3,7 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
let dictionary = require('jsdoc/tag/dictionary');
|
let dictionary = require('jsdoc/tag/dictionary');
|
||||||
const { isFunction } = require('jsdoc/src/astnode');
|
const { isFunction } = require('@jsdoc/parse').astNode;
|
||||||
const {
|
const {
|
||||||
applyNamespace,
|
applyNamespace,
|
||||||
hasLeadingScope,
|
hasLeadingScope,
|
||||||
@ -31,7 +31,7 @@ function fakeMeta(node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// use the meta info about the source code to guess what the doclet kind should be
|
// use the meta info about the source code to guess what the doclet kind should be
|
||||||
// TODO: set this elsewhere (maybe jsdoc/src/astnode.getInfo)
|
// TODO: set this elsewhere (maybe @jsdoc/parse.astNode.getInfo)
|
||||||
function codeToKind(code) {
|
function codeToKind(code) {
|
||||||
let kind = 'member';
|
let kind = 'member';
|
||||||
const node = code.node;
|
const node = code.node;
|
||||||
|
|||||||
@ -2,12 +2,13 @@
|
|||||||
* @module jsdoc/src/parser
|
* @module jsdoc/src/parser
|
||||||
*/
|
*/
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const astNode = require('jsdoc/src/astnode');
|
const { AstBuilder, astNode, Syntax } = require('@jsdoc/parse');
|
||||||
const { EventEmitter } = require('events');
|
const { EventEmitter } = require('events');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const { log } = require('@jsdoc/util');
|
const { log } = require('@jsdoc/util');
|
||||||
const { getBasename, LONGNAMES, SCOPE, toParts } = require('@jsdoc/core').name;
|
const { getBasename, LONGNAMES, SCOPE, toParts } = require('@jsdoc/core').name;
|
||||||
const { Syntax } = require('@jsdoc/parse');
|
const { Visitor } = require('jsdoc/src/visitor');
|
||||||
|
const { Walker } = require('jsdoc/src/walker');
|
||||||
|
|
||||||
const hasOwnProp = Object.prototype.hasOwnProperty;
|
const hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
|
||||||
@ -61,7 +62,7 @@ exports.createParser = (type, conf) => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new (require(modulePath).Parser)(null, null, null, conf);
|
return new (require(modulePath).Parser)(conf);
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: docs
|
// TODO: docs
|
||||||
@ -89,24 +90,18 @@ function definedInScope(doclet, basename) {
|
|||||||
*/
|
*/
|
||||||
class Parser extends EventEmitter {
|
class Parser extends EventEmitter {
|
||||||
// TODO: docs
|
// TODO: docs
|
||||||
constructor(builderInstance, visitorInstance, walkerInstance, conf) {
|
constructor(conf) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.clear();
|
this.clear();
|
||||||
|
|
||||||
this._astBuilder = builderInstance || new (require('jsdoc/src/astbuilder').AstBuilder)();
|
|
||||||
this._conf = conf || {};
|
this._conf = conf || {};
|
||||||
this._visitor = visitorInstance || new (require('jsdoc/src/visitor').Visitor)();
|
this._visitor = new Visitor();
|
||||||
this._walker = walkerInstance || new (require('jsdoc/src/walker').Walker)();
|
this._walker = new Walker();
|
||||||
|
|
||||||
this._visitor.setParser(this);
|
this._visitor.setParser(this);
|
||||||
|
|
||||||
Object.defineProperties(this, {
|
Object.defineProperties(this, {
|
||||||
astBuilder: {
|
|
||||||
get() {
|
|
||||||
return this._astBuilder;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
visitor: {
|
visitor: {
|
||||||
get() {
|
get() {
|
||||||
return this._visitor;
|
return this._visitor;
|
||||||
@ -285,7 +280,7 @@ class Parser extends EventEmitter {
|
|||||||
sourceCode = pretreat(e.source);
|
sourceCode = pretreat(e.source);
|
||||||
sourceType = this._conf.source ? this._conf.source.type : undefined;
|
sourceType = this._conf.source ? this._conf.source.type : undefined;
|
||||||
|
|
||||||
ast = this._astBuilder.build(sourceCode, sourceName, sourceType);
|
ast = AstBuilder.build(sourceCode, sourceName, sourceType);
|
||||||
if (ast) {
|
if (ast) {
|
||||||
this._walkAst(ast, this._visitor, sourceName);
|
this._walkAst(ast, this._visitor, sourceName);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
* @module jsdoc/src/visitor
|
* @module jsdoc/src/visitor
|
||||||
*/
|
*/
|
||||||
// TODO: consider exporting more stuff so users can override it
|
// TODO: consider exporting more stuff so users can override it
|
||||||
const astNode = require('jsdoc/src/astnode');
|
const { astNode } = require('@jsdoc/parse');
|
||||||
const combineDoclets = require('jsdoc/doclet').combine;
|
const combineDoclets = require('jsdoc/doclet').combine;
|
||||||
const { getBasename, LONGNAMES } = require('@jsdoc/core').name;
|
const { getBasename, LONGNAMES } = require('@jsdoc/core').name;
|
||||||
const { Syntax } = require('@jsdoc/parse');
|
const { Syntax } = require('@jsdoc/parse');
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* @module jsdoc/src/walker
|
* @module jsdoc/src/walker
|
||||||
*/
|
*/
|
||||||
const astnode = require('jsdoc/src/astnode');
|
const { astNode } = require('@jsdoc/parse');
|
||||||
const { log } = require('@jsdoc/util');
|
const { log } = require('@jsdoc/util');
|
||||||
const { Syntax } = require('@jsdoc/parse');
|
const { Syntax } = require('@jsdoc/parse');
|
||||||
|
|
||||||
@ -655,9 +655,9 @@ class Walker {
|
|||||||
function cb(node, parent, cbState) {
|
function cb(node, parent, cbState) {
|
||||||
let currentScope;
|
let currentScope;
|
||||||
|
|
||||||
const isScope = astnode.isScope(node);
|
const isScope = astNode.isScope(node);
|
||||||
|
|
||||||
astnode.addNodeProperties(node);
|
astNode.addNodeProperties(node);
|
||||||
node.parent = parent || null;
|
node.parent = parent || null;
|
||||||
|
|
||||||
currentScope = getCurrentScope(cbState.scopes);
|
currentScope = getCurrentScope(cbState.scopes);
|
||||||
|
|||||||
@ -8,7 +8,7 @@ const commonPathPrefix = require('common-path-prefix');
|
|||||||
const env = require('jsdoc/env');
|
const env = require('jsdoc/env');
|
||||||
const { isInlineTag } = require('jsdoc/tag/inline');
|
const { isInlineTag } = require('jsdoc/tag/inline');
|
||||||
const { log } = require('@jsdoc/util');
|
const { log } = require('@jsdoc/util');
|
||||||
const { nodeToValue } = require('jsdoc/src/astnode');
|
const { nodeToValue } = require('@jsdoc/parse').astNode;
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { Syntax } = require('@jsdoc/parse');
|
const { Syntax } = require('@jsdoc/parse');
|
||||||
const parseTagType = require('jsdoc/tag/type').parse;
|
const parseTagType = require('jsdoc/tag/type').parse;
|
||||||
|
|||||||
@ -20,8 +20,8 @@ describe('arrow functions', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// TODO: we currently use the wrong longname in this case; see
|
// TODO: we currently use the wrong longname in this case; see
|
||||||
// `module:jsdoc/src/astnode.nodeToValue` and the comment on `case Syntax.MethodDefinition` for
|
// `module:@jsdoc/parse.astNode.nodeToValue` and the comment on `case Syntax.MethodDefinition`
|
||||||
// details
|
// for details
|
||||||
xit('should use the correct longname for members of a class returned by an arrow function',
|
xit('should use the correct longname for members of a class returned by an arrow function',
|
||||||
() => {
|
() => {
|
||||||
expect(name).toBeArrayOfSize(2);
|
expect(name).toBeArrayOfSize(2);
|
||||||
|
|||||||
@ -1,36 +0,0 @@
|
|||||||
describe('jsdoc/src/astbuilder', () => {
|
|
||||||
const astbuilder = require('jsdoc/src/astbuilder');
|
|
||||||
|
|
||||||
it('should exist', () => {
|
|
||||||
expect(astbuilder).toBeObject();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should export an AstBuilder class', () => {
|
|
||||||
expect(astbuilder.AstBuilder).toBeFunction();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('AstBuilder', () => {
|
|
||||||
// TODO: more tests
|
|
||||||
let builder;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
builder = new astbuilder.AstBuilder();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should provide a "build" method', () => {
|
|
||||||
expect(builder.build).toBeFunction();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('build', () => {
|
|
||||||
// TODO: more tests
|
|
||||||
it('should log (not throw) an error when a file cannot be parsed', () => {
|
|
||||||
function parse() {
|
|
||||||
builder.build('qwerty!!!!!', 'bad.js');
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(parse).not.toThrow();
|
|
||||||
expect(jsdoc.didLog(parse, 'error')).toBeTrue();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -49,10 +49,6 @@ describe('jsdoc/src/parser', () => {
|
|||||||
|
|
||||||
newParser();
|
newParser();
|
||||||
|
|
||||||
it('should have an "astBuilder" property', () => {
|
|
||||||
expect(parser.astBuilder).toBeObject();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have a "visitor" property', () => {
|
it('should have a "visitor" property', () => {
|
||||||
expect(parser.visitor).toBeObject();
|
expect(parser.visitor).toBeObject();
|
||||||
});
|
});
|
||||||
@ -61,22 +57,6 @@ describe('jsdoc/src/parser', () => {
|
|||||||
expect(parser.walker).toBeObject();
|
expect(parser.walker).toBeObject();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should accept an astBuilder, visitor, and walker as arguments', () => {
|
|
||||||
const astBuilder = {};
|
|
||||||
const visitor = {
|
|
||||||
/* eslint-disable no-empty-function */
|
|
||||||
setParser() {}
|
|
||||||
/* eslint-enable no-empty-function */
|
|
||||||
};
|
|
||||||
const walker = {};
|
|
||||||
|
|
||||||
const myParser = new jsdocParser.Parser(astBuilder, visitor, walker);
|
|
||||||
|
|
||||||
expect(myParser.astBuilder).toBe(astBuilder);
|
|
||||||
expect(myParser.visitor).toBe(visitor);
|
|
||||||
expect(myParser.walker).toBe(walker);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have a "parse" method', () => {
|
it('should have a "parse" method', () => {
|
||||||
expect(parser.parse).toBeFunction();
|
expect(parser.parse).toBeFunction();
|
||||||
});
|
});
|
||||||
@ -93,14 +73,6 @@ describe('jsdoc/src/parser', () => {
|
|||||||
expect(parser.getAstNodeVisitors).toBeFunction();
|
expect(parser.getAstNodeVisitors).toBeFunction();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('astBuilder', () => {
|
|
||||||
it('should contain an appropriate astBuilder by default', () => {
|
|
||||||
const { AstBuilder } = require('jsdoc/src/astbuilder');
|
|
||||||
|
|
||||||
expect(parser.astBuilder instanceof AstBuilder).toBeTrue();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('visitor', () => {
|
describe('visitor', () => {
|
||||||
it('should contain an appropriate visitor by default', () => {
|
it('should contain an appropriate visitor by default', () => {
|
||||||
const { Visitor } = require('jsdoc/src/visitor');
|
const { Visitor } = require('jsdoc/src/visitor');
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user