Switch internal scripts to ts

Also adds a formatting script and runs it against all TS files in the samples
This commit is contained in:
Matt Bierner
2024-10-28 16:41:49 -07:00
parent 6097cc753e
commit 1a3ac0c722
39 changed files with 3026 additions and 762 deletions

View File

@ -11,4 +11,4 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: node ./.scripts/validate.js
- run: npm run validate

2
.gitignore vendored
View File

@ -1,7 +1,7 @@
.DS_Store
npm-debug.log
Thumbs.db
*/node_modules/
**/node_modules/
*/out/
*/.vs/
tsconfig.lsif.json

View File

@ -1,22 +0,0 @@
// @ts-check
/**
* Copies a file into every sample, overwriting the existing file if it exists.
*/
const fs = require('fs');
const path = require('path');
const { samples, lspSamples } = require('./samples')
const filePath = process.argv[2];
if (!filePath) {
console.error('Please provide a file path as the argument.');
process.exit(1);
}
const fileName = path.basename(filePath);
const fileContent = fs.readFileSync(filePath);
for (const sample of [...samples, ...lspSamples]) {
const destinationPath = path.join(sample.path, fileName);
fs.writeFileSync(destinationPath, fileContent);
console.log(`Copied ${fileName} to ${sample.path}`);
}

23
.scripts/copy-into.ts Normal file
View File

@ -0,0 +1,23 @@
/**
* Copies a file into every sample, overwriting the existing file if it exists.
*/
import * as fs from 'fs';
import * as path from 'path';
import { lspSamples, samples } from './samples';
if (require.main === module) {
const filePath = process.argv[2];
if (!filePath) {
console.error('Please provide a file path as the argument.');
process.exit(1);
}
const fileName = path.basename(filePath);
const fileContent = fs.readFileSync(filePath);
for (const sample of [...samples, ...lspSamples]) {
const destinationPath = path.join(sample.path, fileName);
fs.writeFileSync(destinationPath, fileContent);
console.log(`Copied ${fileName} to ${sample.path}`);
}
}

82
.scripts/format.ts Normal file
View File

@ -0,0 +1,82 @@
import * as fs from 'fs';
import * as glob from 'glob';
import * as ts from 'typescript';
class LanguageServiceHost implements ts.LanguageServiceHost {
files: ts.MapLike<ts.IScriptSnapshot> = {};
addFile(fileName: string, text: string) {
this.files[fileName] = ts.ScriptSnapshot.fromString(text);
}
fileExists(path: string): boolean {
return !!this.files[path];
}
readFile(path: string): string | undefined {
return this.files[path]?.getText(0, this.files[path]!.getLength());
}
// for ts.LanguageServiceHost
getCompilationSettings = () => ts.getDefaultCompilerOptions();
getScriptFileNames = () => Object.keys(this.files);
getScriptVersion = (_fileName: string) => '0';
getScriptSnapshot = (fileName: string) => this.files[fileName];
getCurrentDirectory = () => process.cwd();
getDefaultLibFileName = (options: ts.CompilerOptions) => ts.getDefaultLibFilePath(options);
}
const defaults: ts.FormatCodeSettings = {
baseIndentSize: 0,
indentSize: 4,
tabSize: 4,
indentStyle: ts.IndentStyle.Smart,
newLineCharacter: '\r\n',
convertTabsToSpaces: false,
insertSpaceAfterCommaDelimiter: true,
insertSpaceAfterSemicolonInForStatements: true,
insertSpaceBeforeAndAfterBinaryOperators: true,
insertSpaceAfterConstructor: false,
insertSpaceAfterKeywordsInControlFlowStatements: true,
insertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false,
insertSpaceAfterTypeAssertion: false,
insertSpaceBeforeFunctionParenthesis: false,
placeOpenBraceOnNewLineForFunctions: false,
placeOpenBraceOnNewLineForControlBlocks: false,
insertSpaceBeforeTypeAnnotation: false,
};
function format(fileName: string, text: string) {
const host = new LanguageServiceHost();
host.addFile(fileName, text);
const languageService = ts.createLanguageService(host);
const edits = languageService.getFormattingEditsForDocument(fileName, { ...defaults });
edits
.sort((a, b) => a.span.start - b.span.start)
.reverse()
.forEach(edit => {
const head = text.slice(0, edit.span.start);
const tail = text.slice(edit.span.start + edit.span.length);
text = `${head}${edit.newText}${tail}`;
});
return text;
}
if (require.main === module) {
glob.sync(`${__dirname}/../**/*.ts`).forEach((file) => {
if (file.endsWith('.d.ts') || file.includes('node_modules')) {
return;
}
const out = format(file, fs.readFileSync(file, 'utf8'));
fs.writeFileSync(file, out);
});
}

View File

@ -2,15 +2,12 @@
/**
* Try running install for all the samples
*/
const fs = require('fs');
const path = require('path');
const child_process = require('child_process');
const { samples, lspSamples } = require('./samples');
import * as child_process from 'child_process';
import * as fs from 'fs';
import * as path from 'path';
import { lspSamples, Sample, samples } from './samples';
async function tryRunCommand(
/** @type {string} */ command,
/** @type {import('./samples').Sample} */ sample,
) {
async function tryRunCommand(command: string, sample: Sample) {
const packageJsonPath = path.join(sample.path, 'package.json');
if (fs.existsSync(packageJsonPath)) {
try {
@ -28,7 +25,9 @@ async function tryRunCommand(
}
}
const command = process.argv.slice(2).join(' ');
for (const sample of [...samples, ...lspSamples]) {
tryRunCommand(command, sample);
if (require.main === module) {
const command = process.argv.slice(2).join(' ');
for (const sample of [...samples, ...lspSamples]) {
tryRunCommand(command, sample);
}
}

View File

@ -1,28 +0,0 @@
// @ts-check
/**
* Try running an npm script for each of the samples.
*/
const fs = require('fs');
const path = require('path');
const child_process = require('child_process');
const { samples, lspSamples } = require('./samples')
function tryRun(
/** @type {string} */ scriptName,
/** @type {import('./samples').Sample} */ sample
) {
const packageJsonPath = path.join(sample.path, 'package.json');
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath).toString());
if (Object.keys(packageJson['scripts'] || {}).includes(scriptName)) {
console.log(`=== Running ${scriptName} on ${path.basename(sample.path)} ===`)
child_process.execSync(`npm run ${scriptName}`, {
cwd: sample.path,
stdio: 'inherit'
});
}
}
const scriptName = process.argv[2];
for (const sample of [...samples, ...lspSamples]) {
tryRun(scriptName, sample);
}

26
.scripts/run-script.ts Normal file
View File

@ -0,0 +1,26 @@
/**
* Try running an npm script for each of the samples.
*/
import * as child_process from 'child_process';
import * as fs from 'fs';
import * as path from 'path';
import { lspSamples, Sample, samples } from './samples';
function tryRun(scriptName: string, sample: Sample) {
const packageJsonPath = path.join(sample.path, 'package.json');
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath).toString());
if (Object.keys(packageJson['scripts'] || {}).includes(scriptName)) {
console.log(`=== Running ${scriptName} on ${path.basename(sample.path)} ===`)
child_process.execSync(`npm run ${scriptName}`, {
cwd: sample.path,
stdio: 'inherit'
});
}
}
if (require.main === module) {
const scriptName = process.argv[2];
for (const sample of [...samples, ...lspSamples]) {
tryRun(scriptName, sample);
}
}

View File

