Split extractors.js into declarations.js and definitions.js

master
Paul Loyd 2017-11-18 14:23:45 +03:00
parent 794167254a
commit 2a24383d59
4 changed files with 239 additions and 230 deletions

View File

@ -2,7 +2,8 @@
.*/node_modules/.*
.*/tests/samples/.*
.*/lib/.*
.*/src/extractors.js
.*/src/definitions.js
.*/src/declarations.js
[libs]
declarations/

View File

@ -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');

229
src/declarations.js Normal file
View File

@ -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;
}

View File

@ -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?