Add two variations to inline-completions sample

Co-authored-by: pierceboggan <1091304+pierceboggan@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-10-27 05:07:09 +00:00
parent d0b8b71e26
commit 399a085c1e
6 changed files with 231 additions and 71 deletions

View File

@ -1,10 +1,52 @@
# Inline Completions Sample
This sample demonstrates usage of the inline completions API.
It also demonstrates some proposed API of the inline completions feature that is not yet finalized.
This sample demonstrates usage of the inline completions API with **two different variations**:
1. **Pattern-Based Provider** - Advanced features including proposed APIs
2. **Simple Context-Aware Provider** - Basic inline completions for common code patterns
![Demo Video](./demo.gif)
## Two Variations
### Variation 1: Pattern-Based Provider (Default)
This provider demonstrates advanced inline completion features:
- Custom syntax for triggering completions via special comments
- Support for snippets with the `s` flag
- Bracket pair completion with the `b` flag
- Proposed API features (`handleDidShowCompletionItem`, `handleDidPartiallyAcceptCompletionItem`)
- Commands attached to completion items
**Usage**: Add special comment lines in your code like:
```javascript
// [0,*):console.log("Hello")
// Type here and the completion will appear
```
The syntax is: `// [start,end)flags:completion_text`
- `start`: Starting column position (0-based)
- `end`: Ending column position, or `*` for end of line
- `flags`: Optional flags (`s` for snippet, `b` for bracket pairs)
- `completion_text`: The text to insert
### Variation 2: Simple Context-Aware Provider
This provider demonstrates basic inline completion features:
- Context-aware completions based on what you're typing
- Simple pattern matching for common code constructs
- No proposed API usage (more stable, production-ready)
**Examples**:
- Type `console.` → suggests `log()`
- Type `function ` → suggests `myFunction() { }`
- Type `if ` → suggests `(condition) { }`
- Type `for ` → suggests `(let i = 0; i < length; i++) { }`
### Switching Between Variations
You can switch between the two providers by running the command:
**"Inline Completion: Switch Provider (Pattern-Based ↔ Simple)"** from the Command Palette (Ctrl+Shift+P / Cmd+Shift+P).
## Running the Sample
@ -13,3 +55,7 @@ It also demonstrates some proposed API of the inline completions feature that is
- Run the `Run Extension` target in the Debug View. This will:
- Start a task `npm: watch` to compile the code
- Run the extension in a new VS Code window
- Try both variations:
- **Pattern-Based**: Use the playground.js file with special comment syntax
- **Simple**: Type common code patterns like `console.`, `if `, `for `, etc.
- Use the Command Palette to switch between providers and see the differences

View File

@ -13,6 +13,7 @@ export default tseslint.config(
ignores: [
'out',
'playground.js',
'playground-simple.js',
'**/vscode*.d.ts'
]
},

View File