@ -1,416 +0,0 @@
//@ts-check
/**
* @typedef {Object} Sample
* @property {string} description - A readable name for the sample
* @property {string} path - Path to the sample's root
* @property {string | null} guide - Link to the guide on https://code.visualstudio.com
* @property {string[]} apis - Listing of VS Code API that is being illustrated. For example, "TextDocumentContentProvider"
* @property {string[]} contributions - Listing of Contribution Points that are being used. For example,
* @property {boolean} [excludeFromReadme] - Don't generate a readme entry for this extension
*/
/** @type {Sample[]} */
const samples = [
{
description: 'Webview Sample',
path: 'webview-sample',
guide: '/api/extension-guides/webview',
apis: ['window.createWebviewPanel', 'window.registerWebviewPanelSerializer'],
contributions: []
},
{
description: 'Webview View Sample',
path: 'webview-view-sample',
guide: null,
apis: ['window.registerWebviewViewProvider'],
contributions: []
},
{
description: 'Webview Codicons Sample',
path: 'webview-codicons-sample',
guide: null,
apis: [],
contributions: []
},
{
description: 'Status Bar Sample',
path: 'statusbar-sample',
guide: null,
apis: ['window.createStatusBarItem', 'StatusBarItem'],
contributions: []
},
{
description: 'Tree View Sample',
path: 'tree-view-sample',
guide: '/api/extension-guides/tree-view',
apis: ['window.createTreeView', 'window.registerTreeDataProvider', 'TreeView', 'TreeDataProvider'],
contributions: ['views', 'viewsContainers']
},
{
description: 'Task Provider Sample',
path: 'task-provider-sample',
guide: '/api/extension-guides/task-provider',
apis: ['tasks.registerTaskProvider', 'Task', 'ShellExecution'],
contributions: ['taskDefinitions']
},
{
description: 'Multi Root Sample',
path: 'basic-multi-root-sample',
guide: null,
apis: ['workspace.getWorkspaceFolder', 'workspace.onDidChangeWorkspaceFolders'],
contributions: []
},
{
description: 'Completion Provider Sample',
path: 'completions-sample',
guide: null,
apis: ['languages.registerCompletionItemProvider', 'CompletionItem', 'SnippetString'],
contributions: []
},
{
description: 'Code Actions Sample',
path: 'code-actions-sample',
guide: null,
apis: ['languages.registerCodeActionsProvider', 'CodeActionProvider'],
contributions: []
},
{
description: 'File System Provider Sample',
path: 'fsprovider-sample',
guide: null,
apis: ['workspace.registerFileSystemProvider'],
contributions: []
},
{
description: 'Editor Decorator Sample',
path: 'decorator-sample',
guide: null,
apis: [
'TextEditor.setDecorations',
'DecorationOptions',
'DecorationInstanceRenderOptions',
'ThemableDecorationInstanceRenderOptions',
'window.createTextEditorDecorationType',
'TextEditorDecorationType'
],
contributions: ['colors']
},
{
description: 'L10n Sample',
path: 'l10n-sample',
guide: null,
apis: [],
contributions: []
},
{
description: 'Terminal Sample',
path: 'terminal-sample',
guide: null,
apis: [
'window.createTerminal',
'window.onDidChangeActiveTerminal',
'window.onDidCloseTerminal',
'window.onDidOpenTerminal',
'window.Terminal',
'window.terminals'
],
contributions: []
},
{
description: 'Extension Terminal Sample',
path: 'extension-terminal-sample',
guide: null,
apis: [
'window.createTerminal',
'window.Pseudoterminal',
'window.ExtensionTerminalOptions'
],
contributions: []
},
{
description: 'Color Theme Sample',
path: 'theme-sample',
guide: '/api/extension-guides/color-theme',
apis: [],
contributions: ['themes']
},
{
description: 'Product Icon Theme Sample',
path: 'product-icon-theme-sample',
guide: '/api/extension-guides/product-icon-theme',
apis: [],
contributions: ['productIconThemes']
},
{
description: 'Vim Sample',
path: 'vim-sample',
guide: null,
apis: [
`commands`,
`StatusBarItem`,
`window.createStatusBarItem`,
`TextEditorCursorStyle`,
`window.activeTextEditor`,
`Position`,
`Range`,
`Selection`,
`TextEditor`,
`TextEditorRevealType`,
`TextDocument`
],
contributions: []
},
{
description: 'webpack-sample',
path: 'webpack-sample',
guide: '/api/working-with-extensions/bundling-extension',
apis: [],
contributions: []
},
{
description: 'esbuild-sample',
path: 'esbuild-sample',
guide: '/api/working-with-extensions/bundling-extension',
apis: [],
contributions: []
},
{
description: 'Source Control Sample',
path: 'source-control-sample',
guide: '/api/extension-guides/scm-provider',
apis: [
'workspace.workspaceFolders',
'SourceControl',
'SourceControlResourceGroup',
'scm.createSourceControl',
'TextDocumentContentProvider'
],
contributions: ["menus"]
},
{
description: 'Commenting API Sample',
path: 'comment-sample',
guide: null,
apis: [],
contributions: []
},
{
description: 'Document Editing Sample',
path: 'document-editing-sample',
guide: null,
apis: [
`commands`
],
contributions: []
},
{
description: 'Custom Data Sample',
path: 'custom-data-sample',
guide: '/api/extension-guides/custom-data-extension',
apis: [],
contributions: []
},
{
description: 'CodeLens Provider Sample',
path: 'codelens-sample',
guide: null,
apis: [`languages.registerCodeLensProvider`, `CodeLensProvider`, `CodeLens`],
contributions: []
},
{
description: 'Call Hierarchy Sample',
path: 'call-hierarchy-sample',
guide: null,
apis: [`languages.registerCallHierarchyProvider`, `CallHierarchyProvider`, `CallHierarchyItem`, `CallHierarchyOutgoingCall`, `CallHierarchyIncomingCall`],
contributions: []
},
{
description: 'Custom Editors Sample',
path: 'custom-editor-sample',
guide: '/api/extension-guides/custom-editors',
apis: ['window.registerCustomEditorProvider', 'CustomTextEditorProvider'],
contributions: ["customEditors"]
},
{
description: 'Semantic tokens',
path: 'semantic-tokens-sample',
guide: '/api/language-extensions/semantic-highlight-guide',
apis: ['languages.registerDocumentSemanticTokensProvider', 'vscode.DocumentSemanticTokensProvider'],
contributions: []
},
{
description: 'Test Provider Sample',
path: 'test-provider-sample',
guide: null,
apis: [],
contributions: []
},
{
description: 'Getting Started Sample',
path: 'getting-started-sample',
guide: null,
apis: [],
contributions: []
},
{
description: 'notebook-renderer-sample',
path: 'notebook-renderer-sample',
guide: "/api/extension-guides/notebook#notebook-renderer",
apis: [],
contributions: ["notebookRenderer"]
},
{
description: 'notebook-extend-markdown-renderer-sample',
path: 'notebook-extend-markdown-renderer-sample',
guide: "/api/extension-guides/notebook#notebook-renderer",
apis: [],
contributions: ["notebookRenderer"]
},
{
description: 'jupyter-server-provider-sample',
path: 'jupyter-server-provider-sample',
guide: null,
apis: [],
contributions: []
},
{
description: 'Chat Sample',
path: 'chat-sample',
guide: null,
apis: [],
contributions: []
},
{
description: 'Chat Tutorial',
path: 'chat-tutorial',
guide: null,
apis: [],
contributions: []
},
{
description: 'Notifications Sample',
path: 'notifications-sample',
guide: null,
apis: [],
contributions: []
},
{ description: 'configuration-sample', excludeFromReadme: true, path: 'configuration-sample', guide: null, apis: [], contributions: [] },
{ description: 'contentprovider-sample', excludeFromReadme: true, path: 'contentprovider-sample', guide: null, apis: [], contributions: [] },
{ description: 'nodefs-provider-sample', excludeFromReadme: true, path: 'nodefs-provider-sample', guide: null, apis: [], contributions: [] },
{ description: 'progress-sample', excludeFromReadme: true, path: 'progress-sample', guide: null, apis: [], contributions: [] },
{ description: 'quickinput-sample', excludeFromReadme: true, path: 'quickinput-sample', guide: null, apis: [], contributions: [] },
{ description: 'diagnostic-related-information-sample', excludeFromReadme: true, path: 'diagnostic-related-information-sample', guide: null, apis: [], contributions: [] },
{ description: 'fsconsumer-sample', excludeFromReadme: true, path: 'fsconsumer-sample', guide: null, apis: [], contributions: [] },
{ description: 'github-authentication-sample', excludeFromReadme: true, path: 'github-authentication-sample', guide: null, apis: [], contributions: [] },
{ description: 'helloworld-sample', excludeFromReadme: true, path: 'helloworld-sample', guide: null, apis: [], contributions: [] },
{ description: 'helloworld-minimal-sample', excludeFromReadme: true, path: 'helloworld-minimal-sample', guide: null, apis: [], contributions: [] },
{ description: 'helloworld-test-sample', excludeFromReadme: true, path: 'helloworld-test-sample', guide: null, apis: [], contributions: [] },
{ description: 'helloworld-web-sample', excludeFromReadme: true, path: 'helloworld-web-sample', guide: null, apis: [], contributions: [] },
{ description: 'helloworld-test-cli-sample', excludeFromReadme: true, path: 'helloworld-test-cli-sample', guide: null, apis: [], contributions: [] },
{ description: 'inline-completions', excludeFromReadme: true, path: 'inline-completions', guide: null, apis: [], contributions: [] },
{ description: 'notebook-renderer-react-sample', excludeFromReadme: true, path: 'notebook-renderer-react-sample', guide: null, apis: [], contributions: [] },
{ description: 'notebook-format-code-action-sample', excludeFromReadme: true, path: 'notebook-format-code-action-sample', guide: null, apis: [], contributions: [] },
{ description: 'notebook-serializer-sample', excludeFromReadme: true, path: 'notebook-serializer-sample', guide: null, apis: [], contributions: [] },
{ description: 'proposed-api-sample', excludeFromReadme: true, path: 'proposed-api-sample', guide: null, apis: [], contributions: [] },
{ description: 'virtual-document-sample', excludeFromReadme: true, path: 'virtual-document-sample', guide: null, apis: [], contributions: [] },
{ description: 'welcome-view-content-sample', excludeFromReadme: true, path: 'welcome-view-content-sample', guide: null, apis: [], contributions: [] },
{ description: 'document-paste', excludeFromReadme: true, path: 'document-paste', guide: null, apis: [], contributions: [] },
{ description: 'drop-on-document', excludeFromReadme: true, path: 'drop-on-document', guide: null, apis: [], contributions: [] },
{ description: 'uri-handler-sample', excludeFromReadme: true, path: 'uri-handler-sample', guide: null, apis: [], contributions: [] },
{ description: 'authenticationprovider-sample', excludeFromReadme: true, path: 'authenticationprovider-sample', guide: null, apis: [], contributions: [] },
{ description: 'jupyter-kernel-execution-sample', excludeFromReadme: true, path: 'jupyter-kernel-execution-sample', guide: null, apis: [], contributions: [] },
{ description: 'shell-integration-sample', excludeFromReadme: true, path: 'shell-integration-sample', guide: null, apis: [], contributions: [] },
{ description: 'tabs-api-sample', excludeFromReadme: true, path: 'tabs-api-sample', guide: null, apis: [], contributions: [] },
{ description: 'telemetry-sample', excludeFromReadme: true, path: 'telemetry-sample', guide: null, apis: [], contributions: [] },
{ description: 'lm-api-tutorial', excludeFromReadme: true, path: 'lm-api-tutorial', guide: null, apis: [], contributions: [] },
{ description: 'wasm-component-model', excludeFromReadme: true, path: 'wasm-component-model', guide: null, apis: [], contributions: [] },
{ description: 'wasm-component-model-async', excludeFromReadme: true, path: 'wasm-component-model-async', guide: null, apis: [], contributions: [] },
{ description: 'wasm-component-model-resource', excludeFromReadme: true, path: 'wasm-component-model-resource', guide: null, apis: [], contributions: [] },
]
/**
* LSP specific samples
* DO NOT add non-LSP items here. Add it to `samples` list.
*
* @type {Sample[]}
*/
const lspSamples = [
{
description: 'Snippet Sample',
path: 'snippet-sample',
guide: '/api/language-extensions/snippet-guide',
apis: [],
contributions: ['snippets']
},
{
description: 'Language Configuration Sample',
path: 'language-configuration-sample',
guide: '/api/language-extensions/language-configuration-guide',
apis: [],
contributions: ['languages']
},
{
description: 'LSP Sample',
path: 'lsp-sample',
guide: '/api/language-extensions/language-server-extension-guide',
apis: [],
contributions: []
},
{
description: 'LSP Log Streaming Sample',
path: 'lsp-log-streaming-sample',
guide: null,
apis: [],
contributions: []
},
{
description: 'LSP Multi Root Server Sample',
path: 'lsp-multi-server-sample',
guide:
'https://github.com/Microsoft/vscode/wiki/Extension-Authoring:-Adopting-Multi-Root-Workspace-APIs#language-client--language-server',
apis: [],
contributions: []
},
{
description: 'LSP Web Extension Sample',
path: 'lsp-web-extension-sample',
guide: '/api/language-extensions/language-server-extension-guide',
apis: [],
contributions: []
},
{
description: 'LSP User Input Sample',
path: 'lsp-user-input-sample',
guide: null,
apis: [],
contributions: []
},
{
description: 'LSP Embedded Language Service',
path: 'lsp-embedded-language-service',
guide: null,
apis: [],
contributions: []
},
{
description: 'LSP Embedded Request Forwarding',
path: 'lsp-embedded-request-forwarding',
guide: null,
apis: [],
contributions: []
},
{
description: 'Wasm language server',
path: 'wasm-language-server',
guide: null,
apis: [],
contributions: []
},
];
// eslint-disable-next-line no-undef
module.exports = {
samples,
lspSamples
}

