LibClang-3.8.0: src/Clang/Diagnostic.hs
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
-- | Functions for manipulating 'FFI.Diagnostic's, which represent
-- diagnostics - warnings, errors, and the like - produced by libclang.
--
-- 'FFI.Diagnostic's are grouped into 'FFI.DiagnosticSet's. You
-- usually obtain a 'FFI.DiagnosticSet' from a 'FFI.TranslationUnit'
-- using 'Clang.TranslationUnit.getDiagnosticSet', and then analyze it
-- using the functions in this module.
--
-- This module is intended to be imported qualified.
module Clang.Diagnostic
(
-- * Diagnostic sets
getElements
-- * Diagnostics
, getChildren
, getSeverity
, FFI.Severity(..)
, getSpelling
, getOptions
, getCategoryName
, getCategoryId
, getRanges
, getFixIts
-- * Rendering diagnostics
, format
, FFI.DisplayOptions(..)
-- * Deserializing diagnostics
, load
, FFI.LoadError(..)
) where
import Control.Monad.IO.Class
import Clang.Internal.BitFlags
import qualified Clang.Internal.FFI as FFI
import Clang.Internal.Monad
-- | Retrieve the diagnostics contained in the given 'FFI.DiagnosticSet'.
--
-- You can obtain a 'FFI.DiagnosticSet' from a 'FFI.TranslationUnit'
-- using 'Clang.TranslationUnit.getDiagnosticSet', or by deserializing
-- it from a file using 'load'.
getElements :: ClangBase m => FFI.DiagnosticSet s' -> ClangT s m [FFI.Diagnostic s]
getElements ds = do
numDiags <- liftIO $ FFI.getNumDiagnosticsInSet ds
mapM (FFI.getDiagnosticInSet ds) [0..(numDiags - 1)]
-- | Get the child diagnostics of the given diagnostic.
getChildren :: ClangBase m => FFI.Diagnostic s' -> ClangT s m (FFI.DiagnosticSet s)
getChildren = FFI.getChildDiagnostics
-- | Determine the severity of the given diagnostic.
getSeverity :: ClangBase m => FFI.Diagnostic s' -> ClangT s m FFI.Severity
getSeverity d = liftIO $ FFI.getDiagnosticSeverity d
-- | Retrieve the text of the given diagnostic.
getSpelling :: ClangBase m => FFI.Diagnostic s' -> ClangT s m (FFI.ClangString s)
getSpelling = FFI.getDiagnosticSpelling
-- | Retrieve the name of the command-line option that enabled this diagnostic.
getOptions :: ClangBase m
=> FFI.Diagnostic s' -- ^ The diagnostic in question.
-> ClangT s m (FFI.ClangString s, FFI.ClangString s) -- ^ The options controlling
-- this diagnostic. The
-- first member of the pair
-- is the option to enable
-- this diagnostic. The
-- second member is the
-- option to disable it.
getOptions = FFI.getDiagnosticOption
-- | Get the name of the diagnostic category for the given diagnostic.
--
-- Diagnostics are categorized into groups along with other,
-- related diagnostics (e.g., diagnostics under the same warning
-- flag).
getCategoryName :: ClangBase m => FFI.Diagnostic s' -> ClangT s m (FFI.ClangString s)
getCategoryName = FFI.getDiagnosticCategoryText
-- | Retrieve the category id for this diagnostic.
--
-- For display to the user, use 'getCategoryName'.
getCategoryId :: ClangBase m => FFI.Diagnostic s' -> ClangT s m Int
getCategoryId d = liftIO $ FFI.getDiagnosticCategory d
-- | Retrieve the source ranges associated with this diagnostic.
--
-- A diagnostic's source ranges highlight important elements in the
-- source code. On the command line, Clang displays source ranges by
-- underlining them with '~' characters.
getRanges :: ClangBase m => FFI.Diagnostic s' -> ClangT s m [FFI.SourceRange s]
getRanges d = liftIO $ do
numRanges <- FFI.getDiagnosticNumRanges d
mapM (FFI.getDiagnosticRange d) [0..(numRanges - 1)]
-- | Retrieve the fix-it hints associated with the given diagnostic.
--
-- Fix-its are described in terms of a source range whose contents
-- should be replaced by a string. This approach generalizes over
-- three kinds of operations: removal of source code (the range covers
-- the code to be removed and the replacement string is empty),
-- replacement of source code (the range covers the code to be
-- replaced and the replacement string provides the new code), and
-- insertion (both the start and end of the range point at the
-- insertion location, and the replacement string provides the text to
-- insert).
getFixIts :: ClangBase m
=> FFI.Diagnostic s' -- ^ The diagnostic in question.
-> ClangT s m [(FFI.SourceRange s, FFI.ClangString s)] -- ^ A list of replacement
-- ranges and strings. Note
-- that source ranges are
-- half-open ranges '[a, b)'
-- so the source code should
-- be replaced from 'a' up
-- to (but not including)
-- 'b'.
getFixIts d = do
numFixes <- liftIO $ FFI.getDiagnosticNumFixIts d
mapM (FFI.getDiagnosticFixIt d) [0..(numFixes - 1)]
-- | Format the given diagnostic in a manner that is suitable for
-- display.
format :: ClangBase m
=> Maybe [FFI.DisplayOptions] -- ^ An optional list of options
-- for rendering the diagnostic.
-- If 'Nothing' is given, default
-- options are used that mimic the
-- behavior of the Clang compiler
-- as closely as possible.
-> FFI.Diagnostic s' -- ^ The diagnostic to format.
-> ClangT s m (FFI.ClangString s) -- ^ A formatted rendering of the
-- given diagnostic.
format Nothing diag = FFI.formatDiagnostic diag =<<
liftIO FFI.defaultDiagnosticDisplayOptions
format (Just opts) diag = FFI.formatDiagnostic diag (orFlags opts)
-- | Deserialize a set of diagnostics from a Clang diagnostics bitcode file.
--
-- If an error is encountered, a 'FFI.LoadError' and a textual error
-- message suitable for display to the user are returned.
load :: ClangBase m
=> FilePath
-> ClangT s m (Either (FFI.LoadError, FFI.ClangString s) (FFI.DiagnosticSet s))
load = FFI.loadDiagnostics