Skip to content

设置 API

设置 API 提供了在 VS Code 中管理用户设置、工作区配置和扩展配置的功能。通过这些 API,扩展可以读取、修改和监听配置变化。

概述

设置 API 允许扩展程序:

  • 读取用户和工作区设置
  • 修改配置值
  • 监听配置变化
  • 定义扩展特定的配置项
  • 管理配置作用域(用户、工作区、文件夹)
  • 提供配置验证和默认值

主要接口

WorkspaceConfiguration

typescript
interface WorkspaceConfiguration {
    /**
     * 获取配置值
     */
    get<T>(section: string): T | undefined;
    get<T>(section: string, defaultValue: T): T;

    /**
     * 检查配置是否存在
     */
    has(section: string): boolean;

    /**
     * 检查配置的详细信息
     */
    inspect<T>(section: string): {
        key: string;
        defaultValue?: T;
        globalValue?: T;
        workspaceValue?: T;
        workspaceFolderValue?: T;
        defaultLanguageValue?: T;
        globalLanguageValue?: T;
        workspaceLanguageValue?: T;
        workspaceFolderLanguageValue?: T;
    } | undefined;

    /**
     * 更新配置值
     */
    update(
        section: string,
        value: any,
        configurationTarget?: ConfigurationTarget | boolean,
        overrideInLanguage?: boolean
    ): Thenable<void>;
}

ConfigurationTarget

typescript
enum ConfigurationTarget {
    /**
     * 全局配置
     */
    Global = 1,

    /**
     * 工作区配置
     */
    Workspace = 2,

    /**
     * 工作区文件夹配置
     */
    WorkspaceFolder = 3
}

ConfigurationChangeEvent

typescript
interface ConfigurationChangeEvent {
    /**
     * 检查指定配置是否发生变化
     */
    affectsConfiguration(section: string, scope?: ConfigurationScope): boolean;
}

type ConfigurationScope = Uri | TextDocument | WorkspaceFolder | { uri?: Uri; languageId: string };

读取配置

基本配置读取

typescript
import * as vscode from 'vscode';

class ConfigurationReader {
    /**
     * 读取扩展配置
     */
    getExtensionConfig(): ExtensionConfig {
        const config = vscode.workspace.getConfiguration('myExtension');
        
        return {
            enabled: config.get<boolean>('enabled', true),
            timeout: config.get<number>('timeout', 5000),
            apiUrl: config.get<string>('apiUrl', 'https://api.example.com'),
            features: config.get<string[]>('features', []),
            advanced: config.get<AdvancedConfig>('advanced', {})
        };
    }

    /**
     * 读取编辑器配置
     */
    getEditorConfig(): EditorConfig {
        const config = vscode.workspace.getConfiguration('editor');
        
        return {
            fontSize: config.get<number>('fontSize', 14),
            fontFamily: config.get<string>('fontFamily', 'Consolas'),
            tabSize: config.get<number>('tabSize', 4),
            insertSpaces: config.get<boolean>('insertSpaces', true),
            wordWrap: config.get<string>('wordWrap', 'off')
        };
    }

    /**
     * 读取语言特定配置
     */
    getLanguageConfig(languageId: string): LanguageConfig {
        const config = vscode.workspace.getConfiguration(`[${languageId}]`);
        
        return {
            tabSize: config.get<number>('editor.tabSize'),
            insertSpaces: config.get<boolean>('editor.insertSpaces'),
            formatOnSave: config.get<boolean>('editor.formatOnSave')
        };
    }

    /**
     * 读取工作区特定配置
     */
    getWorkspaceConfig(workspaceFolder: vscode.WorkspaceFolder): WorkspaceConfig {
        const config = vscode.workspace.getConfiguration('myExtension', workspaceFolder.uri);
        
        return {
            projectType: config.get<string>('projectType', 'default'),
            buildCommand: config.get<string>('buildCommand', 'npm run build'),
            testCommand: config.get<string>('testCommand', 'npm test'),
            excludePatterns: config.get<string[]>('excludePatterns', [])
        };
    }
}

