diff --git a/lib/container.js b/lib/container.js index 60b24e7..fc9f5c2 100644 --- a/lib/container.js +++ b/lib/container.js @@ -62,7 +62,7 @@ function Container(options) { * as a previous call, the same object will be returned. * * @param {string} importedPath - * @param {?Module} fromModule + * @param {Module=} fromModule * @return {Module} */ Container.prototype.getModule = function(importedPath, fromModule) { @@ -102,7 +102,7 @@ Container.prototype.addModule = function(mod) { var name = mod.name; var baseName = name; var counter = 0; - var nameExists = false; + var nameExists; while (true) { nameExists = modules.some(function(existingModule) { @@ -146,7 +146,7 @@ Container.prototype.write = function(target) { /** * Converts the contents of this container using the current formatter. * - * @returns {File[]} + * @return {File[]} */ Container.prototype.convert = function() { if (this.formatter.beforeConvert) { @@ -173,9 +173,7 @@ Container.prototype.findImportedModules = function() { lastModuleCount = knownModules.length; for (var i = 0; i < lastModuleCount; i++) { // Force loading of imported modules. - /* jshint expr:true */ - knownModules[i].imports.modules; - /* jshint expr:false */ + noop(knownModules[i].imports.modules); } } }; @@ -183,7 +181,7 @@ Container.prototype.findImportedModules = function() { /** * Gets the modules in this container in no particular order. * - * @returns {Module[]} + * @return {Module[]} */ Container.prototype.getModules = function() { var modules = this.modules; @@ -192,4 +190,10 @@ Container.prototype.getModules = function() { }); }; +/** + * Does nothing. This is only here to make JSHint/other static analysis + * tools happy about using getters for side effects. + */ +function noop() {} + module.exports = Container; diff --git a/lib/declaration_info.js b/lib/declaration_info.js index 64c9d1e..b4fb31c 100644 --- a/lib/declaration_info.js +++ b/lib/declaration_info.js @@ -26,12 +26,12 @@ var n = types.namedTypes; function DeclarationInfo(declaration, identifier) { /** * @type {Node} - * @property declaration + * @name DeclarationInfo#declaration */ this.declaration = declaration; /** * @type {Identifier} - * @property identifier + * @name DeclarationInfo#identifier */ this.identifier = identifier; } diff --git a/lib/exports.js b/lib/exports.js index 93e5640..1e144a1 100644 --- a/lib/exports.js +++ b/lib/exports.js @@ -20,6 +20,7 @@ var sourcePosition = utils.sourcePosition; * Represents a list of the exports for the given module. * * @constructor + * @extends ModuleBindingList * @param {Module} mod */ function ExportDeclarationList(mod) { @@ -29,7 +30,7 @@ extend(ExportDeclarationList, ModuleBindingList); /** * @private - * @param {Node} node + * @param {AST.Declaration} node * @return {boolean} */ ExportDeclarationList.prototype.isMatchingBinding = function(node) { @@ -40,8 +41,8 @@ ExportDeclarationList.prototype.isMatchingBinding = function(node) { * Gets an export declaration for the given `node`. * * @private - * @param {ExportDeclaration} node - * @return {Import} + * @param {AST.ExportDeclaration} node + * @return {ExportDeclaration} */ ExportDeclarationList.prototype.declarationForNode = function(node) { if (node.default) { @@ -67,7 +68,7 @@ ExportDeclarationList.prototype.declarationForNode = function(node) { ExportDeclarationList.prototype.findSpecifierForReference = function(referencePath) { if (n.ExportSpecifier.check(referencePath.parent.node) && referencePath.parent.parent.node.source) { // This is a direct export from another module, e.g. `export { foo } from 'foo'`. - return this.findSpecifierByIdentifier(referencePath.node); + return /** @type {ExportSpecifier} */this.findSpecifierByIdentifier(referencePath.node); } var declaration = this.findDeclarationForReference(referencePath); @@ -76,7 +77,7 @@ ExportDeclarationList.prototype.findSpecifierForReference = function(referencePa return null; } - var specifier = this.findSpecifierByName(declaration.node.name); + var specifier = /** @type {ExportSpecifier} */this.findSpecifierByName(declaration.node.name); assert.ok( specifier, 'no specifier found for `' + referencePath.node.name + '`! this should not happen!' @@ -113,7 +114,7 @@ ExportDeclaration.prototype.inspect = function() { }; /** - * @alias inspect + * @see ExportDeclaration#inspect */ ExportDeclaration.prototype.toString = ExportDeclaration.prototype.inspect; @@ -125,7 +126,7 @@ ExportDeclaration.prototype.toString = ExportDeclaration.prototype.inspect; * @constructor * @extends ExportDeclaration * @param {Module} mod - * @param {ExportDeclaration} node + * @param {AST.ExportDeclaration} node */ function DefaultExportDeclaration(mod, node) { ExportDeclaration.call(this, mod, node); @@ -136,9 +137,9 @@ extend(DefaultExportDeclaration, ExportDeclaration); * Contains a list of specifier name information for this export. * * @type {ExportSpecifier[]} - * @property specifiers + * @name DefaultExportSpecifier#specifiers */ -memo(DefaultExportDeclaration.prototype, 'specifiers', function() { +memo(DefaultExportDeclaration.prototype, 'specifiers', /** @this DefaultExportDeclaration */function() { var specifier = new DefaultExportSpecifier(this, this.node.declaration); return [specifier]; }); @@ -151,7 +152,7 @@ memo(DefaultExportDeclaration.prototype, 'specifiers', function() { * @constructor * @extends ExportDeclaration * @param {Module} mod - * @param {ExportDeclaration} node + * @param {AST.ExportDeclaration} node */ function NamedExportDeclaration(mod, node) { ExportDeclaration.call(this, mod, node); @@ -162,9 +163,9 @@ extend(NamedExportDeclaration, ExportDeclaration); * Contains a list of specifier name information for this export. * * @type {ExportSpecifier[]} - * @property specifiers + * @name NamedExportDeclaration#specifiers */ -memo(NamedExportDeclaration.prototype, 'specifiers', function() { +memo(NamedExportDeclaration.prototype, 'specifiers', /** @this NamedExportDeclaration */function() { var self = this; return this.node.specifiers.map(function(specifier) { return new ExportSpecifier(self, specifier); @@ -179,7 +180,7 @@ memo(NamedExportDeclaration.prototype, 'specifiers', function() { * @constructor * @extends ExportDeclaration * @param {Module} mod - * @param {ExportDeclaration} node + * @param {AST.ExportDeclaration} node */ function VariableExportDeclaration(mod, node) { ExportDeclaration.call(this, mod, node); @@ -187,8 +188,12 @@ function VariableExportDeclaration(mod, node) { extend(VariableExportDeclaration, ExportDeclaration); /** + * Gets the list of export specifiers for this declaration. + * + * @type {ExportSpecifier[]} + * @name VariableExportDeclaration#specifiers */ -memo(VariableExportDeclaration.prototype, 'specifiers', function() { +memo(VariableExportDeclaration.prototype, 'specifiers', /** @this VariableExportDeclaration */function() { var self = this; return this.node.declaration.declarations.map(function(declarator) { return new ExportSpecifier(self, declarator); @@ -203,7 +208,7 @@ memo(VariableExportDeclaration.prototype, 'specifiers', function() { * @constructor * @extends ExportDeclaration * @param {Module} mod - * @param {ExportDeclaration} node + * @param {AST.ExportDeclaration} node */ function FunctionExportDeclaration(mod, node) { ExportDeclaration.call(this, mod, node); @@ -211,8 +216,12 @@ function FunctionExportDeclaration(mod, node) { extend(FunctionExportDeclaration, ExportDeclaration); /** + * Gets the list of export specifiers for this declaration. + * + * @type {ExportSpecifier[]} + * @name FunctionExportDeclaration#specifiers */ -memo(FunctionExportDeclaration.prototype, 'specifiers', function() { +memo(FunctionExportDeclaration.prototype, 'specifiers', /** @this FunctionExportDeclaration */function() { return [new ExportSpecifier(this, this.node.declaration)]; }); @@ -222,7 +231,7 @@ memo(FunctionExportDeclaration.prototype, 'specifiers', function() { * @constructor * @extends ModuleBindingSpecifier * @param {ExportDeclaration} declaration - * @param {ExportSpecifier} node + * @param {AST.Node} node */ function ExportSpecifier(declaration, node) { ModuleBindingSpecifier.call(this, declaration, node); @@ -239,10 +248,10 @@ extend(ExportSpecifier, ModuleBindingSpecifier); * The module declaration info for the `a` export specifier is the variable * declaration plus the `a` identifier in its first declarator. * - * @type {DeclarationInfo} - * @property moduleDeclaration + * @type {?DeclarationInfo} + * @name ExportSpecifier#moduleDeclaration */ -memo(ExportSpecifier.prototype, 'moduleDeclaration', function() { +memo(ExportSpecifier.prototype, 'moduleDeclaration', /** @this ExportSpecifier */function() { if (this.declaration.source) { // This is part of a direct export, e.g. `export { ... } from '...'`, so // there is no declaration as part of this module. @@ -277,18 +286,26 @@ memo(ExportSpecifier.prototype, 'moduleDeclaration', function() { * @constructor * @extends ExportSpecifier * @param {ExportDeclaration} declaration - * @param {ExportSpecifier} node + * @param {AST.Expression} node */ function DefaultExportSpecifier(declaration, node) { ExportSpecifier.call(this, declaration, node); } extend(DefaultExportSpecifier, ExportSpecifier); +/** + * The node of a default export specifier is an expression, not a specifier. + * + * @type {AST.Expression} + */ +DefaultExportSpecifier.prototype.node = null; + /** * Default export specifier names are always "default". * * @type {string} - * @property name + * @name DefaultExportSpecifier#name + * @default "default" */ DefaultExportSpecifier.prototype.name = 'default'; @@ -296,7 +313,8 @@ DefaultExportSpecifier.prototype.name = 'default'; * Default export specifiers do not bind to a local identifier. * * @type {?Identifier} - * @property identifier + * @name DefaultExportSpecifier#identifier + * @default null */ DefaultExportSpecifier.prototype.identifier = null; @@ -304,7 +322,8 @@ DefaultExportSpecifier.prototype.identifier = null; * Default export specifiers do not have a local bound name. * * @type {?string} - * @property from + * @name DefaultExportSpecifier#from + * @default null */ DefaultExportSpecifier.prototype.from = null; @@ -312,7 +331,8 @@ DefaultExportSpecifier.prototype.from = null; * Default export specifiers do not have a local declaration. * * @type {?DeclarationInfo} - * @property moduleDeclaration + * @name DefaultExportSpecifier#moduleDeclaration + * @default null */ DefaultExportSpecifier.prototype.moduleDeclaration = null; diff --git a/lib/formatters/formatter.js b/lib/formatters/formatter.js index f51e5ef..7c1af6b 100644 --- a/lib/formatters/formatter.js +++ b/lib/formatters/formatter.js @@ -106,7 +106,7 @@ Formatter.prototype.importedReference = function(mod, referencePath) { * * @param {Module} mod * @param {NodePath} referencePath - * @returns {?Node} + * @return {?Node} */ Formatter.prototype.localReference = function(mod, referencePath) { return null; @@ -117,7 +117,7 @@ Formatter.prototype.localReference = function(mod, referencePath) { * * @param {Module} mod * @param {NodePath} nodePath - * @returns {?Node[]} + * @return {?Node[]} */ Formatter.prototype.processFunctionDeclaration = function(mod, nodePath) { throw new Error('#processFunctionDeclaration must be implemented in subclasses'); diff --git a/lib/imports.js b/lib/imports.js index 0166850..0b2d22b 100644 --- a/lib/imports.js +++ b/lib/imports.js @@ -19,6 +19,7 @@ var sourcePosition = utils.sourcePosition; * * @constructor * @param {Module} mod + * @extends ModuleBindingList */ function ImportDeclarationList(mod) { ModuleBindingList.call(this, mod); @@ -27,7 +28,7 @@ extend(ImportDeclarationList, ModuleBindingList); /** * @private - * @param {Node} node + * @param {AST.Node} node * @return {boolean} */ ImportDeclarationList.prototype.isMatchingBinding = function(node) { @@ -38,8 +39,8 @@ ImportDeclarationList.prototype.isMatchingBinding = function(node) { * Gets an import declaration for the given `node`. * * @private - * @param {ImportDeclaration} node - * @return {Import} + * @param {AST.ImportDeclaration} node + * @return {ImportDeclaration} */ ImportDeclarationList.prototype.declarationForNode = function(node) { switch (node.kind) { @@ -64,7 +65,8 @@ ImportDeclarationList.prototype.declarationForNode = function(node) { * @constructor * @abstract * @param {Module} mod - * @param {ImportDeclaration} node + * @param {AST.ImportDeclaration} node + * @extends ModuleBindingDeclaration */ function ImportDeclaration(mod, node) { assert.ok( @@ -72,27 +74,21 @@ function ImportDeclaration(mod, node) { 'expected an import declaration, got ' + (node && node.type) ); - Object.defineProperties(this, { - node: { - value: node - }, - - module: { - value: mod - } - }); + ModuleBindingDeclaration.call(this, mod, node); } extend(ImportDeclaration, ModuleBindingDeclaration); /** * Represents a default import of the form * + * ```js * import List from 'list'; + * ``` * * @constructor * @extends ImportDeclaration * @param {Module} mod - * @param {ImportDeclaration} node + * @param {AST.ImportDeclaration} node */ function DefaultImportDeclaration(mod, node) { assert.equal(node.kind, 'default'); @@ -110,9 +106,9 @@ extend(DefaultImportDeclaration, ImportDeclaration); * Contains a list of specifier name information for this import. * * @type {ImportSpecifier[]} - * @property specifiers + * @name DefaultImportDeclaration#specifiers */ -memo(DefaultImportDeclaration.prototype, 'specifiers', function() { +memo(DefaultImportDeclaration.prototype, 'specifiers', /** @this DefaultImportDeclaration */function() { var specifier = new ImportSpecifier(this, this.node.specifiers[0]); specifier.from = 'default'; assert.equal(specifier.from, 'default'); @@ -122,12 +118,14 @@ memo(DefaultImportDeclaration.prototype, 'specifiers', function() { /** * Represents a named import of the form * + * ```js * import { sin, cos } from 'math'; + * ``` * * @constructor * @extends ImportDeclaration * @param {Module} mod - * @param {ImportDeclaration} node + * @param {AST.ImportDeclaration} node */ function NamedImportDeclaration(mod, node) { assert.equal(node.kind, 'named'); @@ -139,9 +137,9 @@ extend(NamedImportDeclaration, ImportDeclaration); * Contains a list of specifier name information for this import. * * @type {ImportSpecifier[]} - * @property specifiers + * @name NamedImportDeclaration#specifiers */ -memo(NamedImportDeclaration.prototype, 'specifiers', function() { +memo(NamedImportDeclaration.prototype, 'specifiers', /** @this NamedImportDeclaration */function() { var self = this; return this.node.specifiers.map(function(specifier) { return new ImportSpecifier(self, specifier); @@ -156,7 +154,7 @@ memo(NamedImportDeclaration.prototype, 'specifiers', function() { * @constructor * @extends ImportDeclaration * @param {Module} mod - * @param {ImportDeclaration} node + * @param {AST.ImportDeclaration} node */ function BareImportDeclaration(mod, node) { assert.ok( @@ -173,9 +171,9 @@ extend(BareImportDeclaration, ImportDeclaration); * Returns an empty set of specifiers. * * @type {ImportSpecifier[]} - * @property specifiers + * @name BareImportDeclaration#specifiers */ -memo(BareImportDeclaration.prototype, 'specifiers', function() { +memo(BareImportDeclaration.prototype, 'specifiers', /** @this BareImportDeclaration */function() { return []; }); @@ -188,7 +186,7 @@ memo(BareImportDeclaration.prototype, 'specifiers', function() { * @constructor * @extends ModuleBindingSpecifier * @param {ImportDeclaration} declaration - * @param {Node} node + * @param {AST.ImportSpecifier} node */ function ImportSpecifier(declaration, node) { assert.ok( @@ -199,7 +197,11 @@ function ImportSpecifier(declaration, node) { } extend(ImportSpecifier, ModuleBindingSpecifier); -memo(ImportSpecifier.prototype, 'exportSpecifier', function() { +/** + * @type {ExportSpecifier} + * @name ImportSpecifier#exportSpecifier + */ +memo(ImportSpecifier.prototype, 'exportSpecifier', /** @this ImportSpecifier */function() { var source = this.declaration.source; assert.ok(source, 'import specifiers must have a valid source'); var exportSpecifier = source.exports.findSpecifierByName(this.from); diff --git a/lib/module.js b/lib/module.js index 07de83d..17d750f 100644 --- a/lib/module.js +++ b/lib/module.js @@ -27,18 +27,30 @@ var endsWith = utils.endsWith; */ function Module(path, relativePath, container) { Object.defineProperties(this, { + /** + * @type {string} + * @name Module#path + */ path: { value: path, enumerable: true, writable: false }, + /** + * @type {string} + * @name Module#relativePath + */ relativePath: { value: relativePath, enumerable: true, writable: false }, + /** + * @type {Container} + * @name Module#container + */ container: { value: container, enumerable: true, @@ -62,9 +74,9 @@ Module.prototype.reload = function() { * The list of imports declared by this module. * * @type {ImportDeclarationList} - * @property imports + * @name Module#imports */ -memo(Module.prototype, 'imports', function() { +memo(Module.prototype, 'imports', /** @this Module */function() { var result = new ImportDeclarationList(this); result.readProgram(this.ast.program); return result; @@ -74,9 +86,9 @@ memo(Module.prototype, 'imports', function() { * The list of exports declared by this module. * * @type {ExportDeclarationList} - * @property exports + * @name Module#exports */ -memo(Module.prototype, 'exports', function() { +memo(Module.prototype, 'exports', /** @this Module */function() { var result = new ExportDeclarationList(this); result.readProgram(this.ast.program); return result; @@ -86,9 +98,9 @@ memo(Module.prototype, 'exports', function() { * This module's scope. * * @type {Scope} - * @property scope + * @name Module#scope */ -memo(Module.prototype, 'scope', function() { +memo(Module.prototype, 'scope', /** @this Module */function() { return new NodePath(this.ast).get('program').get('body').scope; }); @@ -96,9 +108,9 @@ memo(Module.prototype, 'scope', function() { * This module's source code represented as an abstract syntax tree. * * @type {File} - * @property ast + * @name Module#ast */ -memo(Module.prototype, 'ast', function() { +memo(Module.prototype, 'ast', /** @this Module */function() { return recast.parse( this.src, { esprima: esprima, @@ -111,9 +123,9 @@ memo(Module.prototype, 'ast', function() { * This module's source code. * * @type {String} - * @property src + * @name Module#src */ -memo(Module.prototype, 'src', function() { +memo(Module.prototype, 'src', /** @this Module */function() { return fs.readFileSync(this.path).toString(); }); @@ -121,9 +133,9 @@ memo(Module.prototype, 'src', function() { * A reference to the options from this module's container. * * @type {object} - * @property options + * @name Module#options */ -memo(Module.prototype, 'options', function() { +memo(Module.prototype, 'options', /** @this Module */function() { return this.container.options; }); @@ -132,9 +144,9 @@ memo(Module.prototype, 'options', function() { * This may be modified by a Container if this Module is part of a Container. * * @type {string} - * @property name + * @name Module#name */ -memo(Module.prototype, 'name', function() { +memo(Module.prototype, 'name', /** @this Module */function() { var relativePath = this.relativePath; if (endsWith(relativePath, '.js')) { return relativePath.slice(0, -3); @@ -147,9 +159,9 @@ memo(Module.prototype, 'name', function() { * A string suitable for a JavaScript identifier named for this module. * * @type {string} - * @property id + * @name Module#id */ -memo(Module.prototype, 'id', function() { +memo(Module.prototype, 'id', /** @this Module */function() { return this.name.replace(/[^\w$_]/g, '$') + '$$'; }); @@ -173,7 +185,7 @@ Module.prototype.inspect = function() { }; /** - * @alias {#inspect} + * @see Module#inspect */ Module.prototype.toString = Module.prototype.inspect; diff --git a/lib/module_binding_declaration.js b/lib/module_binding_declaration.js index dede950..0db6442 100644 --- a/lib/module_binding_declaration.js +++ b/lib/module_binding_declaration.js @@ -17,7 +17,7 @@ var memo = utils.memo; * @constructor * @abstract * @param {Module} mod - * @param {ImportDeclaration|ExportDeclaration} node + * @param {AST.ImportDeclaration|AST.ExportDeclaration} node */ function ModuleBindingDeclaration(mod, node) { assert.ok( @@ -26,10 +26,18 @@ function ModuleBindingDeclaration(mod, node) { ); Object.defineProperties(this, { + /** + * @name ModuleBindingDeclaration#node + * @type {AST.ImportDeclaration|AST.ExportDeclaration} + */ node: { value: node }, + /** + * @name ModuleBindingDeclaration#module + * @type {Module} + */ module: { value: mod } @@ -40,7 +48,6 @@ function ModuleBindingDeclaration(mod, node) { * Finds the specifier that creates the local binding given by `name`, if one * exists. Otherwise `null` is returned. * - * @private * @param {string} name * @return {?ModuleBindingSpecifier} */ @@ -58,8 +65,7 @@ ModuleBindingDeclaration.prototype.findSpecifierByName = function(name) { }; /** - * @private - * @param {Identifier} identifier + * @param {AST.Identifier} identifier * @return {?ModuleBindingSpecifier} */ ModuleBindingDeclaration.prototype.findSpecifierByIdentifier = function(identifier) { @@ -73,27 +79,40 @@ ModuleBindingDeclaration.prototype.findSpecifierByIdentifier = function(identifi return null; }; -memo(ModuleBindingDeclaration.prototype, 'sourcePath', function() { - return this.node.source && this.node.source.value; +/** + * Gets the raw path of the `from` part of the declaration, if present. For + * example: + * + * ```js + * import { map } from "array"; + * ``` + * + * The source path for the above declaration is "array". + * + * @type {?string} + * @name ModuleBindingDeclaration#sourcePath + */ +memo(ModuleBindingDeclaration.prototype, 'sourcePath', /** @this ModuleBindingDeclaration */function() { + return this.node.source ? this.node.source.value : null; }); /** * Gets a reference to the module referenced by this declaration. * * @type {Module} - * @property source + * @name ModuleBindingDeclaration#source */ -memo(ModuleBindingDeclaration.prototype, 'source', function() { +memo(ModuleBindingDeclaration.prototype, 'source', /** @this ModuleBindingDeclaration */function() { return this.sourcePath ? this.module.getModule(this.sourcePath) : null; }); /** - * Gets the module scope. + * Gets the containing module's scope. * * @type {Scope} - * @property scope + * @name ModuleBindingDeclaration#moduleScope */ -memo(ModuleBindingDeclaration.prototype, 'moduleScope', function() { +memo(ModuleBindingDeclaration.prototype, 'moduleScope', /** @this ModuleBindingDeclaration */function() { return this.module.scope; }); @@ -107,7 +126,7 @@ ModuleBindingDeclaration.prototype.inspect = function() { }; /** - * @alias {#inspect} + * @see ModuleBindingDeclaration#inspect */ ModuleBindingDeclaration.prototype.toString = ModuleBindingDeclaration.prototype.inspect; diff --git a/lib/module_binding_list.js b/lib/module_binding_list.js index ee63101..e778dcc 100644 --- a/lib/module_binding_list.js +++ b/lib/module_binding_list.js @@ -16,10 +16,19 @@ var sourcePosition = utils.sourcePosition; */ function ModuleBindingList(mod) { Object.defineProperties(this, { + /** + * @name ModuleBindingList#_nodes + * @type {AST.ImportDeclaration[]|AST.ExportDeclaration[]} + * @private + */ _nodes: { value: [] }, + /** + * @name ModuleBindingList#module + * @type {Module} + */ module: { value: mod } @@ -30,7 +39,7 @@ function ModuleBindingList(mod) { * Add all the binding declarations from the given scope body. Generally this * should be the Program node's `body` property, an array of statements. * - * @param {Program} program + * @param {AST.Program} program */ ModuleBindingList.prototype.readProgram = function(program) { var body = program.body; @@ -45,7 +54,7 @@ ModuleBindingList.prototype.readProgram = function(program) { * Adds a declaration to the list. * * @private - * @param {ImportDeclaration|ExportDeclaration} node + * @param {AST.ImportDeclaration|AST.ExportDeclaration} node */ ModuleBindingList.prototype.addDeclaration = function(node) { assert.ok( @@ -62,12 +71,12 @@ ModuleBindingList.prototype.addDeclaration = function(node) { }; /** - * Gets the module scope. + * Gets the associated module's scope. * * @type {Scope} - * @property scope + * @name ModuleBindingList#moduleScope */ -memo(ModuleBindingList.prototype, 'moduleScope', function() { +memo(ModuleBindingList.prototype, 'moduleScope', /** @this ModuleBindingList */function() { return this.module.scope; }); @@ -75,9 +84,9 @@ memo(ModuleBindingList.prototype, 'moduleScope', function() { * Gets all the modules referenced by the declarations in this list. * * @type {Module[]} - * @property modules + * @name ModuleBindingList#modules */ -memo(ModuleBindingList.prototype, 'modules', function() { +memo(ModuleBindingList.prototype, 'modules', /** @this ModuleBindingList */function() { var modules = []; this.declarations.forEach(function(declaration) { @@ -107,8 +116,11 @@ ModuleBindingList.prototype.findSpecifierByName = function(name) { }; /** + * Finds the specifier whose identifier is the given identifier, if one exists. + * Otherwise `null` is returned. + * * @private - * @param {Identifier} identifier + * @param {AST.Identifier} identifier * @return {?ModuleBindingSpecifier} */ ModuleBindingList.prototype.findSpecifierByIdentifier = function(identifier) { @@ -196,7 +208,7 @@ ModuleBindingList.prototype.inspect = function() { }; /** - * @alias {#inspect} + * @see ModuleBindingList#inspect */ ModuleBindingList.prototype.toString = ModuleBindingList.prototype.inspect; @@ -204,9 +216,9 @@ ModuleBindingList.prototype.toString = ModuleBindingList.prototype.inspect; * Contains a list of declarations. * * @type {(ImportDeclaration[]|ExportDeclaration[])} - * @property declarations + * @name ModuleBindingList#declarations */ -memo(ModuleBindingList.prototype, 'declarations', function() { +memo(ModuleBindingList.prototype, 'declarations', /** @this ModuleBindingList */function() { var self = this; return this._nodes.map(function(child) { @@ -219,9 +231,9 @@ memo(ModuleBindingList.prototype, 'declarations', function() { * list. * * @type {string[]} - * @property names + * @name ModuleBindingList#names */ -memo(ModuleBindingList.prototype, 'names', function() { +memo(ModuleBindingList.prototype, 'names', /** @this ModuleBindingList */function() { return this.declarations.reduce(function(names, decl) { return names.concat(decl.specifiers.map(function(specifier) { return specifier.name; diff --git a/lib/module_binding_specifier.js b/lib/module_binding_specifier.js index dc62a7f..7183f96 100644 --- a/lib/module_binding_specifier.js +++ b/lib/module_binding_specifier.js @@ -16,14 +16,22 @@ var sourcePosition = utils.sourcePosition; * * @constructor * @param {ModuleBindingDeclaration} declaration - * @param {Node} node + * @param {AST.NamedSpecifier} node */ function ModuleBindingSpecifier(declaration, node) { Object.defineProperties(this, { + /** + * @name ModuleBindingSpecifier#declaration + * @type {ModuleBindingDeclaration} + */ declaration: { value: declaration }, + /** + * @name ModuleBindingSpecifier#node + * @type {AST.NamedSpecifier} + */ node: { value: node } @@ -34,9 +42,9 @@ function ModuleBindingSpecifier(declaration, node) { * Gets the module this specifier is declared in. * * @type Module - * @property module + * @name ModuleBindingSpecifier#module */ -memo(ModuleBindingSpecifier.prototype, 'module', function() { +memo(ModuleBindingSpecifier.prototype, 'module', /** @this ModuleBindingSpecifier */function() { return this.declaration.module; }); @@ -44,9 +52,9 @@ memo(ModuleBindingSpecifier.prototype, 'module', function() { * Gets the scope at the top level of the module. * * @type {Scope} - * @property moduleScope + * @name ModuleBindingSpecifier#moduleScope */ -memo(ModuleBindingSpecifier.prototype, 'moduleScope', function() { +memo(ModuleBindingSpecifier.prototype, 'moduleScope', /** @this ModuleBindingSpecifier */function() { return this.declaration.moduleScope; }); @@ -65,9 +73,9 @@ memo(ModuleBindingSpecifier.prototype, 'moduleScope', function() { * export var foo = 1; * * @type {string} - * @property name + * @name ModuleBindingSpecifier#name */ -memo(ModuleBindingSpecifier.prototype, 'name', function() { +memo(ModuleBindingSpecifier.prototype, 'name', /** @this ModuleBindingSpecifier */function() { return this.identifier.name; }); @@ -85,9 +93,9 @@ memo(ModuleBindingSpecifier.prototype, 'name', function() { * export { foo }; * * @type {string} - * @property from + * @name ModuleBindingSpecifier#from */ -memo(ModuleBindingSpecifier.prototype, 'from', function() { +memo(ModuleBindingSpecifier.prototype, 'from', /** @this ModuleBindingSpecifier */function() { return this.node.id.name; }); @@ -100,10 +108,10 @@ memo(ModuleBindingSpecifier.prototype, 'from', function() { * export { foo }; * export { bar as foo }; * - * @type {Identifier} - * @property identifier + * @type {AST.Identifier} + * @name ModuleBindingSpecifier#identifier */ -memo(ModuleBindingSpecifier.prototype, 'identifier', function() { +memo(ModuleBindingSpecifier.prototype, 'identifier', /** @this ModuleBindingSpecifier */function() { return this.node.name || this.node.id; }); @@ -118,9 +126,9 @@ memo(ModuleBindingSpecifier.prototype, 'identifier', function() { * of the export statement in the "array" module that exports it. * * @type {?ExportSpecifier} - * @property exportSpecifier + * @name ModuleBindingSpecifier#exportSpecifier */ -memo(ModuleBindingSpecifier.prototype, 'exportSpecifier', function() { +memo(ModuleBindingSpecifier.prototype, 'exportSpecifier', /** @this ModuleBindingSpecifier */function() { var source = this.declaration.source; if (source) { var exports = source.exports; @@ -142,9 +150,9 @@ memo(ModuleBindingSpecifier.prototype, 'exportSpecifier', function() { * `importSpecifier` property value. * * @type {?ImportSpecifier} - * @property importSpecifier + * @name ModuleBindingSpecifier#importSpecifier */ -memo(ModuleBindingSpecifier.prototype, 'importSpecifier', function() { +memo(ModuleBindingSpecifier.prototype, 'importSpecifier', /** @this ModuleBindingSpecifier */function() { // This may be an export from this module, so find the declaration. var localExportDeclarationInfo = this.moduleDeclaration; @@ -178,9 +186,9 @@ memo(ModuleBindingSpecifier.prototype, 'importSpecifier', function() { * a.js, since all of them can be traced back to that one. * * @type {ExportSpecifier} - * @property terminalExportSpecifier + * @name ModuleBindingSpecifier#terminalExportSpecifier */ -memo(ModuleBindingSpecifier.prototype, 'terminalExportSpecifier', function() { +memo(ModuleBindingSpecifier.prototype, 'terminalExportSpecifier', /** @this ModuleBindingSpecifier */function() { if (this.exportSpecifier) { // This is true for both imports and exports with a source, e.g. // `import { foo } from 'foo'` or `export { foo } from 'foo'`. @@ -204,6 +212,11 @@ memo(ModuleBindingSpecifier.prototype, 'terminalExportSpecifier', function() { } }); +/** + * @type {?DeclarationInfo} + */ +ModuleBindingSpecifier.prototype.moduleDeclaration = null; + /** * Gets a string representation of this module binding specifier suitable for * debugging. @@ -219,7 +232,7 @@ ModuleBindingSpecifier.prototype.inspect = function() { }; /** - * @alias inspect + * @see ModuleBindingSpecifier#inspect */ ModuleBindingSpecifier.prototype.toString = ModuleBindingSpecifier.prototype.inspect; diff --git a/lib/replacement.js b/lib/replacement.js index 6957c31..ffffa69 100644 --- a/lib/replacement.js +++ b/lib/replacement.js @@ -1,14 +1,22 @@ /* jshint node:true, undef:true, unused:true */ var recast = require('recast'); + +/** @typedef [NodePath, AST.Node[]] */ +var ReplacementPair; + /** * Represents a replacement of a node path with zero or more nodes. * * @constructor - * @param {NodePath} nodePath - * @param {Node[]} nodes + * @param {NodePath=} nodePath + * @param {AST.Node[]=} nodes */ function Replacement(nodePath, nodes) { + /** + * @private + * @type {ReplacementPair[]} + */ this.queue = []; if (nodePath && nodes) { this.queue.push([nodePath, nodes]); @@ -39,7 +47,7 @@ Replacement.prototype.and = function(anotherReplacement) { * Constructs a Replacement that, when run, will remove the node from the AST. * * @param {NodePath} nodePath - * @returns {Replacement} + * @return {Replacement} */ Replacement.removes = function(nodePath) { return new Replacement(nodePath, []); @@ -50,8 +58,8 @@ Replacement.removes = function(nodePath) { * the one in nodePath. * * @param {NodePath} nodePath - * @param {Node[]} nodes - * @returns {Replacement} + * @param {AST.Node[]} nodes + * @return {Replacement} */ Replacement.adds = function(nodePath, nodes) { return new Replacement(nodePath, [nodePath.node].concat(nodes)); @@ -62,10 +70,10 @@ Replacement.adds = function(nodePath, nodes) { * given node or nodes. * * @param {NodePath} nodePath - * @param {Node|Node[]} nodes + * @param {AST.Node|AST.Node[]} nodes */ Replacement.swaps = function(nodePath, nodes) { - if ({}.toString.call(nodes) !== '[object Array]') { + if (!Array.isArray(nodes)) { nodes = [nodes]; } return new Replacement(nodePath, nodes); diff --git a/lib/rewriter.js b/lib/rewriter.js index a2c200a..b48f1d2 100644 --- a/lib/rewriter.js +++ b/lib/rewriter.js @@ -33,19 +33,23 @@ utils.extend(Rewriter, types.PathVisitor); * Rewrites references to all imported and exported bindings according to the * rules from this rewriter's formatter. For example, this module: * + * ```js * import { sin, cos } from './math'; * import fib from './math/fib'; * * assert.equal(sin(0), 0); * assert.equal(cos(0), 1); * assert.equal(fib(1), 1); + * ``` * * has its references to the imported bindings `sin`, `cos`, and `fib` * rewritten to reference the source module: * + * ```js * assert.equal(math$$.sin(0), 0); * assert.equal(math$$.cos(0), 1); * assert.equal(math$fib$$.fib(1), 1); + * ``` * * @param {Module[]} modules */ @@ -88,7 +92,7 @@ Rewriter.prototype.rewrite = function(modules) { * Process all identifiers looking for references to variables in scope. * * @param {NodePath} nodePath - * @returns {boolean} + * @return {boolean} * @private */ Rewriter.prototype.visitIdentifier = function(nodePath) { diff --git a/test/support/expected_error.js b/test/support/expected_error.js index 632e4ba..9a1b596 100644 --- a/test/support/expected_error.js +++ b/test/support/expected_error.js @@ -16,7 +16,7 @@ function ExpectedError(type, message) { * Builds an ExpectedError from the given source code. * * @param {string} source - * @returns {?ExpectedError} + * @return {?ExpectedError} */ ExpectedError.getFromSource = function(source) { var errorMatch = source.match(/\/\*\s*error:\s*(.+?)\*\//); @@ -44,7 +44,7 @@ ExpectedError.getFromSource = function(source) { * Determines whether the given error matches the expected error type. * * @param {!Error} error - * @returns {boolean} + * @return {boolean} */ ExpectedError.prototype.matchesType = function(error) { return !this.type || @@ -57,7 +57,7 @@ ExpectedError.prototype.matchesType = function(error) { * Determines whether the given error matches the expected error message. * * @param {!Error} error - * @returns {boolean} + * @return {boolean} */ ExpectedError.prototype.matchesMessage = function(error) { return !this.message || @@ -81,7 +81,7 @@ ExpectedError.prototype.assertMatch = function(error) { * Gets the error to throw if the given error does not match. * * @param {?Error} error - * @returns {?AssertionError} + * @return {?AssertionError} */ ExpectedError.prototype.matchError = function(error) { var matchesType = error && this.matchesType(error);