diff --git a/.hlint.yaml b/.hlint.yaml new file mode 100644 index 0000000..85c0ab6 --- /dev/null +++ b/.hlint.yaml @@ -0,0 +1,66 @@ +# HLint configuration file +# https://github.com/ndmitchell/hlint +########################## + +# This file contains a template configuration file, which is typically +# placed as .hlint.yaml in the root of your project + + +# Specify additional command line arguments +# +# - arguments: [--color, --cpp-simple, -XQuasiQuotes] + + +# Control which extensions/flags/modules/functions can be used +# +# - extensions: +# - default: false # all extension are banned by default +# - name: [PatternGuards, ViewPatterns] # only these listed extensions can be used +# - {name: CPP, within: CrossPlatform} # CPP can only be used in a given module +# +# - flags: +# - {name: -w, within: []} # -w is allowed nowhere +# +# - modules: +# - {name: [Data.Set, Data.HashSet], as: Set} # if you import Data.Set qualified, it must be as 'Set' +# - {name: Control.Arrow, within: []} # Certain modules are banned entirely +# +# - functions: +# - {name: unsafePerformIO, within: []} # unsafePerformIO can only appear in no modules + + +# Add custom hints for this project +# +# Will suggest replacing "wibbleMany [myvar]" with "wibbleOne myvar" +# - error: {lhs: "wibbleMany [x]", rhs: wibbleOne x} + + +# Turn on hints that are off by default +# +# Ban "module X(module X) where", to require a real export list +# - warn: {name: Use explicit module export list} +# +# Replace a $ b $ c with a . b $ c +# - group: {name: dollar, enabled: true} +# +# Generalise map to fmap, ++ to <> +# - group: {name: generalise, enabled: true} + + +# Ignore some builtin hints +# - ignore: {name: Use let} +# - ignore: {name: Use const, within: SpecialModule} # Only within certain modules +- ignore: + name: Reduce duplication + within: + - Nirum.Parser + - Nirum.ParserSpec +- ignore: {name: Unnecessary hiding} + + +# Define some custom infix operators +# - fixity: infixr 3 ~^#^~ + + +# To generate a suitable file for HLint do: +# $ hlint --default > .hlint.yaml diff --git a/.travis.yml b/.travis.yml index c05f19b..b7d8f5b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -118,7 +118,8 @@ install: fi script: -- 'TOX="$(which tox)" stack --no-terminal test -j4 --coverage' +- ls -al "$(python3 -m site --user-base)/bin/tox" +- 'TOX="$(python3 -m site --user-base)/bin/tox" stack --no-terminal test -j4 --coverage' - ./lint.sh after_script: diff --git a/appveyor.yml b/appveyor.yml index e9686b5..a560972 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,10 +22,10 @@ install: - ps: > if((Test-Path $env:STACK_ROOT) -ne $true) { if($env:PLATFORM -eq 'x86') { - $stackUrl = 'https://www.stackage.org/stack/windows-i386'; + $stackUrl = 'https://github.com/commercialhaskell/stack/releases/download/v1.6.5/stack-1.6.5-windows-i386.zip'; } elseif($env:PLATFORM -eq 'x64') { - $stackUrl = 'https://www.stackage.org/stack/windows-x86_64'; + $stackUrl = 'https://github.com/commercialhaskell/stack/releases/download/v1.6.5/stack-1.6.5-windows-x86_64.zip'; } Invoke-WebRequest -OutFile C:\stack.zip $stackUrl; Add-Type -AssemblyName System.IO.Compression.FileSystem; @@ -49,6 +49,7 @@ install: - set - C:\Python36\python -m pip install --upgrade tox pip setuptools +- stack --no-terminal install -j4 happy # haskell-src-exts requires happy - stack --no-terminal install -j4 --only-dependencies build_script: - stack --no-terminal build -j4 --copy-bins --flag nirum:static diff --git a/test/HLint.hs b/lint.hs similarity index 83% rename from test/HLint.hs rename to lint.hs index 6de9b57..da22399 100644 --- a/test/HLint.hs +++ b/lint.hs @@ -2,7 +2,7 @@ import Language.Haskell.HLint (hlint) import System.Exit (exitFailure, exitSuccess) arguments :: [String] -arguments = ["src", "test"] +arguments = ["app", "src", "test", "lint.hs"] main :: IO () main = do diff --git a/package.yaml b/package.yaml index af3e551..47115e9 100644 --- a/package.yaml +++ b/package.yaml @@ -33,9 +33,16 @@ flags: description: Static link manual: true default: false -ghc-options: -- -Wall -- -Werror +when: +- condition: os(darwin) + else: + ghc-options: + - -Werror + then: + ghc-options: + - -Werror + - -optP-Wno-nonportable-include-path + # The above option works around https://github.com/haskell/cabal/issues/4739 dependencies: - base >=4.7 && <5 - blaze-html >=0.9.0.1 && <0.10 @@ -46,7 +53,7 @@ dependencies: - filepath >=1.4 && <1.5 - htoml >=1.0.0.0 && <1.1.0.0 - interpolatedstring-perl6 >=1.0.0 && <1.1.0 -- megaparsec >=5 && <5.4 +- megaparsec >=6.3 && <6.4 - mtl >=2.2.1 && <3 - parsec # only for dealing with htoml's ParserError - pretty >=1.1.3 && <2 @@ -56,6 +63,7 @@ dependencies: library: source-dirs: src ghc-options: + - -Wall - -fwarn-incomplete-uni-patterns - -fprint-explicit-kinds other-modules: @@ -65,7 +73,7 @@ library: - cmark >=0.5 && <0.6 - fsnotify >=0.2.1 && <0.3.0 - heterocephalus >=1.0.5 && <1.1.0 - - optparse-applicative >=0.13.1 && <0.14 + - optparse-applicative >=0.14 && <0.15 - shakespeare >=2.0.12 && <2.1 - stm >=2.4.4.1 - template-haskell >=2.11 && <3 @@ -75,6 +83,7 @@ executables: main: nirum.hs source-dirs: app dependencies: + - base - nirum when: - condition: flag(static) @@ -83,6 +92,7 @@ executables: - condition: os(darwin) || os(windows) then: ghc-options: + - -Wall - -fwarn-incomplete-uni-patterns - -threaded - -with-rtsopts=-N @@ -91,6 +101,7 @@ executables: - -optc-Os else: ghc-options: + - -Wall - -fwarn-incomplete-uni-patterns - -threaded - -with-rtsopts=-N @@ -102,21 +113,24 @@ executables: - -fPIC else: ghc-options: + - -Wall - -fwarn-incomplete-uni-patterns - -threaded - -with-rtsopts=-N tests: hlint: - main: HLint.hs - source-dirs: test + main: lint.hs dependencies: - hlint >=2.0.9 && <2.1 spec: - main: Spec.hs - source-dirs: test + main: Main.hs + source-dirs: + - test ghc-options: + - -Wall - -fno-warn-incomplete-uni-patterns - -fno-warn-missing-signatures + - -Wno-missing-signatures - -threaded - -with-rtsopts=-N dependencies: # omit version specifiers for shared dependencies to library diff --git a/src/Nirum/Cli.hs b/src/Nirum/Cli.hs index d96f21c..26f7960 100644 --- a/src/Nirum/Cli.hs +++ b/src/Nirum/Cli.hs @@ -18,11 +18,7 @@ import System.Exit (die) import System.FilePath (takeDirectory, takeExtension, ()) import System.FSNotify import Text.InterpolatedString.Perl6 (qq) -import Text.Megaparsec (Token) -import Text.Megaparsec.Error ( Dec - , ParseError (errorPos) - , parseErrorPretty - ) +import Text.Megaparsec.Error (errorPos, parseErrorPretty) import Text.Megaparsec.Pos (SourcePos (sourceLine, sourceColumn), unPos) import Nirum.Constructs (Construct (toCode)) @@ -33,6 +29,7 @@ import Nirum.Package ( PackageError ( ImportError , ParseError , ScanError ) + , ParseError , scanModules ) import Nirum.Package.ModuleSet ( ImportError ( CircularImportError @@ -67,9 +64,7 @@ data AppOptions = AppOptions { outputPath :: FilePath debounceDelay :: Nanosecond debounceDelay = 1 * 1000 * 1000 -parseErrortoPrettyMessage :: ParseError (Token T.Text) Dec - -> FilePath - -> IO String +parseErrortoPrettyMessage :: ParseError -> FilePath -> IO String parseErrortoPrettyMessage parseError' filePath' = do sourceCode <- readFile filePath' let sourceLines = lines sourceCode diff --git a/src/Nirum/Constructs/Identifier.hs b/src/Nirum/Constructs/Identifier.hs index 1a0b098..336eb40 100644 --- a/src/Nirum/Constructs/Identifier.hs +++ b/src/Nirum/Constructs/Identifier.hs @@ -22,12 +22,12 @@ module Nirum.Constructs.Identifier ( Identifier import Data.Char (toLower, toUpper) import Data.Maybe (fromMaybe) import Data.String (IsString (fromString)) +import Data.Void import qualified Data.Text as T import qualified Data.Set as S import qualified Text.Megaparsec as P import Text.Megaparsec.Char (oneOf, satisfy) -import Text.Megaparsec.Text (Parser) import Nirum.Constructs (Construct (toCode)) @@ -64,7 +64,7 @@ reservedKeywords = [ "enum" , "default" ] -identifierRule :: Parser Identifier +identifierRule :: P.Parsec Void T.Text Identifier identifierRule = do firstChar <- satisfy isAlpha restChars <- P.many $ satisfy isAlnum @@ -89,7 +89,7 @@ fromText text = Right ident -> Just ident Left _ -> Nothing where - rule :: Parser Identifier + rule :: P.Parsec Void T.Text Identifier rule = do identifier' <- identifierRule _ <- P.eof diff --git a/src/Nirum/Package.hs b/src/Nirum/Package.hs index ae3f846..2cdec4f 100644 --- a/src/Nirum/Package.hs +++ b/src/Nirum/Package.hs @@ -1,6 +1,7 @@ module Nirum.Package ( Package (..) , PackageError (..) + , ParseError , docs , resolveModule , scanModules diff --git a/src/Nirum/Package/Metadata.hs b/src/Nirum/Package/Metadata.hs index 1676b9d..3dfc344 100644 --- a/src/Nirum/Package/Metadata.hs +++ b/src/Nirum/Package/Metadata.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE GADTs, QuasiQuotes, RankNTypes, ScopedTypeVariables, +{-# LANGUAGE GADTs, LambdaCase, QuasiQuotes, RankNTypes, ScopedTypeVariables, StandaloneDeriving, TypeFamilies #-} module Nirum.Package.Metadata ( Author (Author, email, name, uri) , Metadata ( Metadata @@ -261,14 +261,14 @@ optional (Left (FieldError _)) = Right Nothing optional (Left error') = Left error' tableField :: MetadataField -> Table -> Either MetadataError Table -tableField = typedField "table" $ \ n -> case n of - VTable t -> Just t - _ -> Nothing +tableField = typedField "table" $ \ case + VTable t -> Just t + _ -> Nothing stringField :: MetadataField -> Table -> Either MetadataError Text -stringField = typedField "string" $ \ n -> case n of - VString s -> Just s - _ -> Nothing +stringField = typedField "string" $ \ case + VString s -> Just s + _ -> Nothing arrayField :: MetadataField -> Table -> Either MetadataError VArray arrayField f t = @@ -278,10 +278,9 @@ arrayField f t = Left error' -> Left error' where arrayF :: MetadataField -> Table -> Either MetadataError VArray - arrayF = typedField "array" $ \ node -> - case node of - VArray array -> Just array - _ -> Nothing + arrayF = typedField "array" $ \ case + VArray array -> Just array + _ -> Nothing tableArrayField :: MetadataField -> Table -> Either MetadataError VTArray @@ -292,10 +291,9 @@ tableArrayField f t = Left error' -> Left error' where arrayF :: MetadataField -> Table -> Either MetadataError VTArray - arrayF = typedField "array of tables" $ \ node -> - case node of - VTArray array -> Just array - _ -> Nothing + arrayF = typedField "array of tables" $ \ case + VTArray array -> Just array + _ -> Nothing uriField :: MetadataField -> Table -> Either MetadataError URI uriField field' table = do diff --git a/src/Nirum/Parser.hs b/src/Nirum/Parser.hs index cdc4a04..f3f745d 100644 --- a/src/Nirum/Parser.hs +++ b/src/Nirum/Parser.hs @@ -33,11 +33,12 @@ module Nirum.Parser ( Parser ) where import Control.Monad (void) +import Data.Void import qualified System.IO as SIO import qualified Data.List as L import Data.Map.Strict as Map hiding (foldl) -import Data.Set hiding (empty, foldl, fromList, map) +import Data.Set hiding (foldl) import qualified Data.Text as T import qualified Data.Text.IO as TIO import Text.Megaparsec hiding (ParseError, parse) @@ -49,8 +50,7 @@ import Text.Megaparsec.Char ( char , string' ) import qualified Text.Megaparsec.Error as E -import Text.Megaparsec.Text (Parser) -import Text.Megaparsec.Lexer (charLiteral) +import Text.Megaparsec.Char.Lexer (charLiteral) import qualified Nirum.Constructs.Annotation as A import Nirum.Constructs.Declaration (Declaration) @@ -80,7 +80,8 @@ import Nirum.Constructs.TypeExpression ( TypeExpression ( ListModifier ) ) -type ParseError = E.ParseError (Token T.Text) E.Dec +type Parser = Parsec Void T.Text +type ParseError = E.ParseError Char Void -- CHECK: If a new reserved keyword is introduced, it has to be also -- added to `reservedKeywords` set in the `Nirum.Constructs.Identifier` @@ -494,7 +495,7 @@ typeDeclaration = do let annotations = A.union annotationSet' $ typeAnnotations typeDecl return $ typeDecl { typeAnnotations = annotations } where - unless' :: [String] -> Parser a -> Parser a + unless' :: [T.Text] -> Parser a -> Parser a unless' [] _ = fail "no candidates" -- Must never happen unless' [s] p = notFollowedBy (string s) >> p unless' (x : xs) p = notFollowedBy (string x) >> unless' xs p @@ -662,5 +663,3 @@ parseFile path = do SIO.hSetEncoding h SIO.utf8_bom TIO.hGetContents h return $ runParser file path code - -{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-} diff --git a/src/Nirum/Targets.hs b/src/Nirum/Targets.hs index 1cfaa4c..08f9891 100644 --- a/src/Nirum/Targets.hs +++ b/src/Nirum/Targets.hs @@ -1,14 +1,7 @@ {-# LANGUAGE QuasiQuotes, ScopedTypeVariables, TemplateHaskell #-} module Nirum.Targets ( BuildError (CompileError, PackageError, TargetNameError) , BuildResult - , Target ( CompileError - , CompileResult - , compilePackage - , parseTarget - , showCompileError - , targetName - , toByteString - ) + , Target (..) , TargetName , buildPackage , targetNames diff --git a/stack.yaml b/stack.yaml index 0acdb56..e9c78f8 100644 --- a/stack.yaml +++ b/stack.yaml @@ -1,8 +1,20 @@ -resolver: lts-9.10 +resolver: lts-10.7 flags: {} packages: - '.' extra-deps: +- turtle-1.5.4 + # Until turtle-1.5.0 it requires Win32<2.4 while unix-compat-0.5.0.1 (which + # is the version pinned by the Stackage LTS 10.7) requires Win32>=2.5.0.0. - uri-0.1.6.4 + # No in the Stackage LTS 10.7 ## INSERT CODECOV HERE -- DO NOT REMOVE THIS COMMENT. SEE ALSO ISSUE #156. ## extra-package-dbs: [] +ghc-options: + "$locals": -fhide-source-paths +# http://hsyl20.fr/home/posts/2018-01-15-ghc-hiding-source-and-object-paths.html + +require-stack-version: + # CHECK: If we change the minimum version of Stack the download URLs in + # *appveyor.yml* file also should be updated. + ">=1.6.5" diff --git a/test/Spec.hs b/test/Main.hs similarity index 100% rename from test/Spec.hs rename to test/Main.hs diff --git a/test/Nirum/ParserSpec.hs b/test/Nirum/ParserSpec.hs index 3bfa8e6..3bbf9a5 100644 --- a/test/Nirum/ParserSpec.hs +++ b/test/Nirum/ParserSpec.hs @@ -17,9 +17,9 @@ import Text.Megaparsec (eof, runParser) import Text.Megaparsec.Char (string) import Text.Megaparsec.Error (errorPos, parseErrorPretty) import Text.Megaparsec.Pos (Pos, SourcePos (sourceColumn, sourceLine), mkPos) -import Text.Megaparsec.Text (Parser) import qualified Nirum.Parser as P +import Nirum.Parser (Parser, ParseError) import Nirum.Constructs (Construct (toCode)) import Nirum.Constructs.Annotation as A import Nirum.Constructs.Docs (Docs (Docs)) @@ -45,16 +45,16 @@ import Util (singleDocs) shouldBeRight :: (Eq l, Eq r, Show l, Show r) => Either l r -> r -> Expectation shouldBeRight actual expected = actual `shouldBe` Right expected -erroredPos :: Either P.ParseError a -> (Pos, Pos) +erroredPos :: Either ParseError a -> (Pos, Pos) erroredPos left = (sourceLine pos, sourceColumn pos) where - error' = head $ lefts [left] :: P.ParseError + error' = head $ lefts [left] :: ParseError pos = NE.head (errorPos error') :: SourcePos helperFuncs :: (Show a) => Parser a - -> ( T.Text -> Either P.ParseError a + -> ( T.Text -> Either ParseError a , T.Text -> Int -> Int -> Expectation ) helperFuncs parser = @@ -66,9 +66,9 @@ helperFuncs parser = return r parse' = runParser parserAndEof "" expectError inputString line col = do - line' <- mkPos line - col' <- mkPos col let parseResult = parse' inputString + line' = mkPos line + col' = mkPos col parseResult `shouldSatisfy` isLeft let Left parseError = parseResult msg = parseErrorPretty parseError @@ -1188,5 +1188,3 @@ service method-dups ( parseFileResult <- P.parseFile filePath parseFileResult `shouldSatisfy` isRight parseFileResult `shouldBe` parseResult - -{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}