设置 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);
}
}