mirror of
https://github.com/unisonweb/unison.git
synced 2024-09-11 10:35:57 +03:00
Merge pull request #5186 from unisonweb/lsp/unused-binding-detection
This commit is contained in:
commit
0331d2287c
@ -49,3 +49,10 @@ annToRange = \case
|
|||||||
Ann.External -> Nothing
|
Ann.External -> Nothing
|
||||||
Ann.GeneratedFrom a -> annToRange a
|
Ann.GeneratedFrom a -> annToRange a
|
||||||
Ann.Ann start end -> Just $ Range (uToLspPos start) (uToLspPos end)
|
Ann.Ann start end -> Just $ Range (uToLspPos start) (uToLspPos end)
|
||||||
|
|
||||||
|
annToURange :: Ann.Ann -> Maybe Range.Range
|
||||||
|
annToURange = \case
|
||||||
|
Ann.Intrinsic -> Nothing
|
||||||
|
Ann.External -> Nothing
|
||||||
|
Ann.GeneratedFrom a -> annToURange a
|
||||||
|
Ann.Ann start end -> Just $ Range.Range start end
|
||||||
|
@ -35,6 +35,7 @@ import Unison.KindInference.Error qualified as KindInference
|
|||||||
import Unison.LSP.Conversions
|
import Unison.LSP.Conversions
|
||||||
import Unison.LSP.Conversions qualified as Cv
|
import Unison.LSP.Conversions qualified as Cv
|
||||||
import Unison.LSP.Diagnostics (DiagnosticSeverity (..), mkDiagnostic, reportDiagnostics)
|
import Unison.LSP.Diagnostics (DiagnosticSeverity (..), mkDiagnostic, reportDiagnostics)
|
||||||
|
import Unison.LSP.FileAnalysis.UnusedBindings qualified as UnusedBindings
|
||||||
import Unison.LSP.Orphans ()
|
import Unison.LSP.Orphans ()
|
||||||
import Unison.LSP.Types
|
import Unison.LSP.Types
|
||||||
import Unison.LSP.VFS qualified as VFS
|
import Unison.LSP.VFS qualified as VFS
|
||||||
@ -111,12 +112,13 @@ checkFile doc = runMaybeT do
|
|||||||
& toRangeMap
|
& toRangeMap
|
||||||
let typeSignatureHints = fromMaybe mempty (mkTypeSignatureHints <$> parsedFile <*> typecheckedFile)
|
let typeSignatureHints = fromMaybe mempty (mkTypeSignatureHints <$> parsedFile <*> typecheckedFile)
|
||||||
let fileSummary = FileSummary.mkFileSummary parsedFile typecheckedFile
|
let fileSummary = FileSummary.mkFileSummary parsedFile typecheckedFile
|
||||||
|
let unusedBindingDiagnostics = fileSummary ^.. _Just . to termsBySymbol . folded . folding (\(topLevelAnn, _refId, trm, _type) -> UnusedBindings.analyseTerm fileUri topLevelAnn trm)
|
||||||
let tokenMap = getTokenMap tokens
|
let tokenMap = getTokenMap tokens
|
||||||
conflictWarningDiagnostics <-
|
conflictWarningDiagnostics <-
|
||||||
fold <$> for fileSummary \fs ->
|
fold <$> for fileSummary \fs ->
|
||||||
lift $ computeConflictWarningDiagnostics fileUri fs
|
lift $ computeConflictWarningDiagnostics fileUri fs
|
||||||
let diagnosticRanges =
|
let diagnosticRanges =
|
||||||
(errDiagnostics <> conflictWarningDiagnostics)
|
(errDiagnostics <> conflictWarningDiagnostics <> unusedBindingDiagnostics)
|
||||||
& fmap (\d -> (d ^. range, d))
|
& fmap (\d -> (d ^. range, d))
|
||||||
& toRangeMap
|
& toRangeMap
|
||||||
let fileAnalysis = FileAnalysis {diagnostics = diagnosticRanges, codeActions = codeActionRanges, fileSummary, typeSignatureHints, ..}
|
let fileAnalysis = FileAnalysis {diagnostics = diagnosticRanges, codeActions = codeActionRanges, fileSummary, typeSignatureHints, ..}
|
||||||
|
47
unison-cli/src/Unison/LSP/FileAnalysis/UnusedBindings.hs
Normal file
47
unison-cli/src/Unison/LSP/FileAnalysis/UnusedBindings.hs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
module Unison.LSP.FileAnalysis.UnusedBindings where
|
||||||
|
|
||||||
|
import Data.Foldable qualified as Foldable
|
||||||
|
import Data.Map qualified as Map
|
||||||
|
import Data.Set qualified as Set
|
||||||
|
import Data.Text qualified as Text
|
||||||
|
import Language.LSP.Protocol.Types (Diagnostic)
|
||||||
|
import Language.LSP.Protocol.Types qualified as Lsp
|
||||||
|
import U.Core.ABT (ABT (..))
|
||||||
|
import U.Core.ABT qualified as ABT
|
||||||
|
import Unison.LSP.Conversions qualified as Cv
|
||||||
|
import Unison.LSP.Diagnostics qualified as Diagnostic
|
||||||
|
import Unison.Lexer.Pos qualified as Pos
|
||||||
|
import Unison.Parser.Ann (Ann)
|
||||||
|
import Unison.Prelude
|
||||||
|
import Unison.Symbol (Symbol (..))
|
||||||
|
import Unison.Term (Term)
|
||||||
|
import Unison.Util.Range qualified as Range
|
||||||
|
import Unison.Var qualified as Var
|
||||||
|
|
||||||
|
analyseTerm :: Lsp.Uri -> Ann -> Term Symbol Ann -> [Diagnostic]
|
||||||
|
analyseTerm fileUri topLevelTermAnn tm =
|
||||||
|
let (unusedVars, _) = ABT.cata alg tm
|
||||||
|
in Map.toList unusedVars & mapMaybe \(v, _ann) -> do
|
||||||
|
name <- getRelevantVarName v
|
||||||
|
-- Unfortunately we don't capture the annotation of the actual binding when parsing :'(, for now the least
|
||||||
|
-- annoying thing to do is just highlight the top of the binding.
|
||||||
|
urange <- Cv.annToURange topLevelTermAnn <&> (\(Range.Range start@(Pos.Pos line _col) _end) -> Range.Range start (Pos.Pos line 9999))
|
||||||
|
let lspRange = Cv.uToLspRange urange
|
||||||
|
pure $ Diagnostic.mkDiagnostic fileUri lspRange Diagnostic.DiagnosticSeverity_Warning ("Unused binding " <> tShow name <> " inside this term.\nUse the binding, or prefix it with an _ to dismiss this warning.") []
|
||||||
|
where
|
||||||
|
getRelevantVarName :: Symbol -> Maybe Text
|
||||||
|
getRelevantVarName = \case
|
||||||
|
-- We only care about user bindings which don't start with an underscore
|
||||||
|
Symbol _ (Var.User n) -> do
|
||||||
|
guard (not (Text.isPrefixOf "_" n))
|
||||||
|
pure n
|
||||||
|
_ -> Nothing
|
||||||
|
alg :: (Foldable f, Ord v) => Ann -> ABT f v (Map v Ann, Set v) -> (Map v Ann, Set v)
|
||||||
|
alg ann abt = case abt of
|
||||||
|
Var v -> (mempty, Set.singleton v)
|
||||||
|
Cycle x -> x
|
||||||
|
Abs v (unusedBindings, usedVars) ->
|
||||||
|
if v `Set.member` usedVars
|
||||||
|
then (unusedBindings, Set.delete v usedVars)
|
||||||
|
else (Map.insert v ann unusedBindings, usedVars)
|
||||||
|
Tm fx -> Foldable.fold fx
|
@ -130,6 +130,7 @@ library
|
|||||||
Unison.LSP.Conversions
|
Unison.LSP.Conversions
|
||||||
Unison.LSP.Diagnostics
|
Unison.LSP.Diagnostics
|
||||||
Unison.LSP.FileAnalysis
|
Unison.LSP.FileAnalysis
|
||||||
|
Unison.LSP.FileAnalysis.UnusedBindings
|
||||||
Unison.LSP.FoldingRange
|
Unison.LSP.FoldingRange
|
||||||
Unison.LSP.Formatting
|
Unison.LSP.Formatting
|
||||||
Unison.LSP.HandlerUtils
|
Unison.LSP.HandlerUtils
|
||||||
|
Loading…
Reference in New Issue
Block a user