From 16597996b170b910e57954ead3c9fc4602267955 Mon Sep 17 00:00:00 2001 From: Adrian Cochrane Date: Sat, 15 Jun 2019 17:03:54 +1200 Subject: [PATCH] Index style rules to quickly narrow down which ones match a given element. --- src/Stylish/Style/Index.hs | 59 ++++++++++++++++++++++++++++++++++++++ stylish-haskell.cabal | 4 +-- 2 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 src/Stylish/Style/Index.hs diff --git a/src/Stylish/Style/Index.hs b/src/Stylish/Style/Index.hs new file mode 100644 index 0000000..360f419 --- /dev/null +++ b/src/Stylish/Style/Index.hs @@ -0,0 +1,59 @@ +module Stylish.Style.Index ( + StyleIndex + ) where + +-- TODO do performance tests to decide beside between strict/lazy. +import Data.HashMap.Strict +import Stylish.Parse + +import Data.Hashable +import Data.Text (unpack) + +data StyleIndex = StyleIndex { + indexed :: HashMap SimpleSelector [StyleRule], + unindexed :: [StyleRule] +} + +styleIndex = StyleIndex {indexed = empty, unindexed = []} + +lookup' :: SimpleSelector -> HashMap SimpleSelector [a] -> [a] +lookup' = lookupDefault [] + +instance StyleSheet StyleIndex where + addRule self (StyleRule _ []) = self + addRule self rule@(StyleRule selector _) = addRuleForSelector self rule $ simpleSelector selector + +simpleSelector (Element s) = s +simpleSelector (Child _ s) = s +simpleSelector (Descendant _ s) = s +simpleSelector (Adjacent _ s) = s +simpleSelector (Sibling _ s) = s + +addRuleForSelector self rule [] = self {unindexed = rule : unindexed self} +addRuleForSelector self rule selector = self { + indexed = insert key (rule : lookup' key index) index + } where + key = selectorKey selector + index = indexed self + +selectorKey (tok@(Tag _) : _) = tok +selectorKey (tok@(Id _) : _) = tok +selectorKey (tok@(Class _) : _) = tok +selectorKey (Property prop _ : _) = Property prop Exists + +-- Implement hashable for SimpleSelector here because it proved challenging to automatically derive it. +instance Hashable SimpleSelector where + hashWithSalt seed (Tag tag) = seed `hashWithSalt` (0::Int) `hashWithSalt` unpack tag + hashWithSalt seed (Id id) = seed `hashWithSalt` (1::Int) `hashWithSalt` unpack id + hashWithSalt seed (Class class_) = seed `hashWithSalt` (2::Int) `hashWithSalt` unpack class_ + hashWithSalt seed (Property prop test) = + seed `hashWithSalt` (3::Int) `hashWithSalt` unpack prop `hashWithSalt` test + +instance Hashable PropertyTest where + hashWithSalt seed Exists = seed `hashWithSalt` (0::Int) + hashWithSalt seed (Equals val) = seed `hashWithSalt` (1::Int) `hashWithSalt` unpack val + hashWithSalt seed (Suffix val) = seed `hashWithSalt` (2::Int) `hashWithSalt` unpack val + hashWithSalt seed (Prefix val) = seed `hashWithSalt` (3::Int) `hashWithSalt` unpack val + hashWithSalt seed (Substring val) = seed `hashWithSalt` (4::Int) `hashWithSalt` unpack val + hashWithSalt seed (Include val) = seed `hashWithSalt` (5::Int) `hashWithSalt` unpack val + hashWithSalt seed (Dash val) = seed `hashWithSalt` (6::Int) `hashWithSalt` unpack val diff --git a/stylish-haskell.cabal b/stylish-haskell.cabal index 49f313f..691cc06 100644 --- a/stylish-haskell.cabal +++ b/stylish-haskell.cabal @@ -57,7 +57,7 @@ library -- other-extensions: -- Other library packages from which modules are imported. - build-depends: base >=4.9 && <4.10, css-syntax, text + build-depends: base >=4.9 && <4.10, css-syntax, text, unordered-containers, hashable -- Directories containing source files. hs-source-dirs: src @@ -71,4 +71,4 @@ test-suite test-stylish type: exitcode-stdio-1.0 main-is: Test.hs other-modules: Stylish.Parse - build-depends: base >=4.9 && <4.10, css-syntax, text, hspec, QuickCheck + build-depends: base >=4.9 && <4.10, css-syntax, text, unordered-containers, hashable, hspec, QuickCheck -- 2.30.2