From c0a7a45ab97b70ff3f580f5a6515b5a466b0f283 Mon Sep 17 00:00:00 2001 From: Alexander Vakrilov Date: Thu, 1 Feb 2018 13:04:55 +0200 Subject: [PATCH] refactor: Handle TS2.7 stricter tuples checks (#5366) --- tns-core-modules/css/parser.ts | 13 ++-- .../ui/styling/css-selector/css-selector.ts | 10 +-- unit-tests/css/parser.ts | 77 +++++++++---------- 3 files changed, 49 insertions(+), 51 deletions(-) diff --git a/tns-core-modules/css/parser.ts b/tns-core-modules/css/parser.ts index cf19db3ee..c0988b8cc 100644 --- a/tns-core-modules/css/parser.ts +++ b/tns-core-modules/css/parser.ts @@ -342,7 +342,7 @@ export function parseAngle(value: string, start: number = 0): Parsed { const angleResult = parseUnit(value, start); if (angleResult) { const { start, end, value } = angleResult; - return (angleUnitsToRadMap[value.unit] || (() => null))(start, end, value.value); + return (angleUnitsToRadMap[value.unit] || ((_,__,___) => null))(start, end, value.value); } return null; } @@ -693,7 +693,8 @@ export interface AttributeSelector { export type SimpleSelector = UniversalSelector | TypeSelector | ClassSelector | IdSelector | PseudoClassSelector | AttributeSelector; export type SimpleSelectorSequence = SimpleSelector[]; -export type Selector = [SimpleSelectorSequence, Combinator]; +export type SelectorCombinatorPair = [SimpleSelectorSequence, Combinator]; +export type Selector = SelectorCombinatorPair[]; const universalSelectorRegEx = /\*/gy; export function parseUniversalSelector(text: string, start: number = 0): Parsed { @@ -781,6 +782,7 @@ export function parseSelector(text: string, start: number = 0): Parsed let value = []; let combinator: Parsed; let expectSimpleSelector = true; // Must have at least one + let pair = []; do { const simpleSelectorSequence = parseSimpleSelectorSequence(text, end); if (!simpleSelectorSequence) { @@ -792,16 +794,17 @@ export function parseSelector(text: string, start: number = 0): Parsed } end = simpleSelectorSequence.end; if (combinator) { - value.push(combinator.value); + pair[1] = combinator.value; } - value.push(simpleSelectorSequence.value); + pair = [simpleSelectorSequence.value, undefined] + value.push(pair) + combinator = parseCombinator(text, end); if (combinator) { end = combinator.end; } expectSimpleSelector = combinator && combinator.value !== " "; // Simple selector must follow non trailing white space combinator } while(combinator); - value.push(undefined); return { start, end, value }; } diff --git a/tns-core-modules/ui/styling/css-selector/css-selector.ts b/tns-core-modules/ui/styling/css-selector/css-selector.ts index ad169e802..da8e90d98 100644 --- a/tns-core-modules/ui/styling/css-selector/css-selector.ts +++ b/tns-core-modules/ui/styling/css-selector/css-selector.ts @@ -432,13 +432,13 @@ function createSimpleSelectorSequenceFromAst(ast: parser.SimpleSelectorSequence) function createSelectorFromAst(ast: parser.Selector): SimpleSelector | SimpleSelectorSequence | Selector { if (ast.length === 0) { return new InvalidSelector(new Error("Empty selector.")); - } else if (ast.length <= 2) { - return createSimpleSelectorSequenceFromAst(ast[0]); + } else if (ast.length === 1) { + return createSimpleSelectorSequenceFromAst(ast[0][0]); } else { let simpleSelectorSequences = []; - for (var i = 0; i < ast.length; i += 2) { - const simpleSelectorSequence = createSimpleSelectorSequenceFromAst(ast[i]); - const combinator = ast[i + 1]; + for (var i = 0; i < ast.length; i ++) { + const simpleSelectorSequence = createSimpleSelectorSequenceFromAst(ast[i][0]); + const combinator = ast[i][1]; if (combinator) { simpleSelectorSequence.combinator = combinator; } diff --git a/unit-tests/css/parser.ts b/unit-tests/css/parser.ts index 3df758c84..667f12177 100644 --- a/unit-tests/css/parser.ts +++ b/unit-tests/css/parser.ts @@ -143,68 +143,63 @@ describe("css", () => { describe("selectors", () => { test(parseSelector, ` listview#products.mark gridlayout:selected[row="2"] a> b > c >d>e *[src] `, { start: 0, end: 79, value: [ - [ + [[ { type: "", identifier: "listview" }, { type: "#", identifier: "products" }, { type: ".", identifier: "mark" } - ], - " ", - [ + ], " "], + [[ { type: "", identifier: "gridlayout" }, { type: ":", identifier: "selected" }, { type: "[]", property: "row", test: "=", value: "2" } - ], - " ", - [{ type: "", identifier: "a"}], - ">", - [{ type: "", identifier: "b"}], - ">", - [{ type: "", identifier: "c"}], - ">", - [{ type: "", identifier: "d"}], - ">", - [{ type: "", identifier: "e"}], - " ", - [ + ], " "], + [[{ type: "", identifier: "a"}], ">"], + [[{ type: "", identifier: "b"}], ">"], + [[{ type: "", identifier: "c"}], ">"], + [[{ type: "", identifier: "d"}], ">"], + [[{ type: "", identifier: "e"}], " "], + [[ { type: "*" }, { type: "[]", property: "src" } - ], - undefined + ], undefined] ], }); - test(parseSelector, "*", { start: 0, end: 1, value: [[{ type: "*" }], undefined ]}); - test(parseSelector, "button", { start: 0, end: 6, value: [[{ type: "", identifier: "button" }], undefined]}); - test(parseSelector, ".login", { start: 0, end: 6, value: [[{ type: ".", identifier: "login" }], undefined]}); - test(parseSelector, "#login", { start: 0, end: 6, value: [[{ type: "#", identifier: "login" }], undefined]}); - test(parseSelector, ":hover", { start: 0, end: 6, value: [[{ type: ":", identifier: "hover" }], undefined]}); - test(parseSelector, "[src]", { start: 0, end: 5, value: [[{ type: "[]", property: "src" }], undefined]}); - test(parseSelector, `[src = "res://"]`, { start: 0, end: 16, value: [[{ type: "[]", property: "src", test: "=", value: `res://`}], undefined]}); + test(parseSelector, "*", { start: 0, end: 1, value: [[[{ type: "*" }], undefined ]] }); + test(parseSelector, "button", { start: 0, end: 6, value: [[[{ type: "", identifier: "button" }], undefined]]}); + test(parseSelector, ".login", { start: 0, end: 6, value: [[[{ type: ".", identifier: "login" }], undefined]]}); + test(parseSelector, "#login", { start: 0, end: 6, value: [[[{ type: "#", identifier: "login" }], undefined]]}); + test(parseSelector, ":hover", { start: 0, end: 6, value: [[[{ type: ":", identifier: "hover" }], undefined]]}); + test(parseSelector, "[src]", { start: 0, end: 5, value: [[[{ type: "[]", property: "src" }], undefined]]}); + test(parseSelector, `[src = "res://"]`, { start: 0, end: 16, value: [[[{ type: "[]", property: "src", test: "=", value: `res://`}], undefined]]}); (["=", "^=", "$=", "*=", "=", "~=", "|="]).forEach(attributeTest => { - test(parseSelector, `[src ${attributeTest} "val"]`, { start: 0, end: 12 + attributeTest.length, value: [[{ type: "[]", property: "src", test: attributeTest, value: "val"}], undefined]}); + test(parseSelector, `[src ${attributeTest} "val"]`, { start: 0, end: 12 + attributeTest.length, value: [[[{ type: "[]", property: "src", test: attributeTest, value: "val"}], undefined]]}); }); - test(parseSelector, "listview > .image", { start: 0, end: 17, value: [[{ type: "", identifier: "listview"}], ">", [{ type: ".", identifier: "image"}], undefined]}); - test(parseSelector, "listview .image", { start: 0, end: 16, value: [[{ type: "", identifier: "listview"}], " ", [{ type: ".", identifier: "image"}], undefined]}); - test(parseSelector, "button:hover", { start: 0, end: 12, value: [[{ type: "", identifier: "button" }, { type: ":", identifier: "hover"}], undefined]}); + test(parseSelector, "listview > .image", { start: 0, end: 17, value: [ + [[{ type: "", identifier: "listview"}], ">"], + [[{ type: ".", identifier: "image"}], undefined] + ]}); + test(parseSelector, "listview .image", { start: 0, end: 16, value: [ + [[{ type: "", identifier: "listview"}], " "], + [[{ type: ".", identifier: "image"}], undefined] + ]}); + test(parseSelector, "button:hover", { start: 0, end: 12, value: [[[{ type: "", identifier: "button" }, { type: ":", identifier: "hover"}], undefined]]}); test(parseSelector, "listview>:selected image.product", { start: 0, end: 32, value: [ - [{ type: "", identifier: "listview" }], - ">", - [{ type: ":", identifier: "selected" }], - " ", - [ + [[{ type: "", identifier: "listview" }], ">"], + [[{ type: ":", identifier: "selected" }], " "], + [[ { type: "", identifier: "image" }, { type: ".", identifier: "product" } - ], - undefined + ], undefined] ]}); test(parseSelector, "button[testAttr]", { start: 0, end: 16, value: [ - [ + [[ { type: "", identifier: "button" }, { type: "[]", property: "testAttr" }, ], - undefined + undefined] ]}); test(parseSelector, "button#login[user][pass]:focused:hovered", { start: 0, end: 40, value: [ - [ + [[ { type: "", identifier: "button" }, { type: "#", identifier: "login" }, { type: "[]", property: "user" }, @@ -212,7 +207,7 @@ describe("css", () => { { type: ":", identifier: "focused" }, { type: ":", identifier: "hovered" } ], - undefined + undefined] ]}); });