Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/microsoft/vscode.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohannes Rieken <johannes.rieken@gmail.com>2022-07-19 16:54:14 +0300
committerGitHub <noreply@github.com>2022-07-19 16:54:14 +0300
commita260dc7b3effcbd1a635ee8df49bd968ccb76be5 (patch)
tree36b9715f8e0f3da86fafd9a138ab46314fb2dc4e /src
parent34f1bc679dadbd07104234ab03eacdd7b8d157f0 (diff)
joh/familiar sparrow (#155613)
* rename to `isFileTemplate` * add code snippet provider for file templates, fix setting model mode https://github.com/microsoft/vscode/issues/145929
Diffstat (limited to 'src')
-rw-r--r--src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts6
-rw-r--r--src/vs/workbench/contrib/snippets/browser/commands/fileTemplateSnippets.ts (renamed from src/vs/workbench/contrib/snippets/browser/commands/emptyFileSnippets.ts)18
-rw-r--r--src/vs/workbench/contrib/snippets/browser/commands/surroundWithSnippet.ts83
-rw-r--r--src/vs/workbench/contrib/snippets/browser/snippetCodeActionProvider.ts139
-rw-r--r--src/vs/workbench/contrib/snippets/browser/snippets.contribution.ts14
-rw-r--r--src/vs/workbench/contrib/snippets/browser/snippets.ts2
-rw-r--r--src/vs/workbench/contrib/snippets/browser/snippetsFile.ts8
-rw-r--r--src/vs/workbench/contrib/snippets/browser/snippetsService.ts2
8 files changed, 166 insertions, 106 deletions
diff --git a/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts b/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts
index bac3e753519..99cd7d942c9 100644
--- a/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts
+++ b/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint.ts
@@ -20,7 +20,7 @@ import { registerEditorContribution } from 'vs/editor/browser/editorExtensions';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IContentActionHandler, renderFormattedText } from 'vs/base/browser/formattedTextRenderer';
-import { SelectSnippetForEmptyFile } from 'vs/workbench/contrib/snippets/browser/commands/emptyFileSnippets';
+import { ApplyFileSnippetAction } from 'vs/workbench/contrib/snippets/browser/commands/fileTemplateSnippets';
const $ = dom.$;
@@ -136,7 +136,7 @@ class UntitledTextEditorHintContentWidget implements IContentWidget {
this.domNode.append(hintElement);
// ugly way to associate keybindings...
- const keybindingsLookup = [ChangeLanguageAction.ID, SelectSnippetForEmptyFile.Id, 'welcome.showNewFileEntries'];
+ const keybindingsLookup = [ChangeLanguageAction.ID, ApplyFileSnippetAction.Id, 'welcome.showNewFileEntries'];
for (const anchor of hintElement.querySelectorAll('A')) {
(<HTMLAnchorElement>anchor).style.cursor = 'pointer';
const id = keybindingsLookup.shift();
@@ -156,7 +156,7 @@ class UntitledTextEditorHintContentWidget implements IContentWidget {
const snippetOnClickOrTab = async (e: MouseEvent) => {
e.stopPropagation();
this.editor.focus();
- this.commandService.executeCommand(SelectSnippetForEmptyFile.Id, { from: 'hint' });
+ this.commandService.executeCommand(ApplyFileSnippetAction.Id, { from: 'hint' });
};
const chooseEditorOnClickOrTap = async (e: MouseEvent) => {
diff --git a/src/vs/workbench/contrib/snippets/browser/commands/emptyFileSnippets.ts b/src/vs/workbench/contrib/snippets/browser/commands/fileTemplateSnippets.ts
index 963c92e60cb..2074eef20bd 100644
--- a/src/vs/workbench/contrib/snippets/browser/commands/emptyFileSnippets.ts
+++ b/src/vs/workbench/contrib/snippets/browser/commands/fileTemplateSnippets.ts
@@ -7,6 +7,7 @@ import { groupBy, isFalsyOrEmpty } from 'vs/base/common/arrays';
import { compare } from 'vs/base/common/strings';
import { getCodeEditor } from 'vs/editor/browser/editorBrowser';
import { ILanguageService } from 'vs/editor/common/languages/language';
+import { IModelService } from 'vs/editor/common/services/model';
import { SnippetController2 } from 'vs/editor/contrib/snippet/browser/snippetController2';
import { localize } from 'vs/nls';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
@@ -16,16 +17,16 @@ import { ISnippetsService } from 'vs/workbench/contrib/snippets/browser/snippets
import { Snippet } from 'vs/workbench/contrib/snippets/browser/snippetsFile';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
-export class SelectSnippetForEmptyFile extends SnippetsAction {
+export class ApplyFileSnippetAction extends SnippetsAction {
- static readonly Id = 'workbench.action.populateFromSnippet';
+ static readonly Id = 'workbench.action.populateFileFromSnippet';
constructor() {
super({
- id: SelectSnippetForEmptyFile.Id,
+ id: ApplyFileSnippetAction.Id,
title: {
- value: localize('label', 'Populate from Snippet'),
- original: 'Populate from Snippet'
+ value: localize('label', 'Populate File from Snippet'),
+ original: 'Populate File from Snippet'
},
f1: true,
});
@@ -36,13 +37,14 @@ export class SelectSnippetForEmptyFile extends SnippetsAction {
const quickInputService = accessor.get(IQuickInputService);
const editorService = accessor.get(IEditorService);
const langService = accessor.get(ILanguageService);
+ const modelService = accessor.get(IModelService);
const editor = getCodeEditor(editorService.activeTextEditorControl);
if (!editor || !editor.hasModel()) {
return;
}
- const snippets = await snippetService.getSnippets(undefined, { topLevelSnippets: true, noRecencySort: true, includeNoPrefixSnippets: true });
+ const snippets = await snippetService.getSnippets(undefined, { fileTemplateSnippets: true, noRecencySort: true, includeNoPrefixSnippets: true });
if (snippets.length === 0) {
return;
}
@@ -60,9 +62,7 @@ export class SelectSnippetForEmptyFile extends SnippetsAction {
}]);
// set language if possible
- if (langService.isRegisteredLanguageId(selection.langId)) {
- editor.getModel().setMode(selection.langId);
- }
+ modelService.setMode(editor.getModel(), langService.createById(selection.langId));
}
}
diff --git a/src/vs/workbench/contrib/snippets/browser/commands/surroundWithSnippet.ts b/src/vs/workbench/contrib/snippets/browser/commands/surroundWithSnippet.ts
index 7a771724f3a..bdd36872158 100644
--- a/src/vs/workbench/contrib/snippets/browser/commands/surroundWithSnippet.ts
+++ b/src/vs/workbench/contrib/snippets/browser/commands/surroundWithSnippet.ts
@@ -3,28 +3,21 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-import { IDisposable } from 'vs/base/common/lifecycle';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { Position } from 'vs/editor/common/core/position';
-import { IRange, Range } from 'vs/editor/common/core/range';
-import { Selection } from 'vs/editor/common/core/selection';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
-import { CodeAction, CodeActionList, CodeActionProvider } from 'vs/editor/common/languages';
import { ITextModel } from 'vs/editor/common/model';
-import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
-import { CodeActionKind } from 'vs/editor/contrib/codeAction/browser/types';
import { SnippetController2 } from 'vs/editor/contrib/snippet/browser/snippetController2';
import { localize } from 'vs/nls';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
-import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { SnippetEditorAction } from 'vs/workbench/contrib/snippets/browser/commands/abstractSnippetsActions';
import { pickSnippet } from 'vs/workbench/contrib/snippets/browser/snippetPicker';
import { Snippet } from 'vs/workbench/contrib/snippets/browser/snippetsFile';
import { ISnippetsService } from '../snippets';
-async function getSurroundableSnippets(snippetsService: ISnippetsService, model: ITextModel, position: Position, includeDisabledSnippets: boolean): Promise<Snippet[]> {
+export async function getSurroundableSnippets(snippetsService: ISnippetsService, model: ITextModel, position: Position, includeDisabledSnippets: boolean): Promise<Snippet[]> {
const { lineNumber, column } = position;
model.tokenization.tokenizeIfCheap(lineNumber);
@@ -83,77 +76,3 @@ export class SurroundWithSnippetEditorAction extends SnippetEditorAction {
snippetsService.updateUsageTimestamp(snippet);
}
}
-
-
-export class SurroundWithSnippetCodeActionProvider implements CodeActionProvider, IWorkbenchContribution {
-
- private static readonly _MAX_CODE_ACTIONS = 4;
-
- private static readonly _overflowCommandCodeAction: CodeAction = {
- kind: CodeActionKind.Refactor.value,
- title: SurroundWithSnippetEditorAction.options.title.value,
- command: {
- id: SurroundWithSnippetEditorAction.options.id,
- title: SurroundWithSnippetEditorAction.options.title.value,
- },
- };
-
- private readonly _registration: IDisposable;
-
- constructor(
- @ISnippetsService private readonly _snippetService: ISnippetsService,
- @ILanguageFeaturesService languageFeaturesService: ILanguageFeaturesService,
- ) {
- this._registration = languageFeaturesService.codeActionProvider.register('*', this);
- }
-
- dispose(): void {
- this._registration.dispose();
- }
-
- async provideCodeActions(model: ITextModel, range: Range | Selection): Promise<CodeActionList | undefined> {
-
- if (range.isEmpty()) {
- return undefined;
- }
-
- const position = Selection.isISelection(range) ? range.getPosition() : range.getStartPosition();
- const snippets = await getSurroundableSnippets(this._snippetService, model, position, false);
- if (!snippets.length) {
- return undefined;
- }
-
- const actions: CodeAction[] = [];
- const hasMore = snippets.length > SurroundWithSnippetCodeActionProvider._MAX_CODE_ACTIONS;
- const len = Math.min(snippets.length, SurroundWithSnippetCodeActionProvider._MAX_CODE_ACTIONS);
-
- for (let i = 0; i < len; i++) {
- actions.push(this._makeCodeActionForSnippet(snippets[i], model, range));
- }
- if (hasMore) {
- actions.push(SurroundWithSnippetCodeActionProvider._overflowCommandCodeAction);
- }
- return {
- actions,
- dispose() { }
- };
- }
-
- private _makeCodeActionForSnippet(snippet: Snippet, model: ITextModel, range: IRange): CodeAction {
- return {
- title: localize('codeAction', "Surround With: {0}", snippet.name),
- kind: CodeActionKind.Refactor.value,
- edit: {
- edits: [{
- versionId: model.getVersionId(),
- resource: model.uri,
- textEdit: {
- range,
- text: snippet.body,
- insertAsSnippet: true,
- }
- }]
- }
- };
- }
-}
diff --git a/src/vs/workbench/contrib/snippets/browser/snippetCodeActionProvider.ts b/src/vs/workbench/contrib/snippets/browser/snippetCodeActionProvider.ts
new file mode 100644
index 00000000000..08afb39eba9
--- /dev/null
+++ b/src/vs/workbench/contrib/snippets/browser/snippetCodeActionProvider.ts
@@ -0,0 +1,139 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import { DisposableStore } from 'vs/base/common/lifecycle';
+import { IRange, Range } from 'vs/editor/common/core/range';
+import { Selection } from 'vs/editor/common/core/selection';
+import { CodeAction, CodeActionList, CodeActionProvider, WorkspaceEdit } from 'vs/editor/common/languages';
+import { ITextModel } from 'vs/editor/common/model';
+import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
+import { CodeActionKind } from 'vs/editor/contrib/codeAction/browser/types';
+import { localize } from 'vs/nls';
+import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
+import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
+import { ApplyFileSnippetAction } from 'vs/workbench/contrib/snippets/browser/commands/fileTemplateSnippets';
+import { getSurroundableSnippets, SurroundWithSnippetEditorAction } from 'vs/workbench/contrib/snippets/browser/commands/surroundWithSnippet';
+import { Snippet } from 'vs/workbench/contrib/snippets/browser/snippetsFile';
+import { ISnippetsService } from './snippets';
+
+class SurroundWithSnippetCodeActionProvider implements CodeActionProvider {
+
+ private static readonly _MAX_CODE_ACTIONS = 4;
+
+ private static readonly _overflowCommandCodeAction: CodeAction = {
+ kind: CodeActionKind.Refactor.value,
+ title: SurroundWithSnippetEditorAction.options.title.value,
+ command: {
+ id: SurroundWithSnippetEditorAction.options.id,
+ title: SurroundWithSnippetEditorAction.options.title.value,
+ },
+ };
+
+ constructor(@ISnippetsService private readonly _snippetService: ISnippetsService) { }
+
+ async provideCodeActions(model: ITextModel, range: Range | Selection): Promise<CodeActionList | undefined> {
+
+ if (range.isEmpty()) {
+ return undefined;
+ }
+
+ const position = Selection.isISelection(range) ? range.getPosition() : range.getStartPosition();
+ const snippets = await getSurroundableSnippets(this._snippetService, model, position, false);
+ if (!snippets.length) {
+ return undefined;
+ }
+
+ const actions: CodeAction[] = [];
+ for (const snippet of snippets) {
+ if (actions.length >= SurroundWithSnippetCodeActionProvider._MAX_CODE_ACTIONS) {
+ actions.push(SurroundWithSnippetCodeActionProvider._overflowCommandCodeAction);
+ break;
+ }
+ actions.push({
+ title: localize('codeAction', "Surround With: {0}", snippet.name),
+ kind: CodeActionKind.Refactor.value,
+ edit: asWorkspaceEdit(model, range, snippet)
+ });
+ }
+
+ return {
+ actions,
+ dispose() { }
+ };
+ }
+}
+
+class FileTemplateCodeActionProvider implements CodeActionProvider {
+
+ private static readonly _MAX_CODE_ACTIONS = 4;
+
+ private static readonly _overflowCommandCodeAction: CodeAction = {
+ title: localize('overflow.start.title', 'Start with Snippet'),
+ kind: CodeActionKind.Refactor.value,
+ command: {
+ id: ApplyFileSnippetAction.Id,
+ title: ''
+ }
+ };
+
+ readonly providedCodeActionKinds?: readonly string[] = [CodeActionKind.Refactor.value];
+
+ constructor(@ISnippetsService private readonly _snippetService: ISnippetsService) { }
+
+ async provideCodeActions(model: ITextModel) {
+ if (model.getValueLength() !== 0) {
+ return undefined;
+ }
+
+ const snippets = await this._snippetService.getSnippets(model.getLanguageId(), { fileTemplateSnippets: true, includeNoPrefixSnippets: true });
+ const actions: CodeAction[] = [];
+ for (const snippet of snippets) {
+ if (actions.length >= FileTemplateCodeActionProvider._MAX_CODE_ACTIONS) {
+ actions.push(FileTemplateCodeActionProvider._overflowCommandCodeAction);
+ break;
+ }
+ actions.push({
+ title: localize('title', 'Start with: {0}', snippet.name),
+ kind: CodeActionKind.Refactor.value,
+ edit: asWorkspaceEdit(model, model.getFullModelRange(), snippet)
+ });
+ }
+ return {
+ actions,
+ dispose() { }
+ };
+ }
+}
+
+function asWorkspaceEdit(model: ITextModel, range: IRange, snippet: Snippet): WorkspaceEdit {
+ return {
+ edits: [{
+ versionId: model.getVersionId(),
+ resource: model.uri,
+ textEdit: {
+ range,
+ text: snippet.body,
+ insertAsSnippet: true,
+ }
+ }]
+ };
+}
+
+export class SnippetCodeActions implements IWorkbenchContribution {
+
+ private readonly _store = new DisposableStore();
+
+ constructor(
+ @IInstantiationService instantiationService: IInstantiationService,
+ @ILanguageFeaturesService languageFeaturesService: ILanguageFeaturesService,
+ ) {
+ this._store.add(languageFeaturesService.codeActionProvider.register('*', instantiationService.createInstance(SurroundWithSnippetCodeActionProvider)));
+ this._store.add(languageFeaturesService.codeActionProvider.register('*', instantiationService.createInstance(FileTemplateCodeActionProvider)));
+ }
+
+ dispose(): void {
+ this._store.dispose();
+ }
+}
diff --git a/src/vs/workbench/contrib/snippets/browser/snippets.contribution.ts b/src/vs/workbench/contrib/snippets/browser/snippets.contribution.ts
index 39f0c8233c5..dfd4bb7e37a 100644
--- a/src/vs/workbench/contrib/snippets/browser/snippets.contribution.ts
+++ b/src/vs/workbench/contrib/snippets/browser/snippets.contribution.ts
@@ -12,9 +12,10 @@ import * as JSONContributionRegistry from 'vs/platform/jsonschemas/common/jsonCo
import { Registry } from 'vs/platform/registry/common/platform';
import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
import { ConfigureSnippets } from 'vs/workbench/contrib/snippets/browser/commands/configureSnippets';
-import { SelectSnippetForEmptyFile } from 'vs/workbench/contrib/snippets/browser/commands/emptyFileSnippets';
+import { ApplyFileSnippetAction } from 'vs/workbench/contrib/snippets/browser/commands/fileTemplateSnippets';
import { InsertSnippetAction } from 'vs/workbench/contrib/snippets/browser/commands/insertSnippet';
-import { SurroundWithSnippetCodeActionProvider, SurroundWithSnippetEditorAction } from 'vs/workbench/contrib/snippets/browser/commands/surroundWithSnippet';
+import { SurroundWithSnippetEditorAction } from 'vs/workbench/contrib/snippets/browser/commands/surroundWithSnippet';
+import { SnippetCodeActions } from 'vs/workbench/contrib/snippets/browser/snippetCodeActionProvider';
import { ISnippetsService } from 'vs/workbench/contrib/snippets/browser/snippets';
import { SnippetsService } from 'vs/workbench/contrib/snippets/browser/snippetsService';
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
@@ -29,10 +30,11 @@ registerAction2(InsertSnippetAction);
CommandsRegistry.registerCommandAlias('editor.action.showSnippets', 'editor.action.insertSnippet');
registerAction2(SurroundWithSnippetEditorAction);
registerAction2(ConfigureSnippets);
-registerAction2(SelectSnippetForEmptyFile);
+registerAction2(ApplyFileSnippetAction);
// workbench contribs
-Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(SurroundWithSnippetCodeActionProvider, LifecyclePhase.Restored);
+Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench)
+ .registerWorkbenchContribution(SnippetCodeActions, LifecyclePhase.Restored);
// schema
const languageScopeSchemaId = 'vscode://schemas/snippets';
@@ -42,8 +44,8 @@ const snippetSchemaProperties: IJSONSchemaMap = {
description: nls.localize('snippetSchema.json.prefix', 'The prefix to use when selecting the snippet in intellisense'),
type: ['string', 'array']
},
- isTopLevel: {
- description: nls.localize('snippetSchema.json.isTopLevel', 'The snippet is only applicable to empty files.'),
+ isFileTemplate: {
+ description: nls.localize('snippetSchema.json.isFileTemplate', 'The snippet is meant to populate or replace a whole file'),
type: 'boolean'
},
body: {
diff --git a/src/vs/workbench/contrib/snippets/browser/snippets.ts b/src/vs/workbench/contrib/snippets/browser/snippets.ts
index fa485ab0f2f..a11c4ccf6a8 100644
--- a/src/vs/workbench/contrib/snippets/browser/snippets.ts
+++ b/src/vs/workbench/contrib/snippets/browser/snippets.ts
@@ -12,7 +12,7 @@ export interface ISnippetGetOptions {
includeDisabledSnippets?: boolean;
includeNoPrefixSnippets?: boolean;
noRecencySort?: boolean;
- topLevelSnippets?: boolean;
+ fileTemplateSnippets?: boolean;
}
export interface ISnippetsService {
diff --git a/src/vs/workbench/contrib/snippets/browser/snippetsFile.ts b/src/vs/workbench/contrib/snippets/browser/snippetsFile.ts
index b6ce272ef28..070fd986cdf 100644
--- a/src/vs/workbench/contrib/snippets/browser/snippetsFile.ts
+++ b/src/vs/workbench/contrib/snippets/browser/snippetsFile.ts
@@ -105,7 +105,7 @@ export class Snippet {
readonly prefixLow: string;
constructor(
- readonly isTopLevel: boolean,
+ readonly isFileTemplate: boolean,
readonly scopes: string[],
readonly name: string,
readonly prefix: string,
@@ -143,7 +143,7 @@ export class Snippet {
interface JsonSerializedSnippet {
- isTopLevel?: boolean;
+ isFileTemplate?: boolean;
body: string | string[];
scope?: string;
prefix: string | string[] | undefined;
@@ -261,7 +261,7 @@ export class SnippetFile {
private _parseSnippet(name: string, snippet: JsonSerializedSnippet, bucket: Snippet[]): void {
- let { isTopLevel, prefix, body, description } = snippet;
+ let { isFileTemplate, prefix, body, description } = snippet;
if (!prefix) {
prefix = '';
@@ -306,7 +306,7 @@ export class SnippetFile {
for (const _prefix of Array.isArray(prefix) ? prefix : Iterable.single(prefix)) {
bucket.push(new Snippet(
- Boolean(isTopLevel),
+ Boolean(isFileTemplate),
scopes,
name,
_prefix,
diff --git a/src/vs/workbench/contrib/snippets/browser/snippetsService.ts b/src/vs/workbench/contrib/snippets/browser/snippetsService.ts
index 3c5ed85f665..069f3bf44f3 100644
--- a/src/vs/workbench/contrib/snippets/browser/snippetsService.ts
+++ b/src/vs/workbench/contrib/snippets/browser/snippetsService.ts
@@ -318,7 +318,7 @@ export class SnippetsService implements ISnippetsService {
// enabled or disabled wanted
continue;
}
- if (typeof opts?.topLevelSnippets === 'boolean' && opts.topLevelSnippets !== snippet.isTopLevel) {
+ if (typeof opts?.fileTemplateSnippets === 'boolean' && opts.fileTemplateSnippets !== snippet.isFileTemplate) {
// isTopLevel requested but mismatching
continue;
}