├── images ├── logo.png ├── screenshot1.png ├── screenshot-cabal1.png └── logo.svg ├── cabal-configuration.json ├── test ├── tests │ ├── InvalidClosingBlockComment.hs │ ├── MultipleFunDecl.hs │ ├── Happy2.y │ ├── GADTTicks.hs │ ├── Tuples.hs │ ├── CPP.hs │ ├── Alex2.x │ ├── Pipe.hs │ ├── WildcardExport.hs │ ├── Forall.hs │ ├── PragmaComments.hs │ ├── Arrows.hs │ ├── Data1.hs │ ├── SymbolicPatternSynonyms.hs │ ├── ExportsMagicHash.hs │ ├── Newtype1.hs │ ├── QualifiedDo.hs │ ├── Data2.hs │ ├── Data3.hs │ ├── LiterateHaskell.lhs │ ├── Newtype2.hs │ ├── Newtype3.hs │ ├── MultiLineTypeSignatures.hs │ ├── TypeVsData.hs │ ├── Specialise.hs │ ├── NonRecord.hs │ ├── ImportIndentation.hs │ ├── Language.hs │ ├── Fixity.hs │ ├── CommentLike.hs │ ├── Prefix.hs │ ├── EndTypeSig.hs │ ├── Kinds.hs │ ├── Keywords.hs │ ├── QualifiedFields.hs │ ├── LinearTypes.hs │ ├── ReservedInComments.hs │ ├── Role.hs │ ├── Comments.hs │ ├── Happy.y │ ├── Imports.hs │ ├── NearReserved.hs │ ├── InfixDataDecl.hs │ ├── GADTRecord.hs │ ├── InfixBacktick.hs │ ├── BlockComments.hs │ ├── Exports.hs │ ├── UnusualTypeApplications.hs │ ├── Alex.x │ ├── Class.hs │ ├── Records.hs │ ├── Fields.hs │ ├── ADTs.hs │ ├── OverloadedLabels.hs │ ├── Haddocks.hs │ ├── GADTs.hs │ ├── MultilineDeriving.hs │ ├── QuasiQuotes.hs │ ├── TypeSigs.hs │ ├── MagicHash.hs │ └── Ticks.hs ├── tickets │ ├── T0029.hs │ ├── T0146c.hs │ ├── T0073b.hs │ ├── T0151.hs │ ├── T0120.hs │ ├── T0170.hs │ ├── T0150.hs │ ├── T0043b.hs │ ├── T0050.hs │ ├── T0189.y │ ├── T230.hs │ ├── T0039.hs │ ├── T0122.hs │ ├── T0088.hs │ ├── T0001.hs │ ├── T0028.hs │ ├── T0104.hs │ ├── T0150b.hs │ ├── T0043.hs │ ├── T0051.hs │ ├── T0018.hs │ ├── T0108.hs │ ├── T0163.hs │ ├── T0071b.hs │ ├── T0150c.hs │ ├── T0028b.hs │ ├── T0172.lhs │ ├── T0091.hs │ ├── T0131.hs │ ├── T0064.hs │ ├── T0070.hs │ ├── T0175.hs │ ├── T0136.hs │ ├── T0039b.hs │ ├── T0023.hs │ ├── T0031.hs │ ├── T0015.hs │ ├── T0121.hs │ ├── T0118.hs │ ├── T0035.hs │ ├── T0002.hs │ ├── T0072b2.hs │ ├── T0111.hs │ ├── T0069.hs │ ├── T0020b.hs │ ├── T0112.hs │ ├── T0178.hs │ ├── T0090.hs │ ├── T0020.hs │ ├── T0066.hs │ ├── T0190.hs │ ├── T0072a.hs │ ├── T0089.hs │ ├── T0038.hs │ ├── T0073.hs │ ├── T0146.hs │ ├── T0102.hs │ ├── T0030.hs │ ├── T0071.hs │ ├── T0116.hs │ ├── T0146b.hs │ ├── T0072b3.hs │ ├── T0167.hs │ ├── T0157.hs │ ├── T0182.hs │ ├── T0132.hs │ ├── T0156.hs │ ├── T0072b.hs │ ├── T0165.hs │ ├── T0161.hs │ ├── T0072c.hs │ └── T0044.hs ├── wontfix │ ├── MultilineFunDecl.hs │ └── MultilineGADT.hs └── test.sh ├── .vscodeignore ├── .gitignore ├── tsconfig.json ├── scope-lists ├── cabal.yaml ├── cabal.md ├── literateHaskell.yaml ├── literateHaskell.md ├── happy.yaml ├── happy.md ├── alex.yaml ├── alex.md └── refresh.hs ├── syntax-examples ├── alex.x ├── haskell.hs ├── cabal.cabal ├── happy.y ├── embedding.md └── backpack.hsig ├── .vscode ├── settings.json ├── launch.json └── tasks.json ├── syntaxes ├── C2Hs.json ├── Hsc2Hs.json ├── codeblock-cabal.json ├── codeblock-haskell.json ├── codeblock-literate-haskell.json ├── literateHaskell.YAML-tmLanguage ├── haddock.YAML-tmLanguage ├── cabal.YAML-tmLanguage ├── happy.YAML-tmLanguage └── alex.YAML-tmLanguage ├── PULL_REQUEST_TEMPLATE.md ├── DEVELOPMENT.md ├── C2Hs-configuration.json ├── .github └── workflows │ └── github-ci.yml ├── haskell-configuration.json ├── Hsc2Hs-configuration.json ├── literate-haskell-configuration.json ├── src └── extension.ts ├── Makefile ├── webpack.config.js ├── LICENSE └── README.md /images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JustusAdam/language-haskell/HEAD/images/logo.png -------------------------------------------------------------------------------- /images/screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JustusAdam/language-haskell/HEAD/images/screenshot1.png -------------------------------------------------------------------------------- /cabal-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | "lineComment": "--", 4 | "blockComment": [] 5 | } 6 | } -------------------------------------------------------------------------------- /images/screenshot-cabal1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JustusAdam/language-haskell/HEAD/images/screenshot-cabal1.png -------------------------------------------------------------------------------- /test/tests/InvalidClosingBlockComment.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Invalid closing block comment" 2 | 3 | -} 4 | -- ^^ invalid 5 | -------------------------------------------------------------------------------- /test/tickets/T0029.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "rec keyword" 2 | 3 | f = do 4 | rec a <- go a 5 | -- <~~--- keyword.control.rec.haskell 6 | return a -------------------------------------------------------------------------------- /test/tickets/T0146c.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Highlighting in multiline data declarations" 2 | 3 | data D 4 | = MethodCall "getDecks" Cards 5 | -------------------------------------------------------------------------------- /test/tickets/T0073b.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Visible kind application" 2 | 3 | type TF l = F @_ @(l :: Nat) A 4 | -- ^ ^ meta.type-application.haskell -------------------------------------------------------------------------------- /test/tickets/T0151.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Constructors and parentheses" 2 | 3 | fail = S (S Z) 4 | -- ^ ^ ^ constant.other.haskell 5 | success = S (S Z ) 6 | -- ^ ^ ^ constant.other.haskell -------------------------------------------------------------------------------- /test/tickets/T0120.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Infix constructors" 2 | 3 | myTail :: [a] -> [a] 4 | myTail ( a `Cons` as ) = as 5 | -- ^^^^ keyword.operator.function.infix.haskell constant.other.haskell -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | typings/** 3 | out/test/** 4 | test/** 5 | src/** 6 | **/*.map 7 | .gitignore 8 | tsconfig.json 9 | test.hs 10 | test.cabal 11 | scope-lists/** 12 | syntaxes/*.YAML-tmLanguage 13 | .github/** -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | dist 3 | *.vsix 4 | node_modules 5 | syntaxes/haskell.json 6 | npm-debug.log 7 | syntaxes/cabal.json 8 | syntaxes/literateHaskell.json 9 | syntaxes/alex.json 10 | syntaxes/happy.json 11 | test/*/*.snap 12 | .vscode-test-web -------------------------------------------------------------------------------- /test/tickets/T0170.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Lists starting with '|'" 2 | 3 | removed as = removeChars ['|', '-'] as 4 | -- ^^^ string.quoted.single.haskell 5 | -- ^^^^^^^^^^^^^ - meta.quasi-quotation.haskell 6 | -------------------------------------------------------------------------------- /test/tests/MultipleFunDecl.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Declaring several functions" 2 | 3 | 4 | 5 | f1, f2, f3 :: a -> b -> c 6 | -- ^^^^^^^^^^ meta.function.type-declaration.haskell 7 | -- ^^ ^^ ^^ entity.name.function.haskell 8 | 9 | 10 | -------------------------------------------------------------------------------- /test/tickets/T0150.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Pragma after data declaration" 2 | 3 | data D = C 4 | 5 | {-# COMPLETE P #-} 6 | -- ^^^^^^^^^^^^^^^^^^ meta.preprocessor.haskell 7 | -- ^^^^^^^^^^^^^^^^^^ - comment.block.haskell 8 | pattern P :: A 9 | pattern P = C -------------------------------------------------------------------------------- /test/tickets/T0043b.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Escaped chars" 2 | 3 | chars = [ '\^A', '\^@', '\n' ] 4 | -- ^^^^^ ^^^^^ ^^^^ string.quoted.single.haskell 5 | -- ^^^ ^^^ constant.character.escape.control.haskell 6 | -- ^^ constant.character.escape.haskell -------------------------------------------------------------------------------- /test/tickets/T0050.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Type-level symbols" 2 | 3 | instance Has Point "of" Int 4 | -- ^^^^ string.quoted.double.haskell 5 | 6 | example = from (Point 1 2) (Get :: Label "of") 7 | -- ^^^^ string.quoted.double.haskell 8 | -------------------------------------------------------------------------------- /test/tickets/T0189.y: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell.happy" "Happy" 2 | 3 | foo :: { Foo } 4 | : foo { $1 } 5 | -- ^^ variable.parameter.happy 6 | 7 | 8 | fooBar :: { (Foo, Bar) } 9 | : foo bar { ($1, $2) } 10 | -- ^^ ^^ variable.parameter.happy 11 | -------------------------------------------------------------------------------- /test/tickets/T230.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Exports with magic hash" 2 | 3 | module M 4 | ( T#(f#,C#,(+#),g#) 5 | -- ^ storage.type.haskell 6 | -- ^ ^ entity.name.function.haskell 7 | , Int, Bool 8 | -- ^^^ ^^^^ storage.type.haskell 9 | 10 | ) 11 | where 12 | -------------------------------------------------------------------------------- /test/tests/Happy2.y: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell.happy" "Happy apostrophes etc" 2 | 3 | %_name parse 4 | -- <----- entity.name.directive.happy 5 | 6 | %tokentype' { Token } 7 | -- <---------- entity.name.directive.happy 8 | 9 | %er'o_r'_ { parseError } 10 | -- <-------- entity.name.directive.happy 11 | -------------------------------------------------------------------------------- /test/tickets/T0039.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "forall keyword in existential types" 2 | 3 | data Exts = forall var . Class var => Exts var 4 | -- ^^^^^^ keyword.other.forall.haskell 5 | 6 | data Exts where 7 | F :: forall var . Class var => Exts var 8 | -- ^^^^^^ keyword.other.forall.haskell -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "esnext", 5 | "outDir": "out", 6 | "sourceMap": true, 7 | "strict": true, 8 | "lib": ["ESNext"], 9 | "rootDir": "." 10 | }, 11 | "exclude": [ 12 | "node_modules", 13 | "out" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /test/tickets/T0122.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Interaction between constructors and symbols" 2 | 3 | f (A,B) = 3 4 | -- ^ ^ constant.other.haskell 5 | f ( A,B ) = 3 6 | -- ^ ^ constant.other.haskell 7 | f ( A ,B ) = 3 8 | -- ^ ^ constant.other.haskell 9 | 10 | g [X,Y,Z] = 0 11 | -- ^ ^ ^ constant.other.haskell -------------------------------------------------------------------------------- /test/tickets/T0088.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Non-ASCII unicode text" 2 | 3 | unicöde :: String -> [Char] 4 | -- <------- entity.name.function.haskell 5 | -- <--------------------------- meta.function.type-declaration.haskell 6 | -- <--------------------------- - invalid 7 | unicöde = undefined 8 | -- <------------------- - invalid -------------------------------------------------------------------------------- /scope-lists/cabal.yaml: -------------------------------------------------------------------------------- 1 | - scope: Cabal 2 | hide: true 3 | - scope: comment.line.double-dash 4 | - scope: constant.numeric.cabal 5 | - scope: entity.name.function.cabal 6 | - scope: entity.name.section.cabal 7 | - scope: keyword.control.cabal 8 | - scope: keyword.operator.cabal 9 | - scope: keyword.other.cabal 10 | - scope: markup.underline.link.cabal 11 | -------------------------------------------------------------------------------- /test/tickets/T0001.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Multiline type signature" 2 | 3 | dbPageWrapper :: (DashBoardPage p, Monad m) => 4 | T.Text -> p -> HtmlT m a -> HtmlT m b -> HtmlT m b 5 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function.type-declaration.haskell 6 | -- ^^^^^ storage.type.haskell 7 | 8 | -------------------------------------------------------------------------------- /test/tickets/T0028.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Highlighting do arrow after type signature" 2 | 3 | someFunc :: IO () 4 | someFunc = do 5 | result <- ioAction 6 | result :: Int <- ioAction 7 | -- ^^ keyword.operator.arrow.left.haskell 8 | ( result :: Int ) <- ioAction 9 | -- ^^ keyword.operator.arrow.left.haskell 10 | -------------------------------------------------------------------------------- /test/tickets/T0104.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Comments in export lists" 2 | 3 | module StockQuote 4 | -- ( getQuote 5 | -- ^^^^^^^^^^^^^ comment.line.double-dash.haskell 6 | -- ) where 7 | -- ^^^^^^^^^^ comment.line.double-dash.haskell 8 | -- ^^^^^ - keyword.other.where.haskell 9 | where 10 | -- ^^^^^ keyword.other.where.haskell -------------------------------------------------------------------------------- /test/tickets/T0150b.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "LiquidHaskell annotation after data declaration" 2 | 3 | data D = C 4 | 5 | {-@ f :: (Ord a) => xs:[a] -> (IncrList a) @-} 6 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ block.liquidhaskell.haskell 7 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - comment.block.haskell 8 | f :: [a] -> [a] -------------------------------------------------------------------------------- /test/tickets/T0043.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Escaped strings" 2 | 3 | astring = "\^A \^@ \^_" 4 | -- ^^^^^^^^^^^^^ string.quoted.double.haskell 5 | -- ^^^ ^^^ ^^^ constant.character.escape.control.haskell 6 | anotherstring = "^\\ \n" 7 | -- ^^^^^^^^ string.quoted.double.haskell 8 | -- ^^ ^^ constant.character.escape.haskell -------------------------------------------------------------------------------- /test/tickets/T0051.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Type-level naturals" 2 | 3 | f :: A 3 -> B 4 4 | -- ^ ^ constant.numeric.integral.decimal.haskell 5 | 6 | let x = (something :: MyLabel 5) 7 | -- ^ constant.numeric.integral.decimal.haskell 8 | g = f @( F 3 + 4 ) 9 | -- ^ ^ constant.numeric.integral.decimal.haskell 10 | -------------------------------------------------------------------------------- /scope-lists/cabal.md: -------------------------------------------------------------------------------- 1 | | Scope Name | Description | Example | 2 | |-|-|-| 3 | | comment.line.double-dash | | | 4 | | constant.numeric.cabal | | | 5 | | entity.name.function.cabal | | | 6 | | entity.name.section.cabal | | | 7 | | keyword.control.cabal | | | 8 | | keyword.operator.cabal | | | 9 | | keyword.other.cabal | | | 10 | | markup.underline.link.cabal | | | 11 | -------------------------------------------------------------------------------- /test/tests/GADTTicks.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Ticks in GADT constructors" 2 | 3 | data D where 4 | T' :: D 5 | -- ^^ constant.other.haskell 6 | T_'_'_''t :: D 7 | -- ^^^^^^^^^ constant.other.haskell 8 | T_'ttt_'t_' :: D 9 | -- ^^^^^^^^^^^ constant.other.haskell 10 | T'x''' :: D 11 | -- ^^^^^^ constant.other.haskell -------------------------------------------------------------------------------- /test/tests/Tuples.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Tuple constructors" 2 | 3 | f = (,) 4 | -- ^^^ support.constant.tuple.haskell 5 | f = (, ) 6 | -- ^^^ support.constant.tuple.haskell 7 | f = ( ,) 8 | -- ^^^^ support.constant.tuple.haskell 9 | f = ( , , ) 10 | -- ^^^^^^^ support.constant.tuple.haskell 11 | f = (, , ,,,) 12 | -- ^^^^^^^^^ support.constant.tuple.haskell 13 | -------------------------------------------------------------------------------- /test/tickets/T0018.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Module exporting a module" 2 | 3 | module Main 4 | ( module M 5 | -- ^^^^^^ meta.declaration.exports.haskell keyword.other.module.haskell 6 | , M 7 | -- ^ meta.declaration.exports.haskell storage.type.haskell 8 | , foo 9 | -- ^^^ meta.declaration.exports.haskell entity.name.function.haskell 10 | ) where -------------------------------------------------------------------------------- /test/tests/CPP.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "C preprocessor instructions" 2 | 3 | module M 4 | ( A 5 | , a 6 | #ifdef XYZ 7 | -- <----- meta.preprocessor.c 8 | , bcd 9 | , X 10 | #endif 11 | -- <----- meta.preprocessor.c 12 | ) 13 | where 14 | 15 | #if MIN_VERSION_BASE(4,12,0) 16 | -- <-- meta.preprocessor.c 17 | foo :: A 18 | foo = A 19 | #endif 20 | -- <----- meta.preprocessor.c -------------------------------------------------------------------------------- /test/tickets/T0108.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Correct support for 'signature'" 2 | 3 | signature M where 4 | -- <--------- keyword.other.signature.haskell 5 | 6 | f = do 7 | let signature = Some value 8 | -- ^^^^^^^^^ - keyword.other.signature.haskell 9 | return 0 10 | where 11 | signature = more testing 12 | -- ^^^^^^^^^ - keyword.other.signature.haskell -------------------------------------------------------------------------------- /test/wontfix/MultilineFunDecl.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Multi-line function type declarations" 2 | 3 | 4 | f 5 | -- <- meta.function.type-declaration.haskell 6 | -- <- entity.name.function.haskell 7 | :: A -> B 8 | 9 | 10 | f 11 | -- <- meta.function.type-declaration.haskell 12 | -- <- entity.name.function.haskell 13 | :: forall a b 14 | . C x 15 | => D a 16 | => E b 17 | -> G -------------------------------------------------------------------------------- /syntax-examples/alex.x: -------------------------------------------------------------------------------- 1 | { 2 | 3 | module Alex where 4 | 5 | import Foo as Bar 6 | import Baz (bax) 7 | 8 | } 9 | 10 | %wrapper "basic" 11 | 12 | $digit = 0-9 13 | $alpha = [a-zA-Z] 14 | 15 | tokens :- 16 | $white+ ; 17 | $digit+ { Number } 18 | $alpha+ { Ident } 19 | 20 | { 21 | 22 | data Token 23 | = Number 24 | | Ident 25 | 26 | main = undefined 27 | 28 | } 29 | -------------------------------------------------------------------------------- /scope-lists/literateHaskell.yaml: -------------------------------------------------------------------------------- 1 | - hide: true 2 | scope: Literate Haskell 3 | - scope: meta.embedded.block.haskell.latex 4 | - scope: meta.embedded.haskell 5 | - scope: punctuation.definition.arguments.begin.latex 6 | - scope: punctuation.definition.arguments.end.latex 7 | - scope: punctuation.definition.bird-track.haskell 8 | - scope: punctuation.definition.function.latex 9 | - scope: support.function.be.latex 10 | -------------------------------------------------------------------------------- /test/tickets/T0163.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "StrictData language pragma" 2 | 3 | {-# LANGUAGE StrictData #-} 4 | -- ^^^^^^^^ keyword.other.preprocessor.pragma.haskell 5 | -- ^^^^^^^^^^ keyword.other.preprocessor.extension.haskell 6 | 7 | 8 | {-# LANGUAGE StrictDataNotAnExtension #-} 9 | -- ^^^^^^^^^^^^^^^^^^^^^^^^ - keyword.other.preprocessor.extension.haskell 10 | -------------------------------------------------------------------------------- /scope-lists/literateHaskell.md: -------------------------------------------------------------------------------- 1 | | Scope Name | Description | Example | 2 | |-|-|-| 3 | | meta.embedded.block.haskell.latex | | | 4 | | meta.embedded.haskell | | | 5 | | punctuation.definition.arguments.begin.latex | | | 6 | | punctuation.definition.arguments.end.latex | | | 7 | | punctuation.definition.bird-track.haskell | | | 8 | | punctuation.definition.function.latex | | | 9 | | support.function.be.latex | | | 10 | -------------------------------------------------------------------------------- /test/tickets/T0071b.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Ticks in qualified names" 2 | 3 | 4 | 5 | f = A''.B'C.g `DE'.G'H.h` k XY'.A'B.+ z 6 | -- ^^^^^^^^ ^^^^^^^^ ^^^^^^^^ entity.name.namespace.haskell 7 | 8 | type S = A'.B.C'D.E `DE'.G'H.T` L XY'.A'B.+ Z 9 | -- ^^^^^^^^^ ^^^^^^^^ ^^^^^^^^ entity.name.namespace.haskell 10 | 11 | type T = 'A.C + 'B.+ D 12 | -- ^ ^ - entity.name.namespace.haskell -------------------------------------------------------------------------------- /test/tickets/T0150c.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Haddock comments after data declaration" 2 | 3 | data D = C 4 | 5 | {-| docs docs -} 6 | -- ^^^^^^^^^^^^^^^^ comment.block.documentation.haskell 7 | -- ^^^^^^^^^^^^^^^^ - comment.block.haskell 8 | 9 | data D = C 10 | 11 | -- | docs docs 12 | -- ^^^^^^^^^^^^^^ comment.block.documentation.haskell 13 | -- ^^^^^^^^^^^^^^ - comment.line.double-dash.haskell -------------------------------------------------------------------------------- /test/tickets/T0028b.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Highlighting type signature before do arrow" 2 | 3 | someFunc :: IO () 4 | someFunc = do 5 | result <- ioAction 6 | result :: Int <- ioAction 7 | -- ^^^ storage.type.haskell 8 | -- ^^ keyword.operator.arrow.left.haskell 9 | ( result :: Int ) <- ioAction 10 | -- ^^^ storage.type.haskell 11 | -- ^^ keyword.operator.arrow.left.haskell -------------------------------------------------------------------------------- /test/tests/Alex2.x: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell.alex" "Alex apostrophes etc" 2 | 3 | %_wrapper "basic" 4 | -- <-------- entity.name.pragma.alex 5 | 6 | %wrapper' "basic" 7 | -- <-------- entity.name.pragma.alex 8 | 9 | %wrap'pe_r_ "basic" 10 | -- <---------- entity.name.pragma.alex 11 | 12 | $digit' = 0-9 13 | -- <------ entity.name.macro.character-set.alex 14 | 15 | $d'igi_t_ = 0-9 16 | -- <-------- entity.name.macro.character-set.alex 17 | -------------------------------------------------------------------------------- /test/tests/Pipe.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Using | in types in an ADT" 2 | 3 | 4 | data A = A (T1 || T2) | A { f :: A |-| B } 5 | -- ^^^^ keyword.other.data.haskell 6 | -- ^ keyword.operator.pipe.haskell 7 | -- ^ variable.other.member.definition.haskell 8 | -- ^^ ^^^ storage.type.operator.infix.haskell 9 | -- ^ ^^ ^^ ^ ^ storage.type.haskell 10 | -------------------------------------------------------------------------------- /test/tickets/T0172.lhs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "text.tex.latex.haskell" "Literate Haskell" 2 | 3 | \begin{code} 4 | -- ^^^^^^^^^^^^ meta.embedded.block.haskell.latex 5 | \ x -> x + x 6 | -- <- keyword.operator.lambda.haskell 7 | -- ^^ keyword.operator.arrow.haskell 8 | -- ^ keyword.operator.infix.haskell 9 | \end{code} 10 | 11 | \ x -> x + x 12 | -- <- - keyword.operator.lambda.haskell 13 | -- ^^ - keyword.operator.arrow.haskell 14 | -- ^ - keyword.operator.infix.haskell 15 | -------------------------------------------------------------------------------- /test/tickets/T0091.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Indented modules" 2 | 3 | module Foo where 4 | 5 | data Foo where 6 | -- ^^^^ keyword.other.data.haskell 7 | MkFoo :: Foo 8 | -- ^^^^^ constant.other.haskell 9 | -- ^^^ storage.type.haskell 10 | 11 | myFoo :: Foo 12 | -- ^^^^^ entity.name.function.haskell 13 | -- ^^^^^^^^^^^^ meta.function.type-declaration.haskell 14 | -- ^^^^^^^^^^^^ - meta.declaration.data.generalized.haskell 15 | myFoo = foo 16 | -------------------------------------------------------------------------------- /test/tests/WildcardExport.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Bug with wildcard export consuming a single parenthesis" 2 | 3 | module M 4 | ( S1(..), S2 (..) 5 | -- ^^ ^^ variable.other.member.wildcard.haskell 6 | , T 7 | ( .. , ( ..! ), ( :.. ), P, Q ) 8 | -- ^^ variable.other.member.wildcard.haskell 9 | -- ^^ ^^ - variable.other.member.wildcard.haskell 10 | , foo 11 | -- ^^^ entity.name.function.haskell 12 | -- ^^^ - invalid 13 | ) 14 | where 15 | -------------------------------------------------------------------------------- /test/tickets/T0131.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "LiquidHaskell annotations" 2 | 3 | {-@ incr :: x:Nat -> {v:Nat | v > x} @-} 4 | -- <--------------------------------------- block.liquidhaskell.haskell 5 | -- ^^ keyword.operator.double-colon.haskell 6 | -- ^^ keyword.operator.arrow.haskell 7 | -- -------------------------------- - comment.block.haskell 8 | -- ^^^ - keyword.type.operator.haskell 9 | incr :: Int -> Int 10 | incr x = x + 1 11 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.exclude": { 4 | "out": true, // set this to true to hide the "out" folder with the compiled JS files 5 | "node_modules": true 6 | }, 7 | "search.exclude": { 8 | "out": true // set this to false to include "out" folder in search results 9 | }, 10 | "typescript.tsdk": "./node_modules/typescript/lib" // we want to use the TS server from our node_modules folder to control its version 11 | } 12 | -------------------------------------------------------------------------------- /test/tickets/T0064.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Comments in module exports" 2 | 3 | module M 4 | -- ( f 5 | -- ^ comment.line.double-dash.haskell 6 | -- where 7 | -- ^^^^^ comment.line.double-dash.haskell 8 | where 9 | -- ^^^^^ keyword.other.where.haskell 10 | 11 | 12 | module M 13 | ( f 14 | -- ^ meta.declaration.exports.haskell entity.name.function.haskell 15 | -- g 16 | -- ^ comment.line.double-dash.haskell 17 | ) where 18 | -- ^^^^^ keyword.other.where.haskell 19 | -------------------------------------------------------------------------------- /test/tickets/T0070.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Custom operators" 2 | 3 | data (:-> ) 4 | -- ^^^ storage.type.operator.haskell 5 | data ( :=>) a b c = D 6 | -- ^^^ storage.type.operator.haskell 7 | -- ^ ^ ^ variable.other.generic-type.haskell 8 | -- ^ constant.other.haskell 9 | 10 | f :: a :-> b -> c :=> e 11 | -- ^^^ storage.type.operator.infix.haskell 12 | -- ^^ keyword.operator.arrow.haskell 13 | -- ^^^ storage.type.operator.infix.haskell 14 | 15 | -------------------------------------------------------------------------------- /test/tests/Forall.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "forall dot over multiple lines" 2 | 3 | 4 | 5 | f :: forall a 6 | -- ^^^^^^ keyword.other.forall.haskell 7 | . b 8 | -- ^ keyword.operator.period.haskell 9 | 10 | 11 | type T :: forall a 12 | -- ^^^^^^ keyword.other.forall.haskell 13 | . b 14 | -- ^ keyword.operator.period.haskell 15 | 16 | type T ( a :: forall b 17 | -- ^^^^^^ keyword.other.forall.haskell 18 | . c ) = D 19 | -- ^ keyword.operator.period.haskell 20 | -------------------------------------------------------------------------------- /syntax-examples/haskell.hs: -------------------------------------------------------------------------------- 1 | 2 | someFunc :: IO Int 3 | someFunc = do 4 | another argument 5 | arg :: Type 6 | let x = 6 :: Int 7 | a `Infix.Operator.func` b 8 | a `func` b 9 | a :: Bool <- something 10 | if a then b :: Int else g 11 | case (a :: Bool) of 12 | Nothing -> b 13 | return 6 14 | where 15 | ident = 4 16 | ident' = 9 17 | 18 | 19 | anotherFunc arg = do 20 | { let thing = 5> 21 | ; arg <- doSomething 5 22 | ; let thing = 5 23 | ; return 8 24 | } 25 | -------------------------------------------------------------------------------- /test/tests/PragmaComments.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Comments inside pragma" 2 | 3 | {-# LANGUAGE 4 | -- Type level programming 5 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-dash.haskell 6 | DataKinds, PolyKinds, 7 | -- Generics 8 | -- ^^^^^^^^^^^ comment.line.double-dash.haskell 9 | DeriveGeneric, DeriveAnyClass, DerivingVia 10 | {- Type applications -} 11 | -- ^^^^^^^^^^^^^^^^^^^^^^^ comment.block.haskell 12 | , TypeApplications, AllowAmbiguousTypes 13 | #-} 14 | -------------------------------------------------------------------------------- /syntaxes/C2Hs.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileTypes": [ "chs" ], 3 | "name": "C2Hs", 4 | "scopeName": "source.c2hs", 5 | "patterns": [ 6 | { 7 | "begin": "\\{#", 8 | "end": "#\\}", 9 | "beginCaptures": { 10 | "0": { 11 | "name": "punctuation.definition.preprocessor.begin.c2hs" 12 | } 13 | }, 14 | "endCaptures": { 15 | "0": { 16 | "name": "punctuation.definition.preprocessor.end.c2hs" 17 | } 18 | }, 19 | "name": "meta.preprocessor.c2hs" 20 | }, 21 | { "include": "source.haskell" } 22 | ] 23 | } -------------------------------------------------------------------------------- /test/tickets/T0175.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Unicode forall" 2 | 3 | foo :: (∀ a. Num a => a -> a) -> (Int,Double) -> (Int,Double) 4 | -- ^ keyword.other.forall.haskell 5 | -- ^ keyword.operator.period.haskell 6 | foo f (a,b) = (f a, f b) 7 | 8 | bar :: (forall a. Num a => a -> a) -> (Int,Double) -> (Int,Double) 9 | -- ^^^^^^ keyword.other.forall.haskell 10 | -- ^ keyword.operator.period.haskell 11 | bar f (a,b) = (f a, f b) 12 | 13 | notForall :: x ∀∀ y -> z 14 | -- ^^ - keyword.other.forall.haskell 15 | -------------------------------------------------------------------------------- /syntax-examples/cabal.cabal: -------------------------------------------------------------------------------- 1 | -- A comment 2 | 3 | name: test-name 4 | author: Someone 5 | 6 | common common 7 | build-depends: base 8 | 9 | library 10 | import: common 11 | build-depends: template-haskell 12 | extra-library-flavours: test 13 | extra-dynamic-library-flavours: test 14 | autogen-includes: test.h 15 | virtual-modules: M 16 | x-my-option-1: test 17 | 18 | library sublib 19 | import: common 20 | visibility: private 21 | hs-source-dirs: src 22 | 23 | executable my-exec 24 | build-depends: test-name, sublib 25 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## For changes related to the grammar 2 | 3 | - Please add a test case. 4 | 5 | - For changes to regular Haskell code simply add a new section to `test/syntax-examples/test.hs`. 6 | Make sure your case has a descriptive comment about what it is covering. 7 | 8 | - When adding foreign definitions, i.e. embeddings, add a new test file for the embedding in 9 | question. 10 | 11 | - Add your changes to the `CHANGELOG.md` file, ideally with a reference to the issue the PR is 12 | fixing. Also feel free to credit yourself there. 13 | -------------------------------------------------------------------------------- /test/tickets/T0136.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Promotion ticks" 2 | 3 | f :: proxy ( 'CD a b ) -> proxy ( a '`CD` b ) 4 | -- ^^ storage.type.haskell 5 | -- ^^ storage.type.infix.haskell 6 | -- ^ ^ keyword.operator.promotion.haskell 7 | 8 | g :: proxy ( '(:< ) a b ) -> proxy ( a ':< b ) 9 | -- ^^ storage.type.operator.haskell 10 | -- ^^ storage.type.operator.infix.haskell 11 | -- ^ ^ keyword.operator.promotion.haskell -------------------------------------------------------------------------------- /syntax-examples/happy.y: -------------------------------------------------------------------------------- 1 | { 2 | 3 | module Happy where 4 | 5 | import Foo as Bar 6 | import Baz (bax) 7 | 8 | } 9 | 10 | %monad { P } 11 | 12 | %name parse 13 | %tokentype { Token } 14 | %error { parseError } 15 | 16 | %token 17 | '+' { PLUS } 18 | num { NUMBER $$ } 19 | 20 | %left '+' 21 | 22 | %% 23 | 24 | value :: { AST } 25 | : value '+' value { Add $1 $3 } 26 | | num { Number $1 } 27 | 28 | { 29 | 30 | data Token 31 | = PLUS 32 | | NUMBER Int 33 | 34 | data AST 35 | = Add AST AST 36 | | Number Int 37 | 38 | } 39 | -------------------------------------------------------------------------------- /test/tests/Arrows.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Arrow keywords" 2 | 3 | h a b = proc (a, r) -> do rec 4 | -- ^^ keyword.operator.arrow.haskell 5 | -- ^^^^ keyword.control.proc.haskell 6 | -- ^^ keyword.control.do.haskell 7 | -- ^^^ keyword.control.rec.haskell 8 | (f -< (a, r)) `h` \e -> g -< ((a, e), r) 9 | -- ^ keyword.operator.lambda.haskell 10 | -- ^^ keyword.operator.arrow.haskell 11 | -- ^^ ^^ keyword.operator.arrow.left.tail.haskell -------------------------------------------------------------------------------- /syntaxes/Hsc2Hs.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileTypes": [ "hsc" ], 3 | "name": "Hsc2Hs", 4 | "scopeName": "source.hsc", 5 | "patterns": [ 6 | { 7 | "begin": "#\\{", 8 | "end": "\\}", 9 | "beginCaptures": { 10 | "0": { 11 | "name": "punctuation.definition.preprocessor.begin.hsc" 12 | } 13 | }, 14 | "endCaptures": { 15 | "0": { 16 | "name": "punctuation.definition.preprocessor.end.hsc" 17 | } 18 | }, 19 | "name": "meta.preprocessor.hsc" 20 | }, 21 | { "include": "source.haskell" } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /DEVELOPMENT.md: -------------------------------------------------------------------------------- 1 | # Developer information 2 | 3 | In version 3.0 the grammar format has changed. For maintenance and conciseness resons we now use YAML as the grammar format. This means when making improvements to the grammar please edit `syntaxes/haskell.YAML-tmLanguage`. 4 | 5 | Since Visual Studio Code does not natively understand yaml grammars we use the `js-yaml` tool to generate `syntaxes/haskell.json`. The task configuration should automatically generate the `syntaxes/haskell.json` file that Visual Studio Code actually loads. Should you experience problems with the task configuration feel free to open a bug report. 6 | -------------------------------------------------------------------------------- /test/tests/Data1.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Indented data declarations" 2 | 3 | data T = C T 4 | 5 | data T = C T 6 | -- ^^^^ keyword.other.data.haskell 7 | -- ^ keyword.operator.eq.haskell 8 | -- ^ constant.other.haskell 9 | -- ^ ^ storage.type.haskell 10 | 11 | 12 | data instance T = C T 13 | -- ^^^^ keyword.other.data.haskell 14 | -- ^^^^^^^^ keyword.other.instance.haskell 15 | -- ^ keyword.operator.eq.haskell 16 | -- ^ constant.other.haskell 17 | -- ^ ^ storage.type.haskell 18 | 19 | -------------------------------------------------------------------------------- /test/tests/SymbolicPatternSynonyms.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Symbolic pattern synonyms" 2 | 3 | 4 | pattern (:<..<), (:<=..<=) :: t -> t -> Interval t 5 | -- ^^^^^^^ keyword.other.pattern.haskell 6 | -- ^^^^^ ^^^^^^^ constant.other.operator.haskell 7 | pattern (:<..<) s e = s :<..< e 8 | -- ^^^^^ constant.other.operator.haskell 9 | -- ^^^^^ constant.other.operator.infix.haskell 10 | pattern (:<=..<=) s e = s :<=..<= e 11 | -- ^^^^^^^ constant.other.operator.haskell 12 | -- ^^^^^^^ constant.other.operator.infix.haskell 13 | -------------------------------------------------------------------------------- /test/tickets/T0039b.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "forall dot not parsed as an operator" 2 | 3 | f :: forall a. a 4 | -- ^ keyword.operator.period.haskell 5 | g :: forall a . a -> ( forall b . b ) -> a 6 | -- ^ ^ keyword.operator.period.haskell 7 | 8 | data Exts = forall var . Class var => Exts var 9 | -- ^^^^^^ keyword.other.forall.haskell 10 | -- ^ keyword.operator.period.haskell 11 | 12 | data Exts where 13 | F :: forall var . Class var => Exts var 14 | -- ^^^^^^ keyword.other.forall.haskell 15 | -- ^ keyword.operator.period.haskell -------------------------------------------------------------------------------- /test/tests/ExportsMagicHash.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Exports with magic hash" 2 | 3 | module M 4 | ( T#(f#,C#,g#) 5 | -- ^ ^ storage.type.haskell 6 | -- ^ ^ entity.name.function.haskell 7 | , pattern P# 8 | -- ^^^^^^^ keyword.other.pattern.haskell 9 | -- ^ constant.other.haskell 10 | , f#, (+#), T# 11 | -- ^ entity.name.function.haskell 12 | -- ^ storage.type.haskell 13 | , type T# 14 | -- ^^^^ keyword.other.type.haskell 15 | -- ^ storage.type.haskell 16 | , type (-#) 17 | -- ^^^^ keyword.other.type.haskell 18 | -- ^^ storage.type.operator.haskell 19 | ) 20 | where 21 | -------------------------------------------------------------------------------- /test/tests/Newtype1.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Indented newtype declarations" 2 | 3 | newtype T = C T 4 | 5 | newtype T = C T 6 | -- ^^^^^^^ keyword.other.newtype.haskell 7 | -- ^ keyword.operator.eq.haskell 8 | -- ^ constant.other.haskell 9 | -- ^ ^ storage.type.haskell 10 | 11 | 12 | newtype instance T = C T 13 | -- ^^^^^^^ keyword.other.newtype.haskell 14 | -- ^^^^^^^^ keyword.other.instance.haskell 15 | -- ^ keyword.operator.eq.haskell 16 | -- ^ constant.other.haskell 17 | -- ^ ^ storage.type.haskell 18 | 19 | -------------------------------------------------------------------------------- /test/tests/QualifiedDo.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "QualifiedDo" 2 | 3 | {-# LANGUAGE QualifiedDo #-} 4 | -- ^^^^^^^^^^^ keyword.other.preprocessor.extension.haskell 5 | 6 | f :: IO () 7 | f = do 8 | -- ^^ keyword.control.do.haskell 9 | x <- runMAC $ 10 | 11 | MAC.mdo 12 | -- ^^^^ entity.name.namespace.haskell 13 | -- ^^^ keyword.control.mdo.haskell 14 | d <- label "y" 15 | box $ 16 | 17 | L.do 18 | -- ^^ entity.name.namespace.haskell 19 | -- ^^ keyword.control.do.haskell 20 | r <- L.f d 21 | L.g r 22 | L.return r 23 | 24 | MAC.return d 25 | 26 | print x 27 | -------------------------------------------------------------------------------- /test/tickets/T0023.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Empty quasi-quote" 2 | 3 | instance Show NixIndexException where 4 | show (NixEnvFail errCode _ _) = [i||] 5 | -- ^ ^ keyword.operator.quasi-quotation.begin.haskell 6 | -- ^ entity.name.quasi-quoter.haskell 7 | -- ^^ keyword.operator.quasi-quotation.end.haskell 8 | show ParseNixEnvResError = "Failed to parse the output of nix-env" 9 | -- <------------------------------------------------------------------ - meta.quasi-quotation.haskell 10 | 11 | type S = String 12 | 13 | -- <--------------- -meta.quasi-quotation.haskell 14 | -------------------------------------------------------------------------------- /test/tickets/T0031.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Keyword identifiers with prime" 2 | 3 | let' = 5 4 | -- <--- - keyword.other.let.haskell 5 | class' = 4 6 | -- <----- - keyword.other.class.haskell 7 | module' = 6 8 | -- <------ - keyword.other.module.haskell 9 | instance' = 3 10 | -- <-------- - keyword.other.instance.haskell 11 | where' = 0 12 | -- <----- - keyword.other.where.haskell 13 | rec' = 6 14 | -- <--- - keyword.other.haskell 15 | import' = 5 16 | -- <------ - meta.import.haskell keyword.other.import.haskell 17 | if' = 6 18 | -- <-- - keyword.control.haskell 19 | else' = 7 20 | -- <---- - keyword.control.haskell 21 | then' = 0 22 | -- <---- - keyword.control.haskell -------------------------------------------------------------------------------- /test/tickets/T0015.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Deriving for ADTs with sums and records" 2 | 3 | data Feed = 4 | BuildTask { 5 | blokName :: String, 6 | outPathBuild :: FilePath, 7 | relPath :: FilePath, 8 | srcFile :: Files.File 9 | } 10 | deriving Eq 11 | -- <~~-------- meta.deriving.haskell 12 | 13 | data Query 14 | = All 15 | | Some { 16 | feeds :: [String], 17 | cats :: [String], 18 | dates :: QueryDate 19 | } 20 | deriving Read 21 | -- <~~---------- meta.deriving.haskell 22 | 23 | 24 | data QueryDate 25 | = AnyDate 26 | | Between String String 27 | deriving Read 28 | -- <~~---------- meta.deriving.haskell 29 | -------------------------------------------------------------------------------- /test/tickets/T0121.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Comments in data constructors" 2 | 3 | data Person = Person 4 | { name :: String, -- comment 5 | -- ^^^^^^^^^^ comment.line.double-dash.haskell 6 | sons :: [Person] -- comment 7 | -- ^^^^^^^^^^ comment.line.double-dash.haskell 8 | } 9 | 10 | 11 | {- comment1 -} 12 | -- <------------- comment.block.haskell 13 | {- comment 2 -} 14 | -- <~~------------- comment.block.haskell 15 | data A where {- comment3 -} 16 | -- ^^^^^^^^^^^^^^ comment.block.haskell 17 | {- comment4 -} 18 | -- <~~------------- comment.block.haskell 19 | {- comment5 -} 20 | -- <------------- comment.block.haskell -------------------------------------------------------------------------------- /test/tickets/T0118.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Record fields with extra spaces" 2 | 3 | data Record a b = 4 | Record 5 | { short :: a 6 | -- ^^^^^ variable.other.member.definition.haskell 7 | -- ^ variable.other.generic-type.haskell 8 | , longer :: b 9 | -- ^^^^^^ variable.other.member.definition.haskell 10 | -- ^ variable.other.generic-type.haskell 11 | , tiny :: a 12 | -- ^^^^ variable.other.member.definition.haskell 13 | -- ^ variable.other.generic-type.haskell 14 | , spacious::b 15 | -- ^^^^^^^^ variable.other.member.definition.haskell 16 | -- ^ variable.other.generic-type.haskell 17 | } 18 | -------------------------------------------------------------------------------- /test/tests/Data2.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Indented multiline data declarations (= on different line)" 2 | 3 | data T 4 | = C T 5 | 6 | data T 7 | -- ^^^^ keyword.other.data.haskell 8 | -- ^ storage.type.haskell 9 | = C T 10 | -- ^ keyword.operator.eq.haskell 11 | -- ^ constant.other.haskell 12 | -- ^ storage.type.haskell 13 | 14 | data instance T 15 | -- ^^^^ keyword.other.data.haskell 16 | -- ^^^^^^^^ keyword.other.instance.haskell 17 | -- ^ storage.type.haskell 18 | = C T 19 | -- ^ keyword.operator.eq.haskell 20 | -- ^ constant.other.haskell 21 | -- ^ storage.type.haskell 22 | -------------------------------------------------------------------------------- /test/tests/Data3.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Indented multiline data declarations (= on same line)" 2 | 3 | data T = 4 | C T 5 | 6 | data T = 7 | -- ^^^^ keyword.other.data.haskell 8 | -- ^ storage.type.haskell 9 | -- ^ keyword.operator.eq.haskell 10 | C T 11 | -- ^ constant.other.haskell 12 | -- ^ storage.type.haskell 13 | 14 | data instance T = 15 | -- ^^^^ keyword.other.data.haskell 16 | -- ^^^^^^^^ keyword.other.instance.haskell 17 | -- ^ storage.type.haskell 18 | -- ^ keyword.operator.eq.haskell 19 | C T 20 | -- ^ constant.other.haskell 21 | -- ^ storage.type.haskell 22 | -------------------------------------------------------------------------------- /test/tests/LiterateHaskell.lhs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "text.tex.latex.haskell" "Literate Haskell" 2 | 3 | > \ x -> x + x 4 | -- <~~- keyword.operator.lambda.haskell 5 | -- ^^ keyword.operator.arrow.haskell 6 | -- ^ keyword.operator.infix.haskell 7 | 8 | \begin{code} 9 | -- <------------ meta.embedded.block.haskell.latex 10 | \ x -> x + x 11 | -- <- keyword.operator.lambda.haskell 12 | -- ^^ keyword.operator.arrow.haskell 13 | -- ^ keyword.operator.infix.haskell 14 | \end{code} 15 | -- <---------- meta.embedded.block.haskell.latex 16 | 17 | \ x -> x + x 18 | -- <- - keyword.operator.lambda.haskell 19 | -- ^^ - keyword.operator.arrow.haskell 20 | -- ^ - keyword.operator.infix.haskell 21 | -------------------------------------------------------------------------------- /test/tickets/T0035.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Data kind signatures" 2 | 3 | data D (a :: Kind) (b :: k -> [Type]) = D 4 | -- <---- keyword.other.data.haskell 5 | -- ^ variable.other.generic-type.haskell 6 | -- ^^ keyword.operator.double-colon.haskell 7 | 8 | data Tuple (ts :: [Type]) where 9 | -- <---- keyword.other.data.haskell 10 | -- ^^ variable.other.generic-type.haskell 11 | -- ^^ keyword.operator.double-colon.haskell 12 | Nil :: Tuple '[] 13 | Cons :: !t -> !(Tuple ts) -> Tuple (t : ts) 14 | 15 | data GADT2 :: Type -> Type where 16 | -- <---- keyword.other.data.haskell 17 | -- ^^ keyword.operator.double-colon.haskell 18 | C2 :: GADT2 Int 19 | -------------------------------------------------------------------------------- /C2Hs-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | "lineComment": "--", 4 | "blockComment": ["{-", "-}"] 5 | }, 6 | "brackets": [ 7 | ["{", "}"], 8 | ["[", "]"], 9 | ["(", ")"] 10 | ], 11 | "autoClosingPairs": [ 12 | { "open": "{", "close": "}" }, 13 | { "open": "[", "close": "]" }, 14 | { "open": "(", "close": ")" }, 15 | { "open": "\"", "close": "\"", "notIn": ["string"] }, 16 | { "open": "`", "close": "`", "notIn": ["string", "comment"] } 17 | ], 18 | "surroundingPairs": [ 19 | ["{", "}"], 20 | ["[", "]"], 21 | ["(", ")"], 22 | ["'", "'"], 23 | ["\"", "\""], 24 | ["`", "`"] 25 | ], 26 | "folding": { 27 | "offSide": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test/tests/Newtype2.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Indented multiline newtype declarations (= on different line)" 2 | 3 | newtype T 4 | = C T 5 | 6 | newtype T 7 | -- ^^^^^^ keyword.other.newtype.haskell 8 | -- ^ storage.type.haskell 9 | = C T 10 | -- ^ keyword.operator.eq.haskell 11 | -- ^ constant.other.haskell 12 | -- ^ storage.type.haskell 13 | 14 | newtype instance T 15 | -- ^^^^^^^ keyword.other.newtype.haskell 16 | -- ^^^^^^^^ keyword.other.instance.haskell 17 | -- ^ storage.type.haskell 18 | = C T 19 | -- ^ keyword.operator.eq.haskell 20 | -- ^ constant.other.haskell 21 | -- ^ storage.type.haskell 22 | -------------------------------------------------------------------------------- /test/tests/Newtype3.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Indented multiline newtype declarations (= on same line)" 2 | 3 | newtype T = 4 | C T 5 | 6 | newtype T = 7 | -- ^^^^^^^ keyword.other.newtype.haskell 8 | -- ^ storage.type.haskell 9 | -- ^ keyword.operator.eq.haskell 10 | C T 11 | -- ^ constant.other.haskell 12 | -- ^ storage.type.haskell 13 | 14 | newtype instance T = 15 | -- ^^^^^^^ keyword.other.newtype.haskell 16 | -- ^^^^^^^^ keyword.other.instance.haskell 17 | -- ^ storage.type.haskell 18 | -- ^ keyword.operator.eq.haskell 19 | C T 20 | -- ^ constant.other.haskell 21 | -- ^ storage.type.haskell 22 | -------------------------------------------------------------------------------- /test/tickets/T0002.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Comments in module exports" 2 | 3 | module Module 4 | -- <------ meta.declaration.module.haskell 5 | ( 6 | -- main func <- disable highlighting 7 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-dash.haskell 8 | foo 9 | -- ^^^ meta.declaration.exports.haskell entity.name.function.haskell 10 | {- disable, too 11 | -- ^^^^^^^^^^^^ comment.block.haskell 12 | -} 13 | , bar, bar 14 | -- ^^^ meta.declaration.exports.haskell entity.name.function.haskell 15 | -- ^^^ meta.declaration.exports.haskell entity.name.function.haskell 16 | ) {- comm -} where 17 | -- ^^^^ comment.block.haskell 18 | -- ^^^^^ keyword.other.where.haskell 19 | -------------------------------------------------------------------------------- /test/tests/MultiLineTypeSignatures.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Multi-line type signatures" 2 | 3 | f :: A 4 | -- ^ storage.type.haskell 5 | -> B 6 | -- ^ storage.type.haskell 7 | -> C 8 | -- ^ storage.type.haskell 9 | 10 | f 11 | :: A -> B 12 | -- ^ ^ storage.type.haskell 13 | 14 | f 15 | :: forall a b 16 | -- ^^^^^^ keyword.other.forall.haskell 17 | -- ^ ^ variable.other.generic-type.haskell 18 | . C x 19 | -- ^ storage.type.haskell 20 | -- ^ variable.other.generic-type.haskell 21 | => D a 22 | -- ^ storage.type.haskell 23 | -- ^ variable.other.generic-type.haskell 24 | => E b 25 | -- ^ storage.type.haskell 26 | -- ^ variable.other.generic-type.haskell 27 | -> G 28 | -- ^ storage.type.haskell -------------------------------------------------------------------------------- /.github/workflows/github-ci.yml: -------------------------------------------------------------------------------- 1 | name: language-haskell CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | strategy: 15 | matrix: 16 | node-version: [18.x] 17 | 18 | steps: 19 | 20 | - uses: actions/checkout@v2 21 | 22 | - name: Setup node 23 | uses: actions/setup-node@v1 24 | with: 25 | node-version: ${{ matrix.node-version }} 26 | 27 | - name: Install dependencies 28 | run: npm install -g js-yaml vscode-tmgrammar-test 29 | 30 | - name: Generate grammar JSON files 31 | run: make grammars 32 | 33 | - name: Run tests 34 | run: make test 35 | -------------------------------------------------------------------------------- /haskell-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | "lineComment": "--", 4 | "blockComment": ["{-", "-}"] 5 | }, 6 | "brackets": [ 7 | ["{", "}"], 8 | ["[", "]"], 9 | ["(", ")"] 10 | ], 11 | "autoClosingPairs": [ 12 | { "open": "{", "close": "}" }, 13 | { "open": "[", "close": "]" }, 14 | { "open": "(", "close": ")" }, 15 | { "open": "\"", "close": "\"", "notIn": ["string"] }, 16 | { "open": "`", "close": "`", "notIn": ["string", "comment"] } 17 | ], 18 | "surroundingPairs": [ 19 | ["{", "}"], 20 | ["[", "]"], 21 | ["(", ")"], 22 | ["'", "'"], 23 | ["\"", "\""], 24 | ["`", "`"] 25 | ], 26 | "folding": { 27 | "offSide": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Hsc2Hs-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | "lineComment": "--", 4 | "blockComment": ["{-", "-}"] 5 | }, 6 | "brackets": [ 7 | ["{", "}"], 8 | ["[", "]"], 9 | ["(", ")"] 10 | ], 11 | "autoClosingPairs": [ 12 | { "open": "{", "close": "}" }, 13 | { "open": "[", "close": "]" }, 14 | { "open": "(", "close": ")" }, 15 | { "open": "\"", "close": "\"", "notIn": ["string"] }, 16 | { "open": "`", "close": "`", "notIn": ["string", "comment"] } 17 | ], 18 | "surroundingPairs": [ 19 | ["{", "}"], 20 | ["[", "]"], 21 | ["(", ")"], 22 | ["'", "'"], 23 | ["\"", "\""], 24 | ["`", "`"] 25 | ], 26 | "folding": { 27 | "offSide": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /literate-haskell-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | "lineComment": "%", 4 | "blockComment": ["{-", "-}"] 5 | }, 6 | "brackets": [ 7 | ["{", "}"], 8 | ["[", "]"], 9 | ["(", ")"] 10 | ], 11 | "autoClosingPairs": [ 12 | { "open": "{", "close": "}" }, 13 | { "open": "[", "close": "]" }, 14 | { "open": "(", "close": ")" }, 15 | { "open": "\"", "close": "\"", "notIn": ["string"] }, 16 | { "open": "`", "close": "`", "notIn": ["string", "comment"] } 17 | ], 18 | "surroundingPairs": [ 19 | ["{", "}"], 20 | ["[", "]"], 21 | ["(", ")"], 22 | ["'", "'"], 23 | ["\"", "\""], 24 | ["`", "`"] 25 | ], 26 | "folding": { 27 | "offSide": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test/tests/TypeVsData.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Edge cases for type vs value highlighting" 2 | 3 | fun = do 4 | x :: T -> T <- D ( \ (x :: T) -> D ) 5 | -- ^ - variable.other.generic-type.haskell 6 | -- ^ ^ ^ storage.type.haskell 7 | -- ^ ^ constant.other.haskell 8 | 9 | a = D { a = D :: T } D 10 | -- ^ storage.type.haskell 11 | -- ^ ^ ^ constant.other.haskell 12 | 13 | x :: T -> 14 | 15 | -- comment 16 | {- 17 | comment 18 | -} 19 | 20 | 21 | T 22 | -- ^ storage.type.haskell 23 | 24 | 25 | x 26 | :: T -> 27 | 28 | -- comment 29 | {- 30 | comment 31 | -} 32 | 33 | 34 | T 35 | -- ^ storage.type.haskell 36 | -------------------------------------------------------------------------------- /src/extension.ts: -------------------------------------------------------------------------------- 1 | 2 | import vscode = require('vscode'); 3 | 4 | const MATCH_NOTHING_RE = /$^/; 5 | 6 | export function activate(context: vscode.ExtensionContext) { 7 | 8 | vscode.languages.setLanguageConfiguration('haskell', { 9 | onEnterRules: [ 10 | { 11 | beforeText: vscode.workspace.getConfiguration('haskell').indentationRules.enabled 12 | ? /(\bif\b(?!')(.(?!then))*|\b(then|else|m?do|of|let|in|where)\b(?!')|=|->|>>=|>=>|=<<|(^(data)( |\t)+(\w|')+( |\t)*))( |\t)*$/ 13 | : MATCH_NOTHING_RE, 14 | action: { indentAction: vscode.IndentAction.Indent } 15 | } 16 | ], 17 | wordPattern: /([\w'_][\w'_\d]*)|([0-9]+\.[0-9]+([eE][+-]?[0-9]+)?|[0-9]+[eE][+-]?[0-9]+)/ 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /test/tickets/T0072b2.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Deriving strategies (same line)" 2 | 3 | newtype B = B deriving A via B 4 | -- ^^^^^^^^ keyword.other.deriving.haskell 5 | -- ^^^ keyword.other.deriving.strategy.via.haskell 6 | -- ^ ^ storage.type.haskell 7 | data B = B deriving stock ( Eq, Generic ) 8 | -- ^^^^^^^^ keyword.other.deriving.haskell 9 | -- ^^^^^ keyword.other.deriving.strategy.stock.haskell 10 | -- ^^ ^^^^^^^ storage.type.haskell 11 | data B = B deriving anyclass NFData 12 | -- ^^^^^^^^ keyword.other.deriving.haskell 13 | -- ^^^^^^^^ keyword.other.deriving.strategy.anyclass.haskell 14 | -- ^^^^^^ storage.type.haskell 15 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CONVERT=npx js-yaml 2 | VSCE=npx vsce 3 | SYNTAXES=haskell cabal literateHaskell alex happy 4 | JSON_TARGETS=$(addsuffix .json,$(addprefix syntaxes/,$(SYNTAXES))) 5 | SCOPE_LISTS=$(addsuffix .md,$(addprefix scope-lists/,$(SYNTAXES))) 6 | 7 | .PHONY: all test publish package 8 | 9 | all: grammars scopes 10 | 11 | grammars: $(JSON_TARGETS) 12 | 13 | scopes: $(SCOPE_LISTS) 14 | 15 | scope-lists/%.md: scope-lists/%.yaml 16 | scope-lists/refresh.hs md $< $@ 17 | 18 | scope-lists/%.yaml: syntaxes/%.YAML-tmLanguage 19 | scope-lists/refresh.hs db $< $@ 20 | 21 | test: grammars 22 | cd test && bash test.sh 23 | 24 | %.json: %.YAML-tmLanguage 25 | $(CONVERT) $< > $@ 26 | 27 | publish: all 28 | $(VSCE) publish 29 | 30 | package: all 31 | $(VSCE) package 32 | 33 | clean: 34 | rm $(JSON_TARGETS) -------------------------------------------------------------------------------- /test/tickets/T0111.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Multi line type aliases" 2 | 3 | type T a = 4 | Constr 5 | -- ^^^^^^ storage.type.haskell 6 | a 7 | -- ^ variable.other.generic-type.haskell 8 | Int 9 | -- ^^^ storage.type.haskell 10 | 11 | -- Multi line type alias with infix constructors 12 | 13 | type UserApi = "users" :> Body '[JSON] 14 | -- ^^ storage.type.operator.infix.haskell 15 | :> Post '[JSON] 16 | -- ^^^^ storage.type.haskell 17 | :<|> "users" :> Capture "userid" 18 | -- ^^^^ ^^ storage.type.operator.infix.haskell 19 | -- ^^^^^^^^ string.quoted.double.haskell 20 | :> ReqBody '[JSON] 21 | -- ^^^^^^^ storage.type.haskell 22 | -------------------------------------------------------------------------------- /test/tickets/T0069.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Parentheses in import and export lists" 2 | module Main ( 3 | Foo((+-)), func1 4 | -- ^^ meta.declaration.exports.haskell entity.name.function.infix.haskell 5 | -- ^^^^^ meta.declaration.exports.haskell entity.name.function.haskell 6 | -- ^^^^^ - invalid 7 | , Bar((:->), (:->>)), Baz, func5 8 | -- ^^^ ^^^^ meta.declaration.exports.haskell constant.other.operator.prefix.haskell 9 | -- ^^^ meta.declaration.exports.haskell storage.type.haskell 10 | -- ^^^^^ meta.declaration.exports.haskell entity.name.function.haskell 11 | ) where 12 | 13 | import Data.Sequence ( Seq() ) 14 | -- ^^^^^ meta.import.haskell 15 | import Unison.Name 16 | -- <------------------ - invalid -------------------------------------------------------------------------------- /test/tickets/T0020b.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Fields in GADTs" 2 | 3 | data A where 4 | A :: { field1 :: Int, field2 :: Int } -> A 5 | -- ^^^^^^ ^^^^^^ meta.record.definition.haskell variable.other.member.definition.haskell 6 | -- ^^^^^^ ^^^^^^^ - variable.other.generic-type.haskell 7 | -- ^^^ ^^^ meta.record.definition.haskell storage.type.haskell 8 | 9 | data B where 10 | B 11 | :: { field3 :: Bool 12 | -- ^^^^^^ meta.record.definition.haskell variable.other.member.definition.haskell 13 | -- ^^^^^^^ - variable.other.generic-type.haskell 14 | , field4 :: Int 15 | -- ^^^^^^ meta.record.definition.haskell variable.other.member.definition.haskell 16 | -- ^^^^^^^ - variable.other.generic-type.haskell 17 | } 18 | -> B -------------------------------------------------------------------------------- /test/tickets/T0112.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Case-insensitive deprecation pragmas" 2 | 3 | module Web.Telegram.API.Lens {-# dEPrecatED "use labels from generic-lens instead" #-} 4 | -- ^^^^^^^^^^ keyword.other.preprocessor.pragma.haskell 5 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ string.quoted.double.haskell 6 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.preprocessor.haskell 7 | where 8 | 9 | {-# dEPrecatED foo "use labels from generic-lens instead" #-} 10 | -- ^^^^^^^^^^ keyword.other.preprocessor.pragma.haskell 11 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ string.quoted.double.haskell 12 | -- <------------------------------------------------------------- meta.preprocessor.haskell 13 | -------------------------------------------------------------------------------- /test/tickets/T0178.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Multiline type signature in brackets" 2 | 3 | proof :: SomeVeryLongExpression a b 4 | :~: SomeOtherLongExpression c d 5 | -- ^^^ storage.type.operator.infix.haskell 6 | -- ^^^^^^^^^^^^^^^^^^^^^^^ storage.type.haskell 7 | -- ^ ^ variable.other.generic-type.haskell 8 | 9 | quux ( proof :: SomeVeryLongExpression a b 10 | :~: SomeOtherLongExpression c d 11 | -- ^^^ storage.type.operator.infix.haskell 12 | -- ^^^^^^^^^^^^^^^^^^^^^^^ storage.type.haskell 13 | -- ^ ^ variable.other.generic-type.haskell 14 | ) 15 | 16 | quux [ x :: a 17 | B c ] 18 | -- ^ storage.type.haskell 19 | -- ^ variable.other.generic-type.haskell 20 | -------------------------------------------------------------------------------- /test/tests/Specialise.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Specialise pragma" 2 | 3 | {-# SPECIALISE INLINE [~2] foo :: B -> A #-} 4 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.preprocessor.haskell 5 | -- ^^^^^^^^^^ ^^^^^^ keyword.other.preprocessor.pragma.haskell 6 | -- ^^^^ meta.inlining-phase.haskell 7 | -- ^ ^ storage.type.haskell 8 | 9 | 10 | instance (Eq a) => Eq (Foo a) where { 11 | {-# SPECIALIZE [1] instance Eq (Foo [(Int, Bar)]) #-} 12 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.preprocessor.haskell 13 | -- ^^^^^^^^^^ keyword.other.preprocessor.pragma.haskell 14 | -- ^^^^^^^^ keyword.other.instance.haskell 15 | -- ^^ ^^^ ^^^ ^^^ storage.type.haskell 16 | } -------------------------------------------------------------------------------- /test/tickets/T0090.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Fixity declarations" 2 | 3 | infixl 6 :+ 4 | -- <------ keyword.other.fixity.infixl.haskell 5 | -- ^ constant.numeric.integral.decimal.haskell 6 | -- ^^ constant.other.operator.infix.haskell 7 | infixr 7 // 8 | -- ^ constant.numeric.integral.decimal.haskell 9 | -- <------ keyword.other.fixity.infixr.haskell 10 | -- ^^ keyword.operator.infix.haskell 11 | infix 2 `elem` 12 | -- ^^^^^ keyword.other.fixity.infix.haskell 13 | -- ^ constant.numeric.integral.decimal.haskell 14 | -- ^^^^^^ keyword.operator.function.infix.haskell 15 | infix 0 `Cons` 16 | -- ^^^^^ keyword.other.fixity.infix.haskell 17 | -- ^ constant.numeric.integral.decimal.haskell 18 | -- ^^^^^^ keyword.operator.function.infix.haskell 19 | -- ^^^^ constant.other.haskell 20 | -------------------------------------------------------------------------------- /test/tests/NonRecord.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Braces not indicating record syntax" 2 | 3 | where { 4 | -- ^^^^^ keyword.other.where.haskell 5 | -- ^ punctuation.brace.haskell 6 | -- ^ - meta.record.haskell 7 | a = A 8 | -- ^^^^^ - meta.record.haskell 9 | -- ^ - variable.other.member.haskell 10 | ; b = B 11 | -- ^^^^^^^^ - meta.record.haskell 12 | -- ^ - variable.other.member.haskell 13 | } 14 | -- ^ punctuation.brace.haskell 15 | -- ^ - meta.record.haskell 16 | 17 | 18 | class C a where { meth :: a } 19 | -- ^ ^ punctuation.brace.haskell 20 | -- ^^^^^^^^^^^^^ - meta.record.haskell 21 | -- ^^^^ - variable.other.member.haskell 22 | 23 | data C :: A -> B -> Type where { C :: A a b } 24 | -- ^^^^^^^^^^^^^^ - meta.record.haskell 25 | -------------------------------------------------------------------------------- /test/tests/ImportIndentation.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Indentation in imports" 2 | 3 | import 4 | -- ^^^^^^ keyword.other.import.haskell 5 | qualified 6 | -- ^^^^^^^^^ keyword.other.qualified.haskell 7 | 8 | 9 | I 10 | -- ^ entity.name.namespace.haskell 11 | 12 | as 13 | -- ^^ keyword.other.as.haskell 14 | 15 | J 16 | -- ^ entity.name.namespace.haskell 17 | hiding 18 | -- ^^^^^^ keyword.other.hiding.haskell 19 | ( 20 | f, A 21 | -- ^ entity.name.function.haskell 22 | -- ^ storage.type.haskell 23 | , B, g, (:<), 24 | -- ^ storage.type.haskell 25 | -- ^ entity.name.function.haskell 26 | -- ^^ storage.type.operator.haskell 27 | (>>>) 28 | -- ^^^ entity.name.function.infix.haskell 29 | ) 30 | -------------------------------------------------------------------------------- /test/tests/Language.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Language pragmas" 2 | 3 | {-# LANGUAGE DataKinds, PolyKinds, TypeFamilyDependencies #-} 4 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.preprocessor.haskell 5 | -- ^^^^^^^^ keyword.other.preprocessor.pragma.haskell 6 | -- ^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ keyword.other.preprocessor.extension.haskell 7 | {-# LANGUAGE NoMonomorphismRestriction #-} 8 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.preprocessor.haskell 9 | -- ^^^^^^^^ keyword.other.preprocessor.pragma.haskell 10 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^ keyword.other.preprocessor.extension.haskell 11 | 12 | {-# LANGUAGE NullaryTypeClasses #-} 13 | -- ^^^^^^^^^^^^^^^^^^ invalid.deprecated 14 | 15 | {-# LANGUAGE NotAKnownExtension #-} 16 | -- ^^^^^^^^^^^^^^^^^^ - keyword.other.preprocessor.extension.haskell 17 | -------------------------------------------------------------------------------- /test/tickets/T0020.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Fields in complex ADTs" 2 | 3 | 4 | data T2 5 | = Constr1 Int 6 | | Record2 { 7 | field1 :: Int, 8 | -- ^^^^^^ meta.record.definition.haskell variable.other.member.definition.haskell 9 | -- ^^^ meta.record.definition.haskell storage.type.haskell 10 | field2 :: Int 11 | -- ^^^^^^ meta.record.definition.haskell variable.other.member.definition.haskell 12 | -- ^^^ meta.record.definition.haskell storage.type.haskell 13 | } 14 | 15 | 16 | data T3 = T3 17 | { f1 :: Int 18 | -- ^^ meta.record.definition.haskell variable.other.member.definition.haskell 19 | -- ^^^ meta.record.definition.haskell storage.type.haskell 20 | , f2 :: Int 21 | -- ^^ meta.record.definition.haskell variable.other.member.definition.haskell 22 | -- ^^^ meta.record.definition.haskell storage.type.haskell 23 | } 24 | -------------------------------------------------------------------------------- /syntaxes/codeblock-cabal.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileTypes": [], 3 | "injectionSelector": "L:markup.fenced_code.block.markdown", 4 | "patterns": [ 5 | { 6 | "include": "#cabal-code-block" 7 | } 8 | ], 9 | "repository": { 10 | "cabal-code-block": { 11 | "begin": "\\b(cabal)\\b(\\s+[^`~]*)?$", 12 | "end": "(^|\\G)(?=\\s*[`~]{3,}\\s*$)", 13 | "patterns": [ 14 | { 15 | "begin": "(^|\\G)(\\s*)(.*)", 16 | "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)", 17 | "contentName": "meta.embedded.block.cabal", 18 | "patterns": [ 19 | { 20 | "include": "source.cabal" 21 | } 22 | ] 23 | } 24 | ] 25 | } 26 | }, 27 | "scopeName": "markdown.cabal.codeblock" 28 | } 29 | -------------------------------------------------------------------------------- /test/tickets/T0066.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Empty typeclass and empty instances" 2 | 3 | class A x where 4 | -- <----- keyword.other.class.haskell 5 | -- <---------- meta.declaration.class.haskell 6 | class B x 7 | -- <----- keyword.other.class.haskell 8 | -- <--------- meta.declaration.class.haskell 9 | 10 | normal :: Int 11 | -- <------ meta.function.type-declaration.haskell entity.name.function.haskell 12 | -- <------------- - invalid 13 | 14 | class C x => Dx 15 | -- <----- keyword.other.class.haskell 16 | -- <--------------- meta.declaration.class.haskell 17 | 18 | instance A x where 19 | -- <-------- keyword.other.instance.haskell 20 | -- <------------- meta.declaration.instance.haskell 21 | instance B x 22 | -- <-------- keyword.other.instance.haskell 23 | -- <------------ meta.declaration.instance.haskell 24 | instance C x => D x 25 | -- <-------- keyword.other.instance.haskell 26 | -- <------------------- meta.declaration.instance.haskell -------------------------------------------------------------------------------- /syntaxes/codeblock-haskell.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileTypes": [], 3 | "injectionSelector": "L:markup.fenced_code.block.markdown", 4 | "patterns": [ 5 | { 6 | "include": "#haskell-code-block" 7 | } 8 | ], 9 | "repository": { 10 | "haskell-code-block": { 11 | "begin": "\\b(haskell|hs)\\b(\\s+[^`~]*)?$", 12 | "end": "(^|\\G)(?=\\s*[`~]{3,}\\s*$)", 13 | "patterns": [ 14 | { 15 | "begin": "(^|\\G)(\\s*)(.*)", 16 | "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)", 17 | "contentName": "meta.embedded.block.haskell", 18 | "patterns": [ 19 | { 20 | "include": "source.haskell" 21 | } 22 | ] 23 | } 24 | ] 25 | } 26 | }, 27 | "scopeName": "markdown.haskell.codeblock" 28 | } 29 | -------------------------------------------------------------------------------- /test/tests/Fixity.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Fixity declarations" 2 | 3 | 4 | infixl 3 :+ 5 | -- ^^^^^^ keyword.other.fixity.infixl.haskell 6 | -- ^ constant.numeric.integral.decimal.haskell 7 | -- ^^ constant.other.operator.infix.haskell 8 | 9 | infixr 7 ---: 10 | -- ^^^^^^ keyword.other.fixity.infixr.haskell 11 | -- ^ constant.numeric.integral.decimal.haskell 12 | -- ^^^^ keyword.operator.infix.haskell 13 | 14 | infix 1 `Cons` 15 | -- ^^^^^ keyword.other.fixity.infix.haskell 16 | -- ^ constant.numeric.integral.decimal.haskell 17 | -- ^^^^ constant.other.haskell 18 | -- ^^^^^^ keyword.operator.function.infix.haskell 19 | 20 | infix 2 <|> -- comment 21 | -- ^^^^^ keyword.other.fixity.infix.haskell 22 | -- ^ constant.numeric.integral.decimal.haskell 23 | -- ^^^ keyword.operator.infix.haskell 24 | -- ^^^^^^^^^^ comment.line.double-dash.haskell 25 | -------------------------------------------------------------------------------- /test/tests/CommentLike.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Test ending of comment-like blocks" 2 | 3 | {- a b -} a b 4 | -- ^^^^^^^^^ comment.block.haskell 5 | -- ^ ^ - comment.block.haskell 6 | 7 | {-$ a b -} a b 8 | -- ^^^^^^^^^^ comment.block.documentation.haskell 9 | -- ^ ^ - comment.block.documentation.haskell 10 | 11 | {-# SPECIALISE foo :: a -> b #-} c d 12 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.preprocessor.haskell 13 | -- ^ ^ - meta.preprocessor.haskell 14 | 15 | {-@ foo :: A -> B @-} c d 16 | -- ^^^^^^^^^^^^^^^^^^^^^ block.liquidhaskell.haskell 17 | -- ^ ^ storage.type.haskell 18 | -- ^ ^ - block.liquidhaskell.haskell 19 | 20 | {-@ type NonEmpty a = {v:[a] | 0 < len v } @-} c d 21 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ block.liquidhaskell.haskell 22 | -- ^ ^ - block.liquidhaskell.haskell 23 | -------------------------------------------------------------------------------- /test/tests/Prefix.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Reserved prefix operators" 2 | 3 | 4 | data A = A !A | B !B 5 | -- ^ ^ keyword.operator.prefix.bang.haskell 6 | 7 | f ~(x,y) = _ 8 | -- ^ keyword.operator.prefix.tilde.haskell 9 | f !(!x,~P(z)) = _ 10 | -- ^ ^ keyword.operator.prefix.bang.haskell 11 | -- ^ keyword.operator.prefix.tilde.haskell 12 | 13 | f (a,b)!g 14 | -- ^ - keyword.operator.prefix.bang.haskell 15 | 16 | vec ! 3 17 | -- ^ - keyword.operator.prefix.bang.haskell 18 | vec Vector.! 3 19 | -- ^ - keyword.operator.prefix.bang.haskell 20 | a ~ b 21 | -- ^ - keyword.operator.prefix.tilde.haskell 22 | 23 | -1 24 | -- ^ keyword.operator.prefix.minus.haskell 25 | 1 - 2 26 | -- ^ - keyword.operator.prefix.minus.haskell 27 | -- ^ keyword.operator.infix.haskell 28 | a -+ b 29 | -- ^ - keyword.operator.prefix.minus.haskell 30 | a -#b 31 | -- ^ - keyword.operator.prefix.minus.haskell 32 | -------------------------------------------------------------------------------- /syntaxes/codeblock-literate-haskell.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileTypes": [], 3 | "injectionSelector": "L:markup.fenced_code.block.markdown", 4 | "patterns": [ 5 | { 6 | "include": "#lhaskell-code-block" 7 | } 8 | ], 9 | "repository": { 10 | "lhaskell-code-block": { 11 | "begin": "\\b(literate-haskell|lhaskell|lhs)\\b(\\s+[^`~]*)?$", 12 | "end": "(^|\\G)(?=\\s*[`~]{3,}\\s*$)", 13 | "patterns": [ 14 | { 15 | "begin": "(^|\\G)(\\s*)(.*)", 16 | "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)", 17 | "contentName": "meta.embedded.block.lhaskell", 18 | "patterns": [ 19 | { 20 | "include": "text.tex.latex.haskell" 21 | } 22 | ] 23 | } 24 | ] 25 | } 26 | }, 27 | "scopeName": "markdown.lhaskell.codeblock" 28 | } 29 | -------------------------------------------------------------------------------- /test/tickets/T0190.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Type variables in foreign import/export" 2 | 3 | foreign import ccall unsafe "memcmp" 4 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.import.foreign.haskell 5 | memcmp :: Ptr a -> Ptr (b :: ty) -> CSize -> IO CInt 6 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.import.foreign.haskell 7 | -- ^^^^^^ entity.name.function.haskell 8 | -- ^^ ^^ keyword.operator.double-colon.haskell 9 | -- ^ ^ ^^ - entity.name.function.haskell 10 | -- ^ ^ ^^ variable.other.generic-type.haskell 11 | -- ^^ ^^ ^^ keyword.operator.arrow.haskell 12 | -- ^^^ ^^^ ^^^^^ ^^ ^^^^ storage.type.haskell 13 | 14 | data A a = Mk A a 15 | -- ^^^^ keyword.other.data.haskell 16 | -- ^ ^ storage.type.haskell 17 | -- ^ ^ variable.other.generic-type.haskell 18 | -- ^^ constant.other.haskell 19 | -------------------------------------------------------------------------------- /test/tickets/T0072a.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Pattern synonyms" 2 | 3 | module Main 4 | ( pattern P ) where 5 | -- ^^^^^^^ meta.declaration.exports.haskell keyword.other.pattern.haskell 6 | -- ^ constant.other.haskell 7 | 8 | import M ( pattern Q ) 9 | -- ^^^^^^^ meta.declaration.exports.haskell keyword.other.pattern.haskell 10 | -- ^ constant.other.haskell 11 | 12 | 13 | pattern A :: T 14 | -- <------- keyword.other.pattern.haskell 15 | -- ^ constant.other.haskell 16 | -- ^ storage.type.haskell 17 | pattern (A b) = C 18 | -- <------- keyword.other.pattern.haskell 19 | -- ^ ^ constant.other.haskell 20 | 21 | pattern B :: A -> B 22 | -- <------- keyword.other.pattern.haskell 23 | -- ^ constant.other.haskell 24 | -- ^ ^ storage.type.haskell 25 | -> C 26 | -- ^ storage.type.haskell 27 | 28 | pattern A, B :: T 29 | -- <------- keyword.other.pattern.haskell 30 | -- ^ ^ constant.other.haskell 31 | -- ^ storage.type.haskell 32 | -------------------------------------------------------------------------------- /test/tickets/T0089.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Standalone deriving statements" 2 | 3 | deriving instance SomeClass => Eq a 4 | -- ^^^^^^^^ keyword.other.deriving.haskell 5 | -- ^^^^^^^^ keyword.other.instance.haskell 6 | -- ^^^^^^^^^ storage.type.haskell 7 | deriving instance Ord a => Ord (Expr a) 8 | -- ^^^^^^^^ keyword.other.deriving.haskell 9 | -- ^^^^^^^^ keyword.other.instance.haskell 10 | -- ^^^^ storage.type.haskell 11 | 12 | normal :: Int 13 | -- ^^^^^^ entity.name.function.haskell 14 | -- ^^^^^^^^^^^^^^ meta.function.type-declaration.haskell 15 | 16 | deriving instance SomeClass => Eq a 17 | -- <-------- keyword.other.deriving.haskell 18 | -- ^^^^^^^^ keyword.other.instance.haskell 19 | -- ^^^^^^^^^ storage.type.haskell 20 | deriving instance Ord a => Ord (Expr a) 21 | -- <-------- keyword.other.deriving.haskell 22 | -- ^^^^^^^^ keyword.other.instance.haskell 23 | -- ^^^^ storage.type.haskell 24 | -------------------------------------------------------------------------------- /test/tickets/T0038.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Record field names" 2 | 3 | data Data = Data { foo :: Int, bar :: Int } 4 | -- ^^^ meta.record.definition.haskell variable.other.member.definition.haskell 5 | -- ^^^ meta.record.definition.haskell variable.other.member.definition.haskell 6 | data Data = Data { 7 | foo :: Int, bar :: Int 8 | -- ^^^ meta.record.definition.haskell variable.other.member.definition.haskell 9 | -- ^^^ meta.record.definition.haskell variable.other.member.definition.haskell 10 | } 11 | data Data = Data { 12 | foo :: Int, 13 | -- ^^^ meta.record.definition.haskell variable.other.member.definition.haskell 14 | bar :: Int 15 | -- ^^^ meta.record.definition.haskell variable.other.member.definition.haskell 16 | } 17 | data Data = Data { 18 | foo :: Int 19 | -- ^^^ meta.record.definition.haskell variable.other.member.definition.haskell 20 | , bar :: Int 21 | -- ^^^ meta.record.definition.haskell variable.other.member.definition.haskell 22 | } 23 | -------------------------------------------------------------------------------- /test/tickets/T0073.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Visible type application" 2 | 3 | function = 4 | let l = [] @[( Int, f [ Bool ] )] in 5 | -- ^ meta.type-application.haskell 6 | -- ^^^ storage.type.haskell 7 | -- ^ variable.other.generic-type.haskell 8 | let x = "Hello" @String in 9 | -- ^ meta.type-application.haskell 10 | -- ^^^^^^ storage.type.haskell 11 | let c@(Some pattern) = undefined in 12 | -- ^ - meta.type-application.haskell 13 | -- ^^^^ constant.other.haskell 14 | let g = f @( g ([]) -> String ) in 15 | -- ^ meta.type-application.haskell 16 | -- ^ variable.other.generic-type.haskell 17 | let h = k @_ @a @Int 18 | -- ^ ^ ^ meta.type-application.haskell 19 | let a = b @ c 20 | -- ^ - meta.type-application.haskell 21 | undefined 22 | 23 | g = f @Bool(A) 24 | -- ^ meta.type-application.haskell 25 | -- ^^^^ storage.type.haskell 26 | -- ^ - storage.type.haskell 27 | -------------------------------------------------------------------------------- /test/tests/EndTypeSig.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Type annotation should end with closing brackets" 2 | 3 | 4 | ( x 5 | :: a b c ) d e f 6 | -- ^ ^ ^ variable.other.generic-type.haskell 7 | -- ^ ^ ^ - variable.other.generic-type.haskell 8 | 9 | (# x 10 | :: a b c #) d e f 11 | -- ^ ^ ^ variable.other.generic-type.haskell 12 | -- ^ ^ ^ - variable.other.generic-type.haskell 13 | 14 | [ x 15 | :: a b c ] d e f 16 | -- ^ ^ ^ variable.other.generic-type.haskell 17 | -- ^ ^ ^ - variable.other.generic-type.haskell 18 | 19 | ( x :: a b c ) d e f 20 | -- ^ ^ ^ variable.other.generic-type.haskell 21 | -- ^ ^ ^ - variable.other.generic-type.haskell 22 | 23 | (# x :: a b c #) d e f 24 | -- ^ ^ ^ variable.other.generic-type.haskell 25 | -- ^ ^ ^ - variable.other.generic-type.haskell 26 | 27 | [ x :: a b c ] d e f 28 | -- ^ ^ ^ variable.other.generic-type.haskell 29 | -- ^ ^ ^ - variable.other.generic-type.haskell -------------------------------------------------------------------------------- /syntax-examples/embedding.md: -------------------------------------------------------------------------------- 1 | # Test file to see if Haskell is embedded in markdown 2 | 3 | 4 | ```hs 5 | class MyClass a where 6 | aMethod :: a -> String 7 | 8 | main :: IO () 9 | main = putStrLn "Hello World" 10 | ``` 11 | 12 | ```haskell 13 | class MyClass a where 14 | aMethod :: a -> String 15 | 16 | main :: IO () 17 | main = putStrLn "Hello World" 18 | ``` 19 | 20 | 21 | ```lhs 22 | \begin{document} 23 | The surrounding stuff should be comments or perhaps even \LaTeX 24 | > class MyClass a where 25 | > aMethod :: a -> String 26 | 27 | > main :: IO () 28 | > main = putStrLn "Hello World" 29 | \end{document} 30 | ``` 31 | 32 | ```literate-haskell 33 | \begin{document} 34 | The surrounding stuff should be comments or perhaps even \LaTeX 35 | > class MyClass a where 36 | > aMethod :: a -> String 37 | 38 | > main :: IO () 39 | > main = putStrLn "Hello World" 40 | \end{document} 41 | ``` 42 | 43 | ```cabal 44 | name: test 45 | version: 0.5.6.7 46 | library 47 | build-depends: 48 | base == 5.0 || >= 3.0 49 | , mtl 50 | default-extensions: 51 | OverloadedStrings 52 | ``` 53 | -------------------------------------------------------------------------------- /syntaxes/literateHaskell.YAML-tmLanguage: -------------------------------------------------------------------------------- 1 | fileTypes: 2 | - lhs 3 | keyEquivalent: ^~H 4 | name: 'Literate Haskell' 5 | patterns: 6 | - begin: '^\s*((\\)begin)({)code(})(\s*\n)?' 7 | captures: 8 | '1': {name: support.function.be.latex} 9 | '2': {name: punctuation.definition.function.latex} 10 | '3': {name: punctuation.definition.arguments.begin.latex} 11 | '4': {name: punctuation.definition.arguments.end.latex} 12 | contentName: source.haskell.embedded.latex 13 | end: '^((\\)end)({)code(})' 14 | name: meta.embedded.block.haskell.latex 15 | patterns: 16 | - {include: source.haskell} 17 | - begin: '^(> )' 18 | beginCaptures: 19 | '1': {name: punctuation.definition.bird-track.haskell} 20 | comment: 'This breaks type signature detection for now, but it''s better than having no highlighting whatsoever.' 21 | contentName: source.haskell 22 | end: $ 23 | name: meta.embedded.haskell 24 | patterns: 25 | - {include: source.haskell} 26 | - include: text.tex.latex 27 | scopeName: text.tex.latex.haskell 28 | uuid: 439807F5-7129-487D-B5DC-95D5272B43DD 29 | -------------------------------------------------------------------------------- /test/tickets/T0146.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Highlighting in multiline type declarations" 2 | 3 | 4 | type GetDecks = 5 | -- <~~---- keyword.other.type.haskell 6 | -- ^^^^^^^^ storage.type.haskell 7 | -- ^ keyword.operator.eq.haskell 8 | MethodCall "getDecks" Cards 9 | -- ^^^^^^^^^^ ^^^^^ storage.type.haskell 10 | 11 | type GetDecks 12 | -- <~~---- keyword.other.type.haskell 13 | -- ^^^^^^^^ storage.type.haskell 14 | = MethodCall "getDecks" Cards 15 | -- ^ keyword.operator.eq.haskell 16 | -- ^^^^^^^^^^ ^^^^^ storage.type.haskell 17 | 18 | 19 | type GetDecks = 20 | -- <---- keyword.other.type.haskell 21 | -- ^^^^^^^^ storage.type.haskell 22 | -- ^ keyword.operator.eq.haskell 23 | MethodCall "getDecks" Cards 24 | -- <~~--------- storage.type.haskell 25 | -- ^^^^^ storage.type.haskell 26 | 27 | type GetDecks 28 | -- <---- keyword.other.type.haskell 29 | -- ^^^^^^^^ storage.type.haskell 30 | = MethodCall "getDecks" Cards 31 | -- <~~- keyword.operator.eq.haskell 32 | -- ^^^^^^^^^^ ^^^^^ storage.type.haskell 33 | -------------------------------------------------------------------------------- /test/tests/Kinds.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Kind signatures" 2 | 3 | data D (a :: Kind) (b :: k -> [Type]) = D 4 | -- ^ ^ ^ variable.other.generic-type.haskell 5 | -- ^^^^ ^^^^ storage.type.haskell 6 | -- ^^ ^^ keyword.operator.double-colon.haskell 7 | data D (a :: Kind) (b :: k -> [Type]) where 8 | -- ^ ^ ^ variable.other.generic-type.haskell 9 | -- ^^^^ ^^^^ storage.type.haskell 10 | -- ^^ ^^ keyword.operator.double-colon.haskell 11 | 12 | data D :: k -> [Type] where 13 | -- ^^ keyword.operator.double-colon.haskell 14 | -- ^ variable.other.generic-type.haskell 15 | -- ^^^^ storage.type.haskell 16 | 17 | 18 | colons :: forall (a :: (k :: l)). a -> (x :: a) -> k 19 | -- ^ ^ ^ ^ ^ ^ ^ variable.other.generic-type.haskell 20 | -- ^^ ^^ ^^ keyword.operator.double-colon.haskell 21 | data X ( a :: ( x :: k ) ) :: k 22 | -- ^ ^ ^ ^ variable.other.generic-type.haskell 23 | -- ^^ ^^ ^^ keyword.operator.double-colon.haskell -------------------------------------------------------------------------------- /test/tickets/T0102.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "GADT constructors" 2 | 3 | data GADT a where 4 | Constr :: A -> B -> GADT a 5 | -- ^^^^^^ constant.other.haskell 6 | -- ^ ^ ^^^^ storage.type.haskell 7 | 8 | data D a where D :: Int -> D String 9 | -- ^ constant.other.haskell 10 | -- ^^^ ^ ^^^^^^ storage.type.haskell 11 | 12 | data Expr a where 13 | I :: Int -> Expr Int 14 | -- ^ constant.other.haskell 15 | -- ^^^ storage.type.haskell 16 | B :: Bool -> Expr Bool 17 | -- ^ constant.other.haskell 18 | -- ^^^^ storage.type.haskell 19 | Add :: Expr Int 20 | -- ^^^ constant.other.haskell 21 | -- ^^^^ storage.type.haskell 22 | -> Expr Int -> Expr Int 23 | -- ^^^^ storage.type.haskell 24 | Mul :: Expr Int 25 | -- ^^^ constant.other.haskell 26 | -- ^^^^ storage.type.haskell 27 | -> Expr Int -> Expr Int 28 | -- ^^^^ storage.type.haskell 29 | Eq 30 | -- ^^ constant.other.haskell 31 | :: Eq a => 32 | -- ^^ storage.type.haskell 33 | Expr a -> Expr a -> Expr Bool 34 | -- ^^^^ storage.type.haskell 35 | -------------------------------------------------------------------------------- /syntax-examples/backpack.hsig: -------------------------------------------------------------------------------- 1 | signature Token 2 | ( Token 3 | , Pair 4 | , LayoutMode 5 | , nested 6 | , mismatch 7 | , unmatchedOpening 8 | , unmatchedClosing 9 | , lexicalError 10 | ) where 11 | 12 | import Data.Default 13 | import Data.Ix 14 | import GHC.Generics 15 | 16 | import Relative.Cat 17 | import Relative.Class 18 | import Relative.Delta 19 | import Relative.Located 20 | 21 | data Token 22 | instance Eq Token 23 | instance Ord Token 24 | instance Show Token 25 | instance Read Token 26 | instance Relative Token 27 | 28 | data Pair 29 | instance Eq Pair 30 | instance Ord Pair 31 | instance Show Pair 32 | instance Read Pair 33 | instance Ix Pair 34 | instance Enum Pair 35 | instance Bounded Pair 36 | instance Generic Pair 37 | 38 | data LayoutMode 39 | instance Eq LayoutMode 40 | instance Ord LayoutMode 41 | instance Show LayoutMode 42 | instance Read LayoutMode 43 | instance Default LayoutMode 44 | 45 | nested :: Located Pair -> Cat Token -> Token 46 | mismatch :: Located Pair -> Located Pair -> Cat Token -> Token 47 | unmatchedOpening :: Located Pair -> Token 48 | unmatchedClosing :: Located Pair -> Token 49 | lexicalError :: Delta -> String -> Token 50 | -------------------------------------------------------------------------------- /test/tickets/T0030.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Qualified infix functions" 2 | 3 | f = item `elem` list 4 | -- ^^^^ keyword.operator.function.infix.haskell 5 | g = item `Qual.member` set 6 | -- ^^^^^^^^^^^ keyword.operator.function.infix.haskell 7 | -- ^^^^^ entity.name.namespace.haskell 8 | -- ^^^^^^ - entity.name.namespace.haskell 9 | g = item `Qual.Fun.member` set 10 | -- ^^^^^^^^^^^^^^^ keyword.operator.function.infix.haskell 11 | -- ^^^^^ entity.name.namespace.haskell 12 | -- ^^^^^^ - entity.name.namespace.haskell 13 | 14 | h = 15 | a `C.A.Constr` b 16 | -- ^^^^^^^^^^^^ keyword.operator.function.infix.haskell 17 | -- ^^^^ entity.name.namespace.haskell 18 | -- ^^^^^^ - entity.name.namespace.haskell 19 | a `C.A.f` b 20 | -- ^^^^^^^ keyword.operator.function.infix.haskell 21 | -- ^^^^ entity.name.namespace.haskell 22 | 23 | a C.A.+ b 24 | ----- ^^^^ entity.name.namespace.haskell 25 | (C.A.*) b c 26 | -- ^^^^ entity.name.namespace.haskell 27 | 28 | a C.A.:& b 29 | -- ^^^^ entity.name.namespace.haskell 30 | (C.A.:+:) b c 31 | -- ^^^^ entity.name.namespace.haskell 32 | -------------------------------------------------------------------------------- /test/wontfix/MultilineGADT.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Multiline GADT declaration" 2 | 3 | data G (a :: A) b (c :: C) :: Type 4 | -- ^^^^ keyword.other.data.haskell 5 | -- ^ ^ variable.other.generic-type.haskell 6 | -- ^^ ^^ ^^ keyword.operator.double-colon.haskell 7 | -- ^ ^ ^ ^^^^ storage.type.haskell 8 | where 9 | -- ^^^^^^ keyword.other.where.haskell 10 | A :: G a b c 11 | -- ^ constant.other.haskell 12 | -- ^^ keyword.operator.double-colon.haskell 13 | -- ^ storage.type.haskell 14 | -- ^ ^ ^ variable.other.generic-type.haskell 15 | (:&) :: G A B c 16 | -- ^^ constant.other.operator.haskell 17 | -- ^^ keyword.operator.double-colon.haskell 18 | -- ^ ^ ^ storage.type.haskell 19 | -- ^ variable.other.generic-type.haskell 20 | (:!!!!!!!!!!!!!!!!!!!!!!!!) 21 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^ constant.other.operator.haskell 22 | :: a -> b -> G a b c 23 | -- ^^ keyword.operator.double-colon.haskell 24 | -- ^ storage.type.haskell 25 | -- ^ ^ ^ ^ ^ variable.other.generic-type.haskell -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | 4 | const webExtensionConfig = { 5 | mode: 'none', 6 | target: 'webworker', 7 | entry: { 8 | extension: './src/extension.ts' 9 | }, 10 | output: { 11 | filename: '[name].js', 12 | path: path.join(__dirname, './dist/web'), 13 | libraryTarget: 'commonjs', 14 | devtoolModuleFilenameTemplate: '../../[resource-path]' 15 | }, 16 | resolve: { 17 | mainFields: ['browser', 'module', 'main'], 18 | extensions: ['.ts', '.js'], 19 | fallback: { 20 | assert: require.resolve('assert') 21 | } 22 | }, 23 | module: { 24 | rules: [ 25 | { 26 | test: /\.ts$/, 27 | exclude: /node_modules/, 28 | use: [ 29 | { 30 | loader: 'ts-loader' 31 | } 32 | ] 33 | } 34 | ] 35 | }, 36 | plugins: [ 37 | new webpack.ProvidePlugin({ 38 | process: 'process/browser' 39 | }) 40 | ], 41 | externals: { 42 | vscode: 'commonjs vscode' 43 | }, 44 | performance: { 45 | hints: false 46 | }, 47 | devtool: 'nosources-source-map' 48 | }; 49 | module.exports = [webExtensionConfig]; -------------------------------------------------------------------------------- /test/tests/Keywords.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Reserved keywords" 2 | 3 | anotherFunc :: MyData -> Int 4 | -- ^^ keyword.operator.double-colon.haskell 5 | -- ^^ keyword.operator.arrow.haskell 6 | anotherFunc arg = 7 | let something = "hello" :: String 8 | -- ^ keyword.operator.eq.haskell 9 | -- ^^ keyword.operator.double-colon.haskell 10 | -- ^^^ keyword.other.let.haskell 11 | in case a :: B of 12 | -- ^^ keyword.other.in.haskell 13 | -- ^^^^ keyword.control.case.haskell 14 | -- ^^ keyword.operator.double-colon.haskell 15 | -- ^^ keyword.control.of.haskell 16 | 17 | Just _ -> do 18 | -- ^^ keyword.operator.arrow.haskell 19 | -- ^^ keyword.control.do.haskell 20 | if a 21 | -- ^^ keyword.control.if.haskell 22 | then b 23 | -- ^^^^ keyword.control.then.haskell 24 | else \cases 25 | -- ^^^^ keyword.control.else.haskell 26 | -- ^^^^^ keyword.control.cases.haskell 27 | arg1 arg2 -> undefined 28 | 29 | where 30 | -- <~~----- keyword.other.where.haskell 31 | expression argument = arg + 7 32 | -------------------------------------------------------------------------------- /test/tickets/T0071.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Ticks in type constructors" 2 | 3 | data A = ABC (X,X) | ABC'' (X, X) 4 | -- ^^^^^ constant.other.haskell 5 | -- ^^ - string.quoted.single.haskell 6 | pattern ABC' = ABC'' 7 | -- ^^^^ ^^^^^ constant.other.haskell 8 | -- ^^^^^^^^^ - string.quoted.single.haskell 9 | 10 | data X = XY'' [X] | XY''' 11 | -- ^^^^ ^^^^^ constant.other.haskell 12 | -- ^^^^^^^^^^^^^^ - string.quoted.single.haskell 13 | 14 | type X'' = 'XY'' 15 | -- ^^^ ^^^^ storage.type.haskell 16 | -- ^^^^^^^^^^ - string.quoted.single.haskell 17 | 18 | f'' :: proxy ( 'ABC '( 'XY''','XY'' '[ 'XY''','XY''']) ':-> a ) 19 | -- <--- entity.name.function.haskell 20 | -- ^^^ ^^^^^ ^^^^ ^^^^^ ^^^^^ storage.type.haskell 21 | -- <-------------------------------------------------------------- - string.quoted.single.haskell 22 | 23 | g'' :: A 24 | -- <--- entity.name.function.haskell 25 | -- <--- - string.quoted.single.haskell 26 | g'' = ABC''' XY''' 27 | -- ^^^^^^ ^^^^^ constant.other.haskell 28 | -- <------------------- - string.quoted.single.haskell 29 | 30 | type Ticked' '(a,b) = '(a,b) 31 | -- ^^^^^^^ storage.type.haskell 32 | -- ^^^ - string.quoted.single.haskell 33 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "extensionHost", 9 | "request": "launch", 10 | "name": "Launch Extension", 11 | "runtimeExecutable": "${execPath}", 12 | "args": [ 13 | "--extensionDevelopmentPath=${workspaceFolder}" 14 | ], 15 | "outFiles": [ 16 | "${workspaceFolder}/out/**/*.js" 17 | ], 18 | "preLaunchTask": "compile-all" 19 | }, 20 | { 21 | "name": "Run Web Extension in VS Code", 22 | "type": "extensionHost", 23 | "debugWebWorkerHost": true, 24 | "request": "launch", 25 | "args": [ 26 | "--extensionDevelopmentPath=${workspaceFolder}", 27 | "--extensionDevelopmentKind=web" 28 | ], 29 | "outFiles": [ 30 | "${workspaceFolder}/dist/web/**/*.js" 31 | ], 32 | "preLaunchTask": "npm: watch-web" 33 | } 34 | ] 35 | } -------------------------------------------------------------------------------- /test/tests/QualifiedFields.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Qualified record fields" 2 | 3 | parserPrefs = OptParse.ParserPrefs 4 | { OptParse.prefMultiSuffix = "" 5 | -- ^^^^^^^^^ entity.name.namespace.haskell 6 | -- ^^^^^^^^^^^^^^^ variable.other.member.haskell 7 | , OptParse.prefDisambiguate = True 8 | -- ^^^^^^^^^ entity.name.namespace.haskell 9 | -- ^^^^^^^^^^^^^^^^ variable.other.member.haskell 10 | , OptParse.prefShowHelpOnError = True 11 | -- ^^^^^^^^^ entity.name.namespace.haskell 12 | -- ^^^^^^^^^^^^^^^^^^^ variable.other.member.haskell 13 | , OptParse.prefShowHelpOnEmpty = False 14 | -- ^^^^^^^^^ entity.name.namespace.haskell 15 | -- ^^^^^^^^^^^^^^^^^^^ variable.other.member.haskell 16 | , OptParse.prefBacktrack = OptParse.Backtrack 17 | -- ^^^^^^^^^ entity.name.namespace.haskell 18 | -- ^^^^^^^^^^^^^ variable.other.member.haskell 19 | , OptParse.prefColumns = 80 20 | -- ^^^^^^^^^ entity.name.namespace.haskell 21 | -- ^^^^^^^^^^^ variable.other.member.haskell 22 | , OptParse.prefHelpLongEquals = False 23 | -- ^^^^^^^^^ entity.name.namespace.haskell 24 | -- ^^^^^^^^^^^^^^^^^^ variable.other.member.haskell 25 | } -------------------------------------------------------------------------------- /test/tickets/T0116.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Nested comments" 2 | 3 | -- comment 4 | -- ^^^^^^^^^^ comment.line.double-dash.haskell 5 | 6 | -- comment -- comment 7 | -- ^^^^^^^^^^^^^^^^^^^^^ comment.line.double-dash.haskell 8 | 9 | {- comments 10 | -- ^^^^^^^^^^^ comment.block.haskell 11 | 12 | {- nested comment -} 13 | -- ^^^^^^^^^^^^^^^^^^^^ comment.block.haskell 14 | 15 | more comment 16 | -- ^^^^^^^^^^^^^ comment.block.haskell 17 | 18 | -- comment 19 | -- ^^^^^^^^^^ comment.block.haskell 20 | 21 | -} 22 | 23 | notAComment :: Int 24 | -- ^^^^^^^^^^^^^^^^^^ - comment.line.double-dash.haskell comment.block.haskell 25 | 26 | -- comment {- comment -} 27 | -- ^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-dash.haskell 28 | 29 | 30 | {- comment 31 | -- ^^^^^^^^^^ comment.block.haskell 32 | 33 | {-# PRAGMA #-} 34 | -- ^^^^^^^^^^^^^^ comment.block.haskell 35 | 36 | {-| 37 | commented 38 | -- ^^^^^^^^^ comment.block.haskell 39 | out 40 | docs -} 41 | -- ^^^^^^^ comment.block.haskell 42 | 43 | {-@ liquid haskell @-} 44 | -- ^^^^^^^^^^^^^^^^^^^^^^ comment.block.haskell 45 | 46 | -} 47 | -- <-- comment.block.haskell 48 | 49 | foo :: Bar 50 | -- ^^^^^^^^^^ - comment.line.double-dash.haskell comment.block.haskell -------------------------------------------------------------------------------- /test/tests/LinearTypes.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "LinearTypes" 2 | 3 | {-# LANGUAGE LinearTypes #-} 4 | -- ^^^^^^^^^^^ keyword.other.preprocessor.extension.haskell 5 | 6 | construct :: a %1 -> T1 a 7 | -- ^ keyword.operator.prefix.modifier.haskell 8 | construct x = MkT1 x 9 | 10 | deconstruct :: T1 a %1 -> a 11 | -- ^ keyword.operator.prefix.modifier.haskell 12 | deconstruct (MkT1 x) = x 13 | 14 | data T2 a b c where 15 | MkT2 :: a -> b %1 -> c %1 -> T2 a b c 16 | -- ^ ^ keyword.operator.prefix.modifier.haskell 17 | 18 | data T3 a m where 19 | MkT3 :: a %m -> T3 a m 20 | -- ^ keyword.operator.prefix.modifier.haskell 21 | 22 | 23 | f2 :: Int %Many -> Bool 24 | -- ^ keyword.operator.prefix.modifier.haskell 25 | f3 :: Int %m -> Bool 26 | -- ^ keyword.operator.prefix.modifier.haskell 27 | f4 :: Int %(m :: Multiplicity) -> Bool 28 | -- ^ keyword.operator.prefix.modifier.haskell 29 | 30 | map :: forall (m :: Multiplicity). (a %m -> b) -> [a] %m -> [b] 31 | -- ^ ^ keyword.operator.prefix.modifier.haskell 32 | 33 | foo :: a % b -> c % d 34 | -- ^ ^ - keyword.operator.prefix.modifier.haskell 35 | 36 | bar :: a %%b -> c %-% d 37 | -- ^^ ^ ^ - keyword.operator.prefix.modifier.haskell 38 | 39 | -------------------------------------------------------------------------------- /test/tests/ReservedInComments.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Reserved names in comments" 2 | 3 | data A = B -- where 4 | -- ^^^^^^^^ comment.line.double-dash.haskell 5 | -- ^^^^^ - keyword.other.where.haskell 6 | data instance A = B -- where 7 | -- ^^^^^^^^ comment.line.double-dash.haskell 8 | -- ^^^^^ - keyword.other.where.haskell 9 | 10 | data Foo a {- = y -} 11 | -- ^ - keyword.operator.eq.haskell 12 | -- ^^^^^^ comment.block.haskell 13 | = A 14 | 15 | type Foo a {- = A -} 16 | -- ^ - keyword.operator.eq.haskell 17 | -- ^^^^^^ comment.block.haskell 18 | = A 19 | 20 | f {- :: xyz -} 21 | -- ^^ - keyword.operator.double-colon.haskell 22 | -- ^^^^^^^^^ comment.block.haskell 23 | :: A -> B 24 | 25 | f {- :: xyz -} 26 | -- ^^ - keyword.operator.double-colon.haskell 27 | -- ^^^^^^^^^^^^ comment.block.haskell 28 | :: A -> B 29 | 30 | data Foo a -- = y 31 | -- ^ - keyword.operator.eq.haskell 32 | -- ^^^^^^ comment.line.double-dash.haskell 33 | = A 34 | 35 | type Foo a -- = A 36 | -- ^ - keyword.operator.eq.haskell 37 | -- ^^^^^^ comment.line.double-dash.haskell 38 | = A 39 | 40 | f -- :: xyz 41 | -- ^^ - keyword.operator.double-colon.haskell 42 | -- ^^^^^^^^^ comment.line.double-dash.haskell 43 | :: A -> B 44 | -------------------------------------------------------------------------------- /scope-lists/happy.yaml: -------------------------------------------------------------------------------- 1 | - scope: Haskell Happy 2 | - scope: comment.block 3 | - scope: comment.line 4 | - scope: constant.character.escape.dec.happy 5 | - scope: constant.character.escape.happy 6 | - scope: constant.character.escape.hex.happy 7 | - scope: constant.character.escape.oct.happy 8 | - scope: entity.name.class.happy 9 | - scope: keyword.operator.happy 10 | - scope: keyword.operator.pragma.happy 11 | - scope: keyword.operator.rules.happy 12 | - scope: meta.embedded.haskell 13 | - scope: punctuation.block.begin.happy 14 | - scope: punctuation.block.end.happy 15 | - scope: punctuation.brackets.happy 16 | - scope: punctuation.quote.double.happy 17 | - scope: punctuation.quote.single.happy 18 | - scope: storage.type.happy 19 | - scope: string.quoted.double.happy 20 | - scope: string.quoted.single.happy 21 | - scope: variable.parameter.happy 22 | - scope: keyword.operator.alt.happy 23 | - scope: keyword.operator.rule.happy 24 | - scope: keyword.operator.type.happy 25 | - scope: keyword.operator.separator.happy 26 | - scope: meta.embedded.block.haskell 27 | - scope: variable.parameter.field.happy 28 | - scope: comment.block.happy 29 | - scope: comment.line.happy 30 | - scope: entity.name.directive.happy 31 | - scope: meta.embedded.block.monad.haskell 32 | - scope: punctuation.block.monad.begin.happy 33 | - scope: punctuation.definition.comment.happy 34 | - scope: punctuation.bracket.happy 35 | -------------------------------------------------------------------------------- /test/tickets/T0146b.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Highlighting in multiline type declarations" 2 | 3 | 4 | type instance GetDecks = 5 | -- <~~---- keyword.other.type.haskell 6 | -- ^^^^^^^^ keyword.other.instance.haskell 7 | -- ^^^^^^^^ storage.type.haskell 8 | -- ^ keyword.operator.eq.haskell 9 | MethodCall "getDecks" Cards 10 | -- ^^^^^^^^^^ ^^^^^ storage.type.haskell 11 | 12 | type instance GetDecks 13 | -- <~~---- keyword.other.type.haskell 14 | -- ^^^^^^^^ keyword.other.instance.haskell 15 | -- ^^^^^^^^ storage.type.haskell 16 | = MethodCall "getDecks" Cards 17 | -- ^ keyword.operator.eq.haskell 18 | -- ^^^^^^^^^^ ^^^^^ storage.type.haskell 19 | 20 | 21 | type instance GetDecks = 22 | -- <---- keyword.other.type.haskell 23 | -- ^^^^^^^^ keyword.other.instance.haskell 24 | -- ^^^^^^^^ storage.type.haskell 25 | -- ^ keyword.operator.eq.haskell 26 | MethodCall "getDecks" Cards 27 | -- <~~--------- storage.type.haskell 28 | -- ^^^^^ storage.type.haskell 29 | 30 | type instance GetDecks 31 | -- <---- keyword.other.type.haskell 32 | -- ^^^^^^^^ keyword.other.instance.haskell 33 | -- ^^^^^^^^ storage.type.haskell 34 | = MethodCall "getDecks" Cards 35 | -- <~~- keyword.operator.eq.haskell 36 | -- ^^^^^^^^^^ ^^^^^ storage.type.haskell 37 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "compile", 9 | "isBackground": true, 10 | "label": "npm", 11 | "group": { 12 | "kind": "build", 13 | "isDefault": true 14 | }, 15 | "presentation": { 16 | "echo": false, 17 | "reveal": "never", 18 | "focus": false, 19 | "panel": "dedicated" 20 | }, 21 | "problemMatcher": [ 22 | "$tsc" 23 | ] 24 | }, 25 | { 26 | "type": "shell", 27 | "label": "make-json", 28 | "command": "make", 29 | "args": [ 30 | "all" 31 | ] 32 | }, 33 | { 34 | "label": "compile-all", 35 | "dependsOn": [ 36 | "npm", 37 | "make-json" 38 | ] 39 | }, 40 | { 41 | "type": "npm", 42 | "script": "watch-web", 43 | "group": "build", 44 | "isBackground": true, 45 | "problemMatcher": [ 46 | "$ts-webpack-watch" 47 | ] 48 | } 49 | ] 50 | } -------------------------------------------------------------------------------- /test/tests/Role.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Role annotations" 2 | 3 | 4 | data A n r p where 5 | 6 | type role A nominal representational phantom 7 | -- ^^^^ keyword.other.type.haskell 8 | -- ^^^^ keyword.other.role.haskell 9 | -- ^ storage.type.haskell 10 | -- ^^^^^^^ keyword.other.role.nominal.haskell 11 | -- ^^^^^^^^^^^^^^^^ keyword.other.role.representational.haskell 12 | -- ^^^^^^^ keyword.other.role.phantom.haskell 13 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.role-annotation.haskell 14 | 15 | 16 | type role A 17 | -- ^^^^ keyword.other.type.haskell 18 | -- ^^^^ keyword.other.role.haskell 19 | -- ^ storage.type.haskell 20 | nominal 21 | -- ^^^^^^^ keyword.other.role.nominal.haskell 22 | representational 23 | -- ^^^^^^^^^^^^^^^^ keyword.other.role.representational.haskell 24 | phantom 25 | -- ^^^^^^^ keyword.other.role.phantom.haskell 26 | 27 | type role 28 | -- ^^^^ keyword.other.type.haskell 29 | -- ^^^^ keyword.other.role.haskell 30 | (:&) 31 | -- ^^ storage.type.operator.haskell 32 | nominal 33 | -- ^^^^^^^ keyword.other.role.nominal.haskell 34 | representational 35 | -- ^^^^^^^^^^^^^^^^ keyword.other.role.representational.haskell 36 | phantom 37 | -- ^^^^^^^ keyword.other.role.phantom.haskell 38 | -------------------------------------------------------------------------------- /scope-lists/happy.md: -------------------------------------------------------------------------------- 1 | | Scope Name | Description | Example | 2 | |-|-|-| 3 | | Haskell Happy | | | 4 | | comment.block | | | 5 | | comment.line | | | 6 | | constant.character.escape.dec.happy | | | 7 | | constant.character.escape.happy | | | 8 | | constant.character.escape.hex.happy | | | 9 | | constant.character.escape.oct.happy | | | 10 | | entity.name.class.happy | | | 11 | | keyword.operator.happy | | | 12 | | keyword.operator.pragma.happy | | | 13 | | keyword.operator.rules.happy | | | 14 | | meta.embedded.haskell | | | 15 | | punctuation.block.begin.happy | | | 16 | | punctuation.block.end.happy | | | 17 | | punctuation.brackets.happy | | | 18 | | punctuation.quote.double.happy | | | 19 | | punctuation.quote.single.happy | | | 20 | | storage.type.happy | | | 21 | | string.quoted.double.happy | | | 22 | | string.quoted.single.happy | | | 23 | | variable.parameter.happy | | | 24 | | keyword.operator.alt.happy | | | 25 | | keyword.operator.rule.happy | | | 26 | | keyword.operator.type.happy | | | 27 | | keyword.operator.separator.happy | | | 28 | | meta.embedded.block.haskell | | | 29 | | variable.parameter.field.happy | | | 30 | | comment.block.happy | | | 31 | | comment.line.happy | | | 32 | | entity.name.directive.happy | | | 33 | | meta.embedded.block.monad.haskell | | | 34 | | punctuation.block.monad.begin.happy | | | 35 | | punctuation.definition.comment.happy | | | 36 | | punctuation.bracket.happy | | | 37 | -------------------------------------------------------------------------------- /images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /test/tickets/T0072b3.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Deriving via (multiline)" 2 | 3 | 4 | deriving via VariantF ( ApplyAll (EGADT vs) vs ) 5 | -- ^^^^^^^^ keyword.other.deriving.haskell 6 | -- ^^^ keyword.other.deriving.strategy.via.haskell 7 | -- ^^^^^^^^ ^^^^^^^ ^^^^ storage.type.haskell 8 | -- ^^ ^^ variable.other.generic-type.haskell 9 | instance BottomUp CodeGen ( ApplyAll (EGADT vs) vs ) 10 | -- ^^^^^^^^ keyword.other.instance.haskell 11 | -- ^^^^^^^^ ^^^^^^^ ^^^^^^^^ ^^^^^ storage.type.haskell 12 | -- ^^ variable.other.generic-type.haskell 13 | => CodeGen (EGADT vs) 14 | -- ^^ keyword.operator.big-arrow.haskell 15 | -- ^^^^^^^ ^^^^^ storage.type.haskell 16 | -- ^^ variable.other.generic-type.haskell 17 | 18 | newtype StateMonad b c r = StateMonad (StateT (MyState (Something b c) b) IO r) 19 | deriving (MonadState (MyState (Something b c) b), MonadIO, Monad) 20 | -- ^^^^^^^^ keyword.other.deriving.haskell 21 | -- ^ ^ ^ variable.other.generic-type.haskell 22 | -- ^^^^^^^^^^ ^^^^^^^ ^^^^^^^^^ ^^^^^^^ ^^^^^ storage.type.haskell 23 | via ( State ( s, t ) r ) 24 | -- ^^^ keyword.other.deriving.strategy.via.haskell 25 | -- ^^^^^ storage.type.haskell 26 | -- ^ ^ ^ variable.other.generic-type.haskell 27 | -------------------------------------------------------------------------------- /scope-lists/alex.yaml: -------------------------------------------------------------------------------- 1 | - scope: Haskell Alex 2 | - scope: comment.block 3 | - scope: comment.line 4 | - scope: constant.character.escape.alex 5 | - scope: constant.character.escape.dec.alex 6 | - scope: constant.character.escape.hex.alex 7 | - scope: constant.character.escape.oct.alex 8 | - scope: entity.name.class.alex 9 | - scope: keyword.operator.alex 10 | - scope: keyword.operator.pragma.alex 11 | - scope: keyword.operator.rules.alex 12 | - scope: meta.embedded.haskell 13 | - scope: punctuation.block.begin.alex 14 | - scope: punctuation.block.end.alex 15 | - scope: punctuation.brackets.alex 16 | - scope: storage.type.alex 17 | - scope: string.quoted.double.alex 18 | - scope: variable.parameter.alex 19 | - scope: meta.embedded.block.haskell 20 | - scope: punctuation.quote.double.alex 21 | - scope: punctuation.semicolon.alex 22 | - scope: punctuation.quote.single.alex 23 | - scope: string.quoted.single.alex 24 | - scope: comment.block.alex 25 | - scope: comment.line.alex 26 | - scope: entity.name.macro.character-set.alex 27 | - scope: entity.name.macro.regular-expression.alex 28 | - scope: entity.name.pragma.alex 29 | - scope: meta.block.startcode.alex 30 | - scope: meta.startcode.alex 31 | - scope: punctuation.block.startcode.begin.alex 32 | - scope: punctuation.block.startcode.end.alex 33 | - scope: punctuation.bracket.startcode.alex 34 | - scope: punctuation.comma.startcode.alex 35 | - scope: punctuation.definition.comment.alex 36 | - scope: variable.other.starcode.alex 37 | - scope: variable.other.startcode.alex 38 | - scope: punctuation.bracket.alex 39 | -------------------------------------------------------------------------------- /test/tests/Comments.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Intervening comments shouldn't affect highlighting" 2 | 3 | 4 | data A 5 | -- ^ storage.type.haskell 6 | -- comment line not gobbled up by the preprocessor 7 | -- <~~-------------------------------------------------- comment.line.double-dash.haskell 8 | = A 9 | -- ^ constant.other.haskell 10 | 11 | newtype B = 12 | -- ^ storage.type.haskell 13 | -- comment line not gobbled up by the preprocessor 14 | -- <~~-------------------------------------------------- comment.line.double-dash.haskell 15 | B 16 | -- ^ constant.other.haskell 17 | 18 | data Foo where 19 | -- comment line not gobbled up by the preprocessor 20 | -- <~~-------------------------------------------------- comment.line.double-dash.haskell 21 | MkFoo :: Foo 22 | -- ^^^^^ constant.other.haskell 23 | -- ^^^ storage.type.haskell 24 | 25 | dbPageWrapper :: (DashBoardPage p, Monad m) => 26 | -- comment line not gobbled up by the preprocessor 27 | -- <~~-------------------------------------------------- comment.line.double-dash.haskell 28 | T.Text -> p -> HtmlT m a -> HtmlT m b -> HtmlT m b 29 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function.type-declaration.haskell 30 | -- ^^^^^ storage.type.haskell 31 | 32 | type T a 33 | -- comment line not gobbled up by the preprocessor 34 | -- <~~-------------------------------------------------- comment.line.double-dash.haskell 35 | = Int 36 | -- ^^^ storage.type.haskell 37 | -------------------------------------------------------------------------------- /test/tests/Happy.y: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell.happy" "Happy" 2 | 3 | { 4 | -- <- meta.embedded.block.haskell 5 | module Happy where 6 | -- <------ keyword.other.module.haskell 7 | -- ^^^^ meta.declaration.module.haskell 8 | } 9 | -- <- meta.embedded.block.haskell 10 | 11 | %monad { P } 12 | -- <------ entity.name.directive.happy 13 | -- ^ punctuation.block.begin.happy 14 | -- ^ punctuation.block.end.happy 15 | 16 | %name parse 17 | %tokentype { Token } 18 | %error { parseError } 19 | 20 | %token 21 | '(' { OPEN_PAREN } 22 | ')' { CLOSE_PAREN } 23 | '+' { PLUS } 24 | -- ^^^ string.quoted.single.happy 25 | -- ^ ^ punctuation.quote.single.happy 26 | num { NUMBER $$ } 27 | 28 | %left '+' 29 | 30 | -- comment {- 31 | %% 32 | -- <-- keyword.operator.separator.happy 33 | -- <-- - comment.block.happy 34 | -- comment -} 35 | 36 | value :: { AST } 37 | -- ^^ keyword.operator.type.happy 38 | : value '+' value { Add $1 $3 } 39 | -- ^ keyword.operator.rule.happy 40 | | num { Number $1 } 41 | -- ^ keyword.operator.alt.happy 42 | | '(' value ')' {% pure $2 } 43 | -- ^^ punctuation.block.monad.begin.happy 44 | | '(' ')' {%% someErr } 45 | -- ^^^ punctuation.block.monad.begin.happy 46 | | ')' '(' {%^ someOtherErr } 47 | -- ^^^ punctuation.block.monad.begin.happy 48 | 49 | { 50 | 51 | data Token 52 | = OPEN_PAREN 53 | | CLOSE_PAREN 54 | | PLUS 55 | | NUMBER Int 56 | 57 | data AST 58 | = Add AST AST 59 | | Number Int 60 | 61 | } 62 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Justus Adam 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | * Neither the name of Justus Adam nor the names of other 17 | contributors may be used to endorse or promote products derived 18 | from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /test/tests/Imports.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Imports" 2 | 3 | import M 4 | ( T(f,C,g) 5 | -- ^ storage.type.haskell 6 | -- ^ ^ entity.name.function.haskell 7 | , S((:<..<), .. ) 8 | -- ^ storage.type.haskell 9 | -- ^^ - variable.other.member.wildcard.haskell 10 | -- ^^^^^ constant.other.operator.prefix.haskell 11 | -- ^^ variable.other.member.wildcard.haskell 12 | , (:->)((:>)) 13 | -- ^^^ storage.type.operator.haskell 14 | -- ^^ constant.other.operator.prefix.haskell 15 | , (:<>)(C,a,D,E) 16 | -- ^^^ storage.type.operator.haskell 17 | , A((<>), (:>>)) 18 | -- ^ storage.type.haskell 19 | -- ^^^ constant.other.operator.prefix.haskell 20 | , f 21 | -- ^ entity.name.function.haskell 22 | , pattern P 23 | -- ^^^^^^^ keyword.other.pattern.haskell 24 | -- ^ constant.other.haskell 25 | , pattern (:| ) 26 | -- ^^^^^^^ keyword.other.pattern.haskell 27 | -- ^^ constant.other.operator.prefix.haskell 28 | , pattern -- Q,) 29 | -- ^^^^^^^ keyword.other.pattern.haskell 30 | Q 31 | -- ^ constant.other.haskell 32 | , f, T 33 | -- ^ entity.name.function.haskell 34 | -- ^ storage.type.haskell 35 | , type T 36 | -- ^^^^ keyword.other.type.haskell 37 | -- ^ storage.type.haskell 38 | , type (:- ) 39 | -- ^^^^ keyword.other.type.haskell 40 | -- ^^ storage.type.operator.haskell 41 | , type (<+>) 42 | -- ^^^^ keyword.other.type.haskell 43 | -- ^^^ storage.type.operator.haskell 44 | , type {- T -} 45 | -- ^^^^ keyword.other.type.haskell 46 | (<->) 47 | -- ^^^ storage.type.operator.haskell 48 | ) 49 | -------------------------------------------------------------------------------- /test/tests/NearReserved.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Issues surrounding reserved operators" 2 | 3 | type a ==> b = a --> b 4 | -- ^ keyword.operator.eq.haskell 5 | -- ^^^ - keyword.operator.eq.haskell 6 | -- ^^^ ^^^ - keyword.operator.arrow.haskell 7 | type family a ==> b = a --> b 8 | -- ^ keyword.operator.eq.haskell 9 | -- ^^^ - keyword.operator.eq.haskell keyword.operator.big-arrow.haskell 10 | -- ^^^ - keyword.operator.arrow.haskell 11 | data a ==> b = a :== b 12 | -- ^ keyword.operator.eq.haskell 13 | -- ^^^ - keyword.operator.eq.haskell keyword.operator.big-arrow.haskell 14 | -- ^^^ - keyword.operator.eq.haskell 15 | data a :==> b where 16 | -- ^^^^ - keyword.operator.eq.haskell keyword.operator.big-arrow.haskell 17 | (::: ) :: a ::: b -> c :==> d 18 | -- ^^^^ ^^^ - keyword.operator.double-colon.haskell 19 | -- ^^^^ - keyword.operator.eq.haskell keyword.operator.big-arrow.haskell 20 | 21 | f :: a ::: b =| c --> d -> e ==> b 22 | -- ^^^ - keyword.operator.double-colon.haskell 23 | -- ^ ^^ - keyword.operator.eq.haskell 24 | -- ^^ - keyword.operator.arrow.haskell 25 | -- ^^ - keyword.operator.big-arrow.haskell 26 | 27 | ( -:: ) :: a -> a -> a 28 | -- <------- - keyword.operator.double-colon.haskell 29 | a -:: b = a 30 | -- <~~--- - keyword.operator.double-colon.haskell 31 | 32 | (:::) :: a -> a -> a 33 | -- <~--- - keyword.operator.double-colon.haskell 34 | a ::: b = a 35 | -- <~~--- - keyword.operator.double-colon.haskell 36 | -------------------------------------------------------------------------------- /scope-lists/alex.md: -------------------------------------------------------------------------------- 1 | | Scope Name | Description | Example | 2 | |-|-|-| 3 | | Haskell Alex | | | 4 | | comment.block | | | 5 | | comment.line | | | 6 | | constant.character.escape.alex | | | 7 | | constant.character.escape.dec.alex | | | 8 | | constant.character.escape.hex.alex | | | 9 | | constant.character.escape.oct.alex | | | 10 | | entity.name.class.alex | | | 11 | | keyword.operator.alex | | | 12 | | keyword.operator.pragma.alex | | | 13 | | keyword.operator.rules.alex | | | 14 | | meta.embedded.haskell | | | 15 | | punctuation.block.begin.alex | | | 16 | | punctuation.block.end.alex | | | 17 | | punctuation.brackets.alex | | | 18 | | storage.type.alex | | | 19 | | string.quoted.double.alex | | | 20 | | variable.parameter.alex | | | 21 | | meta.embedded.block.haskell | | | 22 | | punctuation.quote.double.alex | | | 23 | | punctuation.semicolon.alex | | | 24 | | punctuation.quote.single.alex | | | 25 | | string.quoted.single.alex | | | 26 | | comment.block.alex | | | 27 | | comment.line.alex | | | 28 | | entity.name.macro.character-set.alex | | | 29 | | entity.name.macro.regular-expression.alex | | | 30 | | entity.name.pragma.alex | | | 31 | | meta.block.startcode.alex | | | 32 | | meta.startcode.alex | | | 33 | | punctuation.block.startcode.begin.alex | | | 34 | | punctuation.block.startcode.end.alex | | | 35 | | punctuation.bracket.startcode.alex | | | 36 | | punctuation.comma.startcode.alex | | | 37 | | punctuation.definition.comment.alex | | | 38 | | variable.other.starcode.alex | | | 39 | | variable.other.startcode.alex | | | 40 | | punctuation.bracket.alex | | | 41 | -------------------------------------------------------------------------------- /test/tests/InfixDataDecl.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Infix data declarations" 2 | 3 | 4 | data A a b = ( T b c ( d e ) f ) `C` '[ A b, C, D [ e, f ] g ] 5 | -- ^^^^ keyword.other.data.haskell 6 | -- ^ keyword.operator.eq.haskell 7 | -- ^ ^ punctuation.paren.haskell 8 | -- ^ constant.other.infix.haskell 9 | -- ^ ^ punctuation.backtick.haskell 10 | -- ^ keyword.operator.promotion.haskell 11 | -- ^ ^ ^ ^ ^ storage.type.haskell 12 | -- ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ variable.other.generic-type.haskell 13 | -- ^ ^ punctuation.bracket.haskell 14 | 15 | 16 | data A a b = '[ X, y, Z ] `C` D e 17 | -- ^^^^ keyword.other.data.haskell 18 | -- ^ keyword.operator.eq.haskell 19 | -- ^ keyword.operator.promotion.haskell 20 | -- ^ constant.other.infix.haskell 21 | -- ^ ^ punctuation.backtick.haskell 22 | -- ^ ^ ^ storage.type.haskell 23 | -- ^ ^ ^ ^ variable.other.generic-type.haskell 24 | 25 | data A a b = ABC.D `C` GH 26 | -- ^^^^ keyword.other.data.haskell 27 | -- ^ keyword.operator.eq.haskell 28 | -- ^^^^ entity.name.namespace.haskell 29 | -- ^ constant.other.infix.haskell 30 | -- ^ ^ punctuation.backtick.haskell 31 | -- ^ ^^ storage.type.haskell 32 | -------------------------------------------------------------------------------- /test/tests/GADTRecord.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "GADT record syntax" 2 | 3 | data D :: A -> B -> Type where 4 | C :: { fld1 :: A, (&) :: B } -> D a b 5 | -- ^ constant.other.haskell 6 | -- ^^^^ ^ variable.other.member.definition.haskell 7 | -- ^ ^ punctuation.brace.haskell 8 | -- ^ ^ ^ storage.type.haskell 9 | 10 | 11 | data D a where 12 | C :: { fld :: forall (a :: B). C a => T a } 13 | -- ^ constant.other.haskell 14 | -- ^^^ variable.other.member.definition.haskell 15 | -- ^ ^ ^ storage.type.haskell 16 | -- ^ ^ ^ variable.other.generic-type.haskell 17 | 18 | data (!!!) :: Type where 19 | (:<>) :: { fld1 :: A, (&) :: B } -> (!!!) 20 | -- ^^^ constant.other.operator.prefix.haskell 21 | -- ^^^^ ^ variable.other.member.definition.haskell 22 | -- ^ ^ punctuation.brace.haskell 23 | -- ^ ^ storage.type.haskell 24 | -- ^^^ storage.type.operator.haskell 25 | 26 | data D :: A -> B -> Type where { C :: { fld1 :: A, (&) :: B } -> D a b } 27 | -- ^ constant.other.haskell 28 | -- ^^^^ ^ variable.other.member.definition.haskell 29 | -- ^ ^ punctuation.brace.haskell 30 | -- ^ ^ ^ storage.type.haskell 31 | 32 | foo :: A 33 | -- ^^^^^^^^ - meta.declaration.data.generalized.haskell 34 | -- ^^^ entity.name.function.haskell 35 | -- ^ storage.type.haskell 36 | -------------------------------------------------------------------------------- /test/tickets/T0167.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Interaction between record fields and context arrows" 2 | 3 | data BuilderType = Builder 4 | { (>>=) :: forall m a b. Unrestricted.Monad m => m a -> (a -> m b) -> m b 5 | -- ^^^ variable.other.member.definition.haskell 6 | -- ^^ keyword.operator.double-colon.haskell 7 | -- ^^^^^^ keyword.other.forall.haskell 8 | -- ^ keyword.operator.period.haskell 9 | -- ^^ keyword.operator.big-arrow 10 | , (>>) :: forall m b . Unrestricted.Monad m => m () -> m b -> m b 11 | -- ^^ variable.other.member.definition.haskell 12 | -- ^^ keyword.operator.double-colon.haskell 13 | -- ^^^^^^ keyword.other.forall.haskell 14 | -- ^ keyword.operator.period.haskell 15 | -- ^^ keyword.operator.big-arrow 16 | , fail :: forall m a . Unrestricted.MonadFail m => String -> m a 17 | -- ^^^^ variable.other.member.definition.haskell 18 | -- ^^ keyword.operator.double-colon.haskell 19 | -- ^^^^^^ keyword.other.forall.haskell 20 | -- ^ keyword.operator.period.haskell 21 | -- ^^ keyword.operator.big-arrow 22 | , return :: forall m a . Unrestricted.Monad m => a -> m a 23 | -- ^^^^^^ variable.other.member.definition.haskell 24 | -- ^^ keyword.operator.double-colon.haskell 25 | -- ^^^^^^ keyword.other.forall.haskell 26 | -- ^ keyword.operator.period.haskell 27 | -- ^^ keyword.operator.big-arrow 28 | } 29 | -------------------------------------------------------------------------------- /test/tests/InfixBacktick.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Backticked infix operators" 2 | 3 | 4 | a `foo` b 5 | -- ^^^ keyword.operator.function.infix.haskell 6 | -- ^^^ - constant.other.haskell 7 | -- ^ ^ punctuation.backtick.haskell 8 | a `_foo'` b 9 | -- ^^^^^ keyword.operator.function.infix.haskell 10 | -- ^^^^^ - constant.other.haskell 11 | -- ^ ^ punctuation.backtick.haskell 12 | a `ABC.foo` b 13 | -- ^^^^ entity.name.namespace.haskell 14 | -- ^^^ keyword.operator.function.infix.haskell 15 | -- ^^^ - constant.other.haskell 16 | -- ^ ^ punctuation.backtick.haskell 17 | a `ABC._foo'` b 18 | -- ^^^^ entity.name.namespace.haskell 19 | -- ^^^^^ keyword.operator.function.infix.haskell 20 | -- ^^^^^ - constant.other.haskell 21 | -- ^ ^ punctuation.backtick.haskell 22 | 23 | a `A` b 24 | -- ^ keyword.operator.function.infix.haskell 25 | -- ^ constant.other.haskell 26 | -- ^ ^ punctuation.backtick.haskell 27 | a `ABC.A_'` b 28 | -- ^^^^ entity.name.namespace.haskell 29 | -- ^^^ keyword.operator.function.infix.haskell 30 | -- ^^^ constant.other.haskell 31 | -- ^ ^ punctuation.backtick.haskell 32 | f :: a `A` b 33 | -- ^ storage.type.infix.haskell 34 | -- ^ ^ punctuation.backtick.haskell 35 | f :: a '`A` b 36 | -- ^ keyword.operator.promotion.haskell 37 | -- ^ storage.type.infix.haskell 38 | -- ^ ^ punctuation.backtick.haskell 39 | f :: a `ABC.A` b 40 | -- ^^^^ entity.name.namespace.haskell 41 | -- ^ storage.type.infix.haskell 42 | -- ^ ^ punctuation.backtick.haskell 43 | f :: a '`ABC.A` b 44 | -- ^ keyword.operator.promotion.haskell 45 | -- ^^^^ entity.name.namespace.haskell 46 | -- ^ storage.type.infix.haskell 47 | -- ^ ^ punctuation.backtick.haskell 48 | -------------------------------------------------------------------------------- /test/tests/BlockComments.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Intervening block comments shouldn't affect highlighting" 2 | 3 | 4 | data A 5 | -- ^ storage.type.haskell 6 | {- comment line not gobbled up by the preprocessor 7 | over multiple lines -} 8 | -- <~~---------------------- comment.block.haskell 9 | = A 10 | -- ^ constant.other.haskell 11 | 12 | data B = 13 | -- ^ storage.type.haskell 14 | {- comment line not gobbled up by the preprocessor -} 15 | -- <~~----------------------------------------------------- comment.block.haskell 16 | B 17 | -- ^ constant.other.haskell 18 | 19 | newtype A = 20 | -- ^ storage.type.haskell 21 | {- comment line not gobbled up by the preprocessor 22 | over multiple lines -} 23 | -- <~~---------------------- comment.block.haskell 24 | A 25 | -- ^ constant.other.haskell 26 | 27 | newtype B = 28 | -- ^ storage.type.haskell 29 | {- comment line not gobbled up by the preprocessor -} 30 | -- <~~----------------------------------------------------- comment.block.haskell 31 | B 32 | -- ^ constant.other.haskell 33 | 34 | 35 | data Foo where 36 | {- comment line not gobbled up by the preprocessor 37 | over multiple lines -} 38 | -- <---------------------- comment.block.haskell 39 | MkFoo :: Foo 40 | -- ^^^^^ constant.other.haskell 41 | -- ^^^ storage.type.haskell 42 | 43 | dbPageWrapper :: (DashBoardPage p, Monad m) => 44 | {- comment line not gobbled up by the preprocessor 45 | over 46 | multiple 47 | lines -} 48 | -- <~----------- comment.block.haskell 49 | T.Text -> p -> HtmlT m a -> HtmlT m b -> HtmlT m b 50 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function.type-declaration.haskell 51 | -- ^^^^^ storage.type.haskell 52 | 53 | type T a 54 | {- comment line not gobbled up by the preprocessor 55 | over multiple 56 | lines -} 57 | -- <-------- comment.block.haskell 58 | = Int 59 | -- ^^^ storage.type.haskell 60 | -------------------------------------------------------------------------------- /test/tests/Exports.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Exports" 2 | 3 | module M 4 | ( T(f,C,g) 5 | -- ^ storage.type.haskell 6 | -- ^ ^ entity.name.function.haskell 7 | , S((:<..<), .. ) 8 | -- ^ storage.type.haskell 9 | -- ^^ - variable.other.member.wildcard.haskell 10 | -- ^^^^^ constant.other.operator.prefix.haskell 11 | -- ^^ variable.other.member.wildcard.haskell 12 | , (:->)((:>)) 13 | -- ^^^ storage.type.operator.haskell 14 | -- ^^ constant.other.operator.prefix.haskell 15 | , (:<>)(C,a,D,E) 16 | -- ^^^ storage.type.operator.haskell 17 | , A((<>), (:>>)) 18 | -- ^ storage.type.haskell 19 | -- ^^^ constant.other.operator.prefix.haskell 20 | , f 21 | -- ^ entity.name.function.haskell 22 | , pattern P 23 | -- ^^^^^^^ keyword.other.pattern.haskell 24 | -- ^ constant.other.haskell 25 | , pattern (:|) 26 | -- ^^^^^^^ keyword.other.pattern.haskell 27 | -- ^^ constant.other.operator.prefix.haskell 28 | , pattern -- Q,) 29 | -- ^^^^^^^ keyword.other.pattern.haskell 30 | Q 31 | -- ^ constant.other.haskell 32 | , f, T 33 | -- ^ entity.name.function.haskell 34 | -- ^ storage.type.haskell 35 | , type T 36 | -- ^^^^ keyword.other.type.haskell 37 | -- ^ storage.type.haskell 38 | , type (:-) 39 | -- ^^^^ keyword.other.type.haskell 40 | -- ^^ storage.type.operator.haskell 41 | , type (<+>) 42 | -- ^^^^ keyword.other.type.haskell 43 | -- ^^^ storage.type.operator.haskell 44 | , type {- T -} 45 | -- ^^^^ keyword.other.type.haskell 46 | (<->) 47 | -- ^^^ storage.type.operator.haskell 48 | , type (Qualified.<->) 49 | -- ^^^^ keyword.other.type.haskell 50 | -- ^^^^^^^^^^ entity.name.namespace.haskell 51 | -- ^^^ storage.type.operator.haskell 52 | , type Qualified.T 53 | -- ^^^^ keyword.other.type.haskell 54 | -- ^^^^^^^^^^ entity.name.namespace.haskell 55 | -- ^ storage.type.haskell 56 | ) 57 | where 58 | -- ^^^^^ keyword.other.where.haskell 59 | -------------------------------------------------------------------------------- /test/tests/UnusualTypeApplications.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Unusual type applications" 2 | 3 | 4 | f = g @A 5 | -- ^ keyword.operator.prefix.at.haskell 6 | -- ^^ meta.type-application.haskell 7 | f = [g]@A 8 | -- ^ keyword.operator.prefix.at.haskell 9 | -- ^^ meta.type-application.haskell 10 | f = {g}@A 11 | -- ^ keyword.operator.prefix.at.haskell 12 | -- ^^ meta.type-application.haskell 13 | f = g,@A 14 | -- ^ keyword.operator.prefix.at.haskell 15 | -- ^^ meta.type-application.haskell 16 | f = g;@A 17 | -- ^ keyword.operator.prefix.at.haskell 18 | -- ^^ meta.type-application.haskell 19 | f = g @(A B C) 20 | -- ^ keyword.operator.prefix.at.haskell 21 | -- ^^^^^^^^ meta.type-application.haskell 22 | f = g @'[A B, C] 23 | -- ^ keyword.operator.prefix.at.haskell 24 | -- ^^^^^^^^^^ meta.type-application.haskell 25 | 26 | f = g @'A 27 | -- ^ keyword.operator.prefix.at.haskell 28 | -- ^^^ meta.type-application.haskell 29 | 30 | f = g @() 31 | -- ^ keyword.operator.prefix.at.haskell 32 | -- ^^ support.constant.unit.haskell 33 | 34 | f = g @( ) 35 | -- ^ keyword.operator.prefix.at.haskell 36 | -- ^^^^^^ support.constant.unit.haskell 37 | 38 | f = g @123 39 | -- ^ keyword.operator.prefix.at.haskell 40 | -- ^^^^^^^^^^ meta.type-application.haskell 41 | 42 | f = g @"abc c\" de" 43 | -- ^ keyword.operator.prefix.at.haskell 44 | -- ^^^^^^^^^^^^^ meta.type-application.haskell 45 | 46 | f = g@A 47 | -- ^ - keyword.operator.prefix.at.haskell 48 | -- ^^ - meta.type-application.haskell 49 | f = +@A 50 | -- ^ - keyword.operator.prefix.at.haskell 51 | -- ^^ - meta.type-application.haskell 52 | f = g@@A 53 | -- ^^ - keyword.operator.prefix.at.haskell 54 | -- ^^ - meta.type-application.haskell 55 | f = g @@A 56 | -- ^^ - keyword.operator.prefix.at.haskell 57 | -- ^^ - meta.type-application.haskell 58 | f = g @!A 59 | -- ^ - keyword.operator.prefix.at.haskell 60 | -- ^^ - meta.type-application.haskell 61 | f = (g)@A 62 | -- ^ - keyword.operator.prefix.at.haskell 63 | -- ^^ - meta.type-application.haskell 64 | -------------------------------------------------------------------------------- /test/tests/Alex.x: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell.alex" "Alex" 2 | 3 | { 4 | -- <- meta.embedded.block.haskell 5 | module Alex where 6 | -- <------ keyword.other.module.haskell 7 | -- ^^^^ meta.declaration.module.haskell 8 | } 9 | -- <- meta.embedded.block.haskell 10 | 11 | %wrapper "basic" 12 | -- <-------- entity.name.pragma.alex 13 | -- ^^^^^^^ string.quoted.double.alex 14 | -- ^ ^ punctuation.quote.double.alex 15 | 16 | $digit = 0-9 17 | -- <------ entity.name.macro.character-set.alex 18 | -- ^ ^ keyword.operator.alex 19 | $alpha = [a-zA-Z] 20 | -- ^ ^ punctuation.bracket.alex 21 | 22 | @foobar = foo | bar 23 | -- <------- entity.name.macro.regular-expression.alex 24 | -- ^ ^ keyword.operator.alex 25 | 26 | -- comment {- 27 | tokens :- 28 | -- ^^ keyword.operator.rules.alex 29 | -- <--------- - comment.block.alex 30 | -- comment -} 31 | <0> $white+ ; 32 | -- <-- meta.startcode.alex 33 | -- <- punctuation.bracket.startcode.alex 34 | -- <~~- punctuation.bracket.startcode.alex 35 | -- ^ punctuation.semicolon.alex 36 | <0> $digit+ { NUMBER } 37 | -- ^ punctuation.block.begin.alex 38 | -- ^ punctuation.block.end.alex 39 | <0,1> $alpha+ { IDENT } 40 | --^ punctuation.comma.startcode.alex 41 | { 42 | -- <------------------------ meta.block.startcode.alex 43 | -- <- punctuation.bracket.startcode.alex 44 | -- ^ variable.other.startcode.0.alex 45 | -- ^^^ ^^^ ^^^^^ variable.other.startcode.alex 46 | -- ^ punctuation.bracket.startcode.alex 47 | -- ^ punctuation.block.startcode.begin.alex 48 | \n ; 49 | -- ^ punctuation.semicolon.alex 50 | @foobar { FOO } 51 | -- ^^^^^^^ - source.haskell 52 | } 53 | -- <- punctuation.block.startcode.end.alex 54 | 55 | {- 56 | -- <- punctuation.definition.comment.alex 57 | {- 58 | nested comment 59 | -- <----------------- comment.block.alex 60 | -} 61 | -} 62 | 63 | 64 | { 65 | 66 | data Token 67 | = NUMBER 68 | | IDENT 69 | | FOO 70 | 71 | main = undefined 72 | 73 | } 74 | -------------------------------------------------------------------------------- /test/tickets/T0157.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Specialise pragma" 2 | 3 | {-# SPECIALIZE [0] hammeredLookup :: [(Widget, value)] -> Widget -> value #-} hammeredLookup 4 | -- ^^^^^^^^^^ keyword.other.preprocessor.pragma.haskell 5 | -- ^^^^^^ ^^^^^^ storage.type.haskell 6 | -- ^^^^^ ^^^^^ variable.other.generic-type.haskell 7 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.preprocessor.haskell 8 | -- ^^^^^^^^^^^^^^ - meta.preprocessor.haskell 9 | 10 | 11 | {-# SPECIALISE INLINE (!:) :: Arr (a, b) -> Int -> (a, b) #-} 12 | -- ^^^^^^^^^^ keyword.other.preprocessor.pragma.haskell 13 | -- ^^ entity.name.function.infix.haskell 14 | -- ^^^ ^^^ storage.type.haskell 15 | -- ^ ^ ^ ^ variable.other.generic-type.haskell 16 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.preprocessor.haskell 17 | 18 | {-# SPECIALIZE INLINE [~2] (!:) :: Arr (a, b) -> Int -> (a, b) #-} 19 | -- ^^^^^^^^^^ keyword.other.preprocessor.pragma.haskell 20 | -- ^^^^^^ keyword.other.preprocessor.pragma.haskell 21 | -- ^^ entity.name.function.infix.haskell 22 | -- ^^^ ^^^ storage.type.haskell 23 | -- ^ ^ ^ ^ variable.other.generic-type.haskell 24 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.preprocessor.haskell 25 | 26 | instance (Eq a) => Eq (Foo a) where { 27 | {-# SPECIALISE [1] instance Eq (Foo [(Int, Bar)]) #-} 28 | -- ^^^^^^^^^^ keyword.other.preprocessor.pragma.haskell 29 | -- ^^^^^^^^ keyword.other.instance.haskell 30 | -- ^^ ^^^ ^^^ ^^^ storage.type.haskell 31 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.preprocessor.haskell 32 | } 33 | 34 | -------------------------------------------------------------------------------- /test/tests/Class.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Class declarations" 2 | 3 | 4 | class C a where 5 | -- ^^^^^ keyword.other.class.haskell 6 | -- ^ storage.type.haskell 7 | -- ^ variable.other.generic-type.haskell 8 | -- ^^^^^ keyword.other.where.haskell 9 | meth :: a b 10 | -- ^^^^ entity.name.function.haskell 11 | -- ^ ^ variable.other.generic-type.haskell 12 | 13 | 14 | class ( C a, D a ) 15 | -- ^^^^^ keyword.other.class.haskell 16 | -- ^ ^ storage.type.haskell 17 | -- ^ ^ variable.other.generic-type.haskell 18 | {- comment -} 19 | => E ( A b c ) 20 | -- ^^ keyword.operator.big-arrow.haskell 21 | -- ^ ^ storage.type.haskell 22 | -- ^ ^ variable.other.generic-type.haskell 23 | where 24 | -- ^^^^^ keyword.other.where.haskell 25 | method :: a b 26 | -- ^^^^^^ entity.name.function.haskell 27 | -- ^ ^ variable.other.generic-type.haskell 28 | 29 | 30 | class C ( a :: k ) => 31 | -- ^^^^^ keyword.other.class.haskell 32 | -- ^^ keyword.operator.big-arrow.haskell 33 | G 34 | -- ^ storage.type.haskell 35 | (a :: k) 36 | -- ^ ^ variable.other.generic-type.haskell 37 | (b :: L k) 38 | -- ^ storage.type.haskell 39 | -- ^ ^ variable.other.generic-type.haskell 40 | where 41 | -- ^^^^^ keyword.other.where.haskell 42 | 43 | () :: T k -> T (L k) -> A 44 | -- ^^^ entity.name.function.infix.haskell 45 | -- ^ ^ variable.other.generic-type.haskell 46 | -- ^ ^ ^ ^ storage.type.haskell 47 | 48 | 49 | class G a where 50 | -- ^^^^^ keyword.other.class.haskell 51 | -- ^ storage.type.haskell 52 | -- ^ variable.other.generic-type.haskell 53 | -- ^^^^^ keyword.other.where.haskell 54 | 55 | foo :: A 56 | -- ^^^ meta.function.type-declaration.haskell 57 | -- ^^^ entity.name.function.haskell 58 | -- ^^^^^^^^ - meta.declaration.class.haskell 59 | 60 | class G a 61 | -- ^^^^^ keyword.other.class.haskell 62 | -- ^ storage.type.haskell 63 | -- ^ variable.other.generic-type.haskell -------------------------------------------------------------------------------- /test/tests/Records.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Special record syntax" 2 | 3 | data Rec = Rec { a, b :: AB a b, c :: C, (:+) :: (:-) } 4 | -- ^^^ constant.other.haskell 5 | -- ^^ ^ storage.type.haskell 6 | -- ^ ^ variable.other.generic-type.haskell 7 | -- ^ ^ ^ ^^ variable.other.member.definition.haskell 8 | -- ^^ storage.type.operator.haskell 9 | 10 | f :: Rec -> T 11 | f record@( Rec { a = A, b = b, (:+) = (:-), c, .. } ) 12 | -- ^^^ constant.other.haskell 13 | -- ^ keyword.operator.infix.tight.at.haskell 14 | -- ^ ^^ - variable.other.member.haskell 15 | -- ^ ^ ^^ ^ variable.other.member.haskell 16 | -- ^^ variable.other.member.wildcard.haskell 17 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.record.haskell 18 | 19 | f :: Rec -> Rec 20 | f x = x { a = A, b = b, (:+) = (:-), c, .. } 21 | -- ^ ^^ - variable.other.member.haskell 22 | -- ^ ^ ^^ ^ variable.other.member.haskell 23 | -- ^^ variable.other.member.wildcard.haskell 24 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.record.haskell 25 | 26 | f val@( pattern ) 27 | -- ^ keyword.operator.infix.tight.at.haskell 28 | f val_@( pattern ) 29 | -- ^ keyword.operator.infix.tight.at.haskell 30 | f val'@( pattern ) 31 | -- ^ keyword.operator.infix.tight.at.haskell 32 | f (+)@(g) 33 | -- ^ keyword.operator.infix.tight.at.haskell 34 | 35 | f@@g 36 | -- ^^ -keyword.operator.infix.tight.at.haskell 37 | 38 | f (+)@@(g) 39 | -- ^^ -keyword.operator.infix.tight.at.haskell 40 | 41 | f a@+b 42 | -- ^ -keyword.operator.infix.tight.at.haskell 43 | 44 | 45 | f = \case { "A" -> Just "a"; b -> Nothing } 46 | -- ^^^^^ keyword.control.lambda-case.haskell 47 | -- ^^^ ^^^ string.quoted.double.haskell 48 | -- ^ ^ - variable.other.member.haskell 49 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.record.haskell 50 | -------------------------------------------------------------------------------- /test/tests/Fields.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Record fields" 2 | 3 | data Rec = Rec 4 | { fld1 :: F, -- } 5 | -- ^^^^ variable.other.member.definition.haskell 6 | -- ^^ keyword.operator.double-colon.haskell 7 | -- ^ storage.type.haskell 8 | -- ^^^^ comment.line.double-dash.haskell 9 | fld2 :: F 10 | -- <---- variable.other.member.definition.haskell 11 | -- ^^ keyword.operator.double-colon.haskell 12 | -- ^ storage.type.haskell 13 | , fld3 14 | -- ^^^^ variable.other.member.definition.haskell 15 | :: F 16 | -- <-- keyword.operator.double-colon.haskell 17 | -- ^ storage.type.haskell 18 | , fld4 :: F, -- no :: F, no :: F } 19 | -- ^^^^ variable.other.member.definition.haskell 20 | -- ^^ keyword.operator.double-colon.haskell 21 | -- ^ storage.type.haskell 22 | fld5 :: F -- , no :: F} , 23 | -- <~~---- variable.other.member.definition.haskell 24 | -- ^ storage.type.haskell 25 | } 26 | 27 | 28 | data Rec = Rec 29 | { (& ) :: F, -- } 30 | -- ^ variable.other.member.definition.haskell 31 | -- ^^ keyword.operator.double-colon.haskell 32 | -- ^ storage.type.haskell 33 | -- ^^^^ comment.line.double-dash.haskell 34 | (<>) :: F 35 | -- <~-- variable.other.member.definition.haskell 36 | -- ^^ keyword.operator.double-colon.haskell 37 | -- ^ storage.type.haskell 38 | , ( !!) 39 | -- ^^ variable.other.member.definition.haskell 40 | :: F, (+::) :: F 41 | -- <-- keyword.operator.double-colon.haskell 42 | -- ^ storage.type.haskell 43 | -- ^^^ variable.other.member.definition.haskell 44 | -- ^^ keyword.operator.double-colon.haskell 45 | -- ^ storage.type.haskell 46 | , ( ++ ) :: F, -- no :: F, no :: F } 47 | -- ^^ variable.other.member.definition.haskell 48 | -- ^^ keyword.operator.double-colon.haskell 49 | -- ^ storage.type.haskell 50 | (!::) :: F -- , no :: F} , 51 | -- <~~~--- variable.other.member.definition.haskell 52 | -- ^ storage.type.haskell 53 | } 54 | 55 | 56 | data Rec3 = Rec3 {} 57 | -- ^^ meta.record.definition.haskell 58 | 59 | data Rec4 = Rec4 60 | { 61 | -- <~~- meta.record.definition.haskell 62 | } 63 | -- <- meta.record.definition.haskell 64 | -------------------------------------------------------------------------------- /test/tests/ADTs.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "ADTs" 2 | 3 | data T = C 4 | -- ^^^^ keyword.other.data.haskell 5 | -- ^ storage.type.haskell 6 | -- ^ constant.other.haskell 7 | T 8 | -- ^ storage.type.haskell 9 | 10 | data T = 11 | -- ^^^^ keyword.other.data.haskell 12 | -- ^ storage.type.haskell 13 | C 14 | -- ^ constant.other.haskell 15 | T 16 | -- ^ storage.type.haskell 17 | data T 18 | -- ^^^^ keyword.other.data.haskell 19 | -- ^ storage.type.haskell 20 | = C 21 | -- ^ constant.other.haskell 22 | T 23 | -- ^ storage.type.haskell 24 | data T 25 | -- ^^^^ keyword.other.data.haskell 26 | -- ^ storage.type.haskell 27 | = C T 28 | -- ^ constant.other.haskell 29 | -- ^ storage.type.haskell 30 | data T 31 | -- ^^^^ keyword.other.data.haskell 32 | -- ^ storage.type.haskell 33 | = 34 | C 35 | -- ^ constant.other.haskell 36 | T 37 | -- ^ storage.type.haskell 38 | 39 | data D = C1 T1 | C2 T2 40 | -- ^^^^ keyword.other.data.haskell 41 | -- ^ ^^ ^^ storage.type.haskell 42 | -- ^ keyword.operator.eq.haskell 43 | -- ^ keyword.operator.pipe.haskell 44 | | C3 T3 45 | -- ^ keyword.operator.pipe.haskell 46 | -- ^^ storage.type.haskell 47 | 48 | 49 | data D2 50 | -- ^^^^ keyword.other.data.haskell 51 | = C3 T3 52 | -- ^ keyword.operator.eq.haskell 53 | -- ^^ constant.other.haskell 54 | -- ^^ storage.type.haskell 55 | | C4 T4 56 | -- ^^ constant.other.haskell 57 | -- ^^ storage.type.haskell 58 | -- ^ keyword.operator.pipe.haskell 59 | 60 | data D3 = C5 { f5 :: T5, g5 :: T5 } | C6 T6 61 | -- ^^^^ keyword.other.data.haskell 62 | -- ^ keyword.operator.eq.haskell 63 | -- ^^ ^^ variable.other.member.definition.haskell 64 | -- ^^ ^^ ^^ storage.type.haskell 65 | -- ^ keyword.operator.pipe.haskell 66 | -- ^^ ^^ constant.other.haskell 67 | | C7 { f7 :: T7 } 68 | -- ^ keyword.operator.pipe.haskell 69 | -- ^^ variable.other.member.definition.haskell 70 | -- ^^ storage.type.haskell 71 | -------------------------------------------------------------------------------- /test/tickets/T0182.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Prefix symbolic data constructors" 2 | 3 | data Prop = None -- ^ @_@ 4 | -- ^^^^ storage.type.haskell 5 | -- ^ keyword.operator.eq.haskell 6 | -- ^^^^ constant.other.haskell 7 | -- ^^^^^^^^ comment.line.documentation.haskell 8 | | T -- ^ True 9 | -- ^ keyword.operator.pipe.haskell 10 | -- ^ constant.other.haskell 11 | -- ^^^^^^^^^ comment.line.documentation.haskell 12 | | F -- ^ False 13 | -- ^ keyword.operator.pipe.haskell 14 | -- ^ constant.other.haskell 15 | -- ^^^^^^^^^^ comment.line.documentation.haskell 16 | | Atom String -- ^ prop 17 | -- ^ keyword.operator.pipe.haskell 18 | -- ^^^^ constant.other.haskell 19 | -- ^^^^^^ storage.type.haskell 20 | -- ^^^^^^^^^ comment.line.documentation.haskell 21 | | Not Prop -- ^ negate 22 | -- ^ keyword.operator.pipe.haskell 23 | -- ^^^ constant.other.haskell 24 | -- ^^^^ storage.type.haskell 25 | -- ^^^^^^^^^^^ comment.line.documentation.haskell 26 | | (:/\) Prop Prop -- ^ and 27 | -- ^ keyword.operator.pipe.haskell 28 | -- ^^^ constant.other.operator.prefix.haskell 29 | -- ^^^^ ^^^^ storage.type.haskell 30 | -- ^^^^^^^^ comment.line.documentation.haskell 31 | | (:\/) Prop Prop -- ^ or 32 | -- ^ keyword.operator.pipe.haskell 33 | -- ^^^ constant.other.operator.prefix.haskell 34 | -- ^^^^ ^^^^ storage.type.haskell 35 | -- ^^^^^^^ comment.line.documentation.haskell 36 | | (:->) Prop Prop -- ^ imply 37 | -- ^ keyword.operator.pipe.haskell 38 | -- ^^^ constant.other.operator.prefix.haskell 39 | -- ^^^^ ^^^^ storage.type.haskell 40 | -- ^^^^^^^^^^ comment.line.documentation.haskell 41 | | (:<->) Prop Prop -- ^ <-> 42 | -- ^ keyword.operator.pipe.haskell 43 | -- ^^^^ constant.other.operator.prefix.haskell 44 | -- ^^^^ ^^^^ storage.type.haskell 45 | -- ^^^^^^^^ comment.line.documentation.haskell 46 | -------------------------------------------------------------------------------- /test/tests/OverloadedLabels.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "OverloadedLabels" 2 | 3 | 4 | document = #html [#head [#title [get #title page]], #body [#p ["x=1"] ["Hello!"]]] 5 | -- ^ ^ ^ ^ ^ ^ keyword.operator.prefix.hash.haskell 6 | -- ^^^^^ ^^^^^ ^^^^^^ ^^^^^^ ^^^^^ ^^ entity.name.label.haskell 7 | where page = (#title := "something") 8 | -- ^ keyword.operator.prefix.hash.haskell 9 | -- ^^^^^^ entity.name.label.haskell 10 | 11 | test #a 12 | -- ^ keyword.operator.prefix.hash.haskell 13 | -- ^^ entity.name.label.haskell 14 | test #number17 15 | -- ^ keyword.operator.prefix.hash.haskell 16 | -- ^^^^^^^^^ entity.name.label.haskell 17 | test #do 18 | -- ^ keyword.operator.prefix.hash.haskell 19 | -- ^^^ entity.name.label.haskell 20 | test #type 21 | -- ^ keyword.operator.prefix.hash.haskell 22 | -- ^^^^^ entity.name.label.haskell 23 | test #Foo 24 | -- ^ keyword.operator.prefix.hash.haskell 25 | -- ^^^^ entity.name.label.haskell 26 | test #"Foo" 27 | -- ^ keyword.operator.prefix.hash.haskell 28 | -- ^^^^^^ entity.name.label.haskell 29 | test #3 30 | -- ^ keyword.operator.prefix.hash.haskell 31 | -- ^^ entity.name.label.haskell 32 | test #"3" 33 | -- ^ keyword.operator.prefix.hash.haskell 34 | -- ^^^^ entity.name.label.haskell 35 | test #199.4 36 | -- ^ keyword.operator.prefix.hash.haskell 37 | -- ^^^^^^ entity.name.label.haskell 38 | test #17a23b 39 | -- ^ keyword.operator.prefix.hash.haskell 40 | -- ^^^^^^^ entity.name.label.haskell 41 | test #"The quick brown fox" 42 | -- ^ keyword.operator.prefix.hash.haskell 43 | -- ^^^^^^^^^^^^^^^^^^^^^^ entity.name.label.haskell 44 | test #f'a' 45 | -- ^ keyword.operator.prefix.hash.haskell 46 | -- ^^^^^ entity.name.label.haskell 47 | test #'a' 48 | -- ^ keyword.operator.prefix.hash.haskell 49 | -- ^^^^ entity.name.label.haskell 50 | test #":" 51 | -- ^ keyword.operator.prefix.hash.haskell 52 | -- ^^^^ entity.name.label.haskell 53 | test #' 54 | -- ^ keyword.operator.prefix.hash.haskell 55 | -- ^^ entity.name.label.haskell 56 | test #"\"" 57 | -- ^ keyword.operator.prefix.hash.haskell 58 | -- ^^^^^ entity.name.label.haskell -------------------------------------------------------------------------------- /test/tickets/T0132.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Symbolic type constructors and operators" 2 | 3 | data C a b = C a b 4 | -- <---- keyword.other.data.haskell 5 | -- ^ storage.type.haskell 6 | -- ^ constant.other.haskell 7 | 8 | data a `D` b = a `D` b 9 | -- <---- keyword.other.data.haskell 10 | -- ^ storage.type.infix.haskell 11 | -- ^ constant.other.infix.haskell 12 | 13 | data a `E` b where 14 | -- <---- keyword.other.data.haskell 15 | -- ^ storage.type.infix.haskell 16 | 17 | data (:>) a b = (:>) a b 18 | -- <---- keyword.other.data.haskell 19 | -- ^^ storage.type.operator.haskell 20 | -- ^^ constant.other.operator.prefix.haskell 21 | 22 | data a :< b = a :< b 23 | -- <---- keyword.other.data.haskell 24 | -- ^^ storage.type.operator.infix.haskell 25 | -- ^^ constant.other.operator.infix.haskell 26 | -- ^^ ^^ - keyword.operator.haskell 27 | -- ^^ ^^ - keyword.operator.infix.haskell 28 | 29 | data a := b = a := b 30 | -- <---- keyword.other.data.haskell 31 | -- ^^ storage.type.operator.infix.haskell 32 | -- ^^ constant.other.operator.infix.haskell 33 | -- ^^ ^^ - keyword.operator.haskell 34 | -- ^^ ^^ - keyword.operator.infix.haskell 35 | 36 | data (:<>) a b where 37 | -- <---- keyword.other.data.haskell 38 | (:<>) :: a -> b -> (:<>) a b 39 | -- ^^^ constant.other.operator.prefix.haskell 40 | -- ^^^ storage.type.operator.haskell 41 | 42 | data a :>< b where 43 | -- <---- keyword.other.data.haskell 44 | -- ^^^ storage.type.operator.infix.haskell 45 | 46 | 47 | type F a b = C a b 48 | -- <---- keyword.other.type.haskell 49 | -- ^ ^ storage.type.haskell 50 | 51 | type a `G` b = a `D` b 52 | -- <---- keyword.other.type.haskell 53 | -- ^ ^ storage.type.infix.haskell 54 | 55 | type (<<) a b = a <> b 56 | -- <---- keyword.other.type.haskell 57 | -- ^^ storage.type.operator.haskell 58 | -- ^^ storage.type.operator.infix.haskell 59 | 60 | type (:>>) a b = a :> b 61 | -- <---- keyword.other.type.haskell 62 | -- ^^^ storage.type.operator.haskell 63 | -- ^^ storage.type.operator.infix.haskell 64 | 65 | type a :<< b = a :< b 66 | -- <---- keyword.other.type.haskell 67 | -- ^^^ ^^ storage.type.operator.infix.haskell 68 | 69 | type a :== b = a := b 70 | -- <---- keyword.other.type.haskell 71 | -- ^^^ ^^ storage.type.operator.infix.haskell 72 | -- ^^^ ^^ - keyword.operator.haskell 73 | -------------------------------------------------------------------------------- /test/tickets/T0156.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Non keywords" 2 | 3 | patternFoo :: A 4 | -- <------- - keyword.other.pattern.haskell 5 | patternFoo = A 6 | -- <------- - keyword.other.pattern.haskell 7 | 8 | typeFoo :: A 9 | -- <---- - keyword.other.type.haskell 10 | typeFoo = A 11 | -- <---- - keyword.other.type.haskell 12 | 13 | dataFoo :: A 14 | -- <---- - keyword.other.data.haskell 15 | dataFoo = A 16 | -- <---- - keyword.other.data.haskell 17 | 18 | newtypeFoo :: A 19 | -- <------- - keyword.other.newtype.haskell 20 | newtypeFoo = A 21 | -- <------- - keyword.other.newtype.haskell 22 | 23 | foreignFoo :: A 24 | -- <------- - keyword.other.foreign.haskell 25 | foreignFoo = A 26 | -- <------- - keyword.other.foreign.haskell 27 | 28 | moduleFoo :: A 29 | -- <------ - keyword.other.module.haskell 30 | moduleFoo = A 31 | -- <------ - keyword.other.module.haskell 32 | 33 | classFoo :: A 34 | -- <----- - keyword.other.class.haskell 35 | classFoo = A 36 | -- <----- - keyword.other.class.haskell 37 | 38 | instanceFoo :: A 39 | -- <-------- - keyword.other.instance.haskell 40 | instanceFoo = A 41 | -- <-------- - keyword.other.instance.haskell 42 | 43 | importFoo :: A 44 | -- <------ - keyword.other.import.haskell 45 | importFoo = A 46 | -- <------ - keyword.other.import.haskell 47 | 48 | exportFoo :: A 49 | -- <------ - keyword.other.export.haskell 50 | exportFoo = A 51 | -- <------ - keyword.other.export.haskell 52 | 53 | whereFoo :: A 54 | -- <----- - keyword.other.where.haskell 55 | whereFoo = A 56 | -- <----- - keyword.other.where.haskell 57 | 58 | derivingFoo :: A 59 | -- <-------- - keyword.other.deriving.haskell 60 | derivingFoo = A 61 | -- <-------- - keyword.other.eriving.haskell 62 | 63 | viaFoo :: A 64 | -- <--- - keyword.other.deriving-strategy.via.haskell 65 | viaFoo = A 66 | -- <--- - keyword.other.deriving-strategy.via.haskell 67 | 68 | defaultFoo :: A 69 | -- <------- - keyword.other.default.haskell 70 | defaultFoo = A 71 | -- <------- - keyword.other.default.haskell 72 | 73 | letFoo :: A 74 | -- <--- - keyword.other.let.haskell 75 | letFoo = A 76 | -- <--- - keyword.other.let.haskell 77 | 78 | inFoo :: A 79 | -- <-- - keyword.other.in.haskell 80 | inFoo = A 81 | -- <-- - keyword.other.in.haskell 82 | 83 | doFoo :: A 84 | -- <-- - keyword.other.do.haskell 85 | doFoo = A 86 | -- <-- - keyword.other.do.haskell 87 | 88 | forallFoo :: forallFoo A 89 | -- <------ ^^^^^^ - keyword.other.forall.haskell 90 | -- ^^^^^^^^^ variable.other.generic-type.haskell 91 | forallFoo = A 92 | -- <------ - keyword.other.forall.haskell 93 | -------------------------------------------------------------------------------- /test/tickets/T0072b.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Deriving via and deriving strategies" 2 | 3 | deriving via (A b c) instance C a 4 | -- <------- keyword.other.deriving.haskell 5 | -- ^^^ keyword.other.deriving.strategy.via.haskell 6 | -- ^^^^^^^^ keyword.other.instance.haskell 7 | -- ^ ^ storage.type.haskell 8 | -- ^ ^ ^ variable.other.generic-type.haskell 9 | 10 | deriving via Base a instance C ( Total a ) 11 | -- <------- keyword.other.deriving.haskell 12 | -- ^^^ keyword.other.deriving.strategy.via.haskell 13 | -- ^^^^^^^^ keyword.other.instance.haskell 14 | -- ^^^^ ^ ^^^^^ storage.type.haskell 15 | -- ^ ^ variable.other.generic-type.haskell 16 | 17 | deriving via '(F A, B) instance R '(A, G B) 18 | -- <------- keyword.other.deriving.haskell 19 | -- ^^^ keyword.other.deriving.strategy.via.haskell 20 | -- ^^^^^^^^ keyword.other.instance.haskell 21 | -- ^ ^ ^ ^ ^ ^ ^ storage.type.haskell 22 | 23 | 24 | data B = B 25 | deriving A via B 26 | -- ^^^^^^^^ keyword.other.deriving.haskell 27 | -- ^^^ keyword.other.deriving.strategy.via.haskell 28 | -- ^ ^ storage.type.haskell 29 | deriving stock ( Eq, Generic ) 30 | -- ^^^^^^^^ keyword.other.deriving.haskell 31 | -- ^^^^^ keyword.other.deriving.strategy.stock.haskell 32 | -- ^^ ^^^^^^^ storage.type.haskell 33 | deriving anyclass NFData 34 | -- ^^^^^^^^ keyword.other.deriving.haskell 35 | -- ^^^^^^^^ keyword.other.deriving.strategy.anyclass.haskell 36 | -- ^^^^^^ storage.type.haskell 37 | 38 | newtype N a = MkN a 39 | deriving stock instance Show ( N Int ) 40 | -- <------- keyword.other.deriving.haskell 41 | -- ^^^^^ keyword.other.deriving.strategy.stock.haskell 42 | -- ^^^^^^^^ keyword.other.instance.haskell 43 | -- ^^^^ storage.type.haskell 44 | deriving newtype instance Eq ( N Int ) 45 | -- <------- keyword.other.deriving.haskell 46 | -- ^^^^^^^ keyword.other.deriving.strategy.newtype.haskell 47 | -- ^^^^^^^^ keyword.other.instance.haskell 48 | -- ^^ storage.type.haskell 49 | 50 | newtype StateMonad b c r = StateMonad (StateT (MyState (Something b c) b) IO r) 51 | deriving (MonadState (MyState (Something b c) b), MonadIO, Monad) 52 | -- ^^^^^^^^ keyword.other.deriving.haskell 53 | -- ^^^^^^^^^^ ^^^^^^^ ^^^^^ storage.type.haskell 54 | -- ^ ^ ^ variable.other.generic-type.haskell -------------------------------------------------------------------------------- /test/tests/Haddocks.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Haddock documentation" 2 | 3 | {-# OPTIONS_HADDOCK ignore-exports #-} 4 | -- ^^^^^^^^^^^^^^^ keyword.other.preprocessor.haskell 5 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.preprocessor.haskell 6 | 7 | 8 | -- | Doc 9 | -- ^^^ comment.block.documentation.haskell 10 | 11 | {-| doc 12 | -- ^^^ comment.block.documentation.haskell 13 | doc 14 | -- ^^^ comment.block.documentation.haskell 15 | doc -} 16 | -- ^^^ comment.block.documentation.haskell 17 | 18 | {- | also doc -} 19 | -- ^^^^^^^^^^^^^^^^ comment.block.documentation.haskell 20 | 21 | -- | docs 22 | -- ^^^^^^ comment.block.documentation.haskell 23 | -- $ docs 24 | -- ^^^^^^ comment.block.documentation.haskell 25 | -- ^ docs 26 | -- ^^^^^^ comment.block.documentation.haskell 27 | -- * docs 28 | -- ^^^^^^ comment.block.documentation.haskell 29 | a --| notDocs 30 | -- ^^^^^^^^^^^^^ - comment.block.documentation.haskell 31 | a --$ notDocs 32 | -- ^^^^^^^^^^^^^ - comment.block.documentation.haskell 33 | a --^ notDocs 34 | -- ^^^^^^^^^^^^^ - comment.block.documentation.haskell 35 | a --* notDocs 36 | -- ^^^^^^^^^^^^^ - comment.block.documentation.haskell 37 | -- | notDocs 38 | -- ^^^^^^^^^ - comment.block.documentation.haskell 39 | -- $ notDocs 40 | -- ^^^^^^^^^ - comment.block.documentation.haskell 41 | -- ^ notDocs 42 | -- ^^^^^^^^^ - comment.block.documentation.haskell 43 | -- * notDocs 44 | -- ^^^^^^^^^ - comment.block.documentation.haskell 45 | {-| docs -} 46 | -- ^^^^^^^^^^^ comment.block.documentation.haskell 47 | {-$ docs -} 48 | -- ^^^^^^^^^^^ comment.block.documentation.haskell 49 | {-^ docs -} 50 | -- ^^^^^^^^^^^ comment.block.documentation.haskell 51 | {-* docs -} 52 | -- ^^^^^^^^^^^ comment.block.documentation.haskell 53 | {- | docs -} 54 | -- ^^^^^^^^^^^^ comment.block.documentation.haskell 55 | {- $ docs -} 56 | -- ^^^^^^^^^^^^ comment.block.documentation.haskell 57 | {- ^ docs -} 58 | -- ^^^^^^^^^^^^ comment.block.documentation.haskell 59 | {- * docs -} 60 | -- ^^^^^^^^^^^^ comment.block.documentation.haskell 61 | 62 | -- | docs 63 | -- ^^^^^^^^^ comment.block.documentation.haskell 64 | -- continuing docs 65 | -- ^^^^^^^^^^^^^^^^^^ comment.block.documentation.haskell 66 | -- still docs 67 | -- ^^^^^^^^^^^^^ comment.block.documentation.haskell 68 | -- no longer docs 69 | -- ^^^^^^^^^^^^^^ - comment.block.documentation.haskell 70 | 71 | g :: a -- ^ doc 72 | -- ^^^ comment.line.documentation.haskell 73 | -> b --^ notDoc 74 | -- ^^^^^^^^^^^ - comment.line.documentation.haskell comment.block.documentation.haskell 75 | -> c 76 | -------------------------------------------------------------------------------- /syntaxes/haddock.YAML-tmLanguage: -------------------------------------------------------------------------------- 1 | fileTypes: [] 2 | name: Haddock 3 | patterns: [] 4 | repository: 5 | module_description: 6 | match: | 7 | (?x) 8 | ^\s*(?:--)?\s* 9 | ( Module | Description | Copyright | Maintainer | Stability 10 | | License | Portability 11 | )\s*(:)' 12 | captures: 13 | '1': {name: keyword.other.haddock} 14 | '2': {name: keyword.operator.haddock} 15 | list: 16 | match: '^\s*(?:--\s+)?([-*])\s' 17 | captures: 18 | '1': {name: punctuation.list.begin.haddock} 19 | enumeration: 20 | match: '^\s*(?:--\s+)?(\(\d\)|\d\.)\s' 21 | captures: 22 | '1': {name: punctuation.list.begin.haddock} 23 | definition: 24 | match: '^\s*(?:--\s+)?(\[.*?\]:)\s' 25 | captures: 26 | '1': {name: markup.list.definition.haddock} 27 | markup: 28 | patterns: 29 | - include: '#italic' 30 | - include: '#bold' 31 | - include: '#ref' 32 | birdtracks: 33 | begin: '^(\s*(?:--\s+)?)>' 34 | end: '-}|^(?!\1>)' 35 | patterns: 36 | - include: source.haskell 37 | fenced_code: 38 | begin: '@' 39 | end: '@|-}' 40 | patterns: 41 | - include: '#markup' 42 | example: 43 | match: '^\s*(?:--\s+)?(>>>)(.*)$' 44 | captures: 45 | '1': {name: markup.raw} 46 | '2': { include: source.haskell } 47 | prop: 48 | match: '^\s*(?:--\s+)?(prop>)(.*)$' 49 | captures: 50 | '1': {name: markup.raw} 51 | '2': { include: source.haskell } 52 | ref: 53 | patterns: 54 | - match: '(?<=\s)[''`]([\w_\p{Lt}][\w_\p{Lt}\p{Nd}''])[''`](?=\s|$)' 55 | captures: 56 | '1': {name: markup.underline.link.ref.haddock} 57 | - match: '(?<=\s)"(\p{Lu}[\w_\p{Lt}\p{Nd}''])"(?=\s|$)' 58 | captures: 59 | '1': {name: markup.underline.link.ref.module.haddock} 60 | 61 | italic: 62 | begin: '(?' 76 | name: markup.underline.link.haddock 77 | - match: '!?\[(.*?)\]\((.*?)\)' 78 | captures: 79 | '1': {name: string.other.link.title.haddock} 80 | '2': {name: markup.underline.link.haddock} 81 | 82 | anchor: 83 | match: '\#[\w]+\#|"\w+#\w+"' 84 | name: string.other.anchor.haddock 85 | 86 | headings: 87 | match: '^\s*(?:--\s+)?=+(.+)$' 88 | name: markup.heading.haddock 89 | captures: 90 | '1': {name: punctuation.definition.heading.haddock} 91 | '2': 92 | name: entity.name.section.haddock 93 | patterns: 94 | include: '#markup' 95 | 96 | scopeName: source.haddock 97 | -------------------------------------------------------------------------------- /test/tests/GADTs.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "GADTs" 2 | 3 | data G :: a -> (b :: B) -> c -> Type where 4 | -- ^^^^ keyword.other.data.haskell 5 | -- ^^ ^^ keyword.operator.double-colon.haskell 6 | -- ^ ^ ^ variable.other.generic-type.haskell 7 | -- ^^ ^^ ^^ keyword.operator.arrow.haskell 8 | -- ^ ^ ^^^^ storage.type.haskell 9 | -- ^^^^^^ keyword.other.where.haskell 10 | A :: G A b c 11 | -- ^ constant.other.haskell 12 | -- ^^ keyword.operator.double-colon.haskell 13 | -- ^ ^ storage.type.haskell 14 | -- ^ ^ variable.other.generic-type.haskell 15 | B :: a -> b -> G a B C 16 | -- ^ constant.other.haskell 17 | -- ^^ keyword.operator.double-colon.haskell 18 | -- ^ ^ ^ variable.other.generic-type.haskell 19 | -- ^ ^ ^ storage.type.haskell 20 | 21 | (:&) :: G A B C 22 | -- ^^ constant.other.operator.prefix.haskell 23 | -- ^^ keyword.operator.double-colon.haskell 24 | -- ^ ^ ^ ^ storage.type.haskell 25 | 26 | 27 | data (a :: A) `G` (c :: C) :: Type where 28 | -- ^^^^ keyword.other.data.haskell 29 | -- ^ ^ variable.other.generic-type.haskell 30 | -- ^ storage.type.infix.haskell 31 | -- ^^ ^^ ^^ keyword.operator.double-colon.haskell 32 | -- ^ ^ ^^^^ storage.type.haskell 33 | -- ^^^^^^ keyword.other.where.haskell 34 | 35 | data (:&) a b where 36 | -- ^^^^ keyword.other.data.haskell 37 | -- ^^ storage.type.operator.haskell 38 | -- ^ ^ variable.other.generic-type.haskell 39 | -- ^^^^^^ keyword.other.where.haskell 40 | 41 | data (:&) :: a -> b -> Type where 42 | -- ^^^^ keyword.other.data.haskell 43 | -- ^^ storage.type.operator.haskell 44 | -- ^^ keyword.operator.double-colon.haskell 45 | -- ^ ^ variable.other.generic-type.haskell 46 | -- ^^ ^^ keyword.operator.arrow.haskell 47 | -- ^^^^ storage.type.haskell 48 | -- ^^^^^^ keyword.other.where.haskell 49 | 50 | 51 | data (a :: A) :& (b :: B) :: Type where 52 | -- ^^^^ keyword.other.data.haskell 53 | -- ^^ storage.type.operator.infix.haskell 54 | -- ^ ^ variable.other.generic-type.haskell 55 | -- ^^ ^^ ^^ keyword.operator.double-colon.haskell 56 | -- ^ ^ ^^^^ storage.type.haskell 57 | -- ^^^^^^ keyword.other.where.haskell 58 | 59 | data a :& b where 60 | -- ^^^^ keyword.other.data.haskell 61 | -- ^^ storage.type.operator.infix.haskell 62 | -- ^ ^ variable.other.generic-type.haskell 63 | -- ^^^^^^ keyword.other.where.haskell 64 | -------------------------------------------------------------------------------- /syntaxes/cabal.YAML-tmLanguage: -------------------------------------------------------------------------------- 1 | fileTypes: 2 | - cabal 3 | name: Cabal 4 | patterns: 5 | - name: keyword.other.cabal 6 | match: | 7 | (?ix)(\n|^) 8 | ( name 9 | | version 10 | | cabal-version 11 | | build-type 12 | | license(-file)? 13 | | copyright 14 | | author 15 | | maintainer 16 | | stability 17 | | homepage 18 | | bug-reports 19 | | package-url 20 | | synopsis 21 | | data-(files|dir) 22 | | description 23 | | category 24 | | extra-(source|doc|tmp)-files 25 | | tested-with 26 | ): 27 | - name: keyword.other.cabal 28 | match: | 29 | (?ix)^[ \t]+ 30 | ( (build(-tool)?|pkgconfig|setup)-depends 31 | | (hs-source|include|extra-(lib|frameworks))-dirs 32 | | ((other|default)-)?extensions 33 | | build-tools 34 | | buildable 35 | | ((install|autogen)-)?includes 36 | | (c(xx)?|js)-sources 37 | | extra- 38 | ( ((ghci|bundled)-)?libraries 39 | | (dynamic-)?library-flavours 40 | ) 41 | | (cmm|cxx|cc|cpp|ld|ghc(-(prof|shared))?)-options 42 | | (asm|cmm)-(sources|options) 43 | | other-languages 44 | | default-language 45 | | frameworks 46 | | default 47 | | manual 48 | | location 49 | | branch 50 | | tag 51 | | subdir 52 | | exposed(-modules)? 53 | | (other|virtual|autogen|reexported)-modules 54 | | visibility 55 | | main-is 56 | | type 57 | | test-module 58 | | description 59 | | mixins 60 | | import 61 | | signatures 62 | | scope 63 | | lib-version-(version|linux) 64 | | mod-def-file 65 | | options 66 | | x-\w[1-9\w_-]* 67 | ): 68 | - name: keyword.operator.cabal 69 | match: '(==|>=|<=|<|>|^>=|\|\||&&|!)' 70 | - name: constant.numeric.cabal 71 | match: '(?<=[^\w])\d+(\.\d+)*(\.\*)?' 72 | - name: markup.underline.link.cabal 73 | match: '\w+:/(/[\w._\-\d%])+(\?[\w.+_\-\d%]+)(&[\w._+\-\d%]+)*' 74 | - name: entity.name.section.cabal 75 | match: | 76 | ^(?ix: 77 | ( library 78 | | custom-setup 79 | ) 80 | )$ 81 | - match: | 82 | ^(?ix: 83 | ( executable 84 | | flag 85 | | test-suite 86 | | benchmark 87 | | common 88 | | source-repository 89 | | library 90 | | foreign-library 91 | ) 92 | )( |\t)+([\w\-_]+)$ 93 | captures: 94 | '1': {name: entity.name.section.cabal} 95 | '3': {name: entity.name.function.cabal} 96 | - name: keyword.control.cabal 97 | match: '^[ \t]*(if|elif|else)' 98 | - name: comment.line.double-dash 99 | match: '^\s*--.*$' 100 | scopeName: source.cabal 101 | uuid: 5eb56f02-df11-40b2-b6d5-fa444522416c 102 | -------------------------------------------------------------------------------- /scope-lists/refresh.hs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env stack 2 | -- stack script --resolver lts-15.12 --package aeson --package yaml --package filepath --package directory --package unordered-containers --package text 3 | 4 | {- 5 | This file is used to generate a database of scope keys used in 6 | -} 7 | 8 | {-# LANGUAGE LambdaCase, OverloadedStrings, GeneralizedNewtypeDeriving, RecordWildCards #-} 9 | 10 | import Data.Yaml 11 | import System.Environment 12 | import System.FilePath 13 | import System.Directory 14 | import qualified Data.Text as T 15 | import qualified Data.Text.IO as T 16 | import qualified Data.HashMap.Strict as M 17 | import qualified Data.HashSet as S 18 | import Data.Foldable (toList) 19 | import Data.Maybe 20 | import Data.List (sort) 21 | 22 | newtype Names = Names { names :: S.HashSet T.Text } 23 | deriving (Monoid, Semigroup) 24 | 25 | add :: T.Text -> Names -> Names 26 | add n = Names . S.insert n . names 27 | 28 | instance FromJSON Names where 29 | parseJSON = \case 30 | Object o -> do 31 | new <- o .:? "name" 32 | recursed <- mconcat <$> mapM parseJSON (M.elems o) 33 | pure $ maybe id add new recursed 34 | Array vs -> mconcat . toList <$> traverse parseJSON vs 35 | _ -> pure mempty 36 | 37 | data Info = Info { iname :: T.Text, idesc :: Maybe T.Text, iexample :: Maybe T.Text, ihide :: Bool } 38 | 39 | instance FromJSON Info where 40 | parseJSON = withObject "Info must be an object" $ \o -> 41 | Info <$> o .: "scope" <*> o.:? "description" <*> o .:? "example" <*> o .:? "hide" .!= False 42 | 43 | instance ToJSON Info where 44 | toJSON Info{..} = object $ 45 | "description" .?= idesc $ "example" .?= iexample $ "hide" .?= (if ihide then Just ihide else Nothing) $ ["scope" .= iname] 46 | where 47 | _ .?= Nothing = id 48 | a .?= Just b = (a .= b : ) 49 | 50 | toInfo :: Names -> [Info] 51 | toInfo = map (\name -> Info name Nothing Nothing False) . sort . toList . names 52 | 53 | toNames :: [Info] -> Names 54 | toNames = Names . S.fromList . map iname 55 | 56 | mergeInfo :: [Info] -> Names -> [Info] 57 | mergeInfo ext (Names n) = ext <> toInfo (Names $ n `S.difference` names (toNames ext)) 58 | 59 | toMarkdown :: [Info] -> T.Text 60 | toMarkdown info = T.unlines $ 61 | "| Scope Name | Description | Example |" 62 | : "|-|-|-|" 63 | : map (\Info{..} -> "| " <> iname <> " | " <> fromMaybe "" idesc <> " | " <> fromMaybe "" iexample <> " |") ( filter (not . ihide) info) 64 | 65 | main = 66 | getArgs >>= \case 67 | ["db",target, out] -> refreshDb target out 68 | ["md", target, out] -> makeMarkdown target out 69 | 70 | where 71 | refreshDb syntax outFile = do 72 | fromGrammar <- decodeFileThrow syntax 73 | old <- 74 | doesFileExist outFile >>= \case 75 | True -> Just <$> decodeFileThrow outFile 76 | _ -> pure Nothing 77 | 78 | encodeFile outFile $ maybe toInfo mergeInfo old fromGrammar 79 | makeMarkdown db md = decodeFileThrow db >>= T.writeFile md . toMarkdown 80 | -------------------------------------------------------------------------------- /test/tests/MultilineDeriving.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Multiline deriving" 2 | 3 | 4 | deriving stock instance 5 | -- ^^^^^^^^ keyword.other.deriving.haskell 6 | -- ^^^^^ keyword.other.deriving.strategy.stock.haskell 7 | -- ^^^^^^^^ keyword.other.instance.haskell 8 | ( A b c 9 | -- ^ storage.type.haskell 10 | , D e f 11 | -- ^ ^ variable.other.generic-type.haskell 12 | ) 13 | => C b c e f 14 | -- ^^ keyword.operator.big-arrow.haskell 15 | -- ^ storage.type.haskell 16 | -- ^ ^ ^ ^ variable.other.generic-type.haskell 17 | 18 | deriving anyclass 19 | -- ^^^^^^^^ keyword.other.deriving.haskell 20 | -- ^^^^^^^^ keyword.other.deriving.strategy.anyclass.haskell 21 | instance 22 | -- ^^^^^^^^ keyword.other.instance.haskell 23 | ( A b c 24 | -- ^ storage.type.haskell 25 | , D e f 26 | -- ^ ^ variable.other.generic-type.haskell 27 | ) 28 | => C b c e f 29 | -- ^^ keyword.operator.big-arrow.haskell 30 | -- ^ storage.type.haskell 31 | -- ^ ^ ^ ^ variable.other.generic-type.haskell 32 | 33 | 34 | deriving 35 | -- ^^^^^^^^ keyword.other.deriving.haskell 36 | via X y z 37 | -- ^^^ keyword.other.deriving.strategy.via.haskell 38 | -- ^ storage.type.haskell 39 | -- ^ ^ variable.other.generic-type.haskell 40 | instance 41 | -- ^^^^^^^^ keyword.other.instance.haskell 42 | ( A b c 43 | -- ^ storage.type.haskell 44 | , D e f 45 | -- ^ ^ variable.other.generic-type.haskell 46 | ) 47 | => C b c e f 48 | -- ^^ keyword.operator.big-arrow.haskell 49 | -- ^ storage.type.haskell 50 | -- ^ ^ ^ ^ variable.other.generic-type.haskell 51 | 52 | 53 | deriving 54 | -- ^^^^^^^^ keyword.other.deriving.haskell 55 | via ( X y z ) 56 | -- ^^^ keyword.other.deriving.strategy.via.haskell 57 | instance 58 | -- ^^^^^^^^ keyword.other.instance.haskell 59 | ( A b c 60 | -- ^ storage.type.haskell 61 | , D e f 62 | -- ^ ^ variable.other.generic-type.haskell 63 | ) 64 | => C b c e f 65 | -- ^^ keyword.operator.big-arrow.haskell 66 | -- ^ storage.type.haskell 67 | -- ^ ^ ^ ^ variable.other.generic-type.haskell 68 | 69 | 70 | data AB = AB deriving stock Eq 71 | -- ^^^^^^^^ keyword.other.deriving.haskell 72 | -- ^^^^^ keyword.other.deriving.strategy.stock.haskell 73 | -- ^^ storage.type.haskell 74 | deriving 75 | -- ^^^^^^^^ keyword.other.deriving.haskell 76 | ( C x y z ) 77 | -- ^ storage.type.haskell 78 | -- ^ ^ ^ variable.other.generic-type.haskell 79 | via 80 | -- ^^^ keyword.other.deriving.strategy.via.haskell 81 | XY 82 | -- ^^ storage.type.haskell 83 | -------------------------------------------------------------------------------- /test/tickets/T0165.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Data constructor constraint arrow in comment" 2 | 3 | data D = C {- ( f :: X => X ) -} X 4 | -- ^ constant.other.haskell 5 | -- ^^ - keyword.operator.big-arrow.haskell 6 | -- ^^^^^^^^^^ comment.block.haskell 7 | -- ^ ^ storage.type.haskell 8 | -- ^ ^ - constant.other.haskell 9 | 10 | data D =C {- f :: X => X -} X 11 | -- ^ constant.other.haskell 12 | -- ^^ - keyword.operator.big-arrow.haskell 13 | -- ^^^^^^^^^^ comment.block.haskell 14 | -- ^ ^ storage.type.haskell 15 | -- ^ ^ - constant.other.haskell 16 | 17 | data D =C{- => X -} x => X 18 | -- ^ constant.other.haskell 19 | -- ^^ - keyword.operator.big-arrow.haskell 20 | -- ^^^^^^^^^^ comment.block.haskell 21 | -- ^ ^ storage.type.haskell 22 | -- ^ ^ - constant.other.haskell 23 | 24 | data D = C {- xxx -} => X 25 | -- ^ ^ storage.type.haskell 26 | -- ^^^^^^^^^ comment.block.haskell 27 | -- ^ constant.other.haskell 28 | 29 | data D = C-- => X 30 | -- ^ storage.type.haskell 31 | -- ^ constant.other.haskell 32 | -- ^^ - keyword.operator.big-arrow.haskell 33 | -- ^^^^^^^ comment.line.double-dash.haskell 34 | -- ^^^^^^^^^^ comment.block.haskell 35 | -- ^ - constant.other.haskell 36 | 37 | data D = C -- => X 38 | -- ^ storage.type.haskell 39 | -- ^ constant.other.haskell 40 | -- ^^ - keyword.operator.big-arrow.haskell 41 | -- ^^^^^^^ comment.line.double-dash.haskell 42 | -- ^^^^^^^^^^ comment.block.haskell 43 | -- ^ - constant.other.haskell 44 | 45 | data QCInst -- A much simplified version of ClsInst 46 | -- See Note [Quantified constraints] in GHC.Tc.Solver.Canonical 47 | = QCI { qci_ev :: CtEvidence -- Always of type forall tvs. context => ty 48 | -- ^^^ constant.other.haskell 49 | -- ^^^^^^ variable.other.member.definition.haskel 50 | -- ^^ keyword.operator.double-colon.haskell 51 | -- ^^^^^^^^^^ storage.type.haskell 52 | -- ^^ - keyword.operator.big-arrow.haskell 53 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-dash.haskell 54 | 55 | -- Always Given 56 | , qci_tvs :: [TcTyVar] -- The tvs 57 | -- ^^^^^^^ variable.other.member.definition.haskel 58 | , qci_pred :: TcPredType -- The ty 59 | -- ^^^^^^^^ variable.other.member.definition.haskel 60 | , qci_pend_sc :: Bool -- Same as cc_pend_sc flag in CDictCan 61 | -- ^^^^^^^^^^^ variable.other.member.definition.haskel 62 | -- Invariant: True => qci_pred is a ClassPred 63 | } 64 | -------------------------------------------------------------------------------- /test/tests/QuasiQuotes.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Quasi quotes" 2 | 3 | 4 | [e| A + B + C |] 5 | -- ^ ^ keyword.operator.quasi-quotation.begin.haskell 6 | -- ^ entity.name.quasi-quoter.haskell 7 | -- ^ ^ ^ constant.other.haskell 8 | -- ^ ^ keyword.operator.infix.haskell 9 | -- ^^ keyword.operator.quasi-quotation.end.haskell 10 | -- ^^^^^^^^^^^^^^^^ meta.quasi-quotation.haskell 11 | 12 | [|| A + B + C ||] 13 | -- ^^^ keyword.operator.quasi-quotation.begin.haskell 14 | -- ^ ^ ^ constant.other.haskell 15 | -- ^ ^ keyword.operator.infix.haskell 16 | -- ^^^ keyword.operator.quasi-quotation.end.haskell 17 | -- ^^^^^^^^^^^^^^^^^ meta.quasi-quotation.haskell 18 | 19 | [p| A |] 20 | -- ^ ^ keyword.operator.quasi-quotation.begin.haskell 21 | -- ^ entity.name.quasi-quoter.haskell 22 | -- ^ constant.other.haskell 23 | -- ^^ keyword.operator.quasi-quotation.end.haskell 24 | -- ^^^^^^^^ meta.quasi-quotation.haskell 25 | 26 | 27 | [t| A -> B -> C |] 28 | -- ^ ^ keyword.operator.quasi-quotation.begin.haskell 29 | -- ^ entity.name.quasi-quoter.haskell 30 | -- ^ ^ ^ storage.type.haskell 31 | -- ^^ ^^ keyword.operator.arrow.haskell 32 | -- ^^ keyword.operator.quasi-quotation.end.haskell 33 | -- ^^^^^^^^^^^^^^^^^^ meta.quasi-quotation.haskell 34 | 35 | 36 | [r|\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}|] 37 | -- ^ ^ keyword.operator.quasi-quotation.begin.haskell 38 | -- ^ entity.name.quasi-quoter.haskell 39 | -- ^^ keyword.operator.quasi-quotation.end.haskell 40 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.quasi-quotation.haskell 41 | 42 | 43 | [i|| A |] 44 | -- ^ ^ keyword.operator.quasi-quotation.begin.haskell 45 | -- ^ entity.name.quasi-quoter.haskell 46 | -- ^^^^ meta.quasi-quotation.haskell meta.embedded.block.i 47 | -- ^^ keyword.operator.quasi-quotation.end.haskell 48 | -- ^^^^^^^^^ meta.quasi-quotation.haskell 49 | 50 | [$html| 51 | -- ^ ^ keyword.operator.quasi-quotation.begin.haskell 52 | -- ^^^^ entity.name.quasi-quoter.haskell 53 | -- ^ keyword.operator.prefix.dollar.haskell 54 | -- ^^^^^^^ meta.quasi-quotation.haskell 55 | 56 | 57 | -- ^^^^^^ meta.quasi-quotation.haskell 58 | -- ^^^^^^ meta.embedded.block.html 59 | |] 60 | -- ^^ keyword.operator.quasi-quotation.end.haskell 61 | -- ^^ meta.quasi-quotation.haskell 62 | 63 | [Mod.xml| |] 64 | -- ^ ^ keyword.operator.quasi-quotation.begin.haskell 65 | -- ^^^^ entity.name.namespace.haskell 66 | -- ^^^ entity.name.quasi-quoter.haskell 67 | -- ^^ keyword.operator.quasi-quotation.end.haskell 68 | -- ^^^^^^^^^^^^^^^^^^^^ meta.quasi-quotation.haskell 69 | -- ^^^^^^^ meta.embedded.block.xml 70 | 71 | [a'|'xyz|] 72 | -- ^^ entity.name.quasi-quoter.haskell 73 | -- ^ ^ keyword.operator.quasi-quotation.begin.haskell 74 | -- ^^ keyword.operator.quasi-quotation.end.haskell 75 | -- ^^^^^^^^^^ meta.quasi-quotation.haskell 76 | 77 | [ v | v <- [0..1] ] 78 | -- ^^^^^^^^^^^^^^^^^^^ - meta.quasi-quotation.haskell -------------------------------------------------------------------------------- /test/tickets/T0161.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Data constructor highlighting" 2 | 3 | data Foo a = (:>) a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a 4 | -- ^^^^ keyword.other.data.haskell 5 | -- ^ keyword.operator.eq.haskell 6 | -- ^^ constant.other.operator.prefix.haskell 7 | -- ^ ^ ^ ^ ^ ^ ^ variable.other.generic-type.haskell 8 | 9 | data Foo a = (:>) `C` ( S, O ) deriving ( Show, Ord ) 10 | -- ^^^^ keyword.other.data.haskell 11 | -- ^ variable.other.generic-type.haskell 12 | -- ^ keyword.operator.eq.haskell 13 | -- ^^ storage.type.operator.haskell 14 | -- ^^ - constant.other.operator.haskell 15 | -- ^ constant.other.infix.haskell 16 | -- ^^^^^^^^ keyword.other.deriving.haskell 17 | -- ^^^ ^ ^ ^^^^ ^^^ storage.type.haskell 18 | 19 | data Foo a = (:>) Bar a deriving ( Show, Ord ) 20 | -- ^^^^ keyword.other.data.haskell 21 | -- ^ keyword.operator.eq.haskell 22 | -- ^^ constant.other.operator.prefix.haskell 23 | -- ^ ^ variable.other.generic-type.haskell 24 | -- ^^^^^^^^ keyword.other.deriving.haskell 25 | -- ^^^ ^^^ ^^^^ ^^^ storage.type.haskell 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Haskell Syntax Highlighting Support 2 | 3 | 4 | Syntax highlighting support for Haskell and associated languages (e.g. Cabal, Happy and Alex) in Visual Studio Code. 5 | 6 | ## Syntax highlighting 7 | 8 | Adds syntax highlighting support for Haskell (.hs and .lhs). This is a (now heavily) modified version of 9 | the syntax file from the [Haskell TextMate bundle](https://github.com/textmate/haskell.tmbundle). 10 | Additionally there is support for Cabal files (.cabal) via a concoction of my own. 11 | 12 | Also adds automatic indentation after `where`, `do`, `->` etc. and surrounding brackets (`[]`, `{}` etc) 13 | 14 | ![Screenshot Haskell](/images/screenshot1.png?raw=true) 15 | 16 | ![Screenshot Cabal](/images/screenshot-cabal1.png?raw=true) 17 | 18 | ## Bugs 19 | 20 | If you happen to notice bugs or have suggestions for improvements visit the [issue 21 | section](https://github.com/JustusAdam/language-haskell/issues) of the 22 | [repository](https://github.com/JustusAdam/language-haskell). 23 | 24 | ## Themes 25 | 26 | This extension provides TextMate scopes for use in syntax highlighting, but the colours displayed 27 | depend on the theme being used. 28 | Unfortunately many themes have incomplete support for the different TextMate scopes, and as a 29 | result different tokens can end up with identical colours. 30 | 31 | For a theme that supports all the scopes provided by this extension, see the 32 | [Groovy Lambda theme](https://github.com/sheaf/groovy-lambda). 33 | 34 | ## Theme authors 35 | 36 | I recently realized that I am woefully unaware of whether there are any themes with Haskell-specific 37 | rules and how changes to this extension affect such themes. If you are a theme author that wishes to 38 | use Haskell specific rules, or are aware of a theme with Haskell specific rules, feel free to get in 39 | touch. 40 | 41 | With version `3.0.0` some new tm scopes were added, such that now record and GADT definitions can be 42 | distinguished. Let me know if there are any questions about the scope assignment in this 43 | extension or if there are further scope assigments you'd like to see added. 44 | 45 | We now publish an automatically generated, complete list of the textmate scopes 46 | used in our grammars. You can find the lists of scopes in the 47 | [scope-lists](/scope-lists) directory. 48 | 49 | ## Contributing 50 | 51 | This project currently uses the `YAML-tmLanguage` format for language grammars (Haskell, Cabal, alex, happy, ...). 52 | The grammars can be found in the `syntaxes` directory. 53 | To generate `JSON` grammars (which is the format VS Code expects), we use the Node package `js-yaml` (requires `npx` in PATH): 54 | 55 | ```sh 56 | npx js-yaml haskell.YAML-tmLanguage > haskell.json 57 | ``` 58 | 59 | For testing, we use the Node package `vscode-tmgrammar-test`. For instance, to generate/check 60 | the scopes of a Haskell source file, run: 61 | 62 | ```sh 63 | npx vscode-tmgrammar-test "-s" "source.haskell" "-g" "syntaxes/haskell.json" "-t" "myTestFile.hs" 64 | ``` 65 | 66 | 67 | To run the test-suite, simply call `make test`. 68 | This will build the grammar files and run `vscode-tmgrammar-test` on all the files in the testsuite. 69 | -------------------------------------------------------------------------------- /syntaxes/happy.YAML-tmLanguage: -------------------------------------------------------------------------------- 1 | fileTypes: 2 | - y 3 | name: Haskell Happy 4 | patterns: 5 | - include: "#comments" 6 | - include: "#blocks" 7 | - include: "#syntax" 8 | - include: "#strings" 9 | repository: 10 | block_comment: 11 | applyEndPatternLast: 1 12 | begin: "{-" 13 | captures: 14 | '0': { name: punctuation.definition.comment.happy } 15 | end: "-}" 16 | name: comment.block.happy 17 | patterns: 18 | - include: "#block_comment" 19 | comments: 20 | patterns: 21 | - name: comment.line.happy 22 | match: '\-\-.*$' 23 | - include: "#block_comment" 24 | blocks: 25 | patterns: 26 | - name: meta.embedded.block.monad.haskell 27 | begin: "{%[%^]?" 28 | beginCaptures: 29 | "0": { name: punctuation.block.monad.begin.happy } 30 | end: "}" 31 | endCaptures: 32 | "0": { name: punctuation.block.end.happy } 33 | patterns: 34 | - include: source.haskell 35 | - name: meta.embedded.block.haskell 36 | begin: "{" 37 | beginCaptures: 38 | "0": { name: punctuation.block.begin.happy } 39 | end: "}" 40 | endCaptures: 41 | "0": { name: punctuation.block.end.happy } 42 | patterns: 43 | - name: variable.parameter.happy 44 | match: \$\d+ 45 | - name: variable.parameter.field.happy 46 | match: \$\$ 47 | - include: source.haskell 48 | syntax: 49 | patterns: 50 | - name: entity.name.directive.happy 51 | match: \%([\p{Ll}\p{Lu}_][\p{Ll}_\p{Lu}\p{Lt}\p{Nd}\.']*) 52 | - name: constant.character.escape.hex.happy 53 | match: \\x[\da-fA-F]+ 54 | - name: constant.character.escape.oct.happy 55 | match: \\o[0-7]+ 56 | - name: constant.character.escape.dec.happy 57 | match: \\\d+ 58 | - name: constant.character.escape.happy 59 | match: \\. 60 | - name: punctuation.bracket.happy 61 | match: "[\\[\\]]" 62 | - name: keyword.operator.happy 63 | match: "[-^=\\.*]" 64 | - name: keyword.operator.type.happy 65 | match: "::" 66 | - name: keyword.operator.rule.happy 67 | match: ":" 68 | - name: keyword.operator.alt.happy 69 | match: \| 70 | - name: keyword.operator.separator.happy 71 | match: \%\% 72 | strings: 73 | patterns: 74 | - name: string.quoted.double.happy 75 | begin: '"' 76 | beginCaptures: 77 | "0": { name: punctuation.quote.double.happy } 78 | end: '"' 79 | endCaptures: 80 | "0": { name: punctuation.quote.double.happy } 81 | patterns: 82 | - name: constant.character.escape.happy 83 | match: \\. 84 | - name: string.quoted.single.happy 85 | begin: "'" 86 | beginCaptures: 87 | "0": { name: punctuation.quote.single.happy } 88 | end: "'" 89 | endCaptures: 90 | "0": { name: punctuation.quote.single.happy } 91 | patterns: 92 | - name: constant.character.escape.happy 93 | match: \\. 94 | scopeName: source.haskell.happy 95 | -------------------------------------------------------------------------------- /test/tests/TypeSigs.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Type signatures in various positions" 2 | 3 | f :: ( x :: Int ) -> Int 4 | -- <~~-- ^^ keyword.operator.double-colon.haskell 5 | -- ^^ keyword.operator.arrow.haskell 6 | -- ^^^ ^^^ storage.type.haskell 7 | f x = do 8 | -- ^ keyword.operator.eq.haskell 9 | let x :: Int 10 | -- ^^ keyword.operator.double-colon.haskell 11 | -- ^^^ storage.type.haskell 12 | x = A 13 | -- ^ keyword.operator.eq.haskell 14 | -- ^ constant.other.haskell 15 | let 16 | y :: Int 17 | -- ^^ keyword.operator.double-colon.haskell 18 | -- ^^^ storage.type.haskell 19 | y = A 20 | -- ^ keyword.operator.eq.haskell 21 | -- ^ constant.other.haskell 22 | z :: Int = A 23 | -- ^^ keyword.operator.double-colon.haskell 24 | -- ^^^ storage.type.haskell 25 | -- ^ keyword.operator.eq.haskell 26 | -- ^ constant.other.haskell 27 | z :: Int == A 28 | -- ^^ keyword.operator.double-colon.haskell 29 | -- ^^^ storage.type.haskell 30 | -- ^^ storage.type.operator.infix.haskell 31 | -- ^^ - keyword.operator.eq.haskell 32 | -- ^ storage.type.haskell 33 | ( w :: Int ) = A 34 | -- ^^ keyword.operator.double-colon.haskell 35 | -- ^^^ storage.type.haskell 36 | -- ^ keyword.operator.eq.haskell 37 | -- ^ constant.other.haskell 38 | x :: Int <- A 39 | -- ^^ keyword.operator.double-colon.haskell 40 | -- ^^^ storage.type.haskell 41 | -- ^^ keyword.operator.arrow.left.haskell 42 | -- ^ constant.other.haskell 43 | x :: Int <-- A 44 | -- ^^ keyword.operator.double-colon.haskell 45 | -- ^^^ storage.type.operator.infix.haskell 46 | -- ^^^ - keyword.operator.arrow.left.haskell 47 | -- ^^^ ^ storage.type.haskell 48 | -- 49 | ( x :: Int ) <- A 50 | -- ^^ keyword.operator.double-colon.haskell 51 | -- ^^^ storage.type.haskell 52 | -- ^^ keyword.operator.arrow.left.haskell 53 | -- ^ constant.other.haskell 54 | case x :: Int of 55 | -- ^^ keyword.operator.double-colon.haskell 56 | -- ^^^ storage.type.haskell 57 | ( 2 :: Int ) -> A 58 | -- ^^ keyword.operator.double-colon.haskell 59 | -- ^^^ storage.type.haskell 60 | -- ^^ keyword.operator.arrow.haskell 61 | -- ^ constant.other.haskell 62 | where x :: Int 63 | -- ^^ keyword.operator.double-colon.haskell 64 | -- ^^^ storage.type.haskell 65 | x = A 66 | -- ^ keyword.operator.eq.haskell 67 | -- ^ constant.other.haskell 68 | where 69 | y :: Int 70 | -- ^^ keyword.operator.double-colon.haskell 71 | -- ^^^ storage.type.haskell 72 | y = 3 73 | -- ^ keyword.operator.eq.haskell 74 | 75 | type T ( x :: Int ) :: ( k :: D x ) 76 | -- ^^ ^^ ^^ keyword.operator.double-colon.haskell 77 | -- ^ ^^^ ^ storage.type.haskell 78 | -- ^ ^ ^ variable.other.generic-type.haskell 79 | type T x = X :: D x 80 | -- ^^ keyword.operator.double-colon.haskell 81 | -- ^ ^ ^ storage.type.haskell 82 | -- ^ ^ variable.other.generic-type.haskell 83 | -------------------------------------------------------------------------------- /test/tests/MagicHash.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Magic hash/unboxed tuples" 2 | 3 | 4 | 5 | module M ( Int#, (+#), type Word#, pattern I# ) where 6 | -- ^ ^ ^ ^ keyword.operator.postfix.hash.haskell 7 | import GHC.Exts ( Int#, (+#), type Word#, pattern I# ) 8 | -- ^ ^ ^ keyword.operator.postfix.hash.haskell 9 | 10 | 11 | f :: (# Word8#, Int8#, Bool# #) -> (# Word8#, Int8#, Bool# #) 12 | -- ^ ^ ^ ^ ^ ^ keyword.operator.postfix.hash.haskell 13 | -- ^ ^ ^ ^ keyword.operator.hash.haskell 14 | 15 | f (# a, b, c #) = (# a, b, c #) 16 | -- ^ ^ ^ ^ keyword.operator.hash.haskell 17 | 18 | g :: (##) 19 | -- ^^ keyword.operator.hash.haskell 20 | -- ^^^^ support.constant.unit.unboxed.haskell 21 | g = (##) 22 | -- ^^ keyword.operator.hash.haskell 23 | -- ^^^^ constant.language.unit.unboxed.haskell 24 | 25 | a # b # c 26 | -- ^ ^ - keyword.operator.hash.haskell keyword.operator.postfix.hash.haskell 27 | -- ^ ^ keyword.operator.infix.haskell 28 | 29 | f :: A # B # c 30 | -- ^ ^ - keyword.operator.hash.haskell keyword.operator.postfix.hash.haskell 31 | -- ^ ^ storage.type.operator.infix.haskell 32 | 33 | f :: A -## b 34 | -- ^^ keyword.operator.postfix.hash.haskell 35 | -- ^ - keyword.operator.prefix.minus.haskell 36 | 37 | g = a +## b 38 | -- ^^ keyword.operator.postfix.hash.haskell 39 | 40 | f :: A ## b 41 | -- ^^ - keyword.operator.hash.haskell keyword.operator.postfix.hash.haskell 42 | -- ^^ storage.type.operator.infix.haskell 43 | 44 | g = a ## b 45 | -- ^^ - keyword.operator.hash.haskell keyword.operator.postfix.hash.haskell 46 | -- ^^ keyword.operator.infix.haskell 47 | 48 | 49 | one## :: Word8# 50 | -- ^^^^^ entity.name.function.haskell 51 | -- ^^ ^ keyword.operator.postfix.hash.haskell 52 | 53 | one## = 1## 54 | -- ^^ ^^ keyword.operator.postfix.hash.haskell 55 | 56 | foo# :: Addr# 57 | -- ^^^^ entity.name.function.haskell 58 | -- ^ ^ keyword.operator.postfix.hash.haskell 59 | foo# = "foo"# 60 | -- ^ ^ keyword.operator.postfix.hash.haskell 61 | 62 | (=#=#) :: Int# -> Int# -> Bool# 63 | -- ^^^^ entity.name.function.haskell 64 | -- ^ - keyword.operator.postfix.hash.haskell 65 | -- ^ keyword.operator.postfix.hash.haskell 66 | a =#=# b = a =#=# b 67 | -- ^ ^ - keyword.operator.postfix.hash.haskell 68 | -- ^ ^ keyword.operator.postfix.hash.haskell 69 | 70 | 71 | 72 | type family Tuple# xs = t | t -> xs where 73 | -- ^ keyword.operator.postfix.hash.haskell 74 | Tuple# '[] = (##) 75 | -- ^ keyword.operator.postfix.hash.haskell 76 | -- ^^ keyword.operator.hash.haskell 77 | Tuple# '[a] = (# a #) 78 | -- ^ keyword.operator.postfix.hash.haskell 79 | -- ^ ^ keyword.operator.hash.haskell 80 | Tuple# '[a,b] = (# a,b #) 81 | -- ^ keyword.operator.postfix.hash.haskell 82 | -- ^ ^ keyword.operator.hash.haskell 83 | -------------------------------------------------------------------------------- /test/tickets/T0072c.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Type/data families and instances" 2 | 3 | type family CTF1 a b where 4 | -- <---- keyword.other.type.haskell 5 | -- ^^^^^^ keyword.other.family.haskell 6 | -- ^^^^ storage.type.haskell 7 | -- ^ ^ variable.other.generic-type.haskell 8 | CTF1 a b = D a 9 | -- ^^^^ ^ storage.type.haskell 10 | -- ^ ^ ^ variable.other.generic-type.haskell 11 | type family CTF2 (a :: k) :: B where 12 | -- <---- keyword.other.type.haskell 13 | -- ^^^^^^ keyword.other.family.haskell 14 | -- ^ ^ variable.other.generic-type.haskell 15 | -- ^^^^ ^ storage.type.haskell 16 | 17 | type family CTF3 (a :: A) = (r :: A) | r -> a where 18 | -- <---- keyword.other.type.haskell 19 | -- ^^^^^^ keyword.other.family.haskell 20 | -- ^ keyword.operator.eq.haskell 21 | -- ^ ^ storage.type.haskell 22 | -- ^ keyword.operator.pipe.haskell 23 | -- ^ ^ ^ ^ variable.other.generic-type.haskell 24 | -- ^^^^^ keyword.other.where.haskell 25 | 26 | type family CTF4 27 | -- <---- keyword.other.type.haskell 28 | -- ^^^^^^ keyword.other.family.haskell 29 | (a :: A) 30 | -- ^ variable.other.generic-type.haskell 31 | -- ^ storage.type.haskell 32 | (b :: B) 33 | -- ^ variable.other.generic-type.haskell 34 | -- ^ storage.type.haskell 35 | = (r :: A) 36 | -- ^ keyword.operator.eq.haskell 37 | -- ^ variable.other.generic-type.haskell 38 | -- ^ storage.type.haskell 39 | | r -> a b 40 | -- ^ ^ ^ variable.other.generic-type.haskell 41 | -- ^ keyword.operator.pipe.haskell 42 | where 43 | -- ^^^^^ keyword.other.where.haskell 44 | 45 | type family OTF a b 46 | -- <---- keyword.other.type.haskell 47 | -- ^^^^^^ keyword.other.family.haskell 48 | -- ^^^ storage.type.haskell 49 | -- ^ ^ variable.other.generic-type.haskell 50 | type instance OTF (a,a) c = (a,c) 51 | -- <---- keyword.other.type.haskell 52 | -- ^^^^^^^^ keyword.other.instance.haskell 53 | -- ^^^ storage.type.haskell 54 | -- ^ ^ ^ ^ ^ variable.other.generic-type.haskell 55 | type instance 56 | -- <---- keyword.other.type.haskell 57 | -- ^^^^^^^^ keyword.other.instance.haskell 58 | OTF (Int, Bool) = Char 59 | -- ^^^ ^^^ ^^^^ ^^^^ storage.type.haskell 60 | -- ^ keyword.operator.eq.haskell 61 | 62 | data family DF (x :: Bool) 63 | -- <---- keyword.other.data.haskell 64 | -- ^^^^^^ keyword.other.family.haskell 65 | -- ^ variable.other.generic-type.haskell 66 | -- ^^^^ storage.type.haskell 67 | newtype instance DF 'True = DCTrue Int 68 | -- <------- keyword.other.newtype.haskell 69 | -- ^^^^^^^^ keyword.other.instance.haskell 70 | -- ^^ storage.type.haskell 71 | -- ^^^^^^ constant.other.haskell 72 | -- ^^^ storage.type.haskell 73 | data instance DF 'False where 74 | -- <---- keyword.other.data.haskell 75 | -- ^^^^^^^^ keyword.other.instance.haskell 76 | -- ^^ ^^^^^ storage.type.haskell 77 | DCFalse :: Float -> DF 'False 78 | -- ^^^^^^^ constant.other.haskell 79 | -- ^^^^^ ^^ ^^^^^ storage.type.haskell 80 | -------------------------------------------------------------------------------- /test/tests/Ticks.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Ticks in various positions" 2 | 3 | 4 | x = Tt_'_.T_'__t' T'D_'.C T_'ttt_'t_' T'x T_x T_'_ 5 | -- ^^^^^^ ^^^^^^ entity.name.namespace.haskell 6 | -- ^^^^^^^ ^ ^^^^^^^^^^^ ^^^ ^^^ ^^^^ constant.other.haskell 7 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - invalid 8 | x = a `Tt_'_.T_'__t'` b `T'D_'.C` c `T_'ttt_'t_'` d `T'x` e `T_x` f `T_'_` 9 | -- ^^^^^^ ^^^^^^ entity.name.namespace.haskell 10 | -- ^^^^^^^ ^ ^^^^^^^^^^^ ^^^ ^^^ ^^^^ constant.other.haskell 11 | -- ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ - entity.name.namespace.haskell constant.other.haskell 12 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - invalid 13 | x = 'T' '_' 14 | -- ^^^ ^^^ string.quoted.single.haskell 15 | -- ^^^^^^^ - invalid 16 | 17 | type T = Tt'.T_'__t' 'TD'.C 'Tt'T.T.T' T_'ttt_'t_' 'T T'x T_x T_'_ 18 | -- ^^^^ ^^^^ ^^^^^^^ entity.name.namespace.haskell 19 | -- ^ ^ ^ keyword.operator.promotion.haskell 20 | -- ^^^^^^^ ^ ^^ ^^^^^^^^^^^ ^ ^^^ ^^^ ^^^^ storage.type.haskell 21 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - invalid 22 | type T = a `Tt'.T_'__t'` b '`TD'.C` c '`Tt'T.T.T'` d `T_'ttt_'t_'` e '`T` f `T'x` g `T_x` h `T_'_` 23 | -- ^^^^ ^^^^ ^^^^^^^ entity.name.namespace.haskell 24 | -- ^ ^ ^ keyword.operator.promotion.haskell 25 | -- ^^^^^^^ ^ ^^ ^^^^^^^^^^^ ^ ^^^ ^^^ ^^^^ storage.type.infix.haskell 26 | -- ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ - entity.name.namespace.haskell constant.other.haskell 27 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - invalid 28 | type T = '(F, (B,G.C,'[A,B,C])) 29 | -- ^ ^ ^ ^ ^ ^ storage.type.haskell 30 | -- ^^ entity.name.namespace.haskell 31 | -- ^ ^ keyword.operator.promotion.haskell 32 | 33 | type T = '() '[] 34 | -- ^ ^ keyword.operator.promotion.haskell 35 | -- ^^ support.constant.unit.haskell 36 | -- ^^ support.constant.empty-list.haskell 37 | 38 | type T = T.'C 39 | -- ^^ - entity.name.namespace.haskell 40 | -- ^ storage.type.operator.infix.haskell 41 | -- ^ keyword.operator.promotion.haskell 42 | -- ^ ^ storage.type.haskell 43 | 44 | type T = '(:+) '(AC.:+) 'AC.:++ 'AC.++ 45 | -- ^ ^ ^ keyword.operator.promotion.haskell 46 | -- ^^^ ^^^ entity.name.namespace.haskell 47 | -- ^^ ^^ storage.type.operator.haskell 48 | -- ^^^ ^^ storage.type.operator.infix.haskell 49 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - invalid 50 | 51 | type T = _t'_a' 52 | -- ^^^^^^ variable.other.generic-type.haskell 53 | -- ^^^^^^ - invalid 54 | type T = " a ' b ' c 'de' f'g''' 'a'" 55 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ string.quoted.double.haskell 56 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - invalid 57 | 58 | type T = '_'_t_a' 59 | -- ^^^ invalid 60 | type T = 'T'x 61 | -- ^^^ invalid 62 | type T = '_' 63 | -- ^^^ invalid 64 | type T = '_' 65 | -- ^^^ invalid 66 | -------------------------------------------------------------------------------- /syntaxes/alex.YAML-tmLanguage: -------------------------------------------------------------------------------- 1 | fileTypes: 2 | - x 3 | name: Haskell Alex 4 | patterns: 5 | - include: "#comments" 6 | - include: "#blocks" 7 | - include: "#syntax" 8 | - include: "#strings" 9 | repository: 10 | block_comment: 11 | applyEndPatternLast: 1 12 | begin: "{-" 13 | captures: 14 | '0': {name: punctuation.definition.comment.alex} 15 | end: "-}" 16 | name: comment.block.alex 17 | patterns: 18 | - include: "#block_comment" 19 | comments: 20 | patterns: 21 | - name: comment.line.alex 22 | match: '\-\-.*$' 23 | - include: "#block_comment" 24 | startcode: 25 | patterns: 26 | - name: variable.other.startcode.0.alex 27 | match: '0' 28 | - name: variable.other.startcode.alex 29 | match: ([\p{Ll}\p{Lu}_][\p{Ll}_\p{Lu}\p{Lt}\p{Nd}\.']*) 30 | - name: punctuation.comma.startcode.alex 31 | match: ',' 32 | blocks: 33 | patterns: 34 | - name: meta.block.startcode.alex 35 | begin: (<)([\p{Ll}_\p{Lu}\p{Lt}\p{Nd}\.'\s,]*)(>)\s*(\{) 36 | beginCaptures: 37 | "1": { name: punctuation.bracket.startcode.alex } 38 | "2": 39 | patterns: 40 | - include: '#startcode' 41 | "3": { name: punctuation.bracket.startcode.alex } 42 | "4": { name: punctuation.block.startcode.begin.alex } 43 | end: "}" 44 | endCaptures: 45 | "0": { name: punctuation.block.startcode.end.alex } 46 | patterns: 47 | - include: source.haskell.alex 48 | - name: meta.embedded.block.haskell 49 | begin: "{" 50 | beginCaptures: 51 | "0": { name: punctuation.block.begin.alex } 52 | end: "}" 53 | endCaptures: 54 | "0": { name: punctuation.block.end.alex } 55 | patterns: 56 | - include: source.haskell 57 | 58 | syntax: 59 | patterns: 60 | - name: entity.name.pragma.alex 61 | match: \%([\p{Ll}\p{Lu}_][\p{Ll}_\p{Lu}\p{Lt}\p{Nd}\.']*) 62 | - name: entity.name.macro.character-set.alex 63 | match: \$([\p{Ll}\p{Lu}_][\p{Ll}_\p{Lu}\p{Lt}\p{Nd}\.']*) 64 | - name: entity.name.macro.regular-expression.alex 65 | match: \@([\p{Ll}\p{Lu}_][\p{Ll}_\p{Lu}\p{Lt}\p{Nd}\.']*) 66 | - name: constant.character.escape.hex.alex 67 | match: \\x[\da-fA-F]+ 68 | - name: constant.character.escape.oct.alex 69 | match: \\o[0-7]+ 70 | - name: constant.character.escape.dec.alex 71 | match: \\\d+ 72 | - name: constant.character.escape.alex 73 | match: \\. 74 | - name: punctuation.bracket.alex 75 | match: "[\\[\\]]" 76 | - name: keyword.operator.rules.alex 77 | match: :- 78 | - name: keyword.operator.alex 79 | match: "[-^=\\.*\\|]" 80 | - name: punctuation.semicolon.alex 81 | match: \; 82 | - name: meta.startcode.alex 83 | match: (<)([\p{Ll}_\p{Lu}\p{Lt}\p{Nd}\.'\s,]*)(>) 84 | captures: 85 | "1": { name: punctuation.bracket.startcode.alex } 86 | "2": 87 | patterns: 88 | - include: '#startcode' 89 | "3": { name: punctuation.bracket.startcode.alex } 90 | strings: 91 | patterns: 92 | - name: string.quoted.double.alex 93 | begin: '"' 94 | beginCaptures: 95 | "0": { name: punctuation.quote.double.alex } 96 | end: '"' 97 | endCaptures: 98 | "0": { name: punctuation.quote.double.alex } 99 | patterns: 100 | - name: constant.character.escape.alex 101 | match: \\. 102 | - name: string.quoted.single.alex 103 | begin: "'" 104 | beginCaptures: 105 | "0": { name: punctuation.quote.single.alex } 106 | end: "'" 107 | endCaptures: 108 | "0": { name: punctuation.quote.single.alex } 109 | patterns: 110 | - name: constant.character.escape.alex 111 | match: \\. 112 | scopeName: source.haskell.alex 113 | -------------------------------------------------------------------------------- /test/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | baseDir=$(dirname "$PWD") 4 | echo "Running tests from base directory $baseDir" 5 | 6 | # Arrays containing full test filepaths. 7 | named=("$PWD"/tests/*) 8 | tickets=("$PWD"/tickets/*) 9 | 10 | # Arrays containing filenames of broken tests. 11 | namedBroken=() 12 | ticketsBroken=( 13 | "T0153.hs" 14 | "T0165.hs" 15 | "T0167.hs" 16 | "T0178.hs" 17 | "T0189.y" 18 | "T230.hs" 19 | ) 20 | 21 | # Colours used to display test outputs. 22 | RED='\033[0;31m' 23 | MAGENTA='\033[0;35m' 24 | YELLOW='\033[1;33m' 25 | GREEN='\033[0;32m' 26 | NC='\033[0m' 27 | 28 | # 'runTests' runs the 'vscode-tmgrammar-test' command on all test files in a directory, 29 | # reporting which tests had unexpected outcomes. 30 | # 31 | # runTests 32 | # :: [ FilePath ] -- ^ $1: array of tests to be run. 33 | # -> [ TestName ] -- ^ $2: array of filenames in this directory for tests that are expected to fail. 34 | # -> MArray s TestName -- ^ $3: array of tests that unexpectedly failed (this function appends these to the array) 35 | # -> MArray s TestName -- ^ $4: array of tests that unexpectedly passed (this function appends these to the array). 36 | # -> ST s ExitCode -- ^ Exit code: 0 if no unexpected outcomes, 1 otherwise. 37 | runTests () { 38 | 39 | local -n dir=$1 40 | local -n expectedFails=$2 41 | local -n fails=$3 42 | local -n passes=$4 43 | 44 | syntaxes=() 45 | source="" 46 | 47 | for filepath in "${dir[@]}" 48 | do 49 | file=$(basename -- "$filepath") 50 | ext="${file##*.}" 51 | name="${file%.*}" 52 | 53 | # Check whether the test is expected to fail. 54 | expectBroken=0 55 | for broken in "${expectedFails[@]}" 56 | do 57 | if [ "$broken" == "$file" ] 58 | then 59 | expectBroken=1 60 | fi 61 | done 62 | 63 | # Set the appropriate syntax file for the test. 64 | case $ext in 65 | 66 | "hs" | "hs-boot" | "hsig" ) 67 | syntaxes=( "$baseDir/syntaxes/haskell.json" ) 68 | ;; 69 | 70 | "cabal" ) 71 | syntaxes=( "$baseDir/syntaxes/cabal.json" ) 72 | ;; 73 | 74 | "lhs" ) 75 | syntaxes=( "$baseDir/syntaxes/haskell.json" "$baseDir/syntaxes/literateHaskell.json" ) 76 | ;; 77 | 78 | "x" ) 79 | syntaxes=( "$baseDir/syntaxes/alex.json" "$baseDir/syntaxes/haskell.json" ) 80 | ;; 81 | 82 | "y" ) 83 | syntaxes=( "$baseDir/syntaxes/happy.json" "$baseDir/syntaxes/haskell.json" ) 84 | ;; 85 | 86 | * ) 87 | syntaxes=() 88 | ;; 89 | 90 | esac 91 | 92 | if [ ${#syntaxes[@]} -eq 0 ] 93 | then 94 | echo "runTests: $file has unsupported file extension '$ext', ignoring" 95 | else 96 | specifySyntaxes="" 97 | for i in ${syntaxes[*]}; do 98 | specifySyntaxes="$specifySyntaxes -g $i" 99 | done 100 | # Run the test. 101 | result=$(npx vscode-tmgrammar-test $specifySyntaxes "$filepath") 102 | # Check test result by inspecting the exit code of the previous command. 103 | status=$? 104 | if [ $status -eq 0 ] 105 | then 106 | if [ $expectBroken -eq 0 ] 107 | then 108 | echo -e "${GREEN}Pass (expected)${NC} $file" 109 | else 110 | passes+=("$name") 111 | echo -e "${MAGENTA}Pass (unexpected)${NC} $file" 112 | fi 113 | else 114 | if [ $expectBroken -eq 0 ] 115 | then 116 | fails+=("$name") 117 | echo -e "${RED}Fail (unexpected)${NC} $file" 118 | echo -e "$result" 119 | else 120 | echo -e "${YELLOW}Fail (expected)${NC} $file" 121 | fi 122 | fi 123 | fi 124 | done 125 | } 126 | 127 | # Initialise arrays of tests with unexpected results. 128 | unexpectedFails=() 129 | unexpectedPasses=() 130 | 131 | # Run the named tests (in the 'tests' folder). 132 | runTests named namedBroken unexpectedFails unexpectedPasses 133 | # Run the ticket tests (in the 'tickets' folder). 134 | runTests tickets ticketsBroken unexpectedFails unexpectedPasses 135 | 136 | # Return the appropriate exit code. 137 | if [ ${#unexpectedFails[@]} -eq 0 ] && [ ${#unexpectedPasses[@]} -eq 0 ] 138 | then 139 | # No unexpected test outcomes. 140 | exit 0 141 | else 142 | # Unexpected test outcomes. 143 | exit 1 144 | fi 145 | -------------------------------------------------------------------------------- /test/tickets/T0044.hs: -------------------------------------------------------------------------------- 1 | -- SYNTAX TEST "source.haskell" "Foreign import/export" 2 | 3 | -- Should work for indented modules 4 | 5 | foreign import jvm "string.h strlen" 6 | -- ^^^^^^^ keyword.other.foreign.haskell 7 | -- ^^^^^^ keyword.other.import.haskell 8 | -- ^^^ keyword.other.calling-convention.jvm.haskell 9 | -- ^^^^^^^^^^^^^^^ entity.name.foreign.haskell string.quoted.double.haskell 10 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.import.foreign.haskell 11 | cstrlen :: Ptr CChar -> IO CSize 12 | -- ^^^^^^^ entity.name.function.haskell 13 | -- ^^ keyword.operator.double-colon.haskell 14 | -- ^^^ ^^^^ ^^ ^^^^^ storage.type.haskell 15 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.import.foreign.haskell 16 | 17 | foreign export stdcall "string.h strlen" foo :: Ptr CInt 18 | -- ^^^^^^^ keyword.other.foreign.haskell 19 | -- ^^^^^^ keyword.other.export.haskell 20 | -- ^^^^^^^ keyword.other.calling-convention.stdcall.haskell 21 | -- ^^^^^^^^^^^^^^^ entity.name.foreign.haskell string.quoted.double.haskell 22 | -- ^^^ entity.name.function.haskell 23 | -- ^^ keyword.operator.double-colon.haskell 24 | -- ^^^ ^^^^ storage.type.haskell 25 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.export.foreign.haskell 26 | 27 | foreign import ccall safe "string.h strlen" 28 | -- <------- keyword.other.foreign.haskell 29 | -- ^^^^^^ keyword.other.import.haskell 30 | -- ^^^^^ keyword.other.calling-convention.ccall.haskell 31 | -- ^^^^ keyword.other.safety.safe.haskell 32 | -- ^^^^^^^^^^^^^^^^^ string.quoted.double.haskell 33 | -- <-------------------------------------- meta.import.foreign.haskell 34 | 35 | cstrlen :: Ptr CChar -> IO CSize 36 | -- ^^^^^^^ entity.name.function.haskell 37 | -- ^^^ ^^^^^ ^^ ^^^^^ storage.type.haskell 38 | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.import.foreign.haskell 39 | 40 | foreign export cplusplus "string.h strlen" foo :: Ptr CInt 41 | -- <------- keyword.other.foreign.haskell 42 | -- ^^^^^^ keyword.other.export.haskell 43 | -- ^^^^^^^^^ keyword.other.calling-convention.cplusplus.haskell 44 | -- ^^^^^^^^^^^^^^ entity.name.foreign.haskell string.quoted.double.haskell 45 | -- ^^^ entity.name.function.haskell 46 | -- ^^ keyword.operator.double-colon.haskell 47 | -- ^^^ ^^^^ storage.type.haskell 48 | -- <----------------------------------------------------------- meta.export.foreign.haskell 49 | 50 | foreign export ccall "addInt" (+) :: Int -> Int -> Int 51 | -- <------- keyword.other.foreign.haskell 52 | -- ^^^^^^ keyword.other.export.haskell 53 | -- ^^^^^ keyword.other.calling-convention.ccall.haskell 54 | -- ^^^^^^ entity.name.foreign.haskell string.quoted.double.haskell 55 | -- ^ entity.name.function.infix.haskell 56 | -- ^^ keyword.operator.double-colon.haskell 57 | -- ^^^ ^^^ ^^^ storage.type.haskell 58 | -- <---------------------------------------------------------- meta.export.foreign.haskell 59 | foreign export prim interruptible "addFloat" (+) :: Float -> Float -> Float 60 | -- <------- keyword.other.foreign.haskell 61 | -- ^^^^^^ keyword.other.export.haskell 62 | -- ^^^^^^^^^^^^^ keyword.other.safety.interruptible.haskell 63 | -- ^^^^^^^^ entity.name.foreign.haskell string.quoted.double.haskell 64 | -- ^ entity.name.function.infix.haskell 65 | -- ^^ keyword.operator.double-colon.haskell 66 | -- ^^^^^ ^^^^^ ^^^^^ storage.type.haskell 67 | -- <--------------------------------------------------------------------------- meta.export.foreign.haskell 68 | 69 | 70 | 71 | foreign export ccall safe :: Int -> Int 72 | -- ^^^^ - keyword.other.safety.safe.haskell 73 | -- ^^^^ entity.name.function.haskell 74 | 75 | foreign export ccall "unsafe" unsafe :: Int -> Int 76 | -- ^^^^^^ entity.name.foreign.haskell string.quoted.double.haskell 77 | -- ^^^^^^ - keyword.other.safety.unsafe.haskell 78 | -- ^^^^^^ entity.name.function.haskell --------------------------------------------------------------------------------