LibClang-3.8.0: src/Clang/Internal/Comment.hs
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE FlexibleContexts #-}
module Clang.Internal.Comment
( ParsedComment(..)
, ParamPassDirection(..)
, parseComment
, getFFIComment
) where
import Control.Applicative
import Control.Monad
import Control.Monad.IO.Class
import Data.Typeable
import qualified Clang.Internal.FFI as FFI
import Clang.Internal.Monad
-- | A node in the comment AST.
--
-- Every constructor contains an opaque 'FFI.Comment' value, which represents the AST node
-- itself. The other fields are the user-visible metadata for that node type.
data ParsedComment s
-- | Plain text. Inline content.
= TextComment (FFI.Comment s) (FFI.ClangString s)
-- | A command with word-like arguments that is considered inline content.
| InlineCommandComment (FFI.Comment s) (FFI.ClangString s) FFI.InlineCommandRenderStyle [FFI.ClangString s]
-- | An HTML start tag with attributes (represented as name/value pairs). Considered inline content.
-- The final argument of the constructor is 'True' if the tag is self-closing.
| HTMLStartTagComment (FFI.Comment s) (FFI.ClangString s) [(FFI.ClangString s, FFI.ClangString s)] Bool
-- | An HTML end tag. Considered inline content.
| HTMLEndTagComment (FFI.Comment s) (FFI.ClangString s)
-- | A paragraph, which contains inline content. The paragraph itself is block content.
| ParagraphComment (FFI.Comment s)
-- | A command which has zero or more word-like arguments and a paragraph argument. Block content.
-- The paragraph argument (of type 'ParsedComment') is also a child of the 'BlockCommandComment'.
--
-- As an example, a \'\\brief\' comment creates a 'BlockCommandComment' AST node with no word-like
-- arguments and a paragraph argument.
| BlockCommandComment (FFI.Comment s) (FFI.ClangString s) [FFI.ClangString s] (Maybe (ParsedComment s))
-- | A \'\\param\' or \'\\arg\' command that describes a function parameter. The parameter name,
-- index in the parameter list (or 'Nothing' if the index is invalid), and parameter passing
-- direction are provided as constructor fields. The description is provided as a child node.
| ParamCommandComment (FFI.Comment s) (FFI.ClangString s) (Maybe Int) ParamPassDirection
-- | A \'\\tparam\' command that describes a template parameter. The parameter name and position
-- are provided as constructor fields, while the description is provided as a child node.
--
-- Since template parameters can be nested, the position is a list with a left-to-right position
-- at each nesting depth. For example, for the following declaration:
--
-- > template<typename C, template<typename T> class TT>
-- > void test(TT<int> aaa);
--
-- The resulting position would be [0] for \'C\', [1] for \'TT\', and [1, 0] for \'T\'.
| TypeParamCommandComment (FFI.Comment s) (FFI.ClangString s) (Maybe [Int])
-- | A verbatim block command (e.g. preformatted code). A verbatim block has an opening
-- and a closing command and contains multiple lines of text, represented as
-- 'VerbatimBlockLineComment' nodes.
| VerbatimBlockCommandComment (FFI.Comment s) (Maybe (ParsedComment s))
-- | A line of text that is contained within a 'VerbatimBlockCommandComment' node.
| VerbatimBlockLineComment (FFI.Comment s) (FFI.ClangString s)
-- | A verbatim line command. A verbatim line has an opening command, a single line
-- of text (up to the newline after the opening command), and has no closing command.
| VerbatimLineComment (FFI.Comment s) (FFI.ClangString s)
-- | A full comment attached to a declaration. Contains block content.
| FullComment (FFI.Comment s)
deriving (Eq, Ord, Typeable)
-- | A parameter passing direction, either explicitly provided in the comment text or
-- inferred.
data ParamPassDirection
= ExplicitParamPassDirection FFI.ParamPassDirectionKind
| InferredParamPassDirection FFI.ParamPassDirectionKind
deriving (Eq, Ord, Read, Show, Typeable)
parseComment :: ClangBase m => FFI.Comment s -> ClangT s m (Maybe (ParsedComment s))
parseComment c = do
kind <- liftIO $ FFI.comment_getKind c
case kind of
FFI.NullComment -> pure Nothing
FFI.TextComment -> Just . TextComment c <$> FFI.textComment_getText c
FFI.InlineCommandComment -> do v <- InlineCommandComment c <$> FFI.inlineCommandComment_getCommandName c
<*> inlineCommandComment_getRenderKind c
<*> inlineCommandComment_getArgs c
return $ Just v
FFI.HTMLStartTagComment -> do v <- HTMLStartTagComment c <$> FFI.hTMLTagComment_getTagName c
<*> htmlStartTagComment_getAttrs c
<*> htmlStartTagComment_isSelfClosing c
return $ Just v
FFI.HTMLEndTagComment -> Just . HTMLEndTagComment c <$> FFI.hTMLTagComment_getTagName c
FFI.ParagraphComment -> pure $ Just (ParagraphComment c)
FFI.BlockCommandComment -> do v <- BlockCommandComment c <$> FFI.blockCommandComment_getCommandName c
<*> blockCommandComment_getArgs c
<*> blockCommandComment_getParagraph c
return $ Just v
FFI.ParamCommandComment -> do v <- ParamCommandComment c <$> FFI.paramCommandComment_getParamName c
<*> paramCommandComment_getParamIndex c
<*> paramCommandComment_getDirection c
return $ Just v
FFI.TParamCommandComment -> do v <- TypeParamCommandComment c
<$> FFI.tParamCommandComment_getParamName c
<*> tParamCommandComment_getPosition c
return $ Just v
FFI.VerbatimBlockCommandComment -> Just . VerbatimBlockCommandComment c <$> blockCommandComment_getParagraph c
FFI.VerbatimBlockLineComment -> Just . VerbatimBlockLineComment c <$> FFI.verbatimBlockLineComment_getText c
FFI.VerbatimLineComment -> Just . VerbatimLineComment c <$> FFI.verbatimLineComment_getText c
FFI.FullComment -> pure $ Just (FullComment c)
getFFIComment :: ParsedComment s -> FFI.Comment s
getFFIComment (TextComment c _) = c
getFFIComment (InlineCommandComment c _ _ _) = c
getFFIComment (HTMLStartTagComment c _ _ _) = c
getFFIComment (HTMLEndTagComment c _) = c
getFFIComment (ParagraphComment c) = c
getFFIComment (BlockCommandComment c _ _ _) = c
getFFIComment (ParamCommandComment c _ _ _) = c
getFFIComment (TypeParamCommandComment c _ _) = c
getFFIComment (VerbatimBlockCommandComment c _) = c
getFFIComment (VerbatimBlockLineComment c _) = c
getFFIComment (VerbatimLineComment c _) = c
getFFIComment (FullComment c) = c
inlineCommandComment_getRenderKind :: ClangBase m => FFI.Comment s'
-> ClangT s m FFI.InlineCommandRenderStyle
inlineCommandComment_getRenderKind c = liftIO $ FFI.inlineCommandComment_getRenderKind c
inlineCommandComment_getArgs :: ClangBase m => FFI.Comment s' -> ClangT s m [FFI.ClangString s]
inlineCommandComment_getArgs c = do
numArgs <- liftIO $ FFI.inlineCommandComment_getNumArgs c
mapM (FFI.inlineCommandComment_getArgText c) [0..(numArgs - 1)]
htmlStartTagComment_getAttrs :: ClangBase m => FFI.Comment s'
-> ClangT s m [(FFI.ClangString s, FFI.ClangString s)]
htmlStartTagComment_getAttrs c = do
numAttrs <- liftIO $ FFI.hTMLStartTag_getNumAttrs c
forM [0..numAttrs] $ \attr -> do
attrName <- FFI.hTMLStartTag_getAttrName c attr
attrValue <- FFI.hTMLStartTag_getAttrValue c attr
return (attrName, attrValue)
htmlStartTagComment_isSelfClosing :: ClangBase m => FFI.Comment s' -> ClangT s m Bool
htmlStartTagComment_isSelfClosing c = liftIO $ FFI.hTMLStartTagComment_isSelfClosing c
blockCommandComment_getArgs :: ClangBase m => FFI.Comment s' -> ClangT s m [FFI.ClangString s]
blockCommandComment_getArgs c = do
numArgs <- liftIO $ FFI.blockCommandComment_getNumArgs c
mapM (FFI.blockCommandComment_getArgText c) [0..(numArgs - 1)]
blockCommandComment_getParagraph :: ClangBase m => FFI.Comment s' -> ClangT s m (Maybe (ParsedComment s))
blockCommandComment_getParagraph c =
parseComment =<< liftIO (FFI.blockCommandComment_getParagraph mkProxy c)
paramCommandComment_getParamIndex :: ClangBase m => FFI.Comment s' -> ClangT s m (Maybe Int)
paramCommandComment_getParamIndex c = do
valid <- liftIO $ FFI.paramCommandComment_isParamIndexValid c
if valid
then Just <$> (liftIO $ FFI.paramCommandComment_getParamIndex c)
else return Nothing
paramCommandComment_getDirection :: ClangBase m => FFI.Comment s' -> ClangT s m ParamPassDirection
paramCommandComment_getDirection c = do
dir <- liftIO $ FFI.paramCommandComment_getDirection c
explicit <- liftIO $ FFI.paramCommandComment_isDirectionExplicit c
return $ if explicit
then ExplicitParamPassDirection dir
else InferredParamPassDirection dir
tParamCommandComment_getPosition :: ClangBase m => FFI.Comment s' -> ClangT s m (Maybe [Int])
tParamCommandComment_getPosition c = do
valid <- liftIO $ FFI.tParamCommandComment_isParamPositionValid c
if valid
then do depth <- liftIO $ FFI.tParamCommandComment_getDepth c
indices <- forM [0..depth] $ \d ->
liftIO $ FFI.tParamCommandComment_getIndex c d
return $ Just indices
else return Nothing