404
.scripts/samples.ts Normal file
View File

@ -0,0 +1,404 @@
export interface Sample {
readonly description: string;
readonly path: string;
readonly guide: string | null;
readonly apis: readonly string[];
readonly contributions: readonly string[];
readonly excludeFromReadme?: boolean;
}
export const samples: Sample[] = [
{
description: 'Webview Sample',
path: 'webview-sample',
guide: '/api/extension-guides/webview',
apis: ['window.createWebviewPanel', 'window.registerWebviewPanelSerializer'],
contributions: []
},
{
description: 'Webview View Sample',
path: 'webview-view-sample',
guide: null,
apis: ['window.registerWebviewViewProvider'],
contributions: []
},
{
description: 'Webview Codicons Sample',
path: 'webview-codicons-sample',
guide: null,
apis: [],
contributions: []
},
{
description: 'Status Bar Sample',
path: 'statusbar-sample',
guide: null,
apis: ['window.createStatusBarItem', 'StatusBarItem'],
contributions: []
},
{
description: 'Tree View Sample',
path: 'tree-view-sample',
guide: '/api/extension-guides/tree-view',
apis: ['window.createTreeView', 'window.registerTreeDataProvider', 'TreeView', 'TreeDataProvider'],
contributions: ['views', 'viewsContainers']
},
{
description: 'Task Provider Sample',
path: 'task-provider-sample',
guide: '/api/extension-guides/task-provider',
apis: ['tasks.registerTaskProvider', 'Task', 'ShellExecution'],
contributions: ['taskDefinitions']
},
{
description: 'Multi Root Sample',
path: 'basic-multi-root-sample',
guide: null,
apis: ['workspace.getWorkspaceFolder', 'workspace.onDidChangeWorkspaceFolders'],
contributions: []
},
{
description: 'Completion Provider Sample',
path: 'completions-sample',
guide: null,
apis: ['languages.registerCompletionItemProvider', 'CompletionItem', 'SnippetString'],
contributions: []
},
{
description: 'Code Actions Sample',
path: 'code-actions-sample',
guide: null,
apis: ['languages.registerCodeActionsProvider', 'CodeActionProvider'],
contributions: []
},
{
description: 'File System Provider Sample',
path: 'fsprovider-sample',
guide: null,
apis: ['workspace.registerFileSystemProvider'],
contributions: []
},
{
description: 'Editor Decorator Sample',
path: 'decorator-sample',
guide: null,
apis: [
'TextEditor.setDecorations',
'DecorationOptions',
'DecorationInstanceRenderOptions',
'ThemableDecorationInstanceRenderOptions',
'window.createTextEditorDecorationType',
'TextEditorDecorationType'
],
contributions: ['colors']
},
{
description: 'L10n Sample',
path: 'l10n-sample',
guide: null,
apis: [],
contributions: []
},
{
description: 'Terminal Sample',
path: 'terminal-sample',
guide: null,
apis: [
'window.createTerminal',
'window.onDidChangeActiveTerminal',
'window.onDidCloseTerminal',
'window.onDidOpenTerminal',
'window.Terminal',
'window.terminals'
],
contributions: []
},
{
description: 'Extension Terminal Sample',
path: 'extension-terminal-sample',
guide: null,
apis: [
'window.createTerminal',
'window.Pseudoterminal',
'window.ExtensionTerminalOptions'
],
contributions: []
},
{
description: 'Color Theme Sample',
path: 'theme-sample',
guide: '/api/extension-guides/color-theme',
apis: [],
contributions: ['themes']
},
{
description: 'Product Icon Theme Sample',
path: 'product-icon-theme-sample',
guide: '/api/extension-guides/product-icon-theme',
apis: [],
contributions: ['productIconThemes']
},
{
description: 'Vim Sample',
path: 'vim-sample',
guide: null,
apis: [
`commands`,
`StatusBarItem`,
`window.createStatusBarItem`,
`TextEditorCursorStyle`,
`window.activeTextEditor`,
`Position`,
`Range`,
`Selection`,
`TextEditor`,
`TextEditorRevealType`,
`TextDocument`
],
contributions: []
},
{
description: 'webpack-sample',
path: 'webpack-sample',
guide: '/api/working-with-extensions/bundling-extension',
apis: [],
contributions: []
},
{
description: 'esbuild-sample',
path: 'esbuild-sample',
guide: '/api/working-with-extensions/bundling-extension',
apis: [],
contributions: []
},
{
description: 'Source Control Sample',
path: 'source-control-sample',
guide: '/api/extension-guides/scm-provider',
apis: [
'workspace.workspaceFolders',
'SourceControl',
'SourceControlResourceGroup',
'scm.createSourceControl',
'TextDocumentContentProvider'
],
contributions: ["menus"]
},
{
description: 'Commenting API Sample',
path: 'comment-sample',
guide: null,
apis: [],
contributions: []
},
{
description: 'Document Editing Sample',
path: 'document-editing-sample',
guide: null,
apis: [
`commands`
],
contributions: []
},
{
description: 'Custom Data Sample',
path: 'custom-data-sample',
guide: '/api/extension-guides/custom-data-extension',
apis: [],
contributions: []
},
{
description: 'CodeLens Provider Sample',
path: 'codelens-sample',
guide: null,
apis: [`languages.registerCodeLensProvider`, `CodeLensProvider`, `CodeLens`],
contributions: []
},
{
description: 'Call Hierarchy Sample',
path: 'call-hierarchy-sample',
guide: null,
apis: [`languages.registerCallHierarchyProvider`, `CallHierarchyProvider`, `CallHierarchyItem`, `CallHierarchyOutgoingCall`, `CallHierarchyIncomingCall`],
contributions: []
},
{
description: 'Custom Editors Sample',
path: 'custom-editor-sample',
guide: '/api/extension-guides/custom-editors',
apis: ['window.registerCustomEditorProvider', 'CustomTextEditorProvider'],
contributions: ["customEditors"]
},
{
description: 'Semantic tokens',
path: 'semantic-tokens-sample',
guide: '/api/language-extensions/semantic-highlight-guide',
apis: ['languages.registerDocumentSemanticTokensProvider', 'vscode.DocumentSemanticTokensProvider'],
contributions: []
},
{
description: 'Test Provider Sample',
path: 'test-provider-sample',
guide: null,
apis: [],
contributions: []
},
{
description: 'Getting Started Sample',
path: 'getting-started-sample',
guide: null,
apis: [],
contributions: []
},
{
description: 'notebook-renderer-sample',
path: 'notebook-renderer-sample',
guide: "/api/extension-guides/notebook#notebook-renderer",
apis: [],
contributions: ["notebookRenderer"]
},
{
description: 'notebook-extend-markdown-renderer-sample',
path: 'notebook-extend-markdown-renderer-sample',
guide: "/api/extension-guides/notebook#notebook-renderer",
apis: [],
contributions: ["notebookRenderer"]
},
{
description: 'jupyter-server-provider-sample',
path: 'jupyter-server-provider-sample',
guide: null,
apis: [],
contributions: []
},
{
description: 'Chat Sample',
path: 'chat-sample',
guide: null,
apis: [],
contributions: []
},
{
description: 'Chat Tutorial',
path: 'chat-tutorial',
guide: null,
apis: [],
contributions: []
},
{
description: 'Notifications Sample',
path: 'notifications-sample',
guide: null,
apis: [],
contributions: []
},
{ description: 'configuration-sample', excludeFromReadme: true, path: 'configuration-sample', guide: null, apis: [], contributions: [] },
{ description: 'contentprovider-sample', excludeFromReadme: true, path: 'contentprovider-sample', guide: null, apis: [], contributions: [] },
{ description: 'nodefs-provider-sample', excludeFromReadme: true, path: 'nodefs-provider-sample', guide: null, apis: [], contributions: [] },
{ description: 'progress-sample', excludeFromReadme: true, path: 'progress-sample', guide: null, apis: [], contributions: [] },
{ description: 'quickinput-sample', excludeFromReadme: true, path: 'quickinput-sample', guide: null, apis: [], contributions: [] },
{ description: 'diagnostic-related-information-sample', excludeFromReadme: true, path: 'diagnostic-related-information-sample', guide: null, apis: [], contributions: [] },
{ description: 'fsconsumer-sample', excludeFromReadme: true, path: 'fsconsumer-sample', guide: null, apis: [], contributions: [] },
{ description: 'github-authentication-sample', excludeFromReadme: true, path: 'github-authentication-sample', guide: null, apis: [], contributions: [] },
{ description: 'helloworld-sample', excludeFromReadme: true, path: 'helloworld-sample', guide: null, apis: [], contributions: [] },
{ description: 'helloworld-minimal-sample', excludeFromReadme: true, path: 'helloworld-minimal-sample', guide: null, apis: [], contributions: [] },
{ description: 'helloworld-test-sample', excludeFromReadme: true, path: 'helloworld-test-sample', guide: null, apis: [], contributions: [] },
{ description: 'helloworld-web-sample', excludeFromReadme: true, path: 'helloworld-web-sample', guide: null, apis: [], contributions: [] },
{ description: 'helloworld-test-cli-sample', excludeFromReadme: true, path: 'helloworld-test-cli-sample', guide: null, apis: [], contributions: [] },
{ description: 'inline-completions', excludeFromReadme: true, path: 'inline-completions', guide: null, apis: [], contributions: [] },
{ description: 'notebook-renderer-react-sample', excludeFromReadme: true, path: 'notebook-renderer-react-sample', guide: null, apis: [], contributions: [] },
{ description: 'notebook-format-code-action-sample', excludeFromReadme: true, path: 'notebook-format-code-action-sample', guide: null, apis: [], contributions: [] },
{ description: 'notebook-serializer-sample', excludeFromReadme: true, path: 'notebook-serializer-sample', guide: null, apis: [], contributions: [] },
{ description: 'proposed-api-sample', excludeFromReadme: true, path: 'proposed-api-sample', guide: null, apis: [], contributions: [] },
{ description: 'virtual-document-sample', excludeFromReadme: true, path: 'virtual-document-sample', guide: null, apis: [], contributions: [] },
{ description: 'welcome-view-content-sample', excludeFromReadme: true, path: 'welcome-view-content-sample', guide: null, apis: [], contributions: [] },
{ description: 'document-paste', excludeFromReadme: true, path: 'document-paste', guide: null, apis: [], contributions: [] },
{ description: 'drop-on-document', excludeFromReadme: true, path: 'drop-on-document', guide: null, apis: [], contributions: [] },
{ description: 'uri-handler-sample', excludeFromReadme: true, path: 'uri-handler-sample', guide: null, apis: [], contributions: [] },
{ description: 'authenticationprovider-sample', excludeFromReadme: true, path: 'authenticationprovider-sample', guide: null, apis: [], contributions: [] },
{ description: 'jupyter-kernel-execution-sample', excludeFromReadme: true, path: 'jupyter-kernel-execution-sample', guide: null, apis: [], contributions: [] },
{ description: 'shell-integration-sample', excludeFromReadme: true, path: 'shell-integration-sample', guide: null, apis: [], contributions: [] },
{ description: 'tabs-api-sample', excludeFromReadme: true, path: 'tabs-api-sample', guide: null, apis: [], contributions: [] },
{ description: 'telemetry-sample', excludeFromReadme: true, path: 'telemetry-sample', guide: null, apis: [], contributions: [] },
{ description: 'lm-api-tutorial', excludeFromReadme: true, path: 'lm-api-tutorial', guide: null, apis: [], contributions: [] },
{ description: 'wasm-component-model', excludeFromReadme: true, path: 'wasm-component-model', guide: null, apis: [], contributions: [] },
{ description: 'wasm-component-model-async', excludeFromReadme: true, path: 'wasm-component-model-async', guide: null, apis: [], contributions: [] },
{ description: 'wasm-component-model-resource', excludeFromReadme: true, path: 'wasm-component-model-resource', guide: null, apis: [], contributions: [] },
]
/**
* LSP specific samples
* DO NOT add non-LSP items here. Add it to {@link samples} list.
*/
export const lspSamples: Sample[] = [
{
description: 'Snippet Sample',
path: 'snippet-sample',
guide: '/api/language-extensions/snippet-guide',
apis: [],
contributions: ['snippets']
},
{
description: 'Language Configuration Sample',
path: 'language-configuration-sample',
guide: '/api/language-extensions/language-configuration-guide',
apis: [],
contributions: ['languages']
},
{
description: 'LSP Sample',
path: 'lsp-sample',
guide: '/api/language-extensions/language-server-extension-guide',
apis: [],
contributions: []
},
{
description: 'LSP Log Streaming Sample',
path: 'lsp-log-streaming-sample',
guide: null,
apis: [],
contributions: []
},
{
description: 'LSP Multi Root Server Sample',
path: 'lsp-multi-server-sample',
guide:
'https://github.com/Microsoft/vscode/wiki/Extension-Authoring:-Adopting-Multi-Root-Workspace-APIs#language-client--language-server',
apis: [],
contributions: []
},
{
description: 'LSP Web Extension Sample',
path: 'lsp-web-extension-sample',
guide: '/api/language-extensions/language-server-extension-guide',
apis: [],
contributions: []
},
{
description: 'LSP User Input Sample',
path: 'lsp-user-input-sample',
guide: null,
apis: [],
contributions: []
},
{
description: 'LSP Embedded Language Service',
path: 'lsp-embedded-language-service',
guide: null,
apis: [],
contributions: []
},
{
description: 'LSP Embedded Request Forwarding',
path: 'lsp-embedded-request-forwarding',
guide: null,
apis: [],
contributions: []
},
{
description: 'Wasm language server',
path: 'wasm-language-server',
guide: null,
apis: [],
contributions: []
},
];

