Revert "refactor(core): ensure CSS parser uses ParseSourceSpan to track ast locations"

This reverts commit 5c9f871b21.
This commit is contained in:
Tobias Bosch
2016-07-01 21:21:56 -07:00
parent 5c9f871b21
commit 74b45dfbf8
5 changed files with 362 additions and 594 deletions

View File

@ -7,12 +7,11 @@
*/
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '../../core/testing/testing_internal';
import {CssBlockAst, CssBlockDefinitionRuleAst, CssBlockRuleAst, CssDefinitionAst, CssInlineRuleAst, CssKeyframeDefinitionAst, CssKeyframeRuleAst, CssMediaQueryRuleAst, CssRuleAst, CssSelectorAst, CssSelectorRuleAst, CssStyleSheetAst, CssStyleValueAst} from '../src/css_ast';
import {BlockType, CssParseError, CssParser, CssToken, ParsedCssResult} from '../src/css_parser';
import {CssLexer} from '../src/css_lexer';
import {BlockType, CssBlockAst, CssBlockDefinitionRuleAst, CssBlockRuleAst, CssDefinitionAst, CssInlineRuleAst, CssKeyframeDefinitionAst, CssKeyframeRuleAst, CssMediaQueryRuleAst, CssParseError, CssParser, CssRuleAst, CssSelectorAst, CssSelectorRuleAst, CssStyleSheetAst, CssStyleValueAst, ParsedCssResult} from '../src/css_parser';
import {BaseException} from '../src/facade/exceptions';
import {ParseLocation} from '../src/parse_util';
export function assertTokens(tokens: CssToken[], valuesArr: string[]) {
export function assertTokens(tokens: any /** TODO #9100 */, valuesArr: any /** TODO #9100 */) {
for (var i = 0; i < tokens.length; i++) {
expect(tokens[i].strValue == valuesArr[i]);
}
@ -20,11 +19,14 @@ export function assertTokens(tokens: CssToken[], valuesArr: string[]) {
export function main() {
describe('CssParser', () => {
function parse(css: string): ParsedCssResult {
return new CssParser().parse(css, 'some-fake-css-file.css');
function parse(css: any /** TODO #9100 */): ParsedCssResult {
var lexer = new CssLexer();
var scanner = lexer.scan(css);
var parser = new CssParser(scanner, 'some-fake-file-name.css');
return parser.parse();
}
function makeAst(css: string): CssStyleSheetAst {
function makeAst(css: any /** TODO #9100 */): CssStyleSheetAst {
var output = parse(css);
var errors = output.errors;
if (errors.length > 0) {
@ -34,7 +36,11 @@ export function main() {
}
it('should parse CSS into a stylesheet Ast', () => {
var styles = '.selector { prop: value123; }';
var styles = `
.selector {
prop: value123;
}
`;
var ast = makeAst(styles);
expect(ast.rules.length).toEqual(1);
@ -149,7 +155,7 @@ export function main() {
expect(ast.rules.length).toEqual(1);
var rule = <CssMediaQueryRuleAst>ast.rules[0];
assertTokens(rule.query.tokens, ['all', 'and', '(', 'max-width', ':', '100', 'px', ')']);
assertTokens(rule.query, ['all', 'and', '(', 'max-width', ':', '100', 'px', ')']);
var block = <CssBlockAst>rule.block;
expect(block.entries.length).toEqual(1);
@ -262,8 +268,7 @@ export function main() {
expect(fontFaceRule.block.entries.length).toEqual(2);
var mediaQueryRule = <CssMediaQueryRuleAst>ast.rules[2];
assertTokens(
mediaQueryRule.query.tokens, ['all', 'and', '(', 'max-width', ':', '100', 'px', ')']);
assertTokens(mediaQueryRule.query, ['all', 'and', '(', 'max-width', ':', '100', 'px', ')']);
expect(mediaQueryRule.block.entries.length).toEqual(2);
});
@ -367,7 +372,7 @@ export function main() {
var rules = ast.rules;
var supportsRule = <CssBlockDefinitionRuleAst>rules[0];
assertTokens(supportsRule.query.tokens, ['(', 'animation-name', ':', 'rotate', ')']);
assertTokens(supportsRule.query, ['(', 'animation-name', ':', 'rotate', ')']);
expect(supportsRule.type).toEqual(BlockType.Supports);
var selectorOne = <CssSelectorRuleAst>supportsRule.block.entries[0];
@ -557,148 +562,6 @@ export function main() {
assertTokens(style2.value.tokens, ['white']);
});
describe('location offsets', () => {
var styles: string;
function assertMatchesOffsetAndChar(
location: ParseLocation, expectedOffset: number, expectedChar: string): void {
expect(location.offset).toEqual(expectedOffset);
expect(styles[expectedOffset]).toEqual(expectedChar);
}
it('should collect the source span location of each AST node with regular selectors', () => {
styles = '.problem-class { border-top-right: 1px; color: white; }\n';
styles += '#good-boy-rule_ { background-color: #fe4; color: teal; }';
var output = parse(styles);
var ast = output.ast;
assertMatchesOffsetAndChar(ast.location.start, 0, '.');
assertMatchesOffsetAndChar(ast.location.end, 111, '}');
var rule1 = <CssSelectorRuleAst>ast.rules[0];
assertMatchesOffsetAndChar(rule1.location.start, 0, '.');
assertMatchesOffsetAndChar(rule1.location.end, 54, '}');
var rule2 = <CssSelectorRuleAst>ast.rules[1];
assertMatchesOffsetAndChar(rule2.location.start, 56, '#');
assertMatchesOffsetAndChar(rule2.location.end, 111, '}');
var selector1 = rule1.selectors[0];
assertMatchesOffsetAndChar(selector1.location.start, 0, '.');
assertMatchesOffsetAndChar(selector1.location.end, 1, 'p'); // problem-class
var selector2 = rule2.selectors[0];
assertMatchesOffsetAndChar(selector2.location.start, 56, '#');
assertMatchesOffsetAndChar(selector2.location.end, 57, 'g'); // good-boy-rule_
var block1 = rule1.block;
assertMatchesOffsetAndChar(block1.location.start, 15, '{');
assertMatchesOffsetAndChar(block1.location.end, 54, '}');
var block2 = rule2.block;
assertMatchesOffsetAndChar(block2.location.start, 72, '{');
assertMatchesOffsetAndChar(block2.location.end, 111, '}');
var block1def1 = <CssDefinitionAst>block1.entries[0];
assertMatchesOffsetAndChar(block1def1.location.start, 17, 'b'); // border-top-right
assertMatchesOffsetAndChar(block1def1.location.end, 36, 'p'); // px
var block1def2 = <CssDefinitionAst>block1.entries[1];
assertMatchesOffsetAndChar(block1def2.location.start, 40, 'c'); // color
assertMatchesOffsetAndChar(block1def2.location.end, 47, 'w'); // white
var block2def1 = <CssDefinitionAst>block2.entries[0];
assertMatchesOffsetAndChar(block2def1.location.start, 74, 'b'); // background-color
assertMatchesOffsetAndChar(block2def1.location.end, 93, 'f'); // fe4
var block2def2 = <CssDefinitionAst>block2.entries[1];
assertMatchesOffsetAndChar(block2def2.location.start, 98, 'c'); // color
assertMatchesOffsetAndChar(block2def2.location.end, 105, 't'); // teal
var block1value1 = block1def1.value;
assertMatchesOffsetAndChar(block1value1.location.start, 35, '1');
assertMatchesOffsetAndChar(block1value1.location.end, 36, 'p');
var block1value2 = block1def2.value;
assertMatchesOffsetAndChar(block1value2.location.start, 47, 'w');
assertMatchesOffsetAndChar(block1value2.location.end, 47, 'w');
var block2value1 = block2def1.value;
assertMatchesOffsetAndChar(block2value1.location.start, 92, '#');
assertMatchesOffsetAndChar(block2value1.location.end, 93, 'f');
var block2value2 = block2def2.value;
assertMatchesOffsetAndChar(block2value2.location.start, 105, 't');
assertMatchesOffsetAndChar(block2value2.location.end, 105, 't');
});
it('should collect the source span location of each AST node with media query data', () => {
styles = '@media (all and max-width: 100px) { a { display:none; } }';
var output = parse(styles);
var ast = output.ast;
var mediaQuery = <CssMediaQueryRuleAst>ast.rules[0];
assertMatchesOffsetAndChar(mediaQuery.location.start, 0, '@');
assertMatchesOffsetAndChar(mediaQuery.location.end, 56, '}');
var predicate = mediaQuery.query;
assertMatchesOffsetAndChar(predicate.location.start, 0, '@');
assertMatchesOffsetAndChar(predicate.location.end, 32, ')');
var rule = <CssSelectorRuleAst>mediaQuery.block.entries[0];
assertMatchesOffsetAndChar(rule.location.start, 36, 'a');
assertMatchesOffsetAndChar(rule.location.end, 54, '}');
});
it('should collect the source span location of each AST node with keyframe data', () => {
styles = '@keyframes rotateAndZoomOut { ';
styles += 'from { transform: rotate(0deg); } ';
styles += '100% { transform: rotate(360deg) scale(2); }';
styles += '}';
var output = parse(styles);
var ast = output.ast;
var keyframes = <CssKeyframeRuleAst>ast.rules[0];
assertMatchesOffsetAndChar(keyframes.location.start, 0, '@');
assertMatchesOffsetAndChar(keyframes.location.end, 108, '}');
var step1 = <CssKeyframeDefinitionAst>keyframes.block.entries[0];
assertMatchesOffsetAndChar(step1.location.start, 30, 'f');
assertMatchesOffsetAndChar(step1.location.end, 62, '}');
var step2 = <CssKeyframeDefinitionAst>keyframes.block.entries[1];
assertMatchesOffsetAndChar(step2.location.start, 64, '1');
assertMatchesOffsetAndChar(step2.location.end, 107, '}');
});
it('should collect the source span location of each AST node with an inline rule', () => {
styles = '@import url(something.css)';
var output = parse(styles);
var ast = output.ast;
var rule = <CssInlineRuleAst>ast.rules[0];
assertMatchesOffsetAndChar(rule.location.start, 0, '@');
assertMatchesOffsetAndChar(rule.location.end, 25, ')');
var value = rule.value;
assertMatchesOffsetAndChar(value.location.start, 8, 'u');
assertMatchesOffsetAndChar(value.location.end, 25, ')');
});
it('should property collect the start/end locations with an invalid stylesheet', () => {
styles = '#id { something: value';
var output = parse(styles);
var ast = output.ast;
assertMatchesOffsetAndChar(ast.location.start, 0, '#');
assertMatchesOffsetAndChar(ast.location.end, 22, undefined);
});
});
it('should parse minified CSS content properly', () => {
// this code was taken from the angular.io webpage's CSS code
var styles = `

View File

@ -7,10 +7,10 @@
*/
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '../../core/testing/testing_internal';
import {CssAst, CssAstVisitor, CssAtRulePredicateAst, CssBlockAst, CssBlockDefinitionRuleAst, CssBlockRuleAst, CssDefinitionAst, CssInlineRuleAst, CssKeyframeDefinitionAst, CssKeyframeRuleAst, CssMediaQueryRuleAst, CssPseudoSelectorAst, CssRuleAst, CssSelectorAst, CssSelectorRuleAst, CssSimpleSelectorAst, CssStyleSheetAst, CssStyleValueAst, CssStylesBlockAst, CssUnknownRuleAst, CssUnknownTokenListAst} from '../src/css_ast';
import {BlockType, CssParseError, CssParser, CssToken} from '../src/css_parser';
import {CssLexer} from '../src/css_lexer';
import {BlockType, CssAst, CssAstVisitor, CssAtRulePredicateAst, CssBlockAst, CssBlockDefinitionRuleAst, CssBlockRuleAst, CssDefinitionAst, CssInlineRuleAst, CssKeyframeDefinitionAst, CssKeyframeRuleAst, CssMediaQueryRuleAst, CssParseError, CssParser, CssPseudoSelectorAst, CssRuleAst, CssSelectorAst, CssSelectorRuleAst, CssSimpleSelectorAst, CssStyleSheetAst, CssStyleValueAst, CssStylesBlockAst, CssToken, CssUnknownRuleAst, CssUnknownTokenListAst} from '../src/css_parser';
import {BaseException} from '../src/facade/exceptions';
import {isPresent} from '../src/facade/lang';
import {NumberWrapper, StringWrapper, isPresent} from '../src/facade/lang';
function _assertTokens(tokens: CssToken[], valuesArr: string[]): void {
expect(tokens.length).toEqual(valuesArr.length);
@ -115,7 +115,10 @@ function _getCaptureAst(capture: any[], index = 0): CssAst {
export function main() {
function parse(cssCode: string, ignoreErrors: boolean = false) {
var output = new CssParser().parse(cssCode, 'some-fake-css-file.css');
var lexer = new CssLexer();
var scanner = lexer.scan(cssCode);
var parser = new CssParser(scanner, 'some-fake-file-name.css');
var output = parser.parse();
var errors = output.errors;
if (errors.length > 0 && !ignoreErrors) {
throw new BaseException(errors.map((error: CssParseError) => error.msg).join(', '));
@ -124,7 +127,7 @@ export function main() {
}
describe('CSS parsing and visiting', () => {
var ast: CssStyleSheetAst;
var ast: any /** TODO #9100 */;
var context = {};
beforeEach(() => {