interface ExtensionConfig {
    enabled: boolean;
    timeout: number;
    apiUrl: string;
    features: string[];
    advanced: AdvancedConfig;
}

interface AdvancedConfig {
    debugMode?: boolean;
    logLevel?: string;
    cacheSize?: number;
}

interface EditorConfig {
    fontSize: number;
    fontFamily: string;
    tabSize: number;
    insertSpaces: boolean;
    wordWrap: string;
}

interface LanguageConfig {
    tabSize?: number;
    insertSpaces?: boolean;
    formatOnSave?: boolean;
}

interface WorkspaceConfig {
    projectType: string;
    buildCommand: string;
    testCommand: string;
    excludePatterns: string[];
}

配置检查和验证

typescript
class ConfigurationValidator {
    /**
     * 验证配置值
     */
    validateConfig(): ValidationResult {
        const config = vscode.workspace.getConfiguration('myExtension');
        const errors: string[] = [];
        const warnings: string[] = [];

        // 检查必需配置
        if (!config.has('apiUrl')) {
            errors.push('缺少必需的配置项: apiUrl');
        }

        // 检查配置值范围
        const timeout = config.get<number>('timeout', 5000);
        if (timeout < 1000 || timeout > 30000) {
            warnings.push('timeout 应该在 1000-30000 之间');
        }

        // 检查配置值格式
        const apiUrl = config.get<string>('apiUrl', '');
        if (apiUrl && !this.isValidUrl(apiUrl)) {
            errors.push('apiUrl 格式无效');
        }

        // 检查数组配置
        const features = config.get<string[]>('features', []);
        const validFeatures = ['feature1', 'feature2', 'feature3'];
        const invalidFeatures = features.filter(f => !validFeatures.includes(f));
        if (invalidFeatures.length > 0) {
            warnings.push(`未知的功能: ${invalidFeatures.join(', ')}`);
        }

        return {
            isValid: errors.length === 0,
            errors,
            warnings
        };
    }

    /**
     * 检查配置详细信息
     */
    inspectConfiguration(section: string): ConfigurationInspection {
        const config = vscode.workspace.getConfiguration();
        const inspection = config.inspect(section);

        if (!inspection) {
            return { exists: false };
        }

        return {
            exists: true,
            key: inspection.key,
            defaultValue: inspection.defaultValue,
            globalValue: inspection.globalValue,
            workspaceValue: inspection.workspaceValue,
            workspaceFolderValue: inspection.workspaceFolderValue,
            effectiveValue: config.get(section),
            source: this.getConfigurationSource(inspection)
        };
    }

    private isValidUrl(url: string): boolean {
        try {
            new URL(url);
            return true;
        } catch {
            return false;
        }
    }

    private getConfigurationSource(inspection: any): string {
        if (inspection.workspaceFolderValue !== undefined) {
            return 'workspaceFolder';
        }
        if (inspection.workspaceValue !== undefined) {
            return 'workspace';
        }
        if (inspection.globalValue !== undefined) {
            return 'global';
        }
        return 'default';
    }
}

interface ValidationResult {
    isValid: boolean;
    errors: string[];
    warnings: string[];
}

interface ConfigurationInspection {
    exists: boolean;
    key?: string;
    defaultValue?: any;
    globalValue?: any;
    workspaceValue?: any;
    workspaceFolderValue?: any;
    effectiveValue?: any;
    source?: string;
}

修改配置

基本配置修改

typescript
class ConfigurationManager {
    /**
     * 更新全局配置
     */
    async updateGlobalConfig(section: string, value: any): Promise<void> {
        const config = vscode.workspace.getConfiguration();
        await config.update(section, value, vscode.ConfigurationTarget.Global);
    }

    /**
     * 更新工作区配置
     */
    async updateWorkspaceConfig(section: string, value: any): Promise<void> {
        const config = vscode.workspace.getConfiguration();
        await config.update(section, value, vscode.ConfigurationTarget.Workspace);
    }

