Commit 9402608e authored by Ben Gamari's avatar Ben Gamari 🐢 Committed by Marge Bot
Browse files

gitlab-ci: Check coverage of GHC flags in users guide

This ensures that all GHC flags are documented during the documentation

Fixes #17315.
parent a95f7185
Pipeline #11091 failed with stages
in 1 minute and 3 seconds
#!/usr/bin/env python
# -*- coding: utf-8 -*-
Linter to verify that all flags reported by GHC's --show-options mode
are documented in the user's guide.
import sys
import subprocess
from typing import Set
from pathlib import Path
# A list of known-undocumented flags. This should be considered to be a to-do
# list of flags that need to be documented.
Path(__file__).parent / 'expected-undocumented-flags.txt'
{line for line in open(EXPECTED_UNDOCUMENTED_PATH).read().split()}
def expected_undocumented(flag: str) -> bool:
return True
if flag.startswith('-Werror'):
return True
if flag.startswith('-Wno-') \
or flag.startswith('-dno') \
or flag.startswith('-fno') \
or flag.startswith('-XNo'):
return True
if flag.startswith('-Wwarn=') \
or flag.startswith('-Wno-warn='):
return True
return False
def read_documented_flags(doc_flags) -> Set[str]:
# Map characters that mark the end of a flag
# to whitespace.
trans = str.maketrans({
'=': ' ',
'[': ' ',
'⟨': ' ',
return {line.translate(trans).split()[0]
for line in'\n')
if line != ''}
def read_ghc_flags(ghc_path: str) -> Set[str]:
ghc_output = subprocess.check_output([ghc_path, '--show-options'],
return {flag
for flag in ghc_output.split('\n')
if not expected_undocumented(flag)
if flag != ''}
def main() -> None:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--ghc', type=argparse.FileType('r'),
help='path of GHC executable')
parser.add_argument('--doc-flags', type=argparse.FileType('r'),
help='path of ghc-flags.txt output from Sphinx')
args = parser.parse_args()
doc_flags = read_documented_flags(args.doc_flags)
ghc_flags = read_ghc_flags(
failed = False
undocumented = ghc_flags - doc_flags
if len(undocumented) > 0:
print(f'Found {len(undocumented)} flags not documented in the users guide:')
print('\n'.join(f' {flag}' for flag in sorted(undocumented)))
failed = True
now_documented = EXPECTED_UNDOCUMENTED.intersection(doc_flags)
if len(now_documented) > 0:
print(f'Found flags that are documented yet listed in {EXPECTED_UNDOCUMENTED_PATH}:')
print('\n'.join(f' {flag}' for flag in sorted(now_documented)))
failed = True
if failed:
if __name__ == '__main__':
......@@ -16,6 +16,7 @@ import Context
import Expression (getContextData, interpretInContext, (?), package)
import Flavour
import Oracles.ModuleFiles
import Oracles.Setting (topDirectory)
import Packages
import Settings
import Target
......@@ -111,6 +112,11 @@ documentationRules = do
need $ map (root -/-) targets
when (SphinxPDFs `Set.member` doctargets)
$ checkUserGuideFlags $ pdfRoot -/- "users_guide" -/- "ghc-flags.txt"
when (SphinxHTML `Set.member` doctargets)
$ checkUserGuideFlags $ htmlRoot -/- "users_guide" -/- "ghc-flags.txt"
where archiveTarget "libraries" = Haddocks
archiveTarget _ = SphinxHTML
......@@ -124,6 +130,17 @@ checkSphinxWarnings out = do
when ("reference target not found" `isInfixOf` log)
$ fail "Undefined reference targets found in Sphinx log."
-- | Check that all GHC flags are documented in the users guide.
checkUserGuideFlags :: FilePath -> Action ()
checkUserGuideFlags documentedFlagList = do
scriptPath <- (</> "docs/user_guide/") <$> topDirectory
Please register or sign in to reply
ghcPath <- (</>) <$> topDirectory <*> programPath (vanillaContext Stage1 ghc)
runBuilder Python
[ scriptPath
, "--doc-flags", documentedFlagList
, "--ghc", ghcPath
] [documentedFlagList] []
------------------------------------- HTML -------------------------------------
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment