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

@ -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`.