Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions src/codeLensProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ export class SourceDocCodeLensProvider implements vscode.CodeLensProvider {
}

const lenses: vscode.CodeLens[] = [];
const firstRange = new vscode.Range(0, 0, 0, document.lineAt(0).text.length);
const firstRange = document.lineCount > 0
? new vscode.Range(0, 0, 0, document.lineAt(0).text.length)
: new vscode.Range(0, 0, 0, 0);

// File-level lens at line 0 — always shown (except 'none')
lenses.push(
Expand Down Expand Up @@ -187,7 +189,7 @@ export class SourceDocCodeLensProvider implements vscode.CodeLensProvider {
// For code languages: match function/class/method/def/fn declarations.
const CODE_RE = /^[ \t]*((?:export\s+)?(?:default\s+)?(?:async\s+)?function[\s*]+\w+|(?:export\s+)?(?:abstract\s+|sealed\s+)?class\s+\w+|(?:export\s+)?(?:abstract\s+)?interface\s+\w+|(?:export\s+)?(?:const|let|var)\s+\w+\s*=\s*(?:async\s*)?(?:\([^)]*\)|\w+)\s*=>|(?:public|private|protected|internal)(?:\s+(?:static|override|virtual|abstract|async|readonly))*\s+\S+\s+\w+\s*[({]|def\s+\w+\s*\(|fn\s+\w+\s*[(<]|func\s+\w+\s*[(<])/;

const RE = isXml ? XAML_RE : CODE_RE;;
const RE = isXml ? XAML_RE : CODE_RE;

// In block mode, pass the full element/function text as context.
// For XAML, capture from the opening tag to the matching close or end-of-line.
Expand Down
19 changes: 18 additions & 1 deletion src/explanationProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,29 @@ export class ExplanationProvider implements vscode.Disposable {
}
} catch (err) {
if (err instanceof vscode.LanguageModelError) {
throw new Error(`Copilot error (${err.code}): ${err.message}`);
switch (err.code) {
case 'NoPermissions':
throw new Error(`Copilot error (${err.code}): access denied. Please check your GitHub Copilot subscription.`);
case 'Blocked':
throw new Error(`Copilot error (${err.code}): request was blocked. Please check your GitHub Copilot settings.`);
case 'NotFound':
throw new Error(`Copilot error (${err.code}): model not found. Please check your GitHub Copilot extension.`);
case 'RequestFailed':
throw new Error(`Copilot error (${err.code}): request failed. Please try again.`);
default:
throw new Error(`Copilot error (${err.code}): ${err.message}. Please check your GitHub Copilot extension.`);
}
}
throw err;
}

result = result.trim();
if (token.isCancellationRequested) {
throw new vscode.CancellationError();
}
if (!result) {
throw new Error('Copilot returned an empty explanation. Please try again.');
}
this.addToCache(key, result);
return result;
}
Expand Down
19 changes: 14 additions & 5 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,13 @@ export function activate(context: vscode.ExtensionContext): void {
);

// ── Register CodeLens provider for each configured language ──────────────
registerCodeLensProviders(context, codeLensProvider);
// Track ALL registrations in languageRegistrations (not context.subscriptions)
// so the full set can be disposed when sourceDoc.languages changes.
let languageRegistrations: vscode.Disposable[] = [];
registerCodeLensProviders(codeLensProvider, languageRegistrations);

// Dispose the language registrations when the extension is deactivated.
context.subscriptions.push({ dispose: () => languageRegistrations.forEach(d => d.dispose()) });

// Refresh lenses when the user switches to a different editor tab
context.subscriptions.push(
Expand All @@ -43,13 +49,12 @@ export function activate(context: vscode.ExtensionContext): void {
);

// Re-register providers when sourceDoc.languages changes
let languageRegistrations: vscode.Disposable[] = [];
context.subscriptions.push(
vscode.workspace.onDidChangeConfiguration(e => {
if (e.affectsConfiguration('sourceDoc.languages')) {
languageRegistrations.forEach(d => d.dispose());
languageRegistrations = [];
registerCodeLensProviders(context, codeLensProvider, languageRegistrations);
registerCodeLensProviders(codeLensProvider, languageRegistrations);
}
}),
);
Expand Down Expand Up @@ -153,6 +158,11 @@ export function activate(context: vscode.ExtensionContext): void {
}
}

if (lines.length === 0) {
vscode.window.showInformationMessage('Source Doc: nothing to explain in this file.');
return;
}

await vscode.window.withProgress(
{
location: vscode.ProgressLocation.Window,
Expand Down Expand Up @@ -200,9 +210,8 @@ export function deactivate(): void {
// ── Helpers ───────────────────────────────────────────────────────────────────

function registerCodeLensProviders(
context: vscode.ExtensionContext,
provider: SourceDocCodeLensProvider,
into: vscode.Disposable[] = context.subscriptions as unknown as vscode.Disposable[],
into: vscode.Disposable[],
): void {
const config = vscode.workspace.getConfiguration('sourceDoc');
const languages = config.get<string[]>('languages') ?? [
Expand Down