f065c32 fix: 修复语言热重载导致缓存失效及正则匹配的问题
3fe5f37 fix: 修复扩展加载和自动补全的性能问题
7b8900a feat: 集成 i18n 字典和版本过滤功能到扩展运行时
 src/VivadoCompletionItemProvider.ts |  67 +++++++++++++++++++++
 src/VivadoHoverProvider.ts          |  38 ++++++++++++
 src/extension.ts                    | 114 ++++++++++++++++++++----------------
 3 files changed, 170 insertions(+), 49 deletions(-)
diff --git a/src/VivadoCompletionItemProvider.ts b/src/VivadoCompletionItemProvider.ts
new file mode 100644
index 0000000..238e982
--- /dev/null
+++ b/src/VivadoCompletionItemProvider.ts
@@ -0,0 +1,67 @@
+import * as vscode from 'vscode';
+import { vivadoSchema } from './generated/vivadoSchema';
+import { getDictionary, getVivadoVersion, getLanguageSetting } from './extension';
+
+export class VivadoCompletionItemProvider implements vscode.CompletionItemProvider {
+    private cachedRootCommands: vscode.CompletionItem[] = [];
+    private cachedVersion: string = '';
+    private cachedLanguage: string = '';
+
+    provideCompletionItems(document: vscode.TextDocument, position: vscode.Position) {
+        const versionSetting = getVivadoVersion();
+        const languageSetting = getLanguageSetting();
+        const dict = getDictionary();
+
+        const linePrefix = document.lineAt(position).text.substring(0, position.character);
+        const match = linePrefix.match(/([a-zA-Z0-9_]+)\s+[^;]*-$/);
+
+        if (match) {
+            const commandName = match[1];
+            const cmd = vivadoSchema.find(c => c.name === commandName);
+
+            if (cmd && cmd.versions.includes(versionSetting)) {
+                return cmd.arguments.map(argName => {
+                    const item = new vscode.CompletionItem(argName, vscode.CompletionItemKind.Property);
+                    
+                    const desc = dict[`${commandName}.args.${argName}`];
+                    if (desc) { 
+                        item.documentation = new vscode.MarkdownString(desc); 
+                    }
+
+                    if (argName.startsWith('-')) {
+                        item.insertText = argName.substring(1);
+                    } else {
+                        item.insertText = argName;
+                    }
+
+                    return item;
+                });
+            }
+            return []; // No arguments for unknown command or version mismatch
+        }
+
+        // Return cached commands if matching current version and language
+        if (this.cachedVersion === versionSetting && this.cachedLanguage === languageSetting && this.cachedRootCommands.length > 0) {
+            return this.cachedRootCommands;
+        }
+
+        // Rebuild cache
+        const items: vscode.CompletionItem[] = [];
+        for (const cmd of vivadoSchema) {
+            if (cmd.versions.includes(versionSetting)) {
+                const item = new vscode.CompletionItem(cmd.name, vscode.CompletionItemKind.Function);
+                const desc = dict[`${cmd.name}.short_description`];
+                if (desc) { 
+                    item.documentation = new vscode.MarkdownString(desc); 
+                }
+                items.push(item);
+            }
+        }
+        
+        this.cachedVersion = versionSetting;
+        this.cachedLanguage = languageSetting;
+        this.cachedRootCommands = items;
+
+        return items;
+    }
+}
diff --git a/src/VivadoHoverProvider.ts b/src/VivadoHoverProvider.ts
new file mode 100644
index 0000000..1207269
--- /dev/null
+++ b/src/VivadoHoverProvider.ts
@@ -0,0 +1,38 @@
+import * as vscode from 'vscode';
+import { vivadoSchema } from './generated/vivadoSchema';
+import { getDictionary, getVivadoVersion } from './extension';
+
+export class VivadoHoverProvider implements vscode.HoverProvider {
+    provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): vscode.ProviderResult<vscode.Hover> {
+        const range = document.getWordRangeAtPosition(position);
+        if (!range) {
+            return null;
+        }
+
+        const word = document.getText(range);
+        const versionSetting = getVivadoVersion();
+        const dict = getDictionary();
+
+        const cmd = vivadoSchema.find(c => c.name === word);
+        if (cmd && cmd.versions.includes(versionSetting)) {
+            const desc = dict[`${cmd.name}.short_description`];
+            const help = dict[`${cmd.name}.full_help`];
+            
+            if (!desc && !help) {
+                return null;
+            }
+
+            const ms = new vscode.MarkdownString();
+            if (desc) {
+                ms.appendMarkdown(`**${word}**\n\n${desc}`);
+            }
+            if (help) {
+                ms.appendMarkdown(`\n\n---\n\n${help}`);
+            }
+            
+            return new vscode.Hover(ms);
+        }
+
+        return null;
+    }
+}
diff --git a/src/extension.ts b/src/extension.ts
index 7dfa532..f34bb90 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -1,57 +1,73 @@
-// The module 'vscode' contains the VS Code extensibility API
-// Import the module and reference it with the alias vscode in your code below
 import * as vscode from 'vscode';