    /**
     * 更新工作区文件夹配置
     */
    async updateWorkspaceFolderConfig(
        section: string,
        value: any,
        workspaceFolder: vscode.WorkspaceFolder
    ): Promise<void> {
        const config = vscode.workspace.getConfiguration(undefined, workspaceFolder.uri);
        await config.update(section, value, vscode.ConfigurationTarget.WorkspaceFolder);
    }

    /**
     * 批量更新配置
     */
    async updateMultipleConfigs(updates: ConfigUpdate[]): Promise<void> {
        const promises = updates.map(update => {
            const config = vscode.workspace.getConfiguration(
                undefined,
                update.scope
            );
            return config.update(
                update.section,
                update.value,
                update.target
            );
        });

        await Promise.all(promises);
    }

    /**
     * 重置配置到默认值
     */
    async resetConfigToDefault(section: string, target: vscode.ConfigurationTarget): Promise<void> {
        const config = vscode.workspace.getConfiguration();
        await config.update(section, undefined, target);
    }

    /**
     * 切换布尔配置
     */
    async toggleBooleanConfig(section: string, target: vscode.ConfigurationTarget): Promise<void> {
        const config = vscode.workspace.getConfiguration();
        const currentValue = config.get<boolean>(section, false);
        await config.update(section, !currentValue, target);
    }
}

interface ConfigUpdate {
    section: string;
    value: any;
    target: vscode.ConfigurationTarget;
    scope?: vscode.Uri;
}

高级配置操作

typescript
class AdvancedConfigurationManager {
    /**
     * 合并配置对象
     */
    async mergeObjectConfig(
        section: string,
        newValues: Record<string, any>,
        target: vscode.ConfigurationTarget
    ): Promise<void> {
        const config = vscode.workspace.getConfiguration();
        const currentValue = config.get<Record<string, any>>(section, {});
        
        const mergedValue = { ...currentValue, ...newValues };
        await config.update(section, mergedValue, target);
    }

    /**
     * 添加到数组配置
     */
    async addToArrayConfig(
        section: string,
        newItem: any,
        target: vscode.ConfigurationTarget
    ): Promise<void> {
        const config = vscode.workspace.getConfiguration();
        const currentArray = config.get<any[]>(section, []);
        
        if (!currentArray.includes(newItem)) {
            const updatedArray = [...currentArray, newItem];
            await config.update(section, updatedArray, target);
        }
    }

    /**
     * 从数组配置中移除
     */
    async removeFromArrayConfig(
        section: string,
        itemToRemove: any,
        target: vscode.ConfigurationTarget
    ): Promise<void> {
        const config = vscode.workspace.getConfiguration();
        const currentArray = config.get<any[]>(section, []);
        
        const updatedArray = currentArray.filter(item => item !== itemToRemove);
        await config.update(section, updatedArray, target);
    }

    /**
     * 条件性配置更新
     */
    async updateConfigIf(
        section: string,
        value: any,
        condition: (currentValue: any) => boolean,
        target: vscode.ConfigurationTarget
    ): Promise<boolean> {
        const config = vscode.workspace.getConfiguration();
        const currentValue = config.get(section);
        
        if (condition(currentValue)) {
            await config.update(section, value, target);
            return true;
        }
        
        return false;
    }

    /**
     * 配置迁移
     */
    async migrateConfiguration(migrations: ConfigMigration[]): Promise<void> {
        for (const migration of migrations) {
            await this.executeMigration(migration);
        }
    }

    private async executeMigration(migration: ConfigMigration): Promise<void> {
        const config = vscode.workspace.getConfiguration();
        
        if (config.has(migration.oldKey)) {
            const oldValue = config.get(migration.oldKey);
            const newValue = migration.transform ? migration.transform(oldValue) : oldValue;
            
            // 设置新配置
            await config.update(migration.newKey, newValue, migration.target);
            
            // 删除旧配置
            if (migration.removeOld) {
                await config.update(migration.oldKey, undefined, migration.target);
            }
        }
    }
}

