Split extractors.js into declarations.js and definitions.js
parent
794167254a
commit
2a24383d59
|
@ -2,7 +2,8 @@
|
|||
.*/node_modules/.*
|
||||
.*/tests/samples/.*
|
||||
.*/lib/.*
|
||||
.*/src/extractors.js
|
||||
.*/src/definitions.js
|
||||
.*/src/declarations.js
|
||||
|
||||
[libs]
|
||||
declarations/
|
||||
|
|
|
@ -4,7 +4,9 @@ import type {Node} from '@babel/types';
|
|||
|
||||
import globals from './globals';
|
||||
// $FlowFixMe
|
||||
import * as extractors from './extractors';
|
||||
import definitionGroup from './definitions';
|
||||
// $FlowFixMe
|
||||
import declarationGroup from './declarations';
|
||||
import Module from './module';
|
||||
import Scope from './scope';
|
||||
import CircularList from './list';
|
||||
|
@ -71,7 +73,7 @@ export default class Collector {
|
|||
|
||||
const scope = this._global.extend(module);
|
||||
|
||||
this._freestyle(extractors.declaration, ast.program, scope, []);
|
||||
this._freestyle(declarationGroup, ast.program, scope, []);
|
||||
|
||||
this._modules.set(path, module);
|
||||
|
||||
|
@ -277,7 +279,7 @@ export default class Collector {
|
|||
|
||||
invariant(result.type === 'declaration' || result.type === 'template');
|
||||
|
||||
this._freestyle(extractors.definition, result.node, scope, tmplParams);
|
||||
this._freestyle(definitionGroup, result.node, scope, tmplParams);
|
||||
|
||||
while ((result = scope.query(name, params)).type !== 'definition') {
|
||||
invariant(result.type !== 'external');
|
||||
|
|
|
@ -0,0 +1,229 @@
|
|||
import * as t from '@babel/types';
|
||||
|
||||
import {declare, external, provide, enter, exit} from './commands';
|
||||
import {invariant} from './utils';
|
||||
|
||||
type E = Generator<any, any, any>;
|
||||
|
||||
export default {
|
||||
entries: [
|
||||
// Blocks.
|
||||
'Program',
|
||||
'BlockStatement',
|
||||
// Imports.
|
||||
'ImportDeclaration',
|
||||
'VariableDeclarator',
|
||||
// Exports.
|
||||
'ExportNamedDeclaration',
|
||||
'ExportDefaultDeclaration',
|
||||
],
|
||||
|
||||
/*
|
||||
* Blocks.
|
||||
*/
|
||||
|
||||
* Program(node: t.Program): E {
|
||||
yield node.body;
|
||||
},
|
||||
|
||||
* BlockStatement(node: t.BlockStatement): E {
|
||||
yield enter();
|
||||
yield node.body;
|
||||
yield exit();
|
||||
},
|
||||
|
||||
/*
|
||||
* Imports.
|
||||
*
|
||||
* TODO: warning about "import typeof".
|
||||
* TODO: support form "import *".
|
||||
*/
|
||||
|
||||
* ImportDeclaration(node: t.ImportDeclaration): E {
|
||||
const specifiers = yield node.specifiers;
|
||||
const path = yield node.source;
|
||||
|
||||
for (const specifier of specifiers) {
|
||||
specifier.path = path;
|
||||
|
||||
yield external(specifier);
|
||||
}
|
||||
},
|
||||
|
||||
* ImportDefaultSpecifier(node: t.ImportDefaultSpecifier): E {
|
||||
return {
|
||||
local: yield node.local,
|
||||
imported: null,
|
||||
};
|
||||
},
|
||||
|
||||
* ImportSpecifier(node: t.ImportSpecifier): E {
|
||||
return {
|
||||
local: yield node.local,
|
||||
imported: yield node.imported,
|
||||
};
|
||||
},
|
||||
|
||||
* VariableDeclarator(node: t.VariableDeclarator): E {
|
||||
const path = extractRequire(node.init);
|
||||
|
||||
if (!path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let specifiers = yield node.id;
|
||||
|
||||
if (typeof specifiers === 'string') {
|
||||
specifiers = [{
|
||||
local: specifiers,
|
||||
imported: null,
|
||||
}];
|
||||
}
|
||||
|
||||
for (const specifier of specifiers) {
|
||||
specifier.path = path;
|
||||
|
||||
yield external(specifier);
|
||||
}
|
||||
},
|
||||
|
||||
* ObjectPattern(node: t.ObjectPattern): E {
|
||||
return yield node.properties;
|
||||
},
|
||||
|
||||
* ObjectProperty(node: t.ObjectProperty): E {
|
||||
const key = yield node.key;
|
||||
|
||||
// TODO: different roots.
|
||||
if (node.value.type !== 'Identifier') {
|
||||
return null;
|
||||
}
|
||||
|
||||
//invariant(node.value.type === 'Identifier');
|
||||
|
||||
const value = yield node.value;
|
||||
|
||||
return {
|
||||
local: value,
|
||||
imported: key,
|
||||
};
|
||||
},
|
||||
|
||||
/*
|
||||
* Exports.
|
||||
*
|
||||
* TODO: support "export from" form.
|
||||
* TODO: support commonjs.
|
||||
*/
|
||||
|
||||
* ExportDefaultDeclaration(node: t.ExportDefaultDeclaration): E {
|
||||
const reference = yield node.declaration;
|
||||
|
||||
if (reference) {
|
||||
yield provide(null, reference);
|
||||
}
|
||||
},
|
||||
|
||||
* ExportNamedDeclaration(node: t.ExportNamedDeclaration): E {
|
||||
if (!node.declaration) {
|
||||
yield node.specifiers;
|
||||
return;
|
||||
}
|
||||
|
||||
const reference = yield node.declaration;
|
||||
|
||||
if (reference) {
|
||||
yield provide(reference);
|
||||
}
|
||||
},
|
||||
|
||||
* ExportSpecifier(node: t.ExportSpecifier): E {
|
||||
const reference = yield node.local;
|
||||
let name = yield node.exported;
|
||||
|
||||
if (name === 'default') {
|
||||
name = null;
|
||||
}
|
||||
|
||||
yield provide(name, reference);
|
||||
},
|
||||
|
||||
/*
|
||||
* Declarations.
|
||||
*/
|
||||
|
||||
* TypeAlias(node: t.TypeAlias): E {
|
||||
const name = yield node.id;
|
||||
const params = node.typeParameters && (yield node.typeParameters);
|
||||
|
||||
yield declare(name, node, params);
|
||||
|
||||
return name;
|
||||
},
|
||||
|
||||
* InterfaceDeclaration(node: t.InterfaceDeclaration): E {
|
||||
const name = yield node.id;
|
||||
const params = node.typeParameters && (yield node.typeParameters);
|
||||
|
||||
yield declare(name, node, params);
|
||||
|
||||
return name;
|
||||
},
|
||||
|
||||
* ClassDeclaration(node: t.ClassDeclaration): E {
|
||||
const name = yield node.id;
|
||||
const params = node.typeParameters && (yield node.typeParameters);
|
||||
|
||||
// TODO: do it only for "all"-mode.
|
||||
const body = node.body;
|
||||
yield body.body.filter(n => t.isClassMethod(n));
|
||||
|
||||
yield declare(name, node, params);
|
||||
|
||||
return name;
|
||||
},
|
||||
|
||||
* TypeParameterDeclaration(node: t.TypeParameterDeclaration): E {
|
||||
return yield node.params;
|
||||
},
|
||||
|
||||
* TypeParameter(node: t.TypeParameter): E {
|
||||
return {
|
||||
name: node.name,
|
||||
default: node.default ? yield node.default : null,
|
||||
};
|
||||
},
|
||||
|
||||
/*
|
||||
* Utility.
|
||||
*/
|
||||
|
||||
* StringLiteral(node: t.StringLiteral): E {
|
||||
return node.value;
|
||||
},
|
||||
|
||||
* Identifier(node: t.Identifier): E {
|
||||
return node.name;
|
||||
},
|
||||
};
|
||||
|
||||
function extractRequire(node) {
|
||||
// XXX: refactor it!
|
||||
|
||||
// TODO: use `t.*` helpers.
|
||||
const ok = node &&
|
||||
node.type === 'CallExpression' &&
|
||||
node.callee.type === 'Identifier' &&
|
||||
node.callee.name === 'require';
|
||||
|
||||
if (!ok) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const argument = node.arguments[0];
|
||||
|
||||
// TODO: warning about dynamic imports.
|
||||
invariant(t.isStringLiteral(argument));
|
||||
|
||||
return argument.value;
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
import * as t from '@babel/types';
|
||||
|
||||
import {declare, define, external, provide, query, enter, exit, namespace} from './commands';
|
||||
import {define, query, namespace} from './commands';
|
||||
import {invariant, partition} from './utils';
|
||||
import type {Schema} from './schema';
|
||||
|
||||
type E = Generator<any, any, any>;
|
||||
|
||||
export const definition = {
|
||||
export default {
|
||||
entries: [
|
||||
'TypeAlias',
|
||||
'InterfaceDeclaration',
|
||||
|
@ -247,208 +247,6 @@ export const definition = {
|
|||
},
|
||||
};
|
||||
|
||||
export const declaration = {
|
||||
entries: [
|
||||
// Blocks.
|
||||
'Program',
|
||||
'BlockStatement',
|
||||
// Imports.
|
||||
'ImportDeclaration',
|
||||
'VariableDeclarator',
|
||||
// Exports.
|
||||
'ExportNamedDeclaration',
|
||||
'ExportDefaultDeclaration',
|
||||
],
|
||||
|
||||
/*
|
||||
* Blocks.
|
||||
*/
|
||||
|
||||
* Program(node: t.Program): E {
|
||||
yield node.body;
|
||||
},
|
||||
|
||||
* BlockStatement(node: t.BlockStatement): E {
|
||||
yield enter();
|
||||
yield node.body;
|
||||
yield exit();
|
||||
},
|
||||
|
||||
/*
|
||||
* Imports.
|
||||
*
|
||||
* TODO: warning about "import typeof".
|
||||
* TODO: support form "import *".
|
||||
*/
|
||||
|
||||
* ImportDeclaration(node: t.ImportDeclaration): E {
|
||||
const specifiers = yield node.specifiers;
|
||||
const path = yield node.source;
|
||||
|
||||
for (const specifier of specifiers) {
|
||||
specifier.path = path;
|
||||
|
||||
yield external(specifier);
|
||||
}
|
||||
},
|
||||
|
||||
* ImportDefaultSpecifier(node: t.ImportDefaultSpecifier): E {
|
||||
return {
|
||||
local: yield node.local,
|
||||
imported: null,
|
||||
};
|
||||
},
|
||||
|
||||
* ImportSpecifier(node: t.ImportSpecifier): E {
|
||||
return {
|
||||
local: yield node.local,
|
||||
imported: yield node.imported,
|
||||
};
|
||||
},
|
||||
|
||||
* VariableDeclarator(node: t.VariableDeclarator): E {
|
||||
const path = extractRequire(node.init);
|
||||
|
||||
if (!path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let specifiers = yield node.id;
|
||||
|
||||
if (typeof specifiers === 'string') {
|
||||
specifiers = [{
|
||||
local: specifiers,
|
||||
imported: null,
|
||||
}];
|
||||
}
|
||||
|
||||
for (const specifier of specifiers) {
|
||||
specifier.path = path;
|
||||
|
||||
yield external(specifier);
|
||||
}
|
||||
},
|
||||
|
||||
* ObjectPattern(node: t.ObjectPattern): E {
|
||||
return yield node.properties;
|
||||
},
|
||||
|
||||
* ObjectProperty(node: t.ObjectProperty): E {
|
||||
const key = yield node.key;
|
||||
|
||||
// TODO: different roots.
|
||||
if (node.value.type !== 'Identifier') {
|
||||
return null;
|
||||
}
|
||||
|
||||
//invariant(node.value.type === 'Identifier');
|
||||
|
||||
const value = yield node.value;
|
||||
|
||||
return {
|
||||
local: value,
|
||||
imported: key,
|
||||
};
|
||||
},
|
||||
|
||||
/*
|
||||
* Exports.
|
||||
*
|
||||
* TODO: support "export from" form.
|
||||
* TODO: support commonjs.
|
||||
*/
|
||||
|
||||
* ExportDefaultDeclaration(node: t.ExportDefaultDeclaration): E {
|
||||
const reference = yield node.declaration;
|
||||
|
||||
if (reference) {
|
||||
yield provide(null, reference);
|
||||
}
|
||||
},
|
||||
|
||||
* ExportNamedDeclaration(node: t.ExportNamedDeclaration): E {
|
||||
if (!node.declaration) {
|
||||
yield node.specifiers;
|
||||
return;
|
||||
}
|
||||
|
||||
const reference = yield node.declaration;
|
||||
|
||||
if (reference) {
|
||||
yield provide(reference);
|
||||
}
|
||||
},
|
||||
|
||||
* ExportSpecifier(node: t.ExportSpecifier): E {
|
||||
const reference = yield node.local;
|
||||
let name = yield node.exported;
|
||||
|
||||
if (name === 'default') {
|
||||
name = null;
|
||||
}
|
||||
|
||||
yield provide(name, reference);
|
||||
},
|
||||
|
||||
/*
|
||||
* Declarations.
|
||||
*/
|
||||
|
||||
* TypeAlias(node: t.TypeAlias): E {
|
||||
const name = yield node.id;
|
||||
const params = node.typeParameters && (yield node.typeParameters);
|
||||
|
||||
yield declare(name, node, params);
|
||||
|
||||
return name;
|
||||
},
|
||||
|
||||
* InterfaceDeclaration(node: t.InterfaceDeclaration): E {
|
||||
const name = yield node.id;
|
||||
const params = node.typeParameters && (yield node.typeParameters);
|
||||
|
||||
yield declare(name, node, params);
|
||||
|
||||
return name;
|
||||
},
|
||||
|
||||
* ClassDeclaration(node: t.ClassDeclaration): E {
|
||||
const name = yield node.id;
|
||||
const params = node.typeParameters && (yield node.typeParameters);
|
||||
|
||||
// TODO: do it only for "all"-mode.
|
||||
const body = node.body;
|
||||
yield body.body.filter(n => t.isClassMethod(n));
|
||||
|
||||
yield declare(name, node, params);
|
||||
|
||||
return name;
|
||||
},
|
||||
|
||||
* TypeParameterDeclaration(node: t.TypeParameterDeclaration): E {
|
||||
return yield node.params;
|
||||
},
|
||||
|
||||
* TypeParameter(node: t.TypeParameter): E {
|
||||
return {
|
||||
name: node.name,
|
||||
default: node.default ? yield node.default : null,
|
||||
};
|
||||
},
|
||||
|
||||
/*
|
||||
* Utility.
|
||||
*/
|
||||
|
||||
* StringLiteral(node: t.StringLiteral): E {
|
||||
return node.value;
|
||||
},
|
||||
|
||||
* Identifier(node: t.Identifier): E {
|
||||
return node.name;
|
||||
},
|
||||
};
|
||||
|
||||
function* extractLastPragma(comments: t.Comment[]): ?string {
|
||||
const pragmas = (yield comments).filter(Boolean);
|
||||
|
||||
|
@ -482,27 +280,6 @@ function* extractProperty(prop, value) {
|
|||
};
|
||||
}
|
||||
|
||||
function extractRequire(node) {
|
||||
// XXX: refactor it!
|
||||
|
||||
// TODO: use `t.*` helpers.
|
||||
const ok = node &&
|
||||
node.type === 'CallExpression' &&
|
||||
node.callee.type === 'Identifier' &&
|
||||
node.callee.name === 'require';
|
||||
|
||||
if (!ok) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const argument = node.arguments[0];
|
||||
|
||||
// TODO: warning about dynamic imports.
|
||||
invariant(t.isStringLiteral(argument));
|
||||
|
||||
return argument.value;
|
||||
}
|
||||
|
||||
function parsePragma(pragma) {
|
||||
let [type, arg] = pragma.split(/\s+/);
|
||||
|
||||
|
@ -580,7 +357,7 @@ function makeFullname(schema) {
|
|||
return `${schema.namespace}.${schema.name}`;
|
||||
}
|
||||
|
||||
function mergeSchemas(schemas: Schemas): Schema {
|
||||
function mergeSchemas(schemas: Schema[]): Schema {
|
||||
const map = new Map;
|
||||
|
||||
// TODO: overriding?
|
Loading…
Reference in New Issue