Skip to content

Commit

Permalink
Merge pull request #5188 from unisonweb/lsp/unused-binding-detection
Browse files Browse the repository at this point in the history
Unused binding detection cleanup
  • Loading branch information
ChrisPenner authored Jul 6, 2024
2 parents 0331d22 + dd17539 commit 60bb91a
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 9 deletions.
2 changes: 1 addition & 1 deletion lib/unison-prelude/src/Unison/Debug.hs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ debugPatternCoverageConstraintSolver = PatternCoverageConstraintSolver `Set.memb
debug :: (Show a) => DebugFlag -> String -> a -> a
debug flag msg a =
if shouldDebug flag
then (pTrace (msg <> ":\n" <> into @String (pShow a)) a)
then (trace (msg <> ":\n" <> into @String (pShow a)) a)
else a

-- | Use for selective debug logging in monadic contexts.
Expand Down
27 changes: 19 additions & 8 deletions unison-cli/src/Unison/LSP/FileAnalysis/UnusedBindings.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,37 @@ import Unison.Parser.Ann (Ann)
import Unison.Prelude
import Unison.Symbol (Symbol (..))
import Unison.Term (Term)
import Unison.Util.Monoid qualified as Monoid
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.") []
-- 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.
mayRange =
Cv.annToURange topLevelTermAnn
<&> (\(Range.Range start@(Pos.Pos line _col) _end) -> Range.Range start (Pos.Pos line 9999))
<&> Cv.uToLspRange
vars =
Map.toList unusedVars & mapMaybe \(v, _ann) -> do
getRelevantVarName v
in case mayRange of
Nothing -> []
Just lspRange ->
let bindings = Text.intercalate ", " (tShow <$> vars)
in Monoid.whenM (not $ null vars) [Diagnostic.mkDiagnostic fileUri lspRange Diagnostic.DiagnosticSeverity_Warning ("Unused binding(s) " <> bindings <> " inside this term.\nUse the binding(s), or prefix them with an _ to dismiss this warning.") []]
where
getRelevantVarName :: Symbol -> Maybe Text
getRelevantVarName = \case
-- Sometimes 'do' gets a binding of '()', which we don't care about
Symbol _ (Var.User "()") -> Nothing
Symbol _ (Var.User "") -> Nothing
-- 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
Just 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
Expand Down

0 comments on commit 60bb91a

Please sign in to comment.