interface ConfigMigration {
    oldKey: string;
    newKey: string;
    target: vscode.ConfigurationTarget;
    transform?: (oldValue: any) => any;
    removeOld?: boolean;
}

监听配置变化

基本配置监听

typescript
class ConfigurationWatcher {
    private disposables: vscode.Disposable[] = [];

    /**
     * 监听所有配置变化
     */
    watchAllConfigurations(): void {
        const disposable = vscode.workspace.onDidChangeConfiguration(event => {
            this.handleConfigurationChange(event);
        });
        
        this.disposables.push(disposable);
    }

    /**
     * 监听特定配置变化
     */
    watchSpecificConfiguration(section: string, callback: (newValue: any) => void): void {
        const disposable = vscode.workspace.onDidChangeConfiguration(event => {
            if (event.affectsConfiguration(section)) {
                const config = vscode.workspace.getConfiguration();
                const newValue = config.get(section);
                callback(newValue);
            }
        });
        
        this.disposables.push(disposable);
    }

    /**
     * 监听扩展配置变化
     */
    watchExtensionConfiguration(): void {
        const disposable = vscode.workspace.onDidChangeConfiguration(event => {
            if (event.affectsConfiguration('myExtension')) {
                this.reloadExtensionConfiguration();
            }
        });
        
        this.disposables.push(disposable);
    }

    /**
     * 监听工作区特定配置变化
     */
    watchWorkspaceConfiguration(workspaceFolder: vscode.WorkspaceFolder): void {
        const disposable = vscode.workspace.onDidChangeConfiguration(event => {
            if (event.affectsConfiguration('myExtension', workspaceFolder.uri)) {
                this.reloadWorkspaceConfiguration(workspaceFolder);
            }
        });
        
        this.disposables.push(disposable);
    }

    private handleConfigurationChange(event: vscode.ConfigurationChangeEvent): void {
        // 检查编辑器配置变化
        if (event.affectsConfiguration('editor')) {
            this.handleEditorConfigChange();
        }

        // 检查扩展配置变化
        if (event.affectsConfiguration('myExtension')) {
            this.handleExtensionConfigChange();
        }

        // 检查语言特定配置变化
        if (event.affectsConfiguration('[typescript]')) {
            this.handleLanguageConfigChange('typescript');
        }
    }

    private reloadExtensionConfiguration(): void {
        const config = vscode.workspace.getConfiguration('myExtension');
        
        // 重新加载配置
        const newConfig = {
            enabled: config.get<boolean>('enabled', true),
            timeout: config.get<number>('timeout', 5000),
            features: config.get<string[]>('features', [])
        };

        // 应用新配置
        this.applyConfiguration(newConfig);
    }

    private reloadWorkspaceConfiguration(workspaceFolder: vscode.WorkspaceFolder): void {
        const config = vscode.workspace.getConfiguration('myExtension', workspaceFolder.uri);
        
        // 处理工作区特定配置
        console.log(`工作区 ${workspaceFolder.name} 的配置已更新`);
    }

    private handleEditorConfigChange(): void {
        console.log('编辑器配置已更改');
    }

    private handleExtensionConfigChange(): void {
        console.log('扩展配置已更改');
    }

    private handleLanguageConfigChange(languageId: string): void {
        console.log(`${languageId} 语言配置已更改`);
    }

    private applyConfiguration(config: any): void {
        // 应用新配置的逻辑
        console.log('应用新配置:', config);
    }

    dispose(): void {
        this.disposables.forEach(d => d.dispose());
        this.disposables = [];
    }
}

高级配置监听

typescript
class SmartConfigurationWatcher {
    private watchers = new Map<string, ConfigurationWatcherInfo>();
    private debounceTimers = new Map<string, NodeJS.Timeout>();

