Socket
Socket
Sign inDemoInstall

documentation

Package Overview
Dependencies
560
Maintainers
4
Versions
119
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 10.0.0 to 10.1.0

src/infer/implements.js

10

CHANGELOG.md

@@ -5,2 +5,12 @@ # Change Log

<a name="10.1.0"></a>
# [10.1.0](https://github.com/documentationjs/documentation/compare/v10.0.0...v10.1.0) (2019-04-25)
### Features
* TypeScript support & inference ([3773e02](https://github.com/documentationjs/documentation/commit/3773e02))
<a name="10.0.0"></a>

@@ -7,0 +17,0 @@ # [10.0.0](https://github.com/documentationjs/documentation/compare/v10.0.0-alpha.0...v10.0.0) (2019-04-18)

7

declarations/comment.js

@@ -71,3 +71,4 @@ /* @flow */

type?: DoctrineType,
properties?: Array<CommentTag>
properties?: Array<CommentTag>,
readonly?: boolean
};

@@ -81,2 +82,3 @@

examples: Array<CommentExample>,
implements: Array<CommentTag>,
params: Array<CommentTag>,

@@ -103,2 +105,5 @@ properties: Array<CommentTag>,

access?: Access,
readonly?: boolean,
abstract?: boolean,
generator?: boolean,
alias?: string,

@@ -105,0 +110,0 @@

2

package.json
{
"name": "documentation",
"description": "a documentation generator",
"version": "10.0.0",
"version": "10.1.0",
"author": "Tom MacWright",

@@ -6,0 +6,0 @@ "bin": {

@@ -185,3 +185,3 @@ const traverse = require('@babel/traverse').default;

const input = fs.readFileSync(path, 'utf-8');
const ast = parseToAst(input);
const ast = parseToAst(input, filePath);
value = {

@@ -188,0 +188,0 @@ data: {

@@ -16,2 +16,3 @@ const fs = require('fs');

const inferAugments = require('./infer/augments');
const inferImplements = require('./infer/implements');
const inferParams = require('./infer/params');

@@ -93,2 +94,3 @@ const inferProperties = require('./infer/properties');

inferAugments,
inferImplements,
inferKind,

@@ -95,0 +97,0 @@ nest,

@@ -13,3 +13,3 @@ /**

/**
* Infers access (only private atm) from the name.
* Infers access from TypeScript annotations, and from the name (only private atm).
*

@@ -21,2 +21,12 @@ * @name inferAccess

return function inferAccess(comment) {
// Support typescript access modifiers
const ast = comment.context.ast;
if (ast && ast.node.accessibility) {
comment.access = ast.node.accessibility;
}
if (ast && ast.node.readonly) {
comment.readonly = true;
}
// This needs to run after inferName beacuse we infer the access based on

@@ -23,0 +33,0 @@ // the name.

@@ -34,3 +34,6 @@ const generate = require('@babel/generator').default;

}
} else if (path.isInterfaceDeclaration()) {
} else if (
(path.isInterfaceDeclaration() || path.isTSInterfaceDeclaration()) &&
path.node.extends
) {
/*

@@ -37,0 +40,0 @@ * extends is an array of interface identifiers or

@@ -29,3 +29,3 @@ const t = require('@babel/types');

path = path.get('expression').get('right');
} else if (t.isObjectProperty(path)) {
} else if (t.isObjectProperty(path) || t.isObjectTypeProperty(path)) {
// var foo = { x: TARGET }; object property

@@ -32,0 +32,0 @@ path = path.get('value');

@@ -21,3 +21,12 @@ const t = require('@babel/types');

comment.kind = 'class';
} else if (t.isFunction(node)) {
if (node.abstract) {
comment.abstract = true;
}
} else if (
t.isFunction(node) ||
t.isTSDeclareMethod(node) ||
t.isTSDeclareFunction(node) ||
t.isFunctionTypeAnnotation(node) ||
t.isTSMethodSignature(node)
) {
if (node.kind === 'get' || node.kind === 'set') {

@@ -35,6 +44,12 @@ comment.kind = 'member';

}
if (node.abstract) {
comment.abstract = true;
}
}
} else if (t.isTypeAlias(node)) {
} else if (t.isTypeAlias(node) || t.isTSTypeAliasDeclaration(node)) {
comment.kind = 'typedef';
} else if (t.isInterfaceDeclaration(node)) {
} else if (
t.isInterfaceDeclaration(node) ||
t.isTSInterfaceDeclaration(node)
) {
comment.kind = 'interface';

@@ -58,3 +73,7 @@ } else if (t.isVariableDeclaration(node)) {

findKind(node.expression.right);
} else if (t.isClassProperty(node)) {
} else if (
t.isClassProperty(node) ||
t.isTSPropertySignature(node) ||
t.isTSEnumMember(node)
) {
comment.kind = 'member';

@@ -64,2 +83,12 @@ } else if (t.isProperty(node)) {

findKind(node.value);
} else if (t.isTSModuleDeclaration(node)) {
comment.kind = 'namespace';
} else if (t.isObjectTypeProperty(node)) {
if (t.isFunctionTypeAnnotation(node.value)) {
findKind(node.value);
} else {
comment.kind = 'member';
}
} else if (t.isTSEnumDeclaration(node)) {
comment.kind = 'enum';
}

@@ -66,0 +95,0 @@ }

@@ -344,3 +344,5 @@ const n = require('@babel/types');

if (
(path.isClassMethod() || path.isClassProperty()) &&
(path.isClassMethod() ||
path.isClassProperty() ||
path.isTSDeclareMethod()) &&
path.parentPath.isClassBody() &&

@@ -363,3 +365,3 @@ path.parentPath.parentPath.isClass()

const declarationNode = path.parentPath.parentPath.node;
if (!declarationNode.id) {
if (!declarationNode.id && !declarationNode.key) {
// export default function () {}

@@ -397,2 +399,4 @@ // export default class {}

objectParent = path.parentPath;
} else if (path.isObjectTypeProperty() || path.isTSTypeElement()) {
objectParent = path.parentPath;
}

@@ -402,31 +406,81 @@

if (objectParent) {
// The @lends comment is sometimes attached to the first property rather than
// the object expression itself.
const lendsIdentifiers =
findLendsIdentifiers(objectParent) ||
findLendsIdentifiers(objectParent.get('properties')[0]);
// Collect all keys of parent nested object keys, e.g. {foo: bar: {baz: 1}}
const objectKeys = [];
if (lendsIdentifiers) {
return inferMembershipFromIdentifiers(comment, lendsIdentifiers);
} else if (objectParent.parentPath.isAssignmentExpression()) {
// Foo = { ... };
// Foo.prototype = { ... };
// Foo.bar = { ... };
return inferMembershipFromIdentifiers(
comment,
extractIdentifiers(objectParent.parentPath.get('left'))
);
} else if (objectParent.parentPath.isVariableDeclarator()) {
// var Foo = { ... };
return inferMembershipFromIdentifiers(comment, [
objectParent.parentPath.get('id').node.name
]);
} else if (objectParent.parentPath.isExportDefaultDeclaration()) {
// export default { ... };
return inferMembershipFromIdentifiers(comment, [
inferModuleName(currentModule || comment)
]);
while (!objectParent.isStatement()) {
if (
objectParent.isObjectProperty() ||
objectParent.isObjectTypeProperty() ||
objectParent.isTSPropertySignature()
) {
objectKeys.unshift(objectParent.node.key.name);
}
// The @lends comment is sometimes attached to the first property rather than
// the object expression itself.
const lendsIdentifiers =
findLendsIdentifiers(objectParent) ||
findLendsIdentifiers(objectParent.get('properties')[0]);
if (lendsIdentifiers) {
return inferMembershipFromIdentifiers(comment, [
...lendsIdentifiers,
...objectKeys
]);
} else if (objectParent.parentPath.isAssignmentExpression()) {
// Foo = { ... };
// Foo.prototype = { ... };
// Foo.bar = { ... };
return inferMembershipFromIdentifiers(comment, [
...extractIdentifiers(objectParent.parentPath.get('left')),
...objectKeys
]);
} else if (objectParent.parentPath.isVariableDeclarator()) {
// var Foo = { ... };
return inferMembershipFromIdentifiers(comment, [
objectParent.parentPath.get('id').node.name,
...objectKeys
]);
} else if (objectParent.parentPath.isExportDefaultDeclaration()) {
// export default { ... };
return inferMembershipFromIdentifiers(comment, [
inferModuleName(currentModule || comment),
...objectKeys
]);
} else if (
objectParent.parentPath.isTypeAlias() ||
objectParent.parentPath.isTSTypeAliasDeclaration()
) {
// type X = { ... }
return inferMembershipFromIdentifiers(comment, [
objectParent.parentPath.node.id.name,
...objectKeys
]);
} else if (
objectParent.parentPath.isInterfaceDeclaration() ||
objectParent.parentPath.isTSInterfaceDeclaration()
) {
// interface Foo { ... }
return inferMembershipFromIdentifiers(
comment,
[...inferClassMembership(objectParent.parentPath), ...objectKeys],
'instance'
);
}
objectParent = objectParent.parentPath;
}
}
// TypeScript enums
// enum Foo { A }
if (path.isTSEnumMember()) {
const enumPath = path.parentPath;
return inferMembershipFromIdentifiers(
comment,
[enumPath.node.id.name],
'static'
);
}
// var function Foo() {

@@ -433,0 +487,0 @@ // function bar() {}

@@ -5,3 +5,3 @@ const t = require('@babel/types');

const finders = require('./finders');
const flowDoctrine = require('../flow_doctrine');
const typeAnnotation = require('../type_annotation');

@@ -41,3 +41,9 @@ /**

if (!t.isFunction(path)) {
if (
!t.isFunction(path) &&
!t.isTSDeclareFunction(path) &&
!t.isTSDeclareMethod(path) &&
!t.isFunctionTypeAnnotation(path) &&
!t.isTSMethodSignature(path)
) {
return comment;

@@ -50,7 +56,37 @@ }

return inferAndCombineParams(path.node.params, comment);
let params = t.isTSMethodSignature(path)
? path.node.parameters
: path.node.params;
// Flow function annotations separate rest parameters into a different list
if (t.isFunctionTypeAnnotation(path) && path.node.rest) {
params = params.concat(path.node.rest);
}
const result = inferAndCombineParams(params, comment);
// Wrap flow rest parameter with a RestType
if (t.isFunctionTypeAnnotation(path) && path.node.rest) {
const rest = result.params[result.params.length - 1];
rest.type = {
type: 'RestType',
expression: rest.type
};
}
return result;
}
function inferAndCombineParams(params, comment) {
const inferredParams = params.map((param, i) => paramToDoc(param, '', i));
const inferredParams = params.map((param, i) => {
const doc = paramToDoc(param, '', i);
if (param.optional) {
return {
type: 'OptionalType',
expression: doc
};
}
return doc;
});
const paramsToMerge = comment.params;

@@ -135,3 +171,4 @@ if (comment.constructorComment) {

anonymous: true,
type: (param.typeAnnotation && flowDoctrine(param)) || {
type: (param.typeAnnotation &&
typeAnnotation(param.typeAnnotation)) || {
type: 'NameExpression',

@@ -152,3 +189,4 @@ name: 'Object'

anonymous: true,
type: (param.typeAnnotation && flowDoctrine(param)) || {
type: (param.typeAnnotation &&
typeAnnotation(param.typeAnnotation)) || {
type: 'NameExpression',

@@ -177,3 +215,4 @@ name: 'Object'

anonymous: true,
type: (param.typeAnnotation && flowDoctrine(param)) || {
type: (param.typeAnnotation &&
typeAnnotation(param.typeAnnotation)) || {
type: 'NameExpression',

@@ -220,3 +259,3 @@ name: 'Array'

if (param.typeAnnotation) {
type.expression = flowDoctrine(param.typeAnnotation.typeAnnotation);
type.expression = typeAnnotation(param.typeAnnotation);
}

@@ -230,2 +269,11 @@ return {

}
case 'FunctionTypeParam': // flow interface method signature
return {
title: 'param',
name: prefix ? prefix + '.' + param.name.name : param.name.name,
lineNumber: param.loc.start.line,
type: param.typeAnnotation
? typeAnnotation(param.typeAnnotation)
: undefined
};
default: {

@@ -241,3 +289,3 @@ // (a)

if (param.typeAnnotation && param.typeAnnotation.typeAnnotation) {
newParam.type = flowDoctrine(param.typeAnnotation.typeAnnotation);
newParam.type = typeAnnotation(param.typeAnnotation.typeAnnotation);
}

@@ -244,0 +292,0 @@

@@ -1,2 +0,2 @@

const flowDoctrine = require('../flow_doctrine');
const typeAnnotation = require('../type_annotation');
const findTarget = require('./finders').findTarget;

@@ -12,3 +12,13 @@

function propertyToDoc(property, prefix) {
let type = flowDoctrine(property.value);
let type;
if (property.type === 'ObjectTypeProperty') {
// flow
type = typeAnnotation(property.value);
} else if (property.type === 'TSPropertySignature') {
// typescript
type = typeAnnotation(property.typeAnnotation);
} else if (property.type === 'TSMethodSignature') {
// typescript
type = typeAnnotation(property);
}
const name = property.key.name || property.key.value;

@@ -42,4 +52,8 @@ if (property.optional) {

function inferProperties(value, prefix) {
if (value.type === 'ObjectTypeAnnotation') {
value.properties.forEach(function(property) {
if (
value.type === 'ObjectTypeAnnotation' ||
value.type === 'TSTypeLiteral'
) {
const properties = value.properties || value.members || value.body || [];
properties.forEach(function(property) {
if (!explicitProperties.has(prefixedName(property.key.name, prefix))) {

@@ -49,6 +63,2 @@ comment.properties = comment.properties.concat(

);
// Nested type parameters
if (property.value.type === 'ObjectTypeAnnotation') {
inferProperties(property.value, prefix.concat(property.key.name));
}
}

@@ -64,4 +74,4 @@ });

inferProperties(path.node.right, []);
} else if (path.isInterfaceDeclaration()) {
inferProperties(path.node.body, []);
} else if (path.isTSTypeAliasDeclaration()) {
inferProperties(path.node.typeAnnotation, []);
}

@@ -68,0 +78,0 @@ }

const findTarget = require('./finders').findTarget;
const t = require('@babel/types');
const flowDoctrine = require('../flow_doctrine');
const typeAnnotation = require('../type_annotation');
// TypeScript does not currently support typing the return value of a generator function.
// This is coming in TypeScript 3.3 - https://github.com/Microsoft/TypeScript/pull/30790
const TS_GENERATORS = {
Iterator: 1,
Iterable: 1,
IterableIterator: 1
};
const FLOW_GENERATORS = {
Iterator: 1,
Iterable: 1,
Generator: 3
};
/**

@@ -32,24 +46,46 @@ * Infers returns tags by using Flow return type annotations

if (t.isFunction(fn) && fn.returnType && fn.returnType.typeAnnotation) {
let returnType = flowDoctrine(fn.returnType.typeAnnotation);
if (comment.returns && comment.returns.length > 0) {
comment.returns[0].type = returnType;
} else {
if (
fn.generator &&
returnType.type === 'TypeApplication' &&
returnType.expression.name === 'Generator' &&
returnType.applications.length === 3
) {
comment.generator = true;
const fnReturnType = getReturnType(fn);
if (fnReturnType) {
let returnType = typeAnnotation(fnReturnType);
let yieldsType = null;
if (fn.generator && returnType.type === 'TypeApplication') {
comment.generator = true;
let numArgs;
if (t.isFlow(fnReturnType)) {
numArgs = FLOW_GENERATORS[returnType.expression.name];
} else if (t.isTSTypeAnnotation(fnReturnType)) {
numArgs = TS_GENERATORS[returnType.expression.name];
}
if (returnType.applications.length === numArgs) {
yieldsType = returnType.applications[0];
if (numArgs > 1) {
returnType = returnType.applications[1];
} else {
returnType = {
type: 'VoidLiteral'
};
}
}
}
if (yieldsType) {
if (comment.yields && comment.yields.length > 0) {
comment.yields[0].type = yieldsType;
} else {
comment.yields = [
{
title: 'yields',
type: returnType.applications[0]
type: yieldsType
}
];
returnType = returnType.applications[1];
}
}
if (comment.returns && comment.returns.length > 0) {
comment.returns[0].type = returnType;
} else {
comment.returns = [

@@ -66,2 +102,17 @@ {

function getReturnType(fn) {
if (
t.isFunction(fn) ||
t.isTSDeclareFunction(fn) ||
t.isTSDeclareMethod(fn) ||
t.isFunctionTypeAnnotation(fn)
) {
return fn.returnType;
}
if (t.isTSMethodSignature(fn)) {
return fn.typeAnnotation;
}
}
module.exports = inferReturn;
const findTarget = require('./finders').findTarget;
const flowDoctrine = require('../flow_doctrine');
const t = require('@babel/types');
const typeAnnotation = require('../type_annotation');

@@ -12,3 +11,3 @@ const constTypeMapping = {

/**
* Infers type tags by using Flow type annotations
* Infers type tags by using Flow/TypeScript type annotations
*

@@ -24,3 +23,4 @@ * @name inferType

const path = findTarget(comment.context.ast);
const ast = comment.context.ast;
const path = findTarget(ast);
if (!path) {

@@ -40,13 +40,33 @@ return comment;

case 'ClassProperty':
case 'TSTypeAliasDeclaration':
case 'TSPropertySignature':
type = n.typeAnnotation;
break;
case 'ClassMethod':
case 'TSDeclareMethod':
if (n.kind === 'get') {
type = n.returnType;
} else if (n.kind === 'set' && n.params[0]) {
type = n.params[0].typeAnnotation;
}
break;
case 'TypeAlias':
type = n.right;
break;
case 'TSEnumMember':
if (n.initializer) {
if (constTypeMapping[n.initializer.type]) {
type = constTypeMapping[n.initializer.type];
}
} else {
type = constTypeMapping.NumericLiteral;
}
break;
default:
if (ast.isObjectTypeProperty() && !ast.node.method) {
type = ast.node.value;
}
}
if (type) {
if (t.isTypeAnnotation(type)) {
type = type.typeAnnotation;
}
comment.type = flowDoctrine(type);
comment.type = typeAnnotation(type);
}

@@ -53,0 +73,0 @@ return comment;

@@ -85,3 +85,6 @@ const doctrine = require('doctrine-temporary-fork');

emits: synonym('fires'),
enum: todo,
enum(result, tag) {
result.kind = 'enum';
result.type = tag.type;
},
/**

@@ -175,3 +178,10 @@ * Parse tag

ignore: flattenBoolean,
implements: todo,
implements(result, tag) {
// Match @extends/@augments above.
if (!tag.name && tag.type && tag.type.name) {
tag.name = tag.type.name;
}
result.implements.push(tag);
},
inheritdoc: todo,

@@ -204,3 +214,3 @@ /**

interface(result, tag) {
result.interface = true;
result.kind = 'interface';
if (tag.description) {

@@ -614,2 +624,3 @@ result.name = tag.description;

result.examples = [];
result.implements = [];
result.params = [];

@@ -616,0 +627,0 @@ result.properties = [];

@@ -39,3 +39,3 @@ const _ = require('lodash');

const ast = parseToAst(data.source);
const ast = parseToAst(data.source, data.file);
const addComment = _addComment.bind(null, visited, commentsByNode);

@@ -42,0 +42,0 @@

const babelParser = require('@babel/parser');
const path = require('path');
const opts = {
allowImportExportEverywhere: true,
sourceType: 'module',
plugins: [
'asyncGenerators',
'exportDefaultFrom',
'optionalChaining',
'classConstructorCall',
'classPrivateProperties',
'classProperties',
['decorators', { decoratorsBeforeExport: false }],
'doExpressions',
'exportExtensions',
'flow',
'functionBind',
'functionSent',
'jsx',
'objectRestSpread',
'dynamicImport',
'logicalAssignment'
]
const TYPESCRIPT_EXTS = {
'.ts': true,
'.tsx': true
};
function getParserOpts(file) {
return {
allowImportExportEverywhere: true,
sourceType: 'module',
plugins: [
'asyncGenerators',
'exportDefaultFrom',
'optionalChaining',
'classConstructorCall',
'classPrivateProperties',
'classProperties',
['decorators', { decoratorsBeforeExport: false }],
'doExpressions',
'exportExtensions',
TYPESCRIPT_EXTS[path.extname(file || '')] ? 'typescript' : 'flow',
'functionBind',
'functionSent',
'jsx',
'objectRestSpread',
'dynamicImport',
'logicalAssignment'
]
};
}
/**

@@ -40,6 +48,6 @@ * Convert flow comment types into flow annotations so that

function parseToAst(source) {
return babelParser.parse(commentToFlow(source), opts);
function parseToAst(source, file) {
return babelParser.parse(commentToFlow(source), getParserOpts(file));
}
module.exports.commentToFlow = commentToFlow;
module.exports.parseToAst = parseToAst;
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc