dhall-lsp-server-1.0.0: src/Dhall/LSP/Backend/Linting.hs
module Dhall.LSP.Backend.Linting
( Suggestion(..)
, suggest
, Dhall.lint
)
where
import Dhall.Parser (Src)
import Dhall.Core (Expr(..), Binding(..), Var(..), subExpressions, freeIn, Import)
import qualified Dhall.Lint as Dhall
import Dhall.LSP.Backend.Diagnostics
import Data.Monoid ((<>))
import Data.Text (Text)
import Data.List.NonEmpty (NonEmpty(..), tails, toList)
import Control.Lens (universeOf)
data Suggestion = Suggestion {
range :: Range,
suggestion :: Text
}
-- Diagnose nested let blocks.
diagLetInLet :: Expr Src a -> [Suggestion]
diagLetInLet (Note _ (Let _ (Note src (Let _ _)))) =
[Suggestion (rangeFromDhall src) "Superfluous 'in' before nested let binding"]
diagLetInLet _ = []
-- Given a (noted) let block compute all unused variables in the block.
unusedBindings :: Eq a => Expr s a -> [Text]
unusedBindings (Note _ (Let bindings d)) = concatMap
(\case
Binding var _ _ : [] | not (V var 0 `freeIn` d) -> [var]
Binding var _ _ : (b : bs) | not (V var 0 `freeIn` Let (b :| bs) d) -> [var]
_ -> [])
(toList $ tails bindings)
unusedBindings _ = []
-- Diagnose unused let bindings.
diagUnusedBinding :: Eq a => Expr Src a -> [Suggestion]
diagUnusedBinding e@(Note src (Let _ _)) = map
(\var ->
Suggestion (rangeFromDhall src) ("Unused let binding '" <> var <> "'"))
(unusedBindings e)
diagUnusedBinding _ = []
-- | Given an dhall expression suggest all the possible improvements that would
-- be made by the linter.
suggest :: Expr Src Import -> [Suggestion]
suggest expr = concat [ diagLetInLet e ++ diagUnusedBinding e
| e <- universeOf subExpressions expr ]