    /**
     * 添加防抖配置监听器
     */
    addDebouncedWatcher(
        section: string,
        callback: (newValue: any, oldValue: any) => void,
        debounceMs: number = 300
    ): void {
        const config = vscode.workspace.getConfiguration();
        let oldValue = config.get(section);

        const disposable = vscode.workspace.onDidChangeConfiguration(event => {
            if (event.affectsConfiguration(section)) {
                // 清除之前的定时器
                const existingTimer = this.debounceTimers.get(section);
                if (existingTimer) {
                    clearTimeout(existingTimer);
                }

                // 设置新的防抖定时器
                const timer = setTimeout(() => {
                    const newValue = config.get(section);
                    callback(newValue, oldValue);
                    oldValue = newValue;
                    this.debounceTimers.delete(section);
                }, debounceMs);

                this.debounceTimers.set(section, timer);
            }
        });

        this.watchers.set(section, {
            disposable,
            callback,
            debounceMs
        });
    }

    /**
     * 添加条件配置监听器
     */
    addConditionalWatcher(
        section: string,
        condition: (newValue: any, oldValue: any) => boolean,
        callback: (newValue: any, oldValue: any) => void
    ): void {
        const config = vscode.workspace.getConfiguration();
        let oldValue = config.get(section);

        const disposable = vscode.workspace.onDidChangeConfiguration(event => {
            if (event.affectsConfiguration(section)) {
                const newValue = config.get(section);
                
                if (condition(newValue, oldValue)) {
                    callback(newValue, oldValue);
                }
                
                oldValue = newValue;
            }
        });

        this.watchers.set(`${section}_conditional`, {
            disposable,
            callback,
            condition
        });
    }

    /**
     * 批量监听配置变化
     */
    watchMultipleConfigurations(
        sections: string[],
        callback: (changes: ConfigurationChange[]) => void
    ): void {
        const disposable = vscode.workspace.onDidChangeConfiguration(event => {
            const changes: ConfigurationChange[] = [];
            const config = vscode.workspace.getConfiguration();

            for (const section of sections) {
                if (event.affectsConfiguration(section)) {
                    changes.push({
                        section,
                        newValue: config.get(section),
                        timestamp: Date.now()
                    });
                }
            }

            if (changes.length > 0) {
                callback(changes);
            }
        });

        this.watchers.set('multiple_' + sections.join('_'), {
            disposable,
            callback,
            sections
        });
    }

    /**
     * 移除配置监听器
     */
    removeWatcher(key: string): void {
        const watcher = this.watchers.get(key);
        if (watcher) {
            watcher.disposable.dispose();
            this.watchers.delete(key);
        }

        const timer = this.debounceTimers.get(key);
        if (timer) {
            clearTimeout(timer);
            this.debounceTimers.delete(key);
        }
    }

    /**
     * 清理所有监听器
     */
    dispose(): void {
        for (const [key, watcher] of this.watchers) {
            watcher.disposable.dispose();
        }
        this.watchers.clear();

        for (const timer of this.debounceTimers.values()) {
            clearTimeout(timer);
        }
        this.debounceTimers.clear();
    }
}

interface ConfigurationWatcherInfo {
    disposable: vscode.Disposable;
    callback: Function;
    debounceMs?: number;
    condition?: Function;
    sections?: string[];
}

interface ConfigurationChange {
    section: string;
    newValue: any;
    timestamp: number;
}

配置定义

扩展配置定义

typescript
// package.json 中的配置定义示例
const configurationContribution = {
    "contributes": {
        "configuration": {
            "title": "My Extension",
            "properties": {
                "myExtension.enabled": {
                    "type": "boolean",
                    "default": true,
                    "description": "启用扩展功能"
                },
                "myExtension.timeout": {
                    "type": "number",
                    "default": 5000,
                    "minimum": 1000,
                    "maximum": 30000,
                    "description": "请求超时时间(毫秒)"
                },
                "myExtension.apiUrl": {
                    "type": "string",
                    "default": "https://api.example.com",
                    "format": "uri",
                    "description": "API 服务器地址"
                },
                "myExtension.features": {
                    "type": "array",
                    "items": {
                        "type": "string",
                        "enum": ["feature1", "feature2", "feature3"]
                    },
                    "default": ["feature1"],
                    "description": "启用的功能列表"
                },
                "myExtension.advanced": {
                    "type": "object",
                    "properties": {
                        "debugMode": {
                            "type": "boolean",
                            "default": false
                        },
                        "logLevel": {
                            "type": "string",
                            "enum": ["error", "warn", "info", "debug"],
                            "default": "info"
                        }
                    },
                    "default": {},
                    "description": "高级设置"
                }
            }
        }
    }
};

动态配置管理

typescript
class DynamicConfigurationManager {
    /**
     * 根据环境动态设置默认配置
     */
    async setupEnvironmentDefaults(): Promise<void> {
        const config = vscode.workspace.getConfiguration('myExtension');
        
        // 检查是否是开发环境
        const isDevelopment = vscode.env.appName.includes('Insiders');
        
        if (isDevelopment && !config.has('advanced.debugMode')) {
            await config.update(
                'advanced.debugMode',
                true,
                vscode.ConfigurationTarget.Global
            );
        }

        // 根据工作区类型设置配置
        const workspaceFolders = vscode.workspace.workspaceFolders;
        if (workspaceFolders) {
            for (const folder of workspaceFolders) {
                await this.setupWorkspaceDefaults(folder);
            }
        }
    }

    private async setupWorkspaceDefaults(workspaceFolder: vscode.WorkspaceFolder): Promise<void> {
        const config = vscode.workspace.getConfiguration('myExtension', workspaceFolder.uri);
        
        // 检查项目类型
        const packageJsonPath = vscode.Uri.joinPath(workspaceFolder.uri, 'package.json');
        
        try {
            const packageJsonContent = await vscode.workspace.fs.readFile(packageJsonPath);
            const packageJson = JSON.parse(packageJsonContent.toString());
            
            // 根据项目依赖设置配置
            if (packageJson.dependencies?.react) {
                await config.update(
                    'projectType',
                    'react',
                    vscode.ConfigurationTarget.WorkspaceFolder
                );
            } else if (packageJson.dependencies?.vue) {
                await config.update(
                    'projectType',
                    'vue',
                    vscode.ConfigurationTarget.WorkspaceFolder
                );
            }
        } catch (error) {
            // package.json 不存在或无法读取
        }
    }

    /**
     * 配置模板应用
     */
    async applyConfigurationTemplate(templateName: string): Promise<void> {
        const templates = this.getConfigurationTemplates();
        const template = templates[templateName];
        
        if (!template) {
            throw new Error(`配置模板 ${templateName} 不存在`);
        }

        for (const [section, value] of Object.entries(template.settings)) {
            const config = vscode.workspace.getConfiguration();
            await config.update(section, value, template.target);
        }
    }

    private getConfigurationTemplates(): Record<string, ConfigurationTemplate> {
        return {
            'development': {
                settings: {
                    'myExtension.advanced.debugMode': true,
                    'myExtension.advanced.logLevel': 'debug',
                    'myExtension.timeout': 10000
                },
                target: vscode.ConfigurationTarget.Workspace
            },
            'production': {
                settings: {
                    'myExtension.advanced.debugMode': false,
                    'myExtension.advanced.logLevel': 'error',
                    'myExtension.timeout': 5000
                },
                target: vscode.ConfigurationTarget.Workspace
            }
        };
    }
}

interface ConfigurationTemplate {
    settings: Record<string, any>;
    target: vscode.ConfigurationTarget;
}

实用示例

配置管理器

typescript
class ExtensionConfigurationManager {
    private config: ExtensionConfig;
    private watchers: vscode.Disposable[] = [];

    constructor() {
        this.config = this.loadConfiguration();
        this.setupConfigurationWatching();
    }

    /**
     * 获取当前配置
     */
    getConfig(): ExtensionConfig {
        return { ...this.config };
    }

    /**
     * 更新配置
     */
    async updateConfig(updates: Partial<ExtensionConfig>): Promise<void> {
        const config = vscode.workspace.getConfiguration('myExtension');
        
        for (const [key, value] of Object.entries(updates)) {
            await config.update(key, value, vscode.ConfigurationTarget.Global);
        }
    }

    /**
     * 重置配置
     */
    async resetConfiguration(): Promise<void> {
        const config = vscode.workspace.getConfiguration('myExtension');
        const inspection = config.inspect('');
        
        if (inspection) {
            // 重置所有自定义配置
            for (const key of Object.keys(inspection.globalValue || {})) {
                await config.update(key, undefined, vscode.ConfigurationTarget.Global);
            }
        }
    }

    /**
     * 导出配置
     */
    exportConfiguration(): string {
        return JSON.stringify(this.config, null, 2);
    }

    /**
     * 导入配置
     */
    async importConfiguration(configJson: string): Promise<void> {
        try {
            const importedConfig = JSON.parse(configJson);
            await this.updateConfig(importedConfig);
        } catch (error) {
            throw new Error('无效的配置格式');
        }
    }

    private loadConfiguration(): ExtensionConfig {
        const config = vscode.workspace.getConfiguration('myExtension');
        
        return {
            enabled: config.get<boolean>('enabled', true),
            timeout: config.get<number>('timeout', 5000),
            apiUrl: config.get<string>('apiUrl', ''),
            features: config.get<string[]>('features', []),
            advanced: config.get<AdvancedConfig>('advanced', {})
        };
    }

    private setupConfigurationWatching(): void {
        const disposable = vscode.workspace.onDidChangeConfiguration(event => {
            if (event.affectsConfiguration('myExtension')) {
                this.config = this.loadConfiguration();
                this.onConfigurationChanged(this.config);
            }
        });
        
        this.watchers.push(disposable);
    }

    private onConfigurationChanged(newConfig: ExtensionConfig): void {
        // 配置变化处理逻辑
        console.log('配置已更新:', newConfig);
        
        // 触发配置变化事件
        this.emitConfigurationChanged(newConfig);
    }

    private emitConfigurationChanged(config: ExtensionConfig): void {
        // 发送配置变化事件给其他组件
        vscode.commands.executeCommand('myExtension.configurationChanged', config);
    }

    dispose(): void {
        this.watchers.forEach(watcher => watcher.dispose());
        this.watchers = [];
    }
}

配置向导

typescript
class ConfigurationWizard {
    /**
     * 启动配置向导
     */
    async startWizard(): Promise<void> {
        const steps = [
            this.stepBasicSettings,
            this.stepAdvancedSettings,
            this.stepFeatureSelection,
            this.stepConfirmation
        ];

        const wizardData: WizardData = {};

        for (const step of steps) {
            const result = await step.call(this, wizardData);
            if (!result) {
                // 用户取消了向导
                return;
            }
        }

        // 应用配置
        await this.applyWizardConfiguration(wizardData);
    }

    private async stepBasicSettings(data: WizardData): Promise<boolean> {
        const apiUrl = await vscode.window.showInputBox({
            prompt: '请输入 API 服务器地址',
            value: 'https://api.example.com',
            validateInput: (value) => {
                try {
                    new URL(value);
                    return null;
                } catch {
                    return '请输入有效的 URL';
                }
            }
        });

        if (!apiUrl) return false;

        const timeout = await vscode.window.showInputBox({
            prompt: '请输入请求超时时间(毫秒)',
            value: '5000',
            validateInput: (value) => {
                const num = parseInt(value);
                if (isNaN(num) || num < 1000 || num > 30000) {
                    return '请输入 1000-30000 之间的数字';
                }
                return null;
            }
        });

        if (!timeout) return false;

        data.apiUrl = apiUrl;
        data.timeout = parseInt(timeout);
        return true;
    }

    private async stepAdvancedSettings(data: WizardData): Promise<boolean> {
        const debugMode = await vscode.window.showQuickPick(
            ['是', '否'],
            { placeHolder: '是否启用调试模式?' }
        );

        if (!debugMode) return false;

        const logLevel = await vscode.window.showQuickPick(
            ['error', 'warn', 'info', 'debug'],
            { placeHolder: '选择日志级别' }
        );

        if (!logLevel) return false;

        data.debugMode = debugMode === '是';
        data.logLevel = logLevel;
        return true;
    }

    private async stepFeatureSelection(data: WizardData): Promise<boolean> {
        const availableFeatures = ['feature1', 'feature2', 'feature3'];
        const selectedFeatures = await vscode.window.showQuickPick(
            availableFeatures,
            {
                placeHolder: '选择要启用的功能',
                canPickMany: true
            }
        );

        if (!selectedFeatures) return false;

        data.features = selectedFeatures;
        return true;
    }

    private async stepConfirmation(data: WizardData): Promise<boolean> {
        const summary = this.generateConfigurationSummary(data);
        const confirm = await vscode.window.showInformationMessage(
            `配置摘要:\n${summary}\n\n确认应用这些设置吗?`,
            '确认',
            '取消'
        );

        return confirm === '确认';
    }

    private generateConfigurationSummary(data: WizardData): string {
        return [
            `API 地址: ${data.apiUrl}`,
            `超时时间: ${data.timeout}ms`,
            `调试模式: ${data.debugMode ? '启用' : '禁用'}`,
            `日志级别: ${data.logLevel}`,
            `启用功能: ${data.features?.join(', ') || '无'}`
        ].join('\n');
    }

    private async applyWizardConfiguration(data: WizardData): Promise<void> {
        const config = vscode.workspace.getConfiguration('myExtension');

        await config.update('apiUrl', data.apiUrl, vscode.ConfigurationTarget.Global);
        await config.update('timeout', data.timeout, vscode.ConfigurationTarget.Global);
        await config.update('features', data.features, vscode.ConfigurationTarget.Global);
        await config.update('advanced.debugMode', data.debugMode, vscode.ConfigurationTarget.Global);
        await config.update('advanced.logLevel', data.logLevel, vscode.ConfigurationTarget.Global);

        vscode.window.showInformationMessage('配置已成功应用!');
    }
}

interface WizardData {
    apiUrl?: string;
    timeout?: number;
    debugMode?: boolean;
    logLevel?: string;
    features?: string[];
}

最佳实践

1. 配置验证

typescript
// 始终验证配置值
function getValidatedConfig(): ExtensionConfig {
    const config = vscode.workspace.getConfiguration('myExtension');
    
    const timeout = config.get<number>('timeout', 5000);
    const validatedTimeout = Math.max(1000, Math.min(30000, timeout));
    
    return {
        timeout: validatedTimeout,
        // ... 其他配置
    };
}

2. 配置缓存

typescript
// 缓存配置以提高性能
class ConfigurationCache {
    private cache = new Map<string, any>();
    private lastUpdate = 0;
    private readonly CACHE_TTL = 5000; // 5秒

    get<T>(section: string, defaultValue: T): T {
        const now = Date.now();
        if (now - this.lastUpdate > this.CACHE_TTL) {
            this.cache.clear();
            this.lastUpdate = now;
        }

        if (!this.cache.has(section)) {
            const config = vscode.workspace.getConfiguration();
            this.cache.set(section, config.get(section, defaultValue));
        }

        return this.cache.get(section);
    }
}

3. 配置迁移

typescript
// 处理配置版本迁移
async function migrateConfiguration(): Promise<void> {
    const config = vscode.workspace.getConfiguration('myExtension');
    const version = config.get<string>('configVersion', '1.0.0');

    if (version === '1.0.0') {
        // 迁移到 2.0.0
        const oldApiUrl = config.get<string>('apiEndpoint');
        if (oldApiUrl) {
            await config.update('apiUrl', oldApiUrl, vscode.ConfigurationTarget.Global);
            await config.update('apiEndpoint', undefined, vscode.ConfigurationTarget.Global);
        }
        await config.update('configVersion', '2.0.0', vscode.ConfigurationTarget.Global);
    }
}

相关 API

您的终极 AI 驱动 IDE 学习指南