mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-31 01:00:29 -04:00
Merge from vscode cfc1ab4c5f816765b91fb7ead3c3427a7c8581a3
This commit is contained in:
@@ -12,7 +12,6 @@ import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ISnippetsService } from 'vs/workbench/contrib/snippets/browser/snippets.contribution';
|
||||
import { values } from 'vs/base/common/map';
|
||||
import { IQuickPickItem, IQuickInputService, QuickPickInput } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { SnippetSource } from 'vs/workbench/contrib/snippets/browser/snippetsFile';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
@@ -73,7 +72,7 @@ async function computePicks(snippetService: ISnippetsService, envService: IEnvir
|
||||
filepath: file.location,
|
||||
description: names.size === 0
|
||||
? nls.localize('global.scope', "(global)")
|
||||
: nls.localize('global.1', "({0})", values(names).join(', '))
|
||||
: nls.localize('global.1', "({0})", [...names].join(', '))
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { MarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { compare, startsWith } from 'vs/base/common/strings';
|
||||
import { compare } from 'vs/base/common/strings';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { IRange, Range } from 'vs/editor/common/core/range';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
@@ -55,8 +55,6 @@ export class SnippetCompletion implements CompletionItem {
|
||||
|
||||
export class SnippetCompletionProvider implements CompletionItemProvider {
|
||||
|
||||
private static readonly _maxPrefix = 10000;
|
||||
|
||||
readonly _debugDisplayName = 'snippetCompletions';
|
||||
|
||||
constructor(
|
||||
@@ -66,92 +64,84 @@ export class SnippetCompletionProvider implements CompletionItemProvider {
|
||||
//
|
||||
}
|
||||
|
||||
provideCompletionItems(model: ITextModel, position: Position, context: CompletionContext): Promise<CompletionList> | undefined {
|
||||
|
||||
if (position.column >= SnippetCompletionProvider._maxPrefix) {
|
||||
return undefined;
|
||||
}
|
||||
async provideCompletionItems(model: ITextModel, position: Position, context: CompletionContext): Promise<CompletionList> {
|
||||
|
||||
if (context.triggerKind === CompletionTriggerKind.TriggerCharacter && context.triggerCharacter === ' ') {
|
||||
// no snippets when suggestions have been triggered by space
|
||||
return undefined;
|
||||
return { suggestions: [] };
|
||||
}
|
||||
|
||||
const languageId = this._getLanguageIdAtPosition(model, position);
|
||||
return this._snippets.getSnippets(languageId).then(snippets => {
|
||||
const snippets = await this._snippets.getSnippets(languageId);
|
||||
|
||||
let suggestions: SnippetCompletion[];
|
||||
let pos = { lineNumber: position.lineNumber, column: 1 };
|
||||
let lineOffsets: number[] = [];
|
||||
const lineContent = model.getLineContent(position.lineNumber);
|
||||
const linePrefixLow = lineContent.substr(0, position.column - 1).toLowerCase();
|
||||
let endsInWhitespace = linePrefixLow.match(/\s$/);
|
||||
let pos = { lineNumber: position.lineNumber, column: 1 };
|
||||
let lineOffsets: number[] = [];
|
||||
const lineContent = model.getLineContent(position.lineNumber).toLowerCase();
|
||||
const endsInWhitespace = /\s/.test(lineContent[position.column - 2]);
|
||||
|
||||
while (pos.column < position.column) {
|
||||
let word = model.getWordAtPosition(pos);
|
||||
if (word) {
|
||||
// at a word
|
||||
lineOffsets.push(word.startColumn - 1);
|
||||
pos.column = word.endColumn + 1;
|
||||
if (word.endColumn - 1 < linePrefixLow.length && !/\s/.test(linePrefixLow[word.endColumn - 1])) {
|
||||
lineOffsets.push(word.endColumn - 1);
|
||||
}
|
||||
}
|
||||
else if (!/\s/.test(linePrefixLow[pos.column - 1])) {
|
||||
// at a none-whitespace character
|
||||
lineOffsets.push(pos.column - 1);
|
||||
pos.column += 1;
|
||||
}
|
||||
else {
|
||||
// always advance!
|
||||
pos.column += 1;
|
||||
while (pos.column < position.column) {
|
||||
let word = model.getWordAtPosition(pos);
|
||||
if (word) {
|
||||
// at a word
|
||||
lineOffsets.push(word.startColumn - 1);
|
||||
pos.column = word.endColumn + 1;
|
||||
if (word.endColumn < position.column && !/\s/.test(lineContent[word.endColumn - 1])) {
|
||||
lineOffsets.push(word.endColumn - 1);
|
||||
}
|
||||
}
|
||||
|
||||
const lineSuffixLow = lineContent.substr(position.column - 1).toLowerCase();
|
||||
let availableSnippets = new Set<Snippet>();
|
||||
snippets.forEach(availableSnippets.add, availableSnippets);
|
||||
suggestions = [];
|
||||
for (let start of lineOffsets) {
|
||||
availableSnippets.forEach(snippet => {
|
||||
if (isPatternInWord(linePrefixLow, start, linePrefixLow.length, snippet.prefixLow, 0, snippet.prefixLow.length)) {
|
||||
const snippetPrefixSubstr = snippet.prefixLow.substr(linePrefixLow.length - start);
|
||||
const endColumn = startsWith(lineSuffixLow, snippetPrefixSubstr) ? position.column + snippetPrefixSubstr.length : position.column;
|
||||
const replace = Range.fromPositions(position.delta(0, -(linePrefixLow.length - start)), { lineNumber: position.lineNumber, column: endColumn });
|
||||
const insert = replace.setEndPosition(position.lineNumber, position.column);
|
||||
|
||||
suggestions.push(new SnippetCompletion(snippet, { replace, insert }));
|
||||
availableSnippets.delete(snippet);
|
||||
}
|
||||
});
|
||||
else if (!/\s/.test(lineContent[pos.column - 1])) {
|
||||
// at a none-whitespace character
|
||||
lineOffsets.push(pos.column - 1);
|
||||
pos.column += 1;
|
||||
}
|
||||
if (endsInWhitespace || lineOffsets.length === 0) {
|
||||
// add remaing snippets when the current prefix ends in whitespace or when no
|
||||
// interesting positions have been found
|
||||
availableSnippets.forEach(snippet => {
|
||||
let insert = Range.fromPositions(position);
|
||||
let replace = startsWith(lineSuffixLow, snippet.prefixLow) ? insert.setEndPosition(position.lineNumber, position.column + snippet.prefixLow.length) : insert;
|
||||
else {
|
||||
// always advance!
|
||||
pos.column += 1;
|
||||
}
|
||||
}
|
||||
|
||||
const availableSnippets = new Set<Snippet>(snippets);
|
||||
const suggestions: SnippetCompletion[] = [];
|
||||
|
||||
for (let start of lineOffsets) {
|
||||
availableSnippets.forEach(snippet => {
|
||||
if (isPatternInWord(lineContent, start, position.column - 1, snippet.prefixLow, 0, snippet.prefixLow.length)) {
|
||||
const snippetPrefixSubstr = snippet.prefixLow.substr(position.column - (1 + start));
|
||||
const endColumn = lineContent.indexOf(snippetPrefixSubstr, position.column - 1) >= 0 ? position.column + snippetPrefixSubstr.length : position.column;
|
||||
const replace = Range.fromPositions(position.delta(0, -(position.column - (1 + start))), { lineNumber: position.lineNumber, column: endColumn });
|
||||
const insert = replace.setEndPosition(position.lineNumber, position.column);
|
||||
|
||||
suggestions.push(new SnippetCompletion(snippet, { replace, insert }));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// dismbiguate suggestions with same labels
|
||||
suggestions.sort(SnippetCompletion.compareByLabel);
|
||||
for (let i = 0; i < suggestions.length; i++) {
|
||||
let item = suggestions[i];
|
||||
let to = i + 1;
|
||||
for (; to < suggestions.length && item.label === suggestions[to].label; to++) {
|
||||
suggestions[to].label.name = localize('snippetSuggest.longLabel', "{0}, {1}", suggestions[to].label.name, suggestions[to].snippet.name);
|
||||
availableSnippets.delete(snippet);
|
||||
}
|
||||
if (to > i + 1) {
|
||||
suggestions[i].label.name = localize('snippetSuggest.longLabel', "{0}, {1}", suggestions[i].label.name, suggestions[i].snippet.name);
|
||||
i = to;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (endsInWhitespace || lineOffsets.length === 0) {
|
||||
// add remaing snippets when the current prefix ends in whitespace or when no
|
||||
// interesting positions have been found
|
||||
availableSnippets.forEach(snippet => {
|
||||
const insert = Range.fromPositions(position);
|
||||
const replace = lineContent.indexOf(snippet.prefixLow, position.column - 1) >= 0 ? insert.setEndPosition(position.lineNumber, position.column + snippet.prefixLow.length) : insert;
|
||||
suggestions.push(new SnippetCompletion(snippet, { replace, insert }));
|
||||
});
|
||||
}
|
||||
|
||||
return { suggestions };
|
||||
});
|
||||
|
||||
// dismbiguate suggestions with same labels
|
||||
suggestions.sort(SnippetCompletion.compareByLabel);
|
||||
for (let i = 0; i < suggestions.length; i++) {
|
||||
let item = suggestions[i];
|
||||
let to = i + 1;
|
||||
for (; to < suggestions.length && item.label === suggestions[to].label; to++) {
|
||||
suggestions[to].label.name = localize('snippetSuggest.longLabel', "{0}, {1}", suggestions[to].label.name, suggestions[to].snippet.name);
|
||||
}
|
||||
if (to > i + 1) {
|
||||
suggestions[i].label.name = localize('snippetSuggest.longLabel', "{0}, {1}", suggestions[i].label.name, suggestions[i].snippet.name);
|
||||
i = to;
|
||||
}
|
||||
}
|
||||
|
||||
return { suggestions };
|
||||
}
|
||||
|
||||
resolveCompletionItem(_model: ITextModel, _position: Position, item: CompletionItem): CompletionItem {
|
||||
|
||||
@@ -17,7 +17,7 @@ export interface ISnippetsService {
|
||||
|
||||
_serviceBrand: undefined;
|
||||
|
||||
getSnippetFiles(): Promise<SnippetFile[]>;
|
||||
getSnippetFiles(): Promise<Iterable<SnippetFile>>;
|
||||
|
||||
getSnippets(languageId: LanguageId): Promise<Snippet[]>;
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
import { combinedDisposable, IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { values } from 'vs/base/common/map';
|
||||
import * as resources from 'vs/base/common/resources';
|
||||
import { endsWith, isFalsyOrWhitespace } from 'vs/base/common/strings';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -162,8 +161,9 @@ class SnippetsService implements ISnippetsService {
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
getSnippetFiles(): Promise<SnippetFile[]> {
|
||||
return this._joinSnippets().then(() => values(this._files));
|
||||
async getSnippetFiles(): Promise<Iterable<SnippetFile>> {
|
||||
await this._joinSnippets();
|
||||
return this._files.values();
|
||||
}
|
||||
|
||||
getSnippets(languageId: LanguageId): Promise<Snippet[]> {
|
||||
|
||||
Reference in New Issue
Block a user