{-# 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