monaco-auto-typings
Version:
provides automatic dependency type completion for Monaco Editor
116 lines (115 loc) • 4.78 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DependencyParser = void 0;
const is_builtin_module_1 = __importDefault(require("is-builtin-module"));
const typescript_1 = __importDefault(require("typescript"));
// 匹配本地导入路径的正则表达式(如./或/开头的路径)
const LOCAL_IMPORT_REG = /^[\\/|\\.]/;
// 匹配依赖项名称的正则表达式,解析格式如:registry:@scope/name@version
const DEPENDENCY_REG = /^(?:(\w+):)?(?:(@\w+\/)?)([\w\-\.\/]+)(?:@([\w\-\.]+))?$/;
/**
* 依赖解析器类
*/
class DependencyParser {
/**
* 从导入语句中提取依赖项信息
* @param imports 导入语句数组
* @returns 提取的依赖项数组
*/
static getDependenciesFromImports(imports) {
const dependencies = [];
for (const imp of imports) {
// 跳过内置模块和本地导入
if ((0, is_builtin_module_1.default)(imp) || LOCAL_IMPORT_REG.test(imp)) {
continue;
}
// 解析导入语句,提取registry、scope、name和version
const matches = imp.match(DEPENDENCY_REG);
if (matches) {
const [_, pkgRegistry, pkgScope, pkgFilePath, pkgVersion] = matches;
const pkgName = pkgFilePath.split("/").shift();
const name = pkgScope ? `${pkgScope}${pkgName}` : pkgName;
const version = pkgVersion || "";
const registry = (pkgRegistry === null || pkgRegistry === void 0 ? void 0 : pkgRegistry.split(':').shift()) || "";
dependencies.push({ name, version, registry });
}
}
return dependencies;
}
/**
* 从源代码中提取所有导入语句
* @param code 源代码字符串
* @returns 导入语句数组
*/
static getImportsFromSourceCode(code) {
if (!code || !code.trim()) {
return [];
}
const imports = [];
try {
const sourceFile = typescript_1.default.createSourceFile('__temp__.ts', code, typescript_1.default.ScriptTarget.Latest, true);
function visitNode(node, dependencies) {
// 处理 import 语句
if (typescript_1.default.isImportDeclaration(node)) {
const moduleSpecifier = node.moduleSpecifier;
if (typescript_1.default.isStringLiteral(moduleSpecifier)) {
dependencies.push(moduleSpecifier.text);
}
}
// 处理动态 import()
else if (typescript_1.default.isCallExpression(node)) {
if (node.expression.kind === typescript_1.default.SyntaxKind.ImportKeyword) {
const arg = node.arguments[0];
if (typescript_1.default.isStringLiteral(arg)) {
dependencies.push(arg.text);
}
}
// 处理 require()
else if (typescript_1.default.isIdentifier(node.expression) && node.expression.text === 'require') {
const arg = node.arguments[0];
if (typescript_1.default.isStringLiteral(arg)) {
dependencies.push(arg.text);
}
}
}
// 递归遍历子节点
typescript_1.default.forEachChild(node, child => visitNode(child, dependencies));
}
visitNode(sourceFile, imports);
}
catch (error) {
console.error('Failed to parse source code:', error);
}
return Array.from(new Set(imports));
}
/**
* 从.d.ts文件内容中查找引用
* @param code
* @returns 提取到的类型声明
*/
static getReferencesFromTypes(code) {
const refs = [];
try {
const sourceFile = typescript_1.default.createSourceFile('__temp__.d.ts', code, typescript_1.default.ScriptTarget.Latest, true);
(sourceFile.referencedFiles || []).forEach(item => {
refs.push(item.fileName);
});
}
catch (error) {
}
return refs;
}
/**
* 分析代码并返回依赖项
* @param code 源代码
* @returns 依赖项数组
*/
static analyzeDependencies(code) {
const imports = this.getImportsFromSourceCode(code);
return this.getDependenciesFromImports(imports);
}
}
exports.DependencyParser = DependencyParser;