15
.scripts/tsconfig.json Normal file
View File

@ -0,0 +1,15 @@
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "Node",
"target": "ES2022",
"lib": [
"ES2022"
],
"noEmit": true,
"strict": true
},
"ts-node": {
"esm": true
}
}

View File

@ -1,16 +1,15 @@
// @ts-check
/**
* Update a dependency to a version in all relevant samples
*/
const fs = require('fs');
const path = require('path');
const child_process = require('child_process');
const { samples } = require('./samples');
import * as child_process from 'child_process';
import * as fs from 'fs';
import * as path from 'path';
import { Sample, samples } from './samples';
function setVersion(
/** @type {string} */ dependencyName,
/** @type {string} */ version,
/** @type {import('./samples').Sample} */ sample
dependencyName: string,
version: string,
sample: Sample
) {
const packageJsonPath = path.join(sample.path, 'package.json');
const packageJsonContents = fs.readFileSync(packageJsonPath).toString();

View File

@ -1,7 +1,6 @@
const fs = require('fs').promises;
const path = require('path');
const { samples, lspSamples } = require('./samples')
import * as fs from 'fs/promises';
import * as path from 'path';
import { samples } from './samples';
const root = path.join(__dirname, '..');
@ -22,9 +21,11 @@ async function main() {
},
files: [
],
references: references.map(reference => { return { path: reference }})
references: references.map(reference => { return { path: reference } })
}
await fs.writeFile(path.join(root, 'tsconfig.lsif.json'), JSON.stringify(tsconfig, undefined, '\t'), { encoding: 'utf8' });
}
main().catch(console.error);
if (require.main === module) {
main().catch(console.error);
}

