提交 8f5fc228 编写于 作者: R Ramya Achutha Rao

Refactoring to support #28556 eventually

上级 bd74b632
...@@ -51,7 +51,13 @@ export function expandAbbreviation() { ...@@ -51,7 +51,13 @@ export function expandAbbreviation() {
mappedSyntax = true; mappedSyntax = true;
} }
} }
let output = expandAbbreviationHelper(syntax, editor.document, editor.selection, mappedSyntax); if (!mappedSyntax) {
syntax = syntaxHelper(syntax, editor.document, editor.selection.end);
}
if (!syntax) {
return;
}
let output = expandAbbreviationHelper(syntax, editor.document, editor.selection);
if (output) { if (output) {
editor.insertSnippet(new vscode.SnippetString(output.expandedText), output.abbreviationRange); editor.insertSnippet(new vscode.SnippetString(output.expandedText), output.abbreviationRange);
} }
...@@ -69,21 +75,8 @@ export interface ExpandAbbreviationHelperOutput { ...@@ -69,21 +75,8 @@ export interface ExpandAbbreviationHelperOutput {
* @param syntax string syntax to be used for expanding abbreviations * @param syntax string syntax to be used for expanding abbreviations
* @param document vscode.TextDocument * @param document vscode.TextDocument
* @param abbreviationRange vscode.Range range of the abbreviation that needs to be expanded * @param abbreviationRange vscode.Range range of the abbreviation that needs to be expanded
* @param mappedSyntax Boolean Pass true if given document language was mapped to given syntax to get emmet abbreviation expansions.
* */ * */
export function expandAbbreviationHelper(syntax: string, document: vscode.TextDocument, abbreviationRange: vscode.Range, mappedSyntax: boolean): ExpandAbbreviationHelperOutput { export function expandAbbreviationHelper(syntax: string, document: vscode.TextDocument, abbreviationRange: vscode.Range): ExpandAbbreviationHelperOutput {
if (!mappedSyntax) {
let parseContent = isStyleSheet(syntax) ? parseStylesheet : parse;
let rootNode: Node = parseContent(new DocumentStreamReader(document));
let currentNode = getNode(rootNode, abbreviationRange.end);
if (forceCssSyntax(syntax, currentNode, abbreviationRange.end)) {
syntax = 'css';
} else if (!isValidLocationForEmmetAbbreviation(currentNode, syntax, abbreviationRange.end)) {
return;
}
}
let abbreviation = document.getText(abbreviationRange); let abbreviation = document.getText(abbreviationRange);
if (abbreviationRange.isEmpty) { if (abbreviationRange.isEmpty) {
[abbreviationRange, abbreviation] = extractAbbreviation(document, abbreviationRange.start); [abbreviationRange, abbreviation] = extractAbbreviation(document, abbreviationRange.start);
...@@ -93,6 +86,24 @@ export function expandAbbreviationHelper(syntax: string, document: vscode.TextDo ...@@ -93,6 +86,24 @@ export function expandAbbreviationHelper(syntax: string, document: vscode.TextDo
return { expandedText, abbreviationRange, abbreviation, syntax }; return { expandedText, abbreviationRange, abbreviation, syntax };
} }
/**
* Checks whether given position is valid for emmet abbreviation and returns appropriate syntax
* @param syntax string language mode of current document
* @param document vscode.Textdocument
* @param position vscode.Position position of the abbreviation that needs to be expanded
*/
export function syntaxHelper(syntax: string, document: vscode.TextDocument, position: vscode.Position): string {
let parseContent = isStyleSheet(syntax) ? parseStylesheet : parse;
let rootNode: Node = parseContent(new DocumentStreamReader(document));
let currentNode = getNode(rootNode, position);
if (forceCssSyntax(syntax, currentNode, position)) {
return 'css';
} else if (!isValidLocationForEmmetAbbreviation(currentNode, syntax, position)) {
return;
}
}
/** /**
* Extracts abbreviation from the given position in the given document * Extracts abbreviation from the given position in the given document
*/ */
...@@ -141,7 +152,7 @@ function isValidLocationForEmmetAbbreviation(currentNode: Node, syntax: string, ...@@ -141,7 +152,7 @@ function isValidLocationForEmmetAbbreviation(currentNode: Node, syntax: string,
return false; return false;
} }
function getExpandOptions(syntax: string, textToReplace?: string) { export function getExpandOptions(syntax: string, textToReplace?: string) {
return { return {
field: field, field: field,
syntax: syntax, syntax: syntax,
......
...@@ -7,10 +7,9 @@ ...@@ -7,10 +7,9 @@
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import { expand, createSnippetsRegistry } from '@emmetio/expand-abbreviation'; import { expand, createSnippetsRegistry } from '@emmetio/expand-abbreviation';
import { getSyntax, isStyleSheet } from './util'; import { getSyntax, isStyleSheet } from './util';
import { expandAbbreviationHelper, ExpandAbbreviationHelperOutput } from './abbreviationActions'; import { syntaxHelper, expandAbbreviationHelper, ExpandAbbreviationHelperOutput, getExpandOptions } from './abbreviationActions';
const field = (index, placeholder) => `\${${index}${placeholder ? ':' + placeholder : ''}}`; const snippetKeyCache = new Map<string, string[]>();
const snippetCompletionsCache = new Map<string, vscode.CompletionItem[]>();
export class EmmetCompletionItemProvider implements vscode.CompletionItemProvider { export class EmmetCompletionItemProvider implements vscode.CompletionItemProvider {
private _mappedSyntax = false; private _mappedSyntax = false;
...@@ -21,64 +20,70 @@ export class EmmetCompletionItemProvider implements vscode.CompletionItemProvide ...@@ -21,64 +20,70 @@ export class EmmetCompletionItemProvider implements vscode.CompletionItemProvide
} }
public provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Thenable<vscode.CompletionList> { public provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Thenable<vscode.CompletionList> {
if (!vscode.workspace.getConfiguration('emmet')['useNewEmmet']) { let emmetConfig = vscode.workspace.getConfiguration('emmet');
if (!emmetConfig['useNewEmmet'] || !emmetConfig['showExpandedAbbreviation']) {
return Promise.resolve(null); return Promise.resolve(null);
} }
let syntax = getSyntax(document); let syntax = getSyntax(document);
let expandedAbbr: vscode.CompletionItem; let abbreviationRange = new vscode.Range(position, position);
if (vscode.workspace.getConfiguration('emmet')['showExpandedAbbreviation']) { if (!this._mappedSyntax) {
let output: ExpandAbbreviationHelperOutput = expandAbbreviationHelper(syntax, document, new vscode.Range(position, position), this._mappedSyntax); syntax = syntaxHelper(syntax, document, position);
if (output) { }
expandedAbbr = new vscode.CompletionItem(output.abbreviation);
expandedAbbr.insertText = new vscode.SnippetString(output.expandedText); let output: ExpandAbbreviationHelperOutput = expandAbbreviationHelper(syntax, document, abbreviationRange);
expandedAbbr.documentation = removeTabStops(output.expandedText); if (!output) {
expandedAbbr.range = output.abbreviationRange; return;
expandedAbbr.detail = 'Expand Emmet Abbreviation';
syntax = output.syntax;
}
} }
let expandedAbbr = new vscode.CompletionItem(output.abbreviation);
expandedAbbr.insertText = new vscode.SnippetString(output.expandedText);
expandedAbbr.documentation = removeTabStops(output.expandedText);
expandedAbbr.range = output.abbreviationRange;
expandedAbbr.detail = 'Expand Emmet Abbreviation';
syntax = output.syntax;
let completionItems: vscode.CompletionItem[] = expandedAbbr ? [expandedAbbr] : []; let completionItems: vscode.CompletionItem[] = expandedAbbr ? [expandedAbbr] : [];
if (!isStyleSheet(syntax)) { if (!isStyleSheet(syntax)) {
if (expandedAbbr) {
// In non stylesheet like syntax, this extension returns expanded abbr plus posssible abbr completions
// To differentiate between the 2, the former is given CompletionItemKind.Value so that it gets a different icon
expandedAbbr.kind = vscode.CompletionItemKind.Value;
}
let currentWord = getCurrentWord(document, position); let currentWord = getCurrentWord(document, position);
let abbreviationSuggestions = this.getAbbreviationSuggestions(syntax, currentWord, output.abbreviation, output.abbreviationRange);
let abbreviationSuggestions = this.getAbbreviationSuggestions(syntax, currentWord, (expandedAbbr && currentWord === expandedAbbr.label));
completionItems = completionItems.concat(abbreviationSuggestions); completionItems = completionItems.concat(abbreviationSuggestions);
} }
return Promise.resolve(new vscode.CompletionList(completionItems, true)); return Promise.resolve(new vscode.CompletionList(completionItems, true));
} }
getAbbreviationSuggestions(syntax: string, prefix: string, skipExactMatch: boolean) { getAbbreviationSuggestions(syntax: string, prefix: string, abbreviation: string, abbreviationRange: vscode.Range): vscode.CompletionItem[] {
if (!vscode.workspace.getConfiguration('emmet')['showAbbreviationSuggestions'] || !prefix) { if (!vscode.workspace.getConfiguration('emmet')['showAbbreviationSuggestions'] || !prefix || !abbreviation) {
return []; return [];
} }
if (!snippetCompletionsCache.has(syntax)) { if (!snippetKeyCache.has(syntax)) {
let registry = createSnippetsRegistry(syntax); let registry = createSnippetsRegistry(syntax);
let completions: vscode.CompletionItem[] = registry.all({ type: 'string' }).map(snippet => { let snippetKeys: string[] = registry.all({ type: 'string' }).map(snippet => {
let expandedWord = expand(snippet.value, { return snippet.key;
field: field,
syntax: syntax
});
let item = new vscode.CompletionItem(snippet.key);
item.documentation = removeTabStops(expandedWord);
item.detail = 'Complete Emmet Abbreviation';
item.insertText = snippet.key;
return item;
}); });
snippetCompletionsCache.set(syntax, completions); snippetKeyCache.set(syntax, snippetKeys);
} }
let snippetCompletions = snippetCompletionsCache.get(syntax); let skipExactMatch = prefix === abbreviation;
let snippetKeys = snippetKeyCache.get(syntax);
let snippetCompletions = [];
snippetKeys.forEach(snippetKey => {
if (!snippetKey.startsWith(prefix) || (snippetKey === prefix) || (skipExactMatch && snippetKey === prefix)) {
return;
}
let currentAbbr = snippetKey; // For #28556: abbreviation + snippetKey.substr(prefix.length);
let expandedAbbr = expand(currentAbbr, getExpandOptions(syntax));
let item = new vscode.CompletionItem(snippetKey);
item.documentation = removeTabStops(expandedAbbr);
item.detail = 'Complete Emmet Abbreviation';
item.insertText = snippetKey; // For #28556: new vscode.SnippetString(expandedAbbr);
snippetCompletions = snippetCompletions.filter(x => x.label.startsWith(prefix) && (!skipExactMatch || x.label !== prefix)); snippetCompletions.push(item);
});
return snippetCompletions; return snippetCompletions;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册