eae5d8c807
These conflicts will be resolved in the following commits. We do it this way so that PR review is possible.
262 lines
8.3 KiB
TypeScript
262 lines
8.3 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import 'mocha';
|
|
import * as assert from 'assert';
|
|
import { withRandomFileEditor } from './testUtils';
|
|
import * as vscode from 'vscode';
|
|
import { parsePartialStylesheet, getFlatNode } from '../util';
|
|
import { isValidLocationForEmmetAbbreviation } from '../abbreviationActions';
|
|
|
|
suite('Tests for partial parse of Stylesheets', () => {
|
|
|
|
function isValid(doc: vscode.TextDocument, range: vscode.Range, syntax: string): boolean {
|
|
const rootNode = parsePartialStylesheet(doc, range.end);
|
|
const endOffset = doc.offsetAt(range.end);
|
|
const currentNode = getFlatNode(rootNode, endOffset, true);
|
|
return isValidLocationForEmmetAbbreviation(doc, rootNode, currentNode, syntax, endOffset, range);
|
|
}
|
|
|
|
test('Ignore block comment inside rule', function (): any {
|
|
const cssContents = `
|
|
p {
|
|
margin: p ;
|
|
/*dn: none; p */ p
|
|
p
|
|
p.
|
|
} p
|
|
`;
|
|
return withRandomFileEditor(cssContents, '.css', (_, doc) => {
|
|
let rangesForEmmet = [
|
|
new vscode.Range(3, 18, 3, 19), // Same line after block comment
|
|
new vscode.Range(4, 1, 4, 2), // p after block comment
|
|
new vscode.Range(5, 1, 5, 3) // p. after block comment
|
|
];
|
|
let rangesNotEmmet = [
|
|
new vscode.Range(1, 0, 1, 1), // Selector
|
|
new vscode.Range(2, 9, 2, 10), // Property value
|
|
new vscode.Range(3, 3, 3, 5), // dn inside block comment
|
|
new vscode.Range(3, 13, 3, 14), // p just before ending of block comment
|
|
new vscode.Range(6, 2, 6, 3) // p after ending of block
|
|
|
|
];
|
|
rangesForEmmet.forEach(range => {
|
|
assert.equal(isValid(doc, range, 'css'), true);
|
|
});
|
|
rangesNotEmmet.forEach(range => {
|
|
assert.equal(isValid(doc, range, 'css'), false);
|
|
});
|
|
|
|
return Promise.resolve();
|
|
});
|
|
});
|
|
|
|
test('Ignore commented braces', function (): any {
|
|
const sassContents = `
|
|
.foo
|
|
// .foo { brs
|
|
/* .foo { op.3
|
|
dn {
|
|
*/
|
|
@
|
|
} bg
|
|
`;
|
|
return withRandomFileEditor(sassContents, '.scss', (_, doc) => {
|
|
let rangesNotEmmet = [
|
|
new vscode.Range(1, 0, 1, 4), // Selector
|
|
new vscode.Range(2, 3, 2, 7), // Line commented selector
|
|
new vscode.Range(3, 3, 3, 7), // Block commented selector
|
|
new vscode.Range(4, 0, 4, 2), // dn inside block comment
|
|
new vscode.Range(6, 1, 6, 2), // @ inside a rule whose opening brace is commented
|
|
new vscode.Range(7, 2, 7, 4) // bg after ending of badly constructed block
|
|
];
|
|
rangesNotEmmet.forEach(range => {
|
|
assert.equal(isValid(doc, range, 'scss'), false);
|
|
});
|
|
return Promise.resolve();
|
|
});
|
|
});
|
|
|
|
test('Block comment between selector and open brace', function (): any {
|
|
const cssContents = `
|
|
p
|
|
/* First line
|
|
of a multiline
|
|
comment */
|
|
{
|
|
margin: p ;
|
|
/*dn: none; p */ p
|
|
p
|
|
p.
|
|
} p
|
|
`;
|
|
return withRandomFileEditor(cssContents, '.css', (_, doc) => {
|
|
let rangesForEmmet = [
|
|
new vscode.Range(7, 18, 7, 19), // Same line after block comment
|
|
new vscode.Range(8, 1, 8, 2), // p after block comment
|
|
new vscode.Range(9, 1, 9, 3) // p. after block comment
|
|
];
|
|
let rangesNotEmmet = [
|
|
new vscode.Range(1, 2, 1, 3), // Selector
|
|
new vscode.Range(3, 3, 3, 4), // Inside multiline comment
|
|
new vscode.Range(5, 0, 5, 1), // Opening Brace
|
|
new vscode.Range(6, 9, 6, 10), // Property value
|
|
new vscode.Range(7, 3, 7, 5), // dn inside block comment
|
|
new vscode.Range(7, 13, 7, 14), // p just before ending of block comment
|
|
new vscode.Range(10, 2, 10, 3) // p after ending of block
|
|
];
|
|
rangesForEmmet.forEach(range => {
|
|
assert.equal(isValid(doc, range, 'css'), true);
|
|
});
|
|
rangesNotEmmet.forEach(range => {
|
|
assert.equal(isValid(doc, range, 'css'), false);
|
|
});
|
|
return Promise.resolve();
|
|
});
|
|
});
|
|
|
|
test('Nested and consecutive rulesets with errors', function (): any {
|
|
const sassContents = `
|
|
.foo{
|
|
a
|
|
a
|
|
}}{ p
|
|
}
|
|
.bar{
|
|
@
|
|
.rudi {
|
|
@
|
|
}
|
|
}}}
|
|
`;
|
|
return withRandomFileEditor(sassContents, '.scss', (_, doc) => {
|
|
let rangesForEmmet = [
|
|
new vscode.Range(2, 1, 2, 2), // Inside a ruleset before errors
|
|
new vscode.Range(3, 1, 3, 2), // Inside a ruleset after no serious error
|
|
new vscode.Range(7, 1, 7, 2), // @ inside a so far well structured ruleset
|
|
new vscode.Range(9, 2, 9, 3), // @ inside a so far well structured nested ruleset
|
|
];
|
|
let rangesNotEmmet = [
|
|
new vscode.Range(4, 4, 4, 5), // p inside ruleset without proper selector
|
|
new vscode.Range(6, 3, 6, 4) // In selector
|
|
];
|
|
rangesForEmmet.forEach(range => {
|
|
assert.equal(isValid(doc, range, 'scss'), true);
|
|
});
|
|
rangesNotEmmet.forEach(range => {
|
|
assert.equal(isValid(doc, range, 'scss'), false);
|
|
});
|
|
return Promise.resolve();
|
|
});
|
|
});
|
|
|
|
test('One liner sass', function (): any {
|
|
const sassContents = `
|
|
.foo{dn}.bar{.boo{dn}dn}.comd{/*{dn*/p{div{dn}} }.foo{.other{dn}} dn
|
|
`;
|
|
return withRandomFileEditor(sassContents, '.scss', (_, doc) => {
|
|
let rangesForEmmet = [
|
|
new vscode.Range(1, 5, 1, 7), // Inside a ruleset
|
|
new vscode.Range(1, 18, 1, 20), // Inside a nested ruleset
|
|
new vscode.Range(1, 21, 1, 23), // Inside ruleset after nested one.
|
|
new vscode.Range(1, 43, 1, 45), // Inside nested ruleset after comment
|
|
new vscode.Range(1, 61, 1, 63) // Inside nested ruleset
|
|
];
|
|
let rangesNotEmmet = [
|
|
new vscode.Range(1, 3, 1, 4), // In foo selector
|
|
new vscode.Range(1, 10, 1, 11), // In bar selector
|
|
new vscode.Range(1, 15, 1, 16), // In boo selector
|
|
new vscode.Range(1, 28, 1, 29), // In comd selector
|
|
new vscode.Range(1, 33, 1, 34), // In commented dn
|
|
new vscode.Range(1, 37, 1, 38), // In p selector
|
|
new vscode.Range(1, 39, 1, 42), // In div selector
|
|
new vscode.Range(1, 66, 1, 68) // Outside any ruleset
|
|
];
|
|
rangesForEmmet.forEach(range => {
|
|
assert.equal(isValid(doc, range, 'scss'), true);
|
|
});
|
|
rangesNotEmmet.forEach(range => {
|
|
assert.equal(isValid(doc, range, 'scss'), false);
|
|
});
|
|
return Promise.resolve();
|
|
});
|
|
});
|
|
|
|
test('Variables and interpolation', function (): any {
|
|
const sassContents = `
|
|
p.#{dn} {
|
|
p.3
|
|
#{$attr}-color: blue;
|
|
dn
|
|
} op
|
|
.foo{nes{ted}} {
|
|
dn
|
|
}
|
|
`;
|
|
return withRandomFileEditor(sassContents, '.scss', (_, doc) => {
|
|
let rangesForEmmet = [
|
|
new vscode.Range(2, 1, 2, 4), // p.3 inside a ruleset whose selector uses interpolation
|
|
new vscode.Range(4, 1, 4, 3) // dn inside ruleset after property with variable
|
|
];
|
|
let rangesNotEmmet = [
|
|
new vscode.Range(1, 0, 1, 1), // In p in selector
|
|
new vscode.Range(1, 2, 1, 3), // In # in selector
|
|
new vscode.Range(1, 4, 1, 6), // In dn inside variable in selector
|
|
new vscode.Range(3, 7, 3, 8), // r of attr inside variable
|
|
new vscode.Range(5, 2, 5, 4), // op after ruleset
|
|
new vscode.Range(7, 1, 7, 3), // dn inside ruleset whose selector uses nested interpolation
|
|
new vscode.Range(3, 1, 3, 2), // # inside ruleset
|
|
];
|
|
rangesForEmmet.forEach(range => {
|
|
assert.equal(isValid(doc, range, 'scss'), true);
|
|
});
|
|
rangesNotEmmet.forEach(range => {
|
|
assert.equal(isValid(doc, range, 'scss'), false);
|
|
});
|
|
return Promise.resolve();
|
|
});
|
|
});
|
|
|
|
test('Comments in sass', function (): any {
|
|
const sassContents = `
|
|
.foo{
|
|
/* p // p */ brs6-2p
|
|
dn
|
|
}
|
|
p
|
|
/* c
|
|
om
|
|
ment */{
|
|
m10
|
|
}
|
|
.boo{
|
|
op.3
|
|
}
|
|
`;
|
|
return withRandomFileEditor(sassContents, '.scss', (_, doc) => {
|
|
let rangesForEmmet = [
|
|
new vscode.Range(2, 14, 2, 21), // brs6-2p with a block commented line comment ('/* */' overrides '//')
|
|
new vscode.Range(3, 1, 3, 3), // dn after a line with combined comments inside a ruleset
|
|
new vscode.Range(9, 1, 9, 4), // m10 inside ruleset whose selector is before a comment
|
|
new vscode.Range(12, 1, 12, 5) // op3 inside a ruleset with commented extra braces
|
|
];
|
|
let rangesNotEmmet = [
|
|
new vscode.Range(2, 4, 2, 5), // In p inside block comment
|
|
new vscode.Range(2, 9, 2, 10), // In p inside block comment and after line comment
|
|
new vscode.Range(6, 3, 6, 4) // In c inside block comment
|
|
];
|
|
rangesForEmmet.forEach(range => {
|
|
assert.equal(isValid(doc, range, 'scss'), true);
|
|
});
|
|
rangesNotEmmet.forEach(range => {
|
|
assert.equal(isValid(doc, range, 'scss'), false);
|
|
});
|
|
return Promise.resolve();
|
|
});
|
|
});
|
|
|
|
|
|
});
|