Skip to content
Draft
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
90 changes: 90 additions & 0 deletions src/autocomplete/defaultHoleFiller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { HoleFiller, PromptArgs, AutoCompleteContext } from "./holeFiller";
import { LSPDefinition } from "../types/lsp";
import * as vscode from 'vscode';

// Source: continue/core/autocomplete/templating/AutocompleteTemplate.ts (holeFillerTemplate)
export class DefaultHoleFiller implements HoleFiller {
Expand Down Expand Up @@ -99,9 +101,97 @@ function hypothenuse(a, b) {
if (ctx.language !== '') {
context += `// Programming language: "${ctx.language}" \n`;
}

// Add LSP context if available
if (ctx.lspContext && ctx.lspContext.definitions.length > 0) {
context += this.formatLSPContext(ctx.lspContext.definitions);
}

return `${context}<QUERY>\n${ctx.textBeforeCursor}{{FILL_HERE}}${ctx.textAfterCursor}\n</QUERY>\nTASK: Fill the {{FILL_HERE}} hole. Answer only with the CORRECT completion, and NOTHING ELSE. Do it now.\n<COMPLETION>`;
}

private formatLSPContext(definitions: LSPDefinition[]): string {
if (definitions.length === 0) {return '';}

let context = '// Available definitions and symbols:\n';

// Group definitions by type for better organization
const functions = definitions.filter(d => [vscode.SymbolKind.Function, vscode.SymbolKind.Method].includes(d.kind));
const classes = definitions.filter(d => [vscode.SymbolKind.Class, vscode.SymbolKind.Interface].includes(d.kind));
const variables = definitions.filter(d => [vscode.SymbolKind.Variable, vscode.SymbolKind.Property, vscode.SymbolKind.Field].includes(d.kind));
const types = definitions.filter(d => [vscode.SymbolKind.Enum, vscode.SymbolKind.Struct, vscode.SymbolKind.TypeParameter].includes(d.kind));

// Add functions and methods
if (functions.length > 0) {
context += '// Functions/Methods:\n';
functions.slice(0, 10).forEach(def => {
const signature = this.formatDefinitionSignature(def);
context += `// ${signature}\n`;
});
}

// Add classes and interfaces
if (classes.length > 0) {
context += '// Classes/Interfaces:\n';
classes.slice(0, 8).forEach(def => {
const signature = this.formatDefinitionSignature(def);
context += `// ${signature}\n`;
});
}

// Add variables and properties
if (variables.length > 0) {
context += '// Variables/Properties:\n';
variables.slice(0, 8).forEach(def => {
const signature = this.formatDefinitionSignature(def);
context += `// ${signature}\n`;
});
}

// Add types
if (types.length > 0) {
context += '// Types:\n';
types.slice(0, 5).forEach(def => {
const signature = this.formatDefinitionSignature(def);
context += `// ${signature}\n`;
});
}

return context;
}

private formatDefinitionSignature(def: LSPDefinition): string {
const kindName = this.getSymbolKindName(def.kind);
let signature = `${def.name}`;

if (def.detail) {
signature += `: ${def.detail}`;
}

if (def.containerName) {
signature = `${def.containerName}.${signature}`;
}

return `${kindName} ${signature}`;
}

private getSymbolKindName(kind: vscode.SymbolKind): string {
switch (kind) {
case vscode.SymbolKind.Function: return 'function';
case vscode.SymbolKind.Method: return 'method';
case vscode.SymbolKind.Class: return 'class';
case vscode.SymbolKind.Interface: return 'interface';
case vscode.SymbolKind.Variable: return 'var';
case vscode.SymbolKind.Property: return 'prop';
case vscode.SymbolKind.Field: return 'field';
case vscode.SymbolKind.Enum: return 'enum';
case vscode.SymbolKind.Struct: return 'struct';
case vscode.SymbolKind.TypeParameter: return 'type';
case vscode.SymbolKind.Constant: return 'const';
default: return 'symbol';
}
}

prompt(params: AutoCompleteContext): PromptArgs {
return {
messages: [
Expand Down
2 changes: 2 additions & 0 deletions src/autocomplete/holeFiller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Prompt } from 'ai';
import { ProviderOptions } from '@ai-sdk/provider-utils';
import { LSPContext } from '../types/lsp';

export interface HoleFiller {
prompt(params: AutoCompleteContext): PromptArgs
Expand All @@ -15,4 +16,5 @@ export type AutoCompleteContext = {
currentLineText: string,
filename?: string,
language?: string,
lspContext?: LSPContext,
}
11 changes: 10 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { TabCoderStatusBarProvider } from './vscode/statusBarProvider';
import { ProfileCommandProvider } from './vscode/profileCommandProvider';
import { logger } from './utils/logger';
import { ProfileService } from './services/profileService';
import { LSPProvider } from './services/lspProvider';

export function activate(context: vscode.ExtensionContext) {
// Initialize ConfigurationProvider with context for secure storage.
Expand All @@ -23,8 +24,16 @@ export function activate(context: vscode.ExtensionContext) {
vscode.commands.registerCommand('tabcoder.statusBarClicked', () => statusBarProvider.handleStatusBarClick())
);

// Create LSP provider for gathering code definitions
const lspProvider = new LSPProvider({
maxDefinitions: 50,
includeWorkspaceSymbols: true,
cacheTimeout: 30000, // 30 seconds
relevanceThreshold: 0.3
});

// Register the inline completion provider for all languages.
const inlineCompletionProvider = new TabCoderInlineCompletionProvider(profileService, statusBarProvider);
const inlineCompletionProvider = new TabCoderInlineCompletionProvider(profileService, statusBarProvider, lspProvider);
context.subscriptions.push(
vscode.languages.registerInlineCompletionItemProvider(
'*', // Register for all languages
Expand Down
Loading
Loading