dhall-haskell/dhall-lsp-server/src/Dhall/LSP/Backend/Linting.hs
Gabriel Gonzalez 96921f03ab
Fix dhall format to preserve let comments (#1273)
Related to https://github.com/dhall-lang/dhall-haskell/issues/145

Note that this also refactors `Let` to use `Binding` in order
to avoid having to duplicate `Src`-related fields in two
places.
2019-09-04 23:41:44 -05:00

58 lines
1.9 KiB
Haskell
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

module Dhall.LSP.Backend.Linting
( Suggestion(..)
, suggest
, Dhall.lint
)
where
import Dhall.Parser (Src)
import Dhall.Core ( Expr(..), Binding(..), MultiLet(..), Import
, subExpressions, multiLet, wrapInLets)
import qualified Dhall.Lint as Dhall
import Dhall.LSP.Backend.Diagnostics
import qualified Data.List.NonEmpty as NonEmpty
import Data.Maybe (maybeToList)
import Data.Monoid ((<>))
import Data.Text (Text)
import Control.Lens (universeOf)
data Suggestion = Suggestion {
range :: Range,
suggestion :: Text
}
-- Diagnose nested let-blocks.
--
-- Pattern matching on a 'Let' wrapped in a 'Note' prevents us from repeating
-- the search beginning at different @let@s in the same let-block only
-- the outermost 'Let' of a let-block is wrapped in a 'Note'.
diagLetInLet :: Expr Src a -> Maybe Suggestion
diagLetInLet (Note _ (Let b e)) = case multiLet b e of
MultiLet _ (Note src (Let {})) ->
Just (Suggestion (rangeFromDhall src) "Superfluous 'in' before nested let binding")
_ -> Nothing
diagLetInLet _ = Nothing
-- Given a let-block compute all unused variables in the block.
unusedBindings :: Eq a => MultiLet s a -> [Text]
unusedBindings (MultiLet bindings d) =
let go bs@(Binding { variable = var} : _) | Just _ <- Dhall.removeUnusedBindings (wrapInLets bs d) = [var]
go _ = []
in foldMap go (NonEmpty.tails bindings)
-- Diagnose unused let bindings.
diagUnusedBindings :: Eq a => Expr Src a -> [Suggestion]
diagUnusedBindings (Note src (Let b e)) = map
(\var ->
Suggestion (rangeFromDhall src) ("Unused let binding '" <> var <> "'"))
(unusedBindings (multiLet b e))
diagUnusedBindings _ = []
-- | Given an dhall expression suggest all the possible improvements that would
-- be made by the linter.
suggest :: Expr Src Import -> [Suggestion]
suggest expr = concat [ maybeToList (diagLetInLet e) ++ diagUnusedBindings e
| e <- universeOf subExpressions expr ]