packages feed

aihc-parser-1.0.0.2: test/Test/Properties/MinimalParentheses.hs

{-# LANGUAGE OverloadedStrings #-}

module Test.Properties.MinimalParentheses
  ( prop_minimalParenthesesExpr,
    prop_minimalParenthesesPattern,
    prop_minimalParenthesesType,
    prop_minimalParenthesesSignatureType,
  )
where

import Aihc.Parser (ParseResult (..), ParserConfig (..), defaultConfig, parseExpr, parsePattern, parseSignatureType, parseType)
import Aihc.Parser.Parens (addExprParens, addPatternParens, addSignatureTypeParens, addTypeParens)
import Aihc.Parser.Pretty (prettyExpr, prettyPattern, prettyType)
import Aihc.Parser.Shorthand (Shorthand (shorthand))
import Aihc.Parser.Syntax
import Data.Text qualified as T
import ParserValidation (stripParens)
import Prettyprinter (defaultLayoutOptions, layoutPretty)
import Prettyprinter.Render.Text (renderStrict)
import Test.Properties.Arb.Utils (requiredExtensions)
import Test.QuickCheck

config :: ParserConfig
config =
  defaultConfig
    { parserExtensions = requiredExtensions
    }

prop_minimalParenthesesExpr :: Expr -> Property
prop_minimalParenthesesExpr expr = do
  counterexample
    ( "Found smaller, valid expression. "
        ++ "Original:\n"
        ++ show (shorthand parenthesized)
        ++ "\n"
        ++ T.unpack (renderStrict (layoutPretty defaultLayoutOptions (prettyExpr parenthesized)))
        ++ "\nSmaller:\n"
        ++ show (shorthand noParens)
        ++ "\n"
        ++ T.unpack (renderStrict (layoutPretty defaultLayoutOptions (prettyExpr noParens)))
    )
    (isMinimal || not exprIsValid)
  where
    noParens = stripParens expr
    parenthesized = addExprParens noParens
    source = renderStrict (layoutPretty defaultLayoutOptions (prettyExpr noParens))
    isMinimal = parenthesized == noParens
    exprIsValid = case parseExpr config source of ParseOk parsed -> stripAnnotations parsed == stripAnnotations noParens; ParseErr {} -> False

prop_minimalParenthesesPattern :: Pattern -> Property
prop_minimalParenthesesPattern pat = do
  counterexample
    ( "Found smaller, valid pattern. "
        ++ "Original:\n"
        ++ show (shorthand parenthesized)
        ++ "\n"
        ++ T.unpack (renderStrict (layoutPretty defaultLayoutOptions (prettyPattern parenthesized)))
        ++ "\nSmaller:\n"
        ++ show (shorthand noParens)
        ++ "\n"
        ++ T.unpack (renderStrict (layoutPretty defaultLayoutOptions (prettyPattern noParens)))
    )
    (isMinimal || not patternIsValid)
  where
    noParens = stripParens pat
    parenthesized = addPatternParens noParens
    source = renderStrict (layoutPretty defaultLayoutOptions (prettyPattern noParens))
    isMinimal = parenthesized == noParens
    patternIsValid = case parsePattern config source of ParseOk parsed -> stripAnnotations parsed == stripAnnotations noParens; ParseErr {} -> False

prop_minimalParenthesesSignatureType :: Type -> Property
prop_minimalParenthesesSignatureType ty = do
  counterexample
    ( "Found smaller, valid signature type. "
        ++ "Original:\n"
        ++ show (shorthand parenthesized)
        ++ "\n"
        ++ T.unpack (renderStrict (layoutPretty defaultLayoutOptions (prettyType parenthesized)))
        ++ "\nSmaller:\n"
        ++ show (shorthand noParens)
        ++ "\n"
        ++ T.unpack (renderStrict (layoutPretty defaultLayoutOptions (prettyType noParens)))
    )
    (isMinimal || not typeIsValid)
  where
    noParens = stripParens ty
    parenthesized = addSignatureTypeParens noParens
    source = renderStrict (layoutPretty defaultLayoutOptions (prettyType noParens))
    isMinimal = parenthesized == noParens
    typeIsValid = case parseSignatureType config source of ParseOk parsed -> stripAnnotations parsed == stripAnnotations noParens; ParseErr {} -> False

prop_minimalParenthesesType :: Type -> Property
prop_minimalParenthesesType ty = do
  counterexample
    ( "Found smaller, valid type. "
        ++ "Original:\n"
        ++ show (shorthand parenthesized)
        ++ "\n"
        ++ T.unpack (renderStrict (layoutPretty defaultLayoutOptions (prettyType parenthesized)))
        ++ "\nSmaller:\n"
        ++ show (shorthand noParens)
        ++ "\n"
        ++ T.unpack (renderStrict (layoutPretty defaultLayoutOptions (prettyType noParens)))
    )
    (isMinimal || not typeIsValid)
  where
    noParens = stripParens ty
    parenthesized = addTypeParens noParens
    source = renderStrict (layoutPretty defaultLayoutOptions (prettyType noParens))
    isMinimal = parenthesized == noParens
    typeIsValid = case parseType config source of ParseOk parsed -> stripAnnotations parsed == stripAnnotations noParens; ParseErr {} -> False