View File

@ -1,6 +1,5 @@
// @ts-check
const fs = require('fs')
const { samples, lspSamples } = require('./samples')
import * as fs from 'fs';
import { lspSamples, Sample, samples } from './samples';
const TABLE_HEAD = `<!-- SAMPLES_BEGIN -->
| Sample | Guide on VS Code Website | API & Contribution |
@ -11,7 +10,7 @@ const LSP_TABLE_HEAD = `<!-- LSP_SAMPLES_BEGIN -->
| ------ | ----- | --- |`
const LSP_TABLE_END = `<!-- LSP_SAMPLES_END -->`
const getTableRow = sample => {
const getTableRow = (sample: Sample) => {
const descriptionCell = `[${sample.description}](https://github.com/Microsoft/vscode-extension-samples/tree/main/${sample.path})`
let guideCell
if (!sample.guide) {
@ -33,7 +32,7 @@ const getTableRow = sample => {
return `| ${descriptionCell} | ${guideCell} | ${apiAndContributionCell} |`
}
const getSamplesTable = samples => {
const getSamplesTable = (samples: readonly Sample[]) => {
const samplesMd = samples.map(s => getTableRow(s)).join('\n')
return `${TABLE_HEAD.trim()}
@ -41,7 +40,7 @@ ${samplesMd}
${TABLE_END.trim()}`
}
const getLSPSamplesTable = samples => {
const getLSPSamplesTable = (samples: readonly Sample[]) => {
const samplesMd = samples.map(s => getTableRow(s)).join('\n')
return `${LSP_TABLE_HEAD.trim()}
@ -52,9 +51,9 @@ ${LSP_TABLE_END.trim()}`
/**
* Update the README with the latest samples.
*
* @returns {boolean} true if the README was updated, false otherwise.
* @returns true if the README was updated, false otherwise.
*/
function updateReadme(dryRun = false) {
export function updateReadme(dryRun = false): boolean {
const readme = fs.readFileSync('README.md', 'utf-8')
const newReadme = readme
.replace(/<!-- SAMPLES_BEGIN -->(.|\n)*<!-- SAMPLES_END -->/gm, getSamplesTable(samples.filter(x => !x.excludeFromReadme)))
@ -70,8 +69,6 @@ function updateReadme(dryRun = false) {
}
}
exports.updateReadme = updateReadme;
if (require.main === module) {
updateReadme();
}

View File

@ -1,10 +1,9 @@
// @ts-check
const path = require('path');
const { samples, lspSamples } = require('./samples');
const fs = require('fs');
import * as fs from 'fs';
import * as path from 'path';
import { lspSamples, samples } from './samples';
const root = path.join(__dirname, '..');
console.log(root);
/**
* Validates that all samples are correctly listed in `.scripts/samples.js`.

View File

@ -6,219 +6,219 @@ const CAT_NAMES_COMMAND_ID = 'cat.namesInEditor';
const CAT_PARTICIPANT_ID = 'chat-sample.cat';
interface ICatChatResult extends vscode.ChatResult {
metadata: {
command: string;
}
metadata: {
command: string;
}
}
export function activate(context: vscode.ExtensionContext) {
// Define a Cat chat handler.
const handler: vscode.ChatRequestHandler = async (request: vscode.ChatRequest, context: vscode.ChatContext, stream: vscode.ChatResponseStream, token: vscode.CancellationToken): Promise<ICatChatResult> => {
// To talk to an LLM in your subcommand handler implementation, your
// extension can use VS Code's `requestChatAccess` API to access the Copilot API.
// The GitHub Copilot Chat extension implements this provider.
if (request.command === 'randomTeach') {
stream.progress('Picking the right topic to teach...');
const topic = getTopic(context.history);
try {
const messages = [
vscode.LanguageModelChatMessage.User('You are a cat! Your job is to explain computer science concepts in the funny manner of a cat. Always start your response by stating what concept you are explaining. Always include code samples.'),
vscode.LanguageModelChatMessage.User(topic)
];
// Define a Cat chat handler.
const handler: vscode.ChatRequestHandler = async (request: vscode.ChatRequest, context: vscode.ChatContext, stream: vscode.ChatResponseStream, token: vscode.CancellationToken): Promise<ICatChatResult> => {
// To talk to an LLM in your subcommand handler implementation, your
// extension can use VS Code's `requestChatAccess` API to access the Copilot API.
// The GitHub Copilot Chat extension implements this provider.
if (request.command === 'randomTeach') {
stream.progress('Picking the right topic to teach...');
const topic = getTopic(context.history);
try {
const messages = [
vscode.LanguageModelChatMessage.User('You are a cat! Your job is to explain computer science concepts in the funny manner of a cat. Always start your response by stating what concept you are explaining. Always include code samples.'),
vscode.LanguageModelChatMessage.User(topic)
];
const chatResponse = await request.model.sendRequest(messages, {}, token);
for await (const fragment of chatResponse.text) {
stream.markdown(fragment);
}
} catch(err) {
handleError(logger, err, stream);
}
const chatResponse = await request.model.sendRequest(messages, {}, token);
for await (const fragment of chatResponse.text) {
stream.markdown(fragment);
}
stream.button({
command: CAT_NAMES_COMMAND_ID,
title: vscode.l10n.t('Use Cat Names in Editor')
});
logger.logUsage('request', { kind: 'randomTeach'});
return { metadata: { command: 'randomTeach' } };
} else if (request.command === 'play') {
stream.progress('Throwing away the computer science books and preparing to play with some Python code...');
try {
// Here's an example of how to use the prompt-tsx library to build a prompt
const { messages } = await renderPrompt(
PlayPrompt,
{ userQuery: request.prompt },
{ modelMaxPromptTokens: request.model.maxInputTokens },
request.model);
const chatResponse = await request.model.sendRequest(messages, {}, token);
for await (const fragment of chatResponse.text) {
stream.markdown(fragment);
}
} catch(err) {
handleError(logger, err, stream);
}
} catch (err) {
handleError(logger, err, stream);
}
logger.logUsage('request', { kind: 'play'});
return { metadata: { command: 'play' } };
} else {
try {
const messages = [
vscode.LanguageModelChatMessage.User(`You are a cat! Think carefully and step by step like a cat would.
stream.button({
command: CAT_NAMES_COMMAND_ID,
title: vscode.l10n.t('Use Cat Names in Editor')
});
logger.logUsage('request', { kind: 'randomTeach' });
return { metadata: { command: 'randomTeach' } };
} else if (request.command === 'play') {
stream.progress('Throwing away the computer science books and preparing to play with some Python code...');
try {
// Here's an example of how to use the prompt-tsx library to build a prompt
const { messages } = await renderPrompt(
PlayPrompt,
{ userQuery: request.prompt },
{ modelMaxPromptTokens: request.model.maxInputTokens },
request.model);
const chatResponse = await request.model.sendRequest(messages, {}, token);
for await (const fragment of chatResponse.text) {
stream.markdown(fragment);
}
} catch (err) {
handleError(logger, err, stream);
}
logger.logUsage('request', { kind: 'play' });
return { metadata: { command: 'play' } };
} else {
try {
const messages = [
vscode.LanguageModelChatMessage.User(`You are a cat! Think carefully and step by step like a cat would.
Your job is to explain computer science concepts in the funny manner of a cat, using cat metaphors. Always start your response by stating what concept you are explaining. Always include code samples.`),
vscode.LanguageModelChatMessage.User(request.prompt)
];
const chatResponse = await request.model.sendRequest(messages, {}, token);
for await (const fragment of chatResponse.text) {
// Process the output from the language model
// Replace all python function definitions with cat sounds to make the user stop looking at the code and start playing with the cat
const catFragment = fragment.replaceAll('def', 'meow');
stream.markdown(catFragment);
}
} catch(err) {
handleError(logger, err, stream);
}
vscode.LanguageModelChatMessage.User(request.prompt)
];
logger.logUsage('request', { kind: ''});
return { metadata: { command: '' } };
}
};
const chatResponse = await request.model.sendRequest(messages, {}, token);
for await (const fragment of chatResponse.text) {
// Process the output from the language model
// Replace all python function definitions with cat sounds to make the user stop looking at the code and start playing with the cat
const catFragment = fragment.replaceAll('def', 'meow');
stream.markdown(catFragment);
}
} catch (err) {
handleError(logger, err, stream);
}
// Chat participants appear as top-level options in the chat input
// when you type `@`, and can contribute sub-commands in the chat input
// that appear when you type `/`.
const cat = vscode.chat.createChatParticipant(CAT_PARTICIPANT_ID, handler);
cat.iconPath = vscode.Uri.joinPath(context.extensionUri, 'cat.jpeg');
cat.followupProvider = {
provideFollowups(result: ICatChatResult, context: vscode.ChatContext, token: vscode.CancellationToken) {
return [{
prompt: 'let us play',
label: vscode.l10n.t('Play with the cat'),
command: 'play'
} satisfies vscode.ChatFollowup];
}
};
logger.logUsage('request', { kind: '' });
return { metadata: { command: '' } };
}
};
const logger = vscode.env.createTelemetryLogger({
sendEventData(eventName, data) {
// Capture event telemetry
console.log(`Event: ${eventName}`);
console.log(`Data: ${JSON.stringify(data)}`);
},
sendErrorData(error, data) {
// Capture error telemetry
console.error(`Error: ${error}`);
console.error(`Data: ${JSON.stringify(data)}`);
}
});
// Chat participants appear as top-level options in the chat input
// when you type `@`, and can contribute sub-commands in the chat input
// that appear when you type `/`.
const cat = vscode.chat.createChatParticipant(CAT_PARTICIPANT_ID, handler);
cat.iconPath = vscode.Uri.joinPath(context.extensionUri, 'cat.jpeg');
cat.followupProvider = {
provideFollowups(result: ICatChatResult, context: vscode.ChatContext, token: vscode.CancellationToken) {
return [{
prompt: 'let us play',
label: vscode.l10n.t('Play with the cat'),
command: 'play'
} satisfies vscode.ChatFollowup];
}
};
context.subscriptions.push(cat.onDidReceiveFeedback((feedback: vscode.ChatResultFeedback) => {
// Log chat result feedback to be able to compute the success matric of the participant
// unhelpful / totalRequests is a good success metric
logger.logUsage('chatResultFeedback', {
kind: feedback.kind
});
}));
const logger = vscode.env.createTelemetryLogger({
sendEventData(eventName, data) {
// Capture event telemetry
console.log(`Event: ${eventName}`);
console.log(`Data: ${JSON.stringify(data)}`);
},
sendErrorData(error, data) {
// Capture error telemetry
console.error(`Error: ${error}`);
console.error(`Data: ${JSON.stringify(data)}`);
}
});
context.subscriptions.push(
cat,
// Register the command handler for the /meow followup
vscode.commands.registerTextEditorCommand(CAT_NAMES_COMMAND_ID, async (textEditor: vscode.TextEditor) => {
// Replace all variables in active editor with cat names and words
const text = textEditor.document.getText();
context.subscriptions.push(cat.onDidReceiveFeedback((feedback: vscode.ChatResultFeedback) => {
// Log chat result feedback to be able to compute the success matric of the participant
// unhelpful / totalRequests is a good success metric
logger.logUsage('chatResultFeedback', {
kind: feedback.kind
});
}));
let chatResponse: vscode.LanguageModelChatResponse | undefined;
try {
// Use gpt-4o since it is fast and high quality.
const [model] = await vscode.lm.selectChatModels({ vendor: 'copilot', family: 'gpt-4o' });
if (!model) {
console.log('Model not found. Please make sure the GitHub Copilot Chat extension is installed and enabled.');
return;
}
context.subscriptions.push(
cat,
// Register the command handler for the /meow followup
vscode.commands.registerTextEditorCommand(CAT_NAMES_COMMAND_ID, async (textEditor: vscode.TextEditor) => {
// Replace all variables in active editor with cat names and words
const text = textEditor.document.getText();
const messages = [
vscode.LanguageModelChatMessage.User(`You are a cat! Think carefully and step by step like a cat would.
let chatResponse: vscode.LanguageModelChatResponse | undefined;
try {
// Use gpt-4o since it is fast and high quality.
const [model] = await vscode.lm.selectChatModels({ vendor: 'copilot', family: 'gpt-4o' });
if (!model) {
console.log('Model not found. Please make sure the GitHub Copilot Chat extension is installed and enabled.');
return;
}
const messages = [
vscode.LanguageModelChatMessage.User(`You are a cat! Think carefully and step by step like a cat would.
Your job is to replace all variable names in the following code with funny cat variable names. Be creative. IMPORTANT respond just with code. Do not use markdown!`),
vscode.LanguageModelChatMessage.User(text)
];
chatResponse = await model.sendRequest(messages, {}, new vscode.CancellationTokenSource().token);
vscode.LanguageModelChatMessage.User(text)
];
chatResponse = await model.sendRequest(messages, {}, new vscode.CancellationTokenSource().token);
} catch (err) {
if (err instanceof vscode.LanguageModelError) {
console.log(err.message, err.code, err.cause);
} else {
throw err;
}
return;
}
} catch (err) {
if (err instanceof vscode.LanguageModelError) {
console.log(err.message, err.code, err.cause);
} else {
throw err;
}
return;
}
// Clear the editor content before inserting new content
await textEditor.edit(edit => {
const start = new vscode.Position(0, 0);
const end = new vscode.Position(textEditor.document.lineCount - 1, textEditor.document.lineAt(textEditor.document.lineCount - 1).text.length);
edit.delete(new vscode.Range(start, end));
});
// Clear the editor content before inserting new content
await textEditor.edit(edit => {
const start = new vscode.Position(0, 0);
const end = new vscode.Position(textEditor.document.lineCount - 1, textEditor.document.lineAt(textEditor.document.lineCount - 1).text.length);
edit.delete(new vscode.Range(start, end));
});
// Stream the code into the editor as it is coming in from the Language Model
try {
for await (const fragment of chatResponse.text) {
await textEditor.edit(edit => {
const lastLine = textEditor.document.lineAt(textEditor.document.lineCount - 1);
const position = new vscode.Position(lastLine.lineNumber, lastLine.text.length);
edit.insert(position, fragment);
});
}
} catch (err) {
// async response stream may fail, e.g network interruption or server side error
await textEditor.edit(edit => {
const lastLine = textEditor.document.lineAt(textEditor.document.lineCount - 1);
const position = new vscode.Position(lastLine.lineNumber, lastLine.text.length);
edit.insert(position, (<Error>err).message);
});
}
}),
);
// Stream the code into the editor as it is coming in from the Language Model
try {
for await (const fragment of chatResponse.text) {
await textEditor.edit(edit => {
const lastLine = textEditor.document.lineAt(textEditor.document.lineCount - 1);
const position = new vscode.Position(lastLine.lineNumber, lastLine.text.length);
edit.insert(position, fragment);
});
}
} catch (err) {
// async response stream may fail, e.g network interruption or server side error
await textEditor.edit(edit => {
const lastLine = textEditor.document.lineAt(textEditor.document.lineCount - 1);
const position = new vscode.Position(lastLine.lineNumber, lastLine.text.length);
edit.insert(position, (<Error>err).message);
});
}
}),
);
}
function handleError(logger: vscode.TelemetryLogger, err: any, stream: vscode.ChatResponseStream): void {
// making the chat request might fail because
// - model does not exist
// - user consent not given
// - quote limits exceeded
logger.logError(err);
if (err instanceof vscode.LanguageModelError) {
console.log(err.message, err.code, err.cause);
if (err.cause instanceof Error && err.cause.message.includes('off_topic')) {
stream.markdown(vscode.l10n.t('I\'m sorry, I can only explain computer science concepts.'));
}
} else {
// re-throw other errors so they show up in the UI
throw err;
}
// making the chat request might fail because
// - model does not exist
// - user consent not given
// - quote limits exceeded
logger.logError(err);
if (err instanceof vscode.LanguageModelError) {
console.log(err.message, err.code, err.cause);
if (err.cause instanceof Error && err.cause.message.includes('off_topic')) {
stream.markdown(vscode.l10n.t('I\'m sorry, I can only explain computer science concepts.'));
}
} else {
// re-throw other errors so they show up in the UI
throw err;
}
}
// Get a random topic that the cat has not taught in the chat history yet
function getTopic(history: ReadonlyArray<vscode.ChatRequestTurn | vscode.ChatResponseTurn>): string {
const topics = ['linked list', 'recursion', 'stack', 'queue', 'pointers'];
// Filter the chat history to get only the responses from the cat
const previousCatResponses = history.filter(h => {
return h instanceof vscode.ChatResponseTurn && h.participant === CAT_PARTICIPANT_ID;
}) as vscode.ChatResponseTurn[];
// Filter the topics to get only the topics that have not been taught by the cat yet
const topicsNoRepetition = topics.filter(topic => {
return !previousCatResponses.some(catResponse => {
return catResponse.response.some(r => {
return r instanceof vscode.ChatResponseMarkdownPart && r.value.value.includes(topic);
});
});
});
const topics = ['linked list', 'recursion', 'stack', 'queue', 'pointers'];
// Filter the chat history to get only the responses from the cat
const previousCatResponses = history.filter(h => {
return h instanceof vscode.ChatResponseTurn && h.participant === CAT_PARTICIPANT_ID;
}) as vscode.ChatResponseTurn[];
// Filter the topics to get only the topics that have not been taught by the cat yet
const topicsNoRepetition = topics.filter(topic => {
return !previousCatResponses.some(catResponse => {
return catResponse.response.some(r => {
return r instanceof vscode.ChatResponseMarkdownPart && r.value.value.includes(topic);
});
});
});
return topicsNoRepetition[Math.floor(Math.random() * topicsNoRepetition.length)] || 'I have taught you everything I know. Meow!';
return topicsNoRepetition[Math.floor(Math.random() * topicsNoRepetition.length)] || 'I have taught you everything I know. Meow!';
}
export function deactivate() { }

View File

@ -16,4 +16,4 @@ export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(disposable);
}
export function deactivate() {}
export function deactivate() { }

View File

@ -7,7 +7,7 @@ export function run(): Promise<void> {
const mocha = new Mocha({
ui: 'tdd'
});
const testsRoot = path.resolve(__dirname, '..');
return new Promise((c, e) => {

View File

@ -25,7 +25,7 @@ export function activate(_context: vscode.ExtensionContext) {
if (position.line - offset < 0) {
break;
}
const lineBefore = document.lineAt(position.line - offset).text;
const matches = lineBefore.match(regexp);
if (!matches) {
@ -73,7 +73,7 @@ export function activate(_context: vscode.ExtensionContext) {
handleDidPartiallyAcceptCompletionItem(
_completionItem: vscode.InlineCompletionItem,
_info: vscode.PartialAcceptInfo | number
): void {
): void {
console.log('handleDidPartiallyAcceptCompletionItem');
},
};

View File

@ -67,7 +67,7 @@ async function executeCode(kernel: Kernel, code: string, logger: OutputChannel)
}
logger.appendLine('Code execution completed');
logger.appendLine(`<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<`);
} catch (ex){
} catch (ex) {
logger.appendLine(`Code execution failed with an error '${ex}'`);
logger.appendLine(`<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<`);
} finally {

View File

@ -45,7 +45,7 @@ export function isInsideStyleRegion(
}
token = scanner.scan();
}
return false;
}

View File

@ -8,34 +8,34 @@ import * as assert from 'assert';
import { getDocUri, activate } from './helper';
describe('Should get diagnostics', () => {
const docUri = getDocUri('diagnostics.txt');
const docUri = getDocUri('diagnostics.txt');
it('Diagnoses uppercase texts', async () => {
await testDiagnostics(docUri, [
{ message: 'ANY is all uppercase.', range: toRange(0, 0, 0, 3), severity: vscode.DiagnosticSeverity.Warning, source: 'ex' },
{ message: 'ANY is all uppercase.', range: toRange(0, 14, 0, 17), severity: vscode.DiagnosticSeverity.Warning, source: 'ex' },
{ message: 'OS is all uppercase.', range: toRange(0, 18, 0, 20), severity: vscode.DiagnosticSeverity.Warning, source: 'ex' }
]);
});
it('Diagnoses uppercase texts', async () => {
await testDiagnostics(docUri, [
{ message: 'ANY is all uppercase.', range: toRange(0, 0, 0, 3), severity: vscode.DiagnosticSeverity.Warning, source: 'ex' },
{ message: 'ANY is all uppercase.', range: toRange(0, 14, 0, 17), severity: vscode.DiagnosticSeverity.Warning, source: 'ex' },
{ message: 'OS is all uppercase.', range: toRange(0, 18, 0, 20), severity: vscode.DiagnosticSeverity.Warning, source: 'ex' }
]);
});
});
function toRange(sLine: number, sChar: number, eLine: number, eChar: number) {
const start = new vscode.Position(sLine, sChar);
const end = new vscode.Position(eLine, eChar);
return new vscode.Range(start, end);
const start = new vscode.Position(sLine, sChar);
const end = new vscode.Position(eLine, eChar);
return new vscode.Range(start, end);
}
async function testDiagnostics(docUri: vscode.Uri, expectedDiagnostics: vscode.Diagnostic[]) {
await activate(docUri);
await activate(docUri);
const actualDiagnostics = vscode.languages.getDiagnostics(docUri);
const actualDiagnostics = vscode.languages.getDiagnostics(docUri);
assert.equal(actualDiagnostics.length, expectedDiagnostics.length);
assert.equal(actualDiagnostics.length, expectedDiagnostics.length);
expectedDiagnostics.forEach((expectedDiagnostic, i) => {
const actualDiagnostic = actualDiagnostics[i];
assert.equal(actualDiagnostic.message, expectedDiagnostic.message);
assert.deepEqual(actualDiagnostic.range, expectedDiagnostic.range);
assert.equal(actualDiagnostic.severity, expectedDiagnostic.severity);
});
expectedDiagnostics.forEach((expectedDiagnostic, i) => {
const actualDiagnostic = actualDiagnostics[i];
assert.equal(actualDiagnostic.message, expectedDiagnostic.message);
assert.deepEqual(actualDiagnostic.range, expectedDiagnostic.range);
assert.equal(actualDiagnostic.severity, expectedDiagnostic.severity);
});
}

View File

@ -107,7 +107,7 @@ export function activate(context: ExtensionContext) {
Workspace.onDidOpenTextDocument(didOpenTextDocument);
Workspace.textDocuments.forEach(didOpenTextDocument);
Workspace.onDidChangeWorkspaceFolders((event) => {
for (const folder of event.removed) {
for (const folder of event.removed) {
const client = clients.get(folder.uri.toString());
if (client) {
clients.delete(folder.uri.toString());

View File

@ -34,7 +34,7 @@ function validate(document: TextDocument): void {
uri: document.uri,
version: document.version,
diagnostics: [
Diagnostic.create(Range.create(0,0,0, 10), 'Something is wrong here', DiagnosticSeverity.Warning)
Diagnostic.create(Range.create(0, 0, 0, 10), 'Something is wrong here', DiagnosticSeverity.Warning)
]
});
}
@ -57,7 +57,7 @@ connection.onCodeAction((params) => {
});
connection.onExecuteCommand(async (params) => {
if (params.command !== 'sample.fixMe' || params.arguments === undefined) {
if (params.command !== 'sample.fixMe' || params.arguments === undefined) {
return;
}

View File

@ -29,7 +29,7 @@ export async function activate(context: ExtensionContext) {
client = createWorkerLanguageClient(context, clientOptions);
await client.start();
await client.start();
console.log('lsp-web-extension-sample server is ready');
}

608
node_modules/.package-lock.json generated vendored
View File

@ -3,5 +3,611 @@
"version": "0.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {}
"packages": {
"node_modules/@esbuild/darwin-arm64": {
"version": "0.23.1",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz",
"integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
"dev": true,
"dependencies": {
"string-width": "^5.1.2",
"string-width-cjs": "npm:string-width@^4.2.0",
"strip-ansi": "^7.0.1",
"strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
"wrap-ansi": "^8.1.0",
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@types/node": {
"version": "22.8.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.2.tgz",
"integrity": "sha512-NzaRNFV+FZkvK/KLCsNdTvID0SThyrs5SHB6tsD/lajr22FGC73N2QeDPM2wHtVde8mgcXuSsHQkH5cX1pbPLw==",
"dev": true,
"dependencies": {
"undici-types": "~6.19.8"
}
},
"node_modules/ansi-regex": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/ansi-styles": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"dev": true,
"dependencies": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
"dev": true
},
"node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
"dev": true
},
"node_modules/esbuild": {
"version": "0.23.1",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz",
"integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==",
"dev": true,
"hasInstallScript": true,
"bin": {
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.23.1",
"@esbuild/android-arm": "0.23.1",
"@esbuild/android-arm64": "0.23.1",
"@esbuild/android-x64": "0.23.1",
"@esbuild/darwin-arm64": "0.23.1",
"@esbuild/darwin-x64": "0.23.1",
"@esbuild/freebsd-arm64": "0.23.1",
"@esbuild/freebsd-x64": "0.23.1",
"@esbuild/linux-arm": "0.23.1",
"@esbuild/linux-arm64": "0.23.1",
"@esbuild/linux-ia32": "0.23.1",
"@esbuild/linux-loong64": "0.23.1",
"@esbuild/linux-mips64el": "0.23.1",
"@esbuild/linux-ppc64": "0.23.1",
"@esbuild/linux-riscv64": "0.23.1",
"@esbuild/linux-s390x": "0.23.1",
"@esbuild/linux-x64": "0.23.1",
"@esbuild/netbsd-x64": "0.23.1",
"@esbuild/openbsd-arm64": "0.23.1",
"@esbuild/openbsd-x64": "0.23.1",
"@esbuild/sunos-x64": "0.23.1",
"@esbuild/win32-arm64": "0.23.1",
"@esbuild/win32-ia32": "0.23.1",
"@esbuild/win32-x64": "0.23.1"
}
},
"node_modules/foreground-child": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
"integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
"dev": true,
"dependencies": {
"cross-spawn": "^7.0.0",
"signal-exit": "^4.0.1"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/get-tsconfig": {
"version": "4.8.1",
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz",
"integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==",
"dev": true,
"dependencies": {
"resolve-pkg-maps": "^1.0.0"
},
"funding": {
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
}
},
"node_modules/glob": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz",
"integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==",
"dev": true,
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^4.0.1",
"minimatch": "^10.0.0",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^2.0.0"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true
},
"node_modules/jackspeak": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz",
"integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==",
"dev": true,
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/lru-cache": {
"version": "11.0.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.1.tgz",
"integrity": "sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==",
"dev": true,
"engines": {
"node": "20 || >=22"
}
},
"node_modules/minimatch": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
"integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
"dev": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"dev": true,
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/package-json-from-dist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
"dev": true
},
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/path-scurry": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz",
"integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==",
"dev": true,
"dependencies": {
"lru-cache": "^11.0.0",
"minipass": "^7.1.2"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/resolve-pkg-maps": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
"dev": true,
"funding": {
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
}
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
"dependencies": {
"shebang-regex": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/shebang-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
"dev": true,
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"dev": true,
"dependencies": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/string-width-cjs": {
"name": "string-width",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/string-width-cjs/node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/string-width-cjs/node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
"node_modules/string-width-cjs/node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-ansi": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"dev": true,
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/strip-ansi-cjs": {
"name": "strip-ansi",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/tsx": {
"version": "4.19.2",
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.2.tgz",
"integrity": "sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==",
"dev": true,
"dependencies": {
"esbuild": "~0.23.0",
"get-tsconfig": "^4.7.5"
},
"bin": {
"tsx": "dist/cli.mjs"
},
"engines": {
"node": ">=18.0.0"
},
"optionalDependencies": {
"fsevents": "~2.3.3"
}
},
"node_modules/typescript": {
"version": "5.6.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
"integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/undici-types": {
"version": "6.19.8",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
"dev": true
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"dependencies": {
"isexe": "^2.0.0"
},
"bin": {
"node-which": "bin/node-which"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/wrap-ansi": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
"dev": true,
"dependencies": {
"ansi-styles": "^6.1.0",
"string-width": "^5.0.1",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrap-ansi-cjs": {
"name": "wrap-ansi",
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
"node_modules/wrap-ansi-cjs/node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
}
}
}

View File

@ -22,11 +22,11 @@ export function activate(context: vscode.ExtensionContext) {
// Notification with actions
const showWarningNotificationWithActions = vscode.commands.registerCommand('notifications-sample.showWarningWithActions', async () => {
const selection = await vscode.window.showWarningMessage('Warning Notification With Actions', 'Action 1', 'Action 2', 'Action 3');
if (selection !== undefined) {
vscode.window.showInformationMessage(`You selected: ${selection}`, { modal: true });
}
});
// Progress notification with option to cancel

1570
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,12 +3,20 @@
"license": "MIT",
"publisher": "Microsoft",
"version": "0.0.1",
"private": true,
"scripts": {
"compile": "node .scripts/run-script.js compile",
"lint": "node .scripts/run-script.js lint",
"install": "node .scripts/run-command.js npm install",
"auditFix": "node .scripts/run-command.js npm audit fix",
"update-readme": "node .scripts/update-readme.js",
"update-lsif": "node .scripts/update-lsif.js"
"compile": "tsx .scripts/run-script.ts compile",
"lint": "tsx .scripts/run-script.ts lint",
"install": "tsx .scripts/run-command.ts npm install",
"auditFix": "tsx .scripts/run-command.ts npm audit fix",
"update-readme": "tsx .scripts/update-readme.ts",
"update-lsif": "tsx .scripts/update-lsif.ts",
"validate": "tsx .scripts/validate.ts"
},
"devDependencies": {
"@types/node": "^22.8.2",
"glob": "^11.0.0",
"tsx": "^4.19.2",
"typescript": "^5.6.3"
}
}
}

View File

@ -87,7 +87,7 @@ class DocumentSemanticTokensProvider implements vscode.DocumentSemanticTokensPro
tokenModifiers: tokenData.tokenModifiers
});
currentOffset = closeOffset;
// eslint-disable-next-line no-constant-condition
// eslint-disable-next-line no-constant-condition
} while (true);
}
return r;

View File

@ -116,12 +116,12 @@ export namespace Types._ {
export namespace calculator.$ {
export const Operation = Types.$.Operation;
export namespace imports {
export const log = new $wcm.FunctionType<calculator.Imports['log']>('log',[
export const log = new $wcm.FunctionType<calculator.Imports['log']>('log', [
['msg', $wcm.wstring],
], undefined);
}
export namespace exports {
export const calc = new $wcm.FunctionType<calculator.Exports['calc']>('calc',[
export const calc = new $wcm.FunctionType<calculator.Exports['calc']>('calc', [
['o', Operation],
], $wcm.u32);
}

View File

@ -35,7 +35,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
context.subscriptions.push(vscode.commands.registerCommand('vscode-samples.wasm-component-model-async.run', async () => {
channel.show();
channel.appendLine('Running calculator example');
const add = Types.Operation.Add({ left: 1, right: 2});
const add = Types.Operation.Add({ left: 1, right: 2 });
channel.appendLine(`Add ${await api.calc(add)}`);
const sub = Types.Operation.Sub({ left: 10, right: 8 });
channel.appendLine(`Sub ${await api.calc(sub)}`);

View File

@ -24,7 +24,7 @@ export namespace Types {
export type Statics = {
$new?(): Interface;
};
export type Class = Statics & (new() => Interface);
export type Class = Statics & (new () => Interface);
}
export type Engine = Engine.Interface;
}

View File

@ -32,22 +32,22 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
// Bind the JavaScript Api
const api = calculator._.exports.bind(instance.exports as calculator._.Exports, wasmContext);
context.subscriptions.push(vscode.commands.registerCommand('vscode-samples.wasm-component-model.run', () => {
channel.show();
channel.appendLine('Running calculator example');
context.subscriptions.push(vscode.commands.registerCommand('vscode-samples.wasm-component-model.run', () => {
channel.show();
channel.appendLine('Running calculator example');
// Create a new calculator engine
const calculator = new api.types.Engine();
// Create a new calculator engine
const calculator = new api.types.Engine();
// Push some operands and operations
calculator.pushOperand(10);
calculator.pushOperand(20);
calculator.pushOperation(Types.Operation.add);
calculator.pushOperand(2);
calculator.pushOperation(Types.Operation.mul);
// Push some operands and operations
calculator.pushOperand(10);
calculator.pushOperand(20);
calculator.pushOperation(Types.Operation.add);
calculator.pushOperand(2);
calculator.pushOperation(Types.Operation.mul);
// Calculate the result
const result = calculator.execute();
channel.appendLine(`Result: ${result}`);
}));
// Calculate the result
const result = calculator.execute();
channel.appendLine(`Result: ${result}`);
}));
}

View File

@ -137,12 +137,12 @@ export namespace calculator.$ {
export const Operation = Types.$.Operation;
export const ErrorCode = Types.$.ErrorCode;
export namespace imports {
export const log = new $wcm.FunctionType<calculator.Imports['log']>('log',[
export const log = new $wcm.FunctionType<calculator.Imports['log']>('log', [
['msg', $wcm.wstring],
], undefined);
}
export namespace exports {
export const calc = new $wcm.FunctionType<calculator.Exports['calc']>('calc',[
export const calc = new $wcm.FunctionType<calculator.Exports['calc']>('calc', [
['o', Operation],
], new $wcm.ResultType<u32, calculator.ErrorCode>($wcm.u32, ErrorCode, Types.ErrorCode.Error_));
}

View File

@ -46,7 +46,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
context.subscriptions.push(vscode.commands.registerCommand('vscode-samples.wasm-component-model.run', () => {
channel.show();
channel.appendLine('Running calculator example');
const add = Types.Operation.Add({ left: 1, right: 2});
const add = Types.Operation.Add({ left: 1, right: 2 });
channel.appendLine(`Add ${api.calc(add)}`);
const sub = Types.Operation.Sub({ left: 10, right: 8 });
channel.appendLine(`Sub ${api.calc(sub)}`);

View File

@ -35,7 +35,7 @@ export async function activate(context: ExtensionContext) {
};
const clientOptions: LanguageClientOptions = {
documentSelector: [ { language: 'plaintext' } ],
documentSelector: [{ language: 'plaintext' }],
outputChannel: channel,
uriConverters: createUriConverters(),
};

View File

@ -8,6 +8,9 @@
"name": "cat-codicons",
"version": "0.0.1",
"license": "MIT",
"dependencies": {
"@vscode/codicons": "0.0.20"
},
"devDependencies": {
"@eslint/js": "^9.13.0",
"@stylistic/eslint-plugin": "^2.9.0",

View File

@ -42,7 +42,7 @@
"typescript": "^5.6.2",
"typescript-eslint": "^8.11.0"
},
"dependencies": {
"dependencies": {
"@vscode/codicons": "0.0.20"
}
}
}
}