diff --git a/extensions/emmet/src/abbreviationActions.ts b/extensions/emmet/src/abbreviationActions.ts index 5d341c2c636..eaec9939c2e 100644 --- a/extensions/emmet/src/abbreviationActions.ts +++ b/extensions/emmet/src/abbreviationActions.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import { Node, HtmlNode, Rule } from 'EmmetNode'; +import { Node, HtmlNode, Rule, Property } from 'EmmetNode'; import { getNode, getInnerRange, getMappingForIncludedLanguages, parseDocument, validate, getEmmetConfiguration } from './util'; import { getExpandOptions, extractAbbreviation, extractAbbreviationFromText, isStyleSheet, isAbbreviationValid, getEmmetMode, expandAbbreviation } from 'vscode-emmet-helper'; @@ -149,8 +149,8 @@ export function expandEmmetAbbreviation(args): Thenable { return; } - let currentNode = getNode(rootNode, position); - if (!isValidLocationForEmmetAbbreviation(currentNode, syntax, position)) { + let currentNode = getNode(rootNode, position, true); + if (!isValidLocationForEmmetAbbreviation(currentNode, syntax, position, abbreviation)) { return; } @@ -182,7 +182,7 @@ function fallbackTab(): Thenable { * @param syntax syntax of the abbreviation * @param position position to validate */ -export function isValidLocationForEmmetAbbreviation(currentNode: Node, syntax: string, position: vscode.Position): boolean { +export function isValidLocationForEmmetAbbreviation(currentNode: Node, syntax: string, position: vscode.Position, abbreviation: string): boolean { // Continue validation only if the file was parse-able and the currentNode has been found if (!currentNode) { return true; @@ -190,6 +190,14 @@ export function isValidLocationForEmmetAbbreviation(currentNode: Node, syntax: s if (isStyleSheet(syntax)) { + // CSS Emmet snippets are for property-value or in case of colors, just value + if (currentNode.type === 'property' && (currentNode).value) { + if (position.isBefore((currentNode).valueToken.start)) { + return false; + } + return /^#\d+$/.test(abbreviation); + } + // If current node is a rule or at-rule, then perform additional checks to ensure // emmet suggestions are not provided in the rule selector if (currentNode.type !== 'rule' && currentNode.type !== 'at-rule') { diff --git a/extensions/emmet/src/defaultCompletionProvider.ts b/extensions/emmet/src/defaultCompletionProvider.ts index f01fb6db568..36b07ea06aa 100644 --- a/extensions/emmet/src/defaultCompletionProvider.ts +++ b/extensions/emmet/src/defaultCompletionProvider.ts @@ -95,7 +95,7 @@ export class DefaultCompletionItemProvider implements vscode.CompletionItemProvi return; } - let currentNode = getNode(rootNode, position); + let currentNode = getNode(rootNode, position, true); if (!isStyleSheet(syntax)) { const currentHtmlNode = currentNode; @@ -111,7 +111,7 @@ export class DefaultCompletionItemProvider implements vscode.CompletionItemProvi } } - if (!isValidLocationForEmmetAbbreviation(currentNode, syntax, position)) { + if (!isValidLocationForEmmetAbbreviation(currentNode, syntax, position, document.getText(document.getWordRangeAtPosition(position)))) { return; } return syntax; diff --git a/extensions/emmet/src/test/abbreviationAction.test.ts b/extensions/emmet/src/test/abbreviationAction.test.ts index 4dd97f7a7e1..d35fc4a394b 100644 --- a/extensions/emmet/src/test/abbreviationAction.test.ts +++ b/extensions/emmet/src/test/abbreviationAction.test.ts @@ -211,6 +211,29 @@ suite('Tests for Expand Abbreviations (CSS)', () => { }); }); }); + + test('Invalid locations for abbreviations in css', () => { + const scssContentsNoExpand = ` +m10 + .boo { + margin: 10px; + .hoo { + background: + } + } + ` + + return withRandomFileEditor(scssContentsNoExpand, 'scss', (editor, doc) => { + editor.selections = [ + new Selection(1, 3, 1, 3), // outside rule + new Selection(5, 15, 5, 15) // in the value part of property value + ]; + return expandEmmetAbbreviation(null).then(() => { + assert.equal(editor.document.getText(), scssContentsNoExpand); + return Promise.resolve(); + }); + }); + }); }); suite('Tests for Wrap with Abbreviations', () => {