-import { vivadoCommands, vivadoArgs } from './generated/vivadoCommands';
-
-// This method is called when your extension is activated
-// Your extension is activated the very first time the command is executed
-export function activate(context: vscode.ExtensionContext) {
-
-	// Use the console to output diagnostic information (console.log) and errors (console.error)
-	// This line of code will only be executed once when your extension is activated
-	console.log('Congratulations, your extension "vivado-completion" is now active!');
-
-	// The command has been defined in the package.json file
-	// Now provide the implementation of the command with registerCommand
-	// The commandId parameter must match the command field in package.json
-	const provider = vscode.languages.registerCompletionItemProvider(
-        ['tcl', 'xdc'], 
-        {
-            provideCompletionItems(document: vscode.TextDocument, position: vscode.Position) {
-
-                const linePrefix = document.lineAt(position).text.substring(0, position.character);
-
-                const match = linePrefix.match(/([a-zA-Z0-9_]+)\s+.*-$/);
-                if (match) {
-                    const commandName = match[1];
-
-                    if (vivadoArgs[commandName]) {
-                        return vivadoArgs[commandName].map((arg: any) => {
-                            const label = arg.label || arg.name;
-                            
-                            const item = new vscode.CompletionItem(label, vscode.CompletionItemKind.Property);
-                            
-                            if (arg.documentation) { item.documentation = arg.documentation; }
-                            if (arg.description) { item.documentation = new vscode.MarkdownString(arg.description); }
-                            if (arg.detail) { item.detail = arg.detail; }
-
-                            if (typeof label === 'string' && label.startsWith('-')) {
-                                item.insertText = label.substring(1);
-                            }
-
-                            return item;
-                        });
-                    }
-                }
-
-                return vivadoCommands;
+import { promises as fs } from 'fs';
+import * as path from 'path';
+import { VivadoCompletionItemProvider } from './VivadoCompletionItemProvider';
+import { VivadoHoverProvider } from './VivadoHoverProvider';
+
+let globalDict: Record<string, string> = {};
+
+export function getDictionary(): Record<string, string> {
+    return globalDict;
+}
+
+async function loadDictionary(context: vscode.ExtensionContext, langSetting: string) {
+    let lang = langSetting === 'auto' ? vscode.env.language : langSetting;
+    let dictPath = path.join(context.extensionPath, 'dist', `strings.${lang}.json`);
+    
+    try {
+        await fs.access(dictPath);
+    } catch {
+        // Fallback to English if translation doesn't exist
+        dictPath = path.join(context.extensionPath, 'dist', 'strings.en.json');
+    }
+    
+    try {
+        const content = await fs.readFile(dictPath, 'utf8');
+        globalDict = JSON.parse(content);
+    } catch (e) {
+        console.error(`Failed to load dictionary from ${dictPath}:`, e);
+        globalDict = {}; // Fallback to empty dictionary on error
+    }
+}
+
+export function getVivadoVersion(): string {
+    return vscode.workspace.getConfiguration('vivado-completion').get<string>('vivadoVersion', '2024.1');
+}
+
+export function getLanguageSetting(): string {
+    return vscode.workspace.getConfiguration('vivado-completion').get<string>('language', 'auto');
+}
+
+export async function activate(context: vscode.ExtensionContext) {
+    console.log('Congratulations, your extension "vivado-completion" is now active!');
+
+    const langSetting = getLanguageSetting();
+    await loadDictionary(context, langSetting);
+    
+    // Listen for configuration changes
+    context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(async e => {
+        if (e.affectsConfiguration('vivado-completion.language')) {
+            try {
+                const newLangSetting = getLanguageSetting();
+                await loadDictionary(context, newLangSetting);
+            } catch (err) {
+                console.error('Error reloading dictionary:', err);
             }
-        },
+        }
+    }));
+
+    const completionProvider = vscode.languages.registerCompletionItemProvider(
+        ['tcl', 'xdc'],
+        new VivadoCompletionItemProvider(),
         '-', ' '
     );
 
-    context.subscriptions.push(provider);
+    const hoverProvider = vscode.languages.registerHoverProvider(
+        ['tcl', 'xdc'],
+        new VivadoHoverProvider()
+    );
+
+    context.subscriptions.push(completionProvider, hoverProvider);
 }
 
-// This method is called when your extension is deactivated
 export function deactivate() {}
