Skip to content

Commit

Permalink
Lazy load emmet helper to ease startup #35120
Browse files Browse the repository at this point in the history
  • Loading branch information
ramya-rao-a committed Oct 31, 2017
1 parent 0c112c7 commit 81cca6c
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 38 deletions.
23 changes: 13 additions & 10 deletions extensions/emmet/src/abbreviationActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@

import * as vscode from 'vscode';
import { Node, HtmlNode, Rule } from 'EmmetNode';
import { getNode, getInnerRange, getMappingForIncludedLanguages, parseDocument, validate, getEmmetConfiguration } from './util';
import { getExpandOptions, extractAbbreviation, extractAbbreviationFromText, isStyleSheet, isAbbreviationValid, getEmmetMode, expandAbbreviation } from 'vscode-emmet-helper';
import { getEmmetHelper, getNode, getInnerRange, getMappingForIncludedLanguages, parseDocument, validate, getEmmetConfiguration, isStyleSheet, getEmmetMode } from './util';

const trimRegex = /[\u00a0]*[\d|#|\-|\*|\u2022]+\.?/;

Expand All @@ -26,9 +25,10 @@ export function wrapWithAbbreviation(args) {
const editor = vscode.window.activeTextEditor;
const abbreviationPromise = (args && args['abbreviation']) ? Promise.resolve(args['abbreviation']) : vscode.window.showInputBox({ prompt: 'Enter Abbreviation' });
const syntax = getSyntaxFromArgs({ language: editor.document.languageId });
const helper = getEmmetHelper();

return abbreviationPromise.then(abbreviation => {
if (!abbreviation || !abbreviation.trim() || !isAbbreviationValid(syntax, abbreviation)) { return; }
if (!abbreviation || !abbreviation.trim() || !helper.isAbbreviationValid(syntax, abbreviation)) { return; }

let expandAbbrList: ExpandAbbreviationInput[] = [];

Expand Down Expand Up @@ -64,11 +64,12 @@ export function wrapIndividualLinesWithAbbreviation(args) {
const abbreviationPromise = (args && args['abbreviation']) ? Promise.resolve(args['abbreviation']) : vscode.window.showInputBox({ prompt: 'Enter Abbreviation' });
const syntax = getSyntaxFromArgs({ language: editor.document.languageId });
const lines = editor.document.getText(editor.selection).split('\n').map(x => x.trim());
const helper = getEmmetHelper();

return abbreviationPromise.then(inputAbbreviation => {
if (!inputAbbreviation || !inputAbbreviation.trim() || !isAbbreviationValid(syntax, inputAbbreviation)) { return; }
if (!inputAbbreviation || !inputAbbreviation.trim() || !helper.isAbbreviationValid(syntax, inputAbbreviation)) { return; }

let extractedResults = extractAbbreviationFromText(inputAbbreviation);
let extractedResults = helper.extractAbbreviationFromText(inputAbbreviation);
if (!extractedResults) {
return;
}
Expand Down Expand Up @@ -105,12 +106,13 @@ export function expandEmmetAbbreviation(args): Thenable<boolean> {
let abbreviationList: ExpandAbbreviationInput[] = [];
let firstAbbreviation: string;
let allAbbreviationsSame: boolean = true;
const helper = getEmmetHelper();

let getAbbreviation = (document: vscode.TextDocument, selection: vscode.Selection, position: vscode.Position, syntax: string): [vscode.Range, string, string] => {
let rangeToReplace: vscode.Range = selection;
let abbr = document.getText(rangeToReplace);
if (!rangeToReplace.isEmpty) {
let extractedResults = extractAbbreviationFromText(abbr);
let extractedResults = helper.extractAbbreviationFromText(abbr);
if (extractedResults) {
return [rangeToReplace, extractedResults.abbreviation, extractedResults.filter];
}
Expand All @@ -130,7 +132,7 @@ export function expandEmmetAbbreviation(args): Thenable<boolean> {
return [rangeToReplace, abbr, ''];
}
}
let extractedResults = extractAbbreviation(editor.document, position, false);
let extractedResults = helper.extractAbbreviation(editor.document, position, false);
if (!extractedResults) {
return [null, '', ''];
}
Expand All @@ -152,7 +154,7 @@ export function expandEmmetAbbreviation(args): Thenable<boolean> {
if (!rangeToReplace) {
return;
}
if (!isAbbreviationValid(syntax, abbreviation)) {
if (!helper.isAbbreviationValid(syntax, abbreviation)) {
return;
}

Expand Down Expand Up @@ -277,7 +279,8 @@ function expandAbbreviationInRange(editor: vscode.TextEditor, expandAbbrList: Ex
* Expands abbreviation as detailed in given input.
*/
function expandAbbr(input: ExpandAbbreviationInput): string {
const expandOptions = getExpandOptions(input.syntax, getEmmetConfiguration(input.syntax), input.filter);
const helper = getEmmetHelper();
const expandOptions = helper.getExpandOptions(input.syntax, getEmmetConfiguration(input.syntax), input.filter);

if (input.textToWrap) {
if (input.filter && input.filter.indexOf('t') > -1) {
Expand All @@ -297,7 +300,7 @@ function expandAbbr(input: ExpandAbbreviationInput): string {

try {
// Expand the abbreviation
let expandedText = expandAbbreviation(input.abbreviation, expandOptions);
let expandedText = helper.expandAbbreviation(input.abbreviation, expandOptions);

if (input.textToWrap) {
// All $anyword would have been escaped by the emmet helper.
Expand Down
8 changes: 4 additions & 4 deletions extensions/emmet/src/defaultCompletionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@

import * as vscode from 'vscode';
import { HtmlNode } from 'EmmetNode';
import { doComplete, isStyleSheet, getEmmetMode, extractAbbreviation } from 'vscode-emmet-helper';
import { isValidLocationForEmmetAbbreviation } from './abbreviationActions';
import { getNode, getInnerRange, getMappingForIncludedLanguages, parseDocument, getEmmetConfiguration } from './util';
import { getEmmetHelper, getNode, getInnerRange, getMappingForIncludedLanguages, parseDocument, getEmmetConfiguration, getEmmetMode, isStyleSheet } from './util';

const allowedMimeTypesInScriptTag = ['text/html', 'text/plain', 'text/x-template', 'text/template'];

Expand All @@ -33,13 +32,14 @@ export class DefaultCompletionItemProvider implements vscode.CompletionItemProvi
return;
}

const helper = getEmmetHelper();
let noiseCheckPromise: Thenable<any> = Promise.resolve();

// Fix for https://github.com/Microsoft/vscode/issues/32647
// Check for document symbols in js/ts/jsx/tsx and avoid triggering emmet for abbreviations of the form symbolName.sometext
// Presence of > or * or + in the abbreviation denotes valid abbreviation that should trigger emmet
if (!isStyleSheet(syntax) && (document.languageId === 'javascript' || document.languageId === 'javascriptreact' || document.languageId === 'typescript' || document.languageId === 'typescriptreact')) {
let extractAbbreviationResults = extractAbbreviation(document, position);
let extractAbbreviationResults = helper.extractAbbreviation(document, position);
if (extractAbbreviationResults) {
let abbreviation: string = extractAbbreviationResults.abbreviation;
if (abbreviation.startsWith('this.')) {
Expand All @@ -57,7 +57,7 @@ export class DefaultCompletionItemProvider implements vscode.CompletionItemProvi
return;
}

let result = doComplete(document, position, syntax, getEmmetConfiguration(syntax));
let result = helper.doComplete(document, position, syntax, getEmmetConfiguration(syntax));
let newItems: vscode.CompletionItem[] = [];
if (result && result.items) {
result.items.forEach(item => {
Expand Down
17 changes: 1 addition & 16 deletions extensions/emmet/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,10 @@ import { fetchEditPoint } from './editPoint';
import { fetchSelectItem } from './selectItem';
import { evaluateMathExpression } from './evaluateMathExpression';
import { incrementDecrement } from './incrementDecrement';
import { LANGUAGE_MODES, getMappingForIncludedLanguages } from './util';
import { updateExtensionsPath } from 'vscode-emmet-helper';
import { LANGUAGE_MODES, getMappingForIncludedLanguages, resolveUpdateExtensionsPath } from './util';
import { updateImageSize } from './updateImageSize';
import { reflectCssValue } from './reflectCssValue';

import * as path from 'path';

export function activate(context: vscode.ExtensionContext) {
registerCompletionProviders(context);

Expand Down Expand Up @@ -128,18 +125,6 @@ export function activate(context: vscode.ExtensionContext) {
return reflectCssValue();
}));

let currentExtensionsPath = undefined;
let resolveUpdateExtensionsPath = () => {
let extensionsPath = vscode.workspace.getConfiguration('emmet')['extensionsPath'];
if (extensionsPath && !path.isAbsolute(extensionsPath)) {
extensionsPath = path.join(vscode.workspace.rootPath, extensionsPath);
}
if (currentExtensionsPath !== extensionsPath) {
currentExtensionsPath = extensionsPath;
updateExtensionsPath(currentExtensionsPath).then(null, err => vscode.window.showErrorMessage(err));
}
};

resolveUpdateExtensionsPath();

context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(() => {
Expand Down
4 changes: 1 addition & 3 deletions extensions/emmet/src/selectItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import { validate, parseDocument } from './util';
import { validate, parseDocument, isStyleSheet } from './util';
import { nextItemHTML, prevItemHTML } from './selectItemHTML';
import { nextItemStylesheet, prevItemStylesheet } from './selectItemStylesheet';
import { isStyleSheet } from 'vscode-emmet-helper';


export function fetchSelectItem(direction: string): void {
let editor = vscode.window.activeTextEditor;
Expand Down
3 changes: 1 addition & 2 deletions extensions/emmet/src/toggleComment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import { getNodesInBetween, getNode, parseDocument, sameNodes } from './util';
import { getNodesInBetween, getNode, parseDocument, sameNodes, isStyleSheet } from './util';
import { Node, Stylesheet, Rule, HtmlNode } from 'EmmetNode';
import { isStyleSheet } from 'vscode-emmet-helper';
import parseStylesheet from '@emmetio/css-parser';
import { DocumentStreamReader } from './bufferStream';

Expand Down
3 changes: 1 addition & 2 deletions extensions/emmet/src/updateImageSize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
import { TextEditor, Range, Position, window, TextEdit } from 'vscode';
import * as path from 'path';
import { getImageSize } from './imageSizeHelper';
import { isStyleSheet } from 'vscode-emmet-helper';
import { parseDocument, getNode, iterateCSSToken, getCssPropertyFromRule } from './util';
import { parseDocument, getNode, iterateCSSToken, getCssPropertyFromRule, isStyleSheet } from './util';
import { HtmlNode, CssToken, HtmlToken, Attribute, Property } from 'EmmetNode';
import { locateFile } from './locateFile';
import parseStylesheet from '@emmetio/css-parser';
Expand Down
61 changes: 60 additions & 1 deletion extensions/emmet/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,32 @@ import parse from '@emmetio/html-matcher';
import parseStylesheet from '@emmetio/css-parser';
import { Node, HtmlNode, CssToken, Property } from 'EmmetNode';
import { DocumentStreamReader } from './bufferStream';
import { isStyleSheet } from 'vscode-emmet-helper';
import * as path from 'path';

let _emmetHelper;
let _currentExtensionsPath = undefined;

export function getEmmetHelper() {
if (!_emmetHelper) {
_emmetHelper = require('vscode-emmet-helper');
}
resolveUpdateExtensionsPath();
return _emmetHelper;
}

export function resolveUpdateExtensionsPath() {
if (!_emmetHelper) {
return;
}
let extensionsPath = vscode.workspace.getConfiguration('emmet')['extensionsPath'];
if (extensionsPath && !path.isAbsolute(extensionsPath)) {
extensionsPath = path.join(vscode.workspace.rootPath, extensionsPath);
}
if (_currentExtensionsPath !== extensionsPath) {
_currentExtensionsPath = extensionsPath;
_emmetHelper.updateExtensionsPath(_currentExtensionsPath).then(null, err => vscode.window.showErrorMessage(err));
}
}

export const LANGUAGE_MODES: Object = {
'html': ['!', '.', '}', ':', '*', '$', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
Expand All @@ -26,6 +51,8 @@ export const LANGUAGE_MODES: Object = {
'typescriptreact': ['.', '}', '*', '$', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
};

const emmetModes = ['html', 'pug', 'slim', 'haml', 'xml', 'xsl', 'jsx', 'css', 'scss', 'sass', 'less', 'stylus'];

// Explicitly map languages that have built-in grammar in VS Code to their parent language
// to get emmet completion support
// For other languages, users will have to use `emmet.includeLanguages` or
Expand All @@ -35,6 +62,11 @@ export const MAPPED_MODES: Object = {
'php': 'html'
};

export function isStyleSheet(syntax): boolean {
let stylesheetSyntaxes = ['css', 'scss', 'sass', 'less', 'stylus'];
return (stylesheetSyntaxes.indexOf(syntax) > -1);
}

export function validate(allowStylesheet: boolean = true): boolean {
let editor = vscode.window.activeTextEditor;
if (!editor) {
Expand All @@ -59,6 +91,33 @@ export function getMappingForIncludedLanguages(): any {
return finalMappedModes;
}

/**
* Get the corresponding emmet mode for given vscode language mode
* Eg: jsx for typescriptreact/javascriptreact or pug for jade
* If the language is not supported by emmet or has been exlcuded via `exlcudeLanguages` setting,
* then nothing is returned
*
* @param language
* @param exlcudedLanguages Array of language ids that user has chosen to exlcude for emmet
*/
export function getEmmetMode(language: string, excludedLanguages: string[]): string {
if (!language || excludedLanguages.indexOf(language) > -1) {
return;
}
if (/\b(typescriptreact|javascriptreact|jsx-tags)\b/.test(language)) { // treat tsx like jsx
return 'jsx';
}
if (language === 'sass-indented') { // map sass-indented to sass
return 'sass';
}
if (language === 'jade') {
return 'pug';
}
if (emmetModes.indexOf(language) > -1) {
return language;
}
}

/**
* Parses the given document using emmet parsing modules
* @param document
Expand Down

0 comments on commit 81cca6c

Please sign in to comment.