summaryrefslogtreecommitdiff
path: root/utils/check-api-annotations
diff options
context:
space:
mode:
Diffstat (limited to 'utils/check-api-annotations')
-rw-r--r--utils/check-api-annotations/Main.hs34
-rw-r--r--utils/check-api-annotations/README85
2 files changed, 103 insertions, 16 deletions
diff --git a/utils/check-api-annotations/Main.hs b/utils/check-api-annotations/Main.hs
index 7dc2eb3f77..20e6aa0ca2 100644
--- a/utils/check-api-annotations/Main.hs
+++ b/utils/check-api-annotations/Main.hs
@@ -7,6 +7,7 @@ import DynFlags
import Outputable
import ApiAnnotation
import System.Environment( getArgs )
+import System.Exit
import qualified Data.Map as Map
import qualified Data.Set as Set
@@ -19,7 +20,7 @@ main = do
testOneFile :: FilePath -> String -> IO ()
testOneFile libdir fileName = do
- ((anns,cs),p) <- runGhc (Just libdir) $ do
+ ((anns,_cs),p) <- runGhc (Just libdir) $ do
dflags <- getSessionDynFlags
_ <- setSessionDynFlags dflags
let mn =mkModuleName fileName
@@ -33,9 +34,6 @@ testOneFile libdir fileName = do
let sspans = Set.fromList $ getAllSrcSpans (pm_parsed_source p)
- problems = filter (\(s,_a) -> not (Set.member s sspans))
- $ getAnnSrcSpans (anns,cs)
-
exploded = [((kw,ss),[anchor])
| ((anchor,kw),sss) <- Map.toList anns,ss <- sss]
@@ -45,17 +43,20 @@ testOneFile libdir fileName = do
-> not (any (\a -> Set.member a sspans) anchors))
exploded'
- putStrLn "---Problems---------------------"
- putStrLn (intercalate "\n" [showAnns $ Map.fromList $ map snd problems])
- putStrLn "---Problems'--------------------"
- putStrLn (intercalate "\n" [pp $ Map.fromList $ map fst problems'])
- putStrLn "--------------------------------"
- putStrLn (intercalate "\n" [showAnns anns])
+ problems'' = filter (\((a,_),_) -> a /= AnnEofPos) problems'
- where
- getAnnSrcSpans :: ApiAnns -> [(SrcSpan,(ApiAnnKey,[SrcSpan]))]
- getAnnSrcSpans (anns,_) = map (\a@((ss,_),_) -> (ss,a)) $ Map.toList anns
+ putStrLn "---Problems (should be empty list)---"
+ putStrLn (intercalate "\n" [pp $ Map.fromList $ map fst problems''])
+ putStrLn "---Annotations-----------------------"
+ putStrLn "-- SrcSpan the annotation is attached to, AnnKeywordId,"
+ putStrLn "-- list of locations the keyword item appears in"
+ -- putStrLn (intercalate "\n" [showAnns anns])
+ putStrLn (showAnns anns)
+ if null problems''
+ then exitSuccess
+ else exitFailure
+ where
getAllSrcSpans :: (Data t) => t -> [SrcSpan]
getAllSrcSpans ast = everything (++) ([] `mkQ` getSrcSpan) ast
where
@@ -64,11 +65,12 @@ testOneFile libdir fileName = do
showAnns :: Map.Map ApiAnnKey [SrcSpan] -> String
-showAnns anns = "[\n" ++ (intercalate "\n"
+showAnns anns = "[\n" ++ (intercalate ",\n"
$ map (\((s,k),v)
- -> ("(AK " ++ pp s ++ " " ++ show k ++" = " ++ pp v ++ ")\n"))
+ -- -> ("(AK " ++ pp s ++ " " ++ show k ++" = " ++ pp v ++ ")\n"))
+ -> ("((" ++ pp s ++ "," ++ show k ++"), " ++ pp v ++ ")"))
$ Map.toList anns)
- ++ "]\n"
+ ++ "\n]\n"
pp :: (Outputable a) => a -> String
pp a = showPpr unsafeGlobalDynFlags a
diff --git a/utils/check-api-annotations/README b/utils/check-api-annotations/README
index 7c2815a403..fcadc50ff6 100644
--- a/utils/check-api-annotations/README
+++ b/utils/check-api-annotations/README
@@ -16,3 +16,88 @@ In a test Makefile
$(CHECK_API_ANNOTATIONS) "`'$(TEST_HC)' $(TEST_HC_OPTS) --print-libdir | tr -d '\r'`" FileToParse.hs
See examples in (REPO_HOME)/testsuite/tests/ghc-api/annotations/Makefile
+
+
+Description of operation
+------------------------
+
+The programme is called with the name of a haskell source file.
+
+It uses the GHC API to load and parse this, and extracts the API annotations.
+
+These are of the form
+
+ Map.Map ApiAnnKey [SrcSpan]
+
+where
+
+ type ApiAnnKey = (SrcSpan,AnnKeywordId)
+
+So an annotation is a key comprising the parent SrcSpan in the ParsedSource
+together with an AnnKeywordId, and this maps to a list of locations where the
+specific keyword item occurs in the original source.
+
+The utility extracts all SrcSpans in the ParsedSource, and makes sure that for
+every ApiAnnKey the SrcSpan is actually present in the final ParsedSource. This
+is to ensure that when a given parser production is postprocessed anywhere along
+the line the relevant SrcSpan is not discarded, thus detaching the annotation
+from the final output.
+
+It also provides a list of each ApiAnnKey and the corresponding source
+locations, so these can be checked against the original source for correctness.
+
+Example
+-------
+
+Test10255.hs in the ghc-api/annotations tests has the following source
+
+------------------------------
+1:{-# LANGUAGE ScopedTypeVariables #-}
+2:module Test10255 where
+3:
+4:import Data.Maybe
+5:
+6:fob (f :: (Maybe t -> Int)) =
+7: undefined
+------------------------------
+
+The output of this utility is
+
+------------------------------------------------------------------------
+---Problems (should be empty list)---
+[]
+---Annotations-----------------------
+-- SrcSpan the annotation is attached to, AnnKeywordId,
+-- list of locations the keyword item appears in
+[
+((Test10255.hs:1:1,AnnModule), [Test10255.hs:2:1-6]),
+((Test10255.hs:1:1,AnnWhere), [Test10255.hs:2:18-22]),
+((Test10255.hs:4:1-17,AnnImport), [Test10255.hs:4:1-6]),
+((Test10255.hs:4:1-17,AnnSemi), [Test10255.hs:6:1]),
+((Test10255.hs:(6,1)-(7,11),AnnEqual), [Test10255.hs:6:29]),
+((Test10255.hs:(6,1)-(7,11),AnnFunId), [Test10255.hs:6:1-3]),
+((Test10255.hs:(6,1)-(7,11),AnnSemi), [Test10255.hs:8:1]),
+((Test10255.hs:6:5-27,AnnCloseP), [Test10255.hs:6:27]),
+((Test10255.hs:6:5-27,AnnOpenP), [Test10255.hs:6:5]),
+((Test10255.hs:6:6-26,AnnDcolon), [Test10255.hs:6:8-9]),
+((Test10255.hs:6:11-26,AnnCloseP), [Test10255.hs:6:26]),
+((Test10255.hs:6:11-26,AnnOpenP), [Test10255.hs:6:11]),
+((Test10255.hs:6:12-18,AnnRarrow), [Test10255.hs:6:20-21]),
+((Test10255.hs:6:12-25,AnnRarrow), [Test10255.hs:6:20-21]),
+((<no location info>,AnnEofPos), [Test10255.hs:8:1])
+]
+------------------------------------------------------------------------
+
+To interpret this, firstly the problems list is empty, so there are not
+annotations that do not appear in the final AST.
+
+Secondly, the list of annotations and locations can be checked against the test
+source code to ensure that every AnnKeywordId does in fact appear.
+
+It will return a zero exit code if the list of problems is empty, non-zero
+otherwise.
+
+Note: In some cases, such as T10269 in the ghc-api/annotations tests the list is
+non-empty, due to postprocessing of the parsed result. In general this should
+only happen for an `AnnVal` and if it does the actual annotations provided need
+to be inspected to check that an equivalent annotation is provided.