@ -23,6 +23,10 @@
{
"command": "extension.inline-completion-settings",
"title": "My Inline Completion Demo Settings"
},
{
"command": "extension.switch-inline-completion-provider",
"title": "Inline Completion: Switch Provider (Pattern-Based ↔ Simple)"
}
],
"menus": {

View File

@ -0,0 +1,19 @@
// Simple Provider Playground
// This file demonstrates the Simple Context-Aware Provider
// Switch to the Simple Provider using Command Palette: "Inline Completion: Switch Provider"
// Try typing the following patterns to see inline completions:
// 1. Console logging
console.
// 2. Function declaration
function
// 3. If statement
if
// 4. For loop
for
// The simple provider will suggest completions as you type these common patterns!

View File

@ -1,3 +1,5 @@
// Pattern-Based Provider Playground
// This file demonstrates the Pattern-Based Provider (default)
// Trigger inline completions after each line
// [0,*):// Trigger inline completions in this line, they work!

View File

@ -1,81 +1,169 @@
import * as vscode from 'vscode';
import { Range } from 'vscode';
/**
* VARIATION 1: Pattern-Based Inline Completion Provider
* This provider demonstrates advanced features including:
* - Custom syntax for triggering completions via comments
* - Snippet support
* - Bracket pair completion
* - Proposed API features (handleDidShowCompletionItem, handleDidPartiallyAcceptCompletionItem)
* - Commands attached to completions
*/
const patternBasedProvider: vscode.InlineCompletionItemProvider = {
async provideInlineCompletionItems(document, position, _context, _token) {
console.log('[Pattern Provider] provideInlineCompletionItems triggered');
const regexp = /\/\/ \[(.+?),(.+?)\)(.*?):(.*)/;
if (position.line <= 0) {
return;
}
const result: vscode.InlineCompletionList = {
items: [],
commands: [],
};
let offset = 1;
while (offset > 0) {
if (position.line - offset < 0) {
break;
}
const lineBefore = document.lineAt(position.line - offset).text;
const matches = lineBefore.match(regexp);
if (!matches) {
break;
}
offset++;
const start = matches[1];
const startInt = parseInt(start, 10);
const end = matches[2];
const endInt =
end === '*'
? document.lineAt(position.line).text.length
: parseInt(end, 10);
const flags = matches[3];
const completeBracketPairs = flags.includes('b');
const isSnippet = flags.includes('s');
const text = matches[4].replace(/\\n/g, '\n');
result.items.push({
insertText: isSnippet ? new vscode.SnippetString(text) : text,
range: new Range(position.line, startInt, position.line, endInt),
completeBracketPairs,
});
}
if (result.items.length > 0) {
result.commands!.push({
command: 'demo-ext.command1',
title: 'My Inline Completion Demo Command',
arguments: [1, 2],
});
}
return result;
},
handleDidShowCompletionItem(_completionItem: vscode.InlineCompletionItem): void {
console.log('[Pattern Provider] handleDidShowCompletionItem');
},
/**
* Is called when an inline completion item was accepted partially.
* @param acceptedLength The length of the substring of the inline completion that was accepted already.
*/
handleDidPartiallyAcceptCompletionItem(
_completionItem: vscode.InlineCompletionItem,
_info: vscode.PartialAcceptInfo | number
): void {
console.log('[Pattern Provider] handleDidPartiallyAcceptCompletionItem');
},
};
/**
* VARIATION 2: Simple Context-Aware Inline Completion Provider
* This provider demonstrates basic inline completion features:
* - Context-aware completions based on current line content
* - Simple pattern matching for common code constructs
* - No proposed API usage (more stable, production-ready)
*/
const simpleProvider: vscode.InlineCompletionItemProvider = {
async provideInlineCompletionItems(document, position, _context, _token) {
console.log('[Simple Provider] provideInlineCompletionItems triggered');
const linePrefix = document.lineAt(position).text.substring(0, position.character);
const items: vscode.InlineCompletionItem[] = [];
// Example 1: Complete console.log statements
if (linePrefix.trim() === 'console.') {
items.push({
insertText: 'log()',
range: new Range(position, position)
});
}
// Example 2: Complete function declarations
if (linePrefix.trim() === 'function ') {
items.push({
insertText: 'myFunction() {\n\t\n}',
range: new Range(position, position)
});
}
// Example 3: Complete if statements
if (linePrefix.trim() === 'if ') {
items.push({
insertText: '(condition) {\n\t\n}',
range: new Range(position, position)
});
}
// Example 4: Complete for loops
if (linePrefix.trim() === 'for ') {
items.push({
insertText: '(let i = 0; i < length; i++) {\n\t\n}',
range: new Range(position, position)
});
}
return items.length > 0 ? { items } : undefined;
}
};
export function activate(_context: vscode.ExtensionContext) {
console.log('inline-completions demo started');
console.log('inline-completions demo started with TWO variations');
// Register command used by the pattern-based provider
vscode.commands.registerCommand('demo-ext.command1', async (...args) => {
vscode.window.showInformationMessage('command1: ' + JSON.stringify(args));
});
const provider: vscode.InlineCompletionItemProvider = {
async provideInlineCompletionItems(document, position, _context, _token) {
console.log('provideInlineCompletionItems triggered');
const regexp = /\/\/ \[(.+?),(.+?)\)(.*?):(.*)/;
if (position.line <= 0) {
return;
// Register command to switch between providers
let currentProvider: 'pattern' | 'simple' = 'pattern';
let providerDisposable: vscode.Disposable;
const switchProvider = () => {
if (currentProvider === 'pattern') {
currentProvider = 'simple';
if (providerDisposable) {
providerDisposable.dispose();
}
const result: vscode.InlineCompletionList = {
items: [],
commands: [],
};
let offset = 1;
while (offset > 0) {
if (position.line - offset < 0) {
break;
}
const lineBefore = document.lineAt(position.line - offset).text;
const matches = lineBefore.match(regexp);
if (!matches) {
break;
}
offset++;
const start = matches[1];
const startInt = parseInt(start, 10);
const end = matches[2];
const endInt =
end === '*'
? document.lineAt(position.line).text.length
: parseInt(end, 10);
const flags = matches[3];
const completeBracketPairs = flags.includes('b');
const isSnippet = flags.includes('s');
const text = matches[4].replace(/\\n/g, '\n');
result.items.push({
insertText: isSnippet ? new vscode.SnippetString(text) : text,
range: new Range(position.line, startInt, position.line, endInt),
completeBracketPairs,
});
providerDisposable = vscode.languages.registerInlineCompletionItemProvider({ pattern: '**' }, simpleProvider);
vscode.window.showInformationMessage('Switched to Simple Provider');
} else {
currentProvider = 'pattern';
if (providerDisposable) {
providerDisposable.dispose();
}
if (result.items.length > 0) {
result.commands!.push({
command: 'demo-ext.command1',
title: 'My Inline Completion Demo Command',
arguments: [1, 2],
});
}
return result;
},
handleDidShowCompletionItem(_completionItem: vscode.InlineCompletionItem): void {
console.log('handleDidShowCompletionItem');
},
/**
* Is called when an inline completion item was accepted partially.
* @param acceptedLength The length of the substring of the inline completion that was accepted already.
*/
handleDidPartiallyAcceptCompletionItem(
_completionItem: vscode.InlineCompletionItem,
_info: vscode.PartialAcceptInfo | number
): void {
console.log('handleDidPartiallyAcceptCompletionItem');
},
providerDisposable = vscode.languages.registerInlineCompletionItemProvider({ pattern: '**' }, patternBasedProvider);
vscode.window.showInformationMessage('Switched to Pattern-Based Provider');
}
};
vscode.languages.registerInlineCompletionItemProvider({ pattern: '**' }, provider);
vscode.commands.registerCommand('extension.switch-inline-completion-provider', switchProvider);
// Register the pattern-based provider by default
providerDisposable = vscode.languages.registerInlineCompletionItemProvider({ pattern: '**' }, patternBasedProvider);
_context.subscriptions.push(providerDisposable);
}