monaco-auto-typings
Version:
provides automatic dependency type completion for Monaco Editor
113 lines (112 loc) • 4.55 kB
JavaScript
import debounceFn from "debounce";
import deepMerge from "deepmerge";
import { isValidUrl, createLogger } from '../utils/index';
import { getDependenciesFromImports, getImportsFromSourceCode } from './dependency-parser';
import { TypesManager } from './types-manager';
import { DEFAULT_OPTIONS } from '../config/index';
/**
* Monaco自动类型提示核心类
*/
export class MonacoAutoTypings {
constructor(options = {}) {
this.disposable = null;
// 验证配置选项
if (options.debounce !== undefined && (options.debounce < 0 || options.debounce > 5000)) {
throw new Error('Debounce time must be between 0-5000 milliseconds');
}
if (options.registry && !isValidUrl(options.registry)) {
throw new Error('Registry must be a valid URL');
}
if (options.maxConcurrency !== undefined && (options.maxConcurrency < 1 || options.maxConcurrency > 20)) {
throw new Error('Maximum concurrency must be between 1-20');
}
// 合并默认选项和用户选项
this.options = deepMerge(MonacoAutoTypings.defaultOptions, options);
this.logger = createLogger(this.options.verbose);
this.typesManager = new TypesManager(this.options, this.logger);
this.logger.info('Initializing Monaco Auto Typings plugin', this.options);
}
/**
* 初始化插件
*/
initialize(monaco, editor) {
try {
// 加载内置类型定义
const builtinLibs = Object.keys(this.options.builtins).filter(key => this.options.builtins[key]);
if (builtinLibs.length > 0) {
this.typesManager.createBuiltinExtraLibs(builtinLibs).then(libs => {
this.addTypescriptExtraLibs(monaco, libs);
}).catch(error => {
this.logger.error('Failed to load built-in types:', error);
});
}
// 创建代码变更处理函数并添加防抖
const changeHandler = this.createCodeChangeHandler(monaco, editor);
const debouncedHandler = debounceFn(changeHandler, this.options.debounce);
this.disposable = editor.onDidChangeModelContent(debouncedHandler);
this.logger.info('Monaco Auto Typings plugin initialization completed');
// 立即执行一次处理函数
changeHandler();
return {
dispose: () => this.dispose()
};
}
catch (error) {
this.logger.error('Initialization failed:', error);
throw error;
}
}
/**
* 添加类型定义
*/
addTypescriptExtraLibs(monaco, libs) {
libs.forEach(lib => {
const { filepath, content } = lib;
if (this.options.languages.includes('javascript')) {
monaco.languages.typescript.javascriptDefaults.addExtraLib(content, filepath);
}
if (this.options.languages.includes('typescript')) {
monaco.languages.typescript.typescriptDefaults.addExtraLib(content, filepath);
}
});
}
/**
* 创建代码变更处理函数
*/
createCodeChangeHandler(monaco, editor) {
return async () => {
try {
const model = editor.getModel();
if (!model) {
this.logger.warn('Editor model does not exist');
return;
}
const code = model.getValue();
if (!code.trim()) {
this.logger.info('Code is empty, skipping processing');
return;
}
this.logger.info('Starting code dependency analysis');
const imports = getImportsFromSourceCode(code);
const dependencies = getDependenciesFromImports(imports);
const extraLibs = await this.typesManager.createDenpendenciesExtraLibs(dependencies);
this.addTypescriptExtraLibs(monaco, extraLibs);
}
catch (error) {
this.logger.error('Error processing code changes:', error);
}
};
}
/**
* 销毁插件
*/
dispose() {
if (this.disposable) {
this.disposable.dispose();
this.disposable = null;
}
this.logger.info('Monaco Auto Typings plugin has been disposed');
}
}
// 默认配置选项
MonacoAutoTypings.defaultOptions = DEFAULT_OPTIONS;