mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-17 16:38:33 +00:00
stricter checks for RST headlines (#17089)
This commit is contained in:
@@ -142,6 +142,7 @@ template declareClosures =
|
||||
of mwUnknownSubstitution: k = warnUnknownSubstitutionX
|
||||
of mwUnsupportedLanguage: k = warnLanguageXNotSupported
|
||||
of mwUnsupportedField: k = warnFieldXNotSupported
|
||||
of mwRstStyle: k = warnRstStyle
|
||||
{.gcsafe.}:
|
||||
globalError(conf, newLineInfo(conf, AbsoluteFile filename, line, col), k, arg)
|
||||
|
||||
|
||||
@@ -44,8 +44,10 @@ type
|
||||
warnDeprecated = "Deprecated", warnConfigDeprecated = "ConfigDeprecated",
|
||||
warnSmallLshouldNotBeUsed = "SmallLshouldNotBeUsed", warnUnknownMagic = "UnknownMagic",
|
||||
warnRedefinitionOfLabel = "RedefinitionOfLabel", warnUnknownSubstitutionX = "UnknownSubstitutionX",
|
||||
warnLanguageXNotSupported = "LanguageXNotSupported", warnFieldXNotSupported = "FieldXNotSupported",
|
||||
warnCommentXIgnored = "CommentXIgnored", warnTypelessParam = "TypelessParam",
|
||||
warnLanguageXNotSupported = "LanguageXNotSupported",
|
||||
warnFieldXNotSupported = "FieldXNotSupported",
|
||||
warnRstStyle = "warnRstStyle", warnCommentXIgnored = "CommentXIgnored",
|
||||
warnTypelessParam = "TypelessParam",
|
||||
warnUseBase = "UseBase", warnWriteToForeignHeap = "WriteToForeignHeap",
|
||||
warnUnsafeCode = "UnsafeCode", warnUnusedImportX = "UnusedImport",
|
||||
warnInheritFromException = "InheritFromException", warnEachIdentIsTuple = "EachIdentIsTuple",
|
||||
@@ -83,7 +85,7 @@ const
|
||||
errGridTableNotImplemented: "grid table is not implemented",
|
||||
errMarkdownIllformedTable: "illformed delimiter row of a markdown table",
|
||||
errGeneralParseError: "general parse error",
|
||||
errNewSectionExpected: "new section expected",
|
||||
errNewSectionExpected: "new section expected $1",
|
||||
errInvalidDirectiveX: "invalid directive: '$1'",
|
||||
errFootnoteMismatch: "number of footnotes and their references don't match: $1",
|
||||
errProveInit: "Cannot prove that '$1' is initialized.", # deadcode
|
||||
@@ -101,6 +103,7 @@ const
|
||||
warnUnknownSubstitutionX: "unknown substitution '$1'",
|
||||
warnLanguageXNotSupported: "language '$1' not supported",
|
||||
warnFieldXNotSupported: "field '$1' not supported",
|
||||
warnRstStyle: "RST style: $1",
|
||||
warnCommentXIgnored: "comment '$1' ignored",
|
||||
warnTypelessParam: "'$1' has no type. Typeless parameters are deprecated; only allowed for 'template'",
|
||||
warnUseBase: "use {.base.} for base methods; baseless methods are deprecated",
|
||||
|
||||
@@ -261,6 +261,10 @@ proc mainCommand*(graph: ModuleGraph) =
|
||||
if optGenIndex in conf.globalOptions and optWholeProject in conf.globalOptions:
|
||||
commandBuildIndex(conf, $conf.outDir)
|
||||
of cmdRst2html:
|
||||
# XXX: why are warnings disabled by default for rst2html and rst2tex?
|
||||
for warn in [warnUnknownSubstitutionX, warnLanguageXNotSupported,
|
||||
warnFieldXNotSupported, warnRstStyle]:
|
||||
conf.setNoteDefaults(warn, true)
|
||||
conf.setNoteDefaults(warnRedefinitionOfLabel, false) # similar to issue #13218
|
||||
when defined(leanCompiler):
|
||||
quit "compiler wasn't built with documentation generator"
|
||||
@@ -268,6 +272,10 @@ proc mainCommand*(graph: ModuleGraph) =
|
||||
loadConfigs(DocConfig, cache, conf, graph.idgen)
|
||||
commandRst2Html(cache, conf)
|
||||
of cmdRst2tex:
|
||||
for warn in [warnRedefinitionOfLabel, warnUnknownSubstitutionX,
|
||||
warnLanguageXNotSupported,
|
||||
warnFieldXNotSupported, warnRstStyle]:
|
||||
conf.setNoteDefaults(warn, true)
|
||||
when defined(leanCompiler):
|
||||
quit "compiler wasn't built with documentation generator"
|
||||
else:
|
||||
|
||||
@@ -77,7 +77,7 @@ the garbage collector with ``GC_enableMarkAndSweep`` and ``GC_disableMarkAndSwee
|
||||
|
||||
|
||||
Soft real-time support
|
||||
---------------------
|
||||
----------------------
|
||||
|
||||
To enable real-time support, the symbol `useRealtimeGC`:idx: needs to be
|
||||
defined via ``--define:useRealtimeGC`` (you can put this into your config
|
||||
|
||||
@@ -183,7 +183,7 @@ Usually we just track the result of an expression: probably this should apply fo
|
||||
Also related to tracking initialization of expressions/fields.
|
||||
|
||||
unstructured control flow rules
|
||||
-------------------------
|
||||
-------------------------------
|
||||
|
||||
Unstructured control flow keywords as ``return``, ``break``, ``continue``, ``raise`` mean that we jump from a branch out.
|
||||
This means that if there is code after the finishing of the branch, it would be ran if one hasn't hit the direct parent branch of those: so it is similar to an ``else``. In those cases we should use the reverse nilabilities for the local to the condition expressions. E.g.
|
||||
|
||||
@@ -154,7 +154,7 @@ but does nothing else. Here is an example of such a tree representation:
|
||||
|
||||
|
||||
Custom Semantic Checking
|
||||
-----------------------
|
||||
------------------------
|
||||
|
||||
The first thing that a macro should do with its arguments is to check
|
||||
if the argument is in the correct form. Not every type of wrong input
|
||||
|
||||
@@ -165,14 +165,15 @@ type
|
||||
meExpected = "'$1' expected",
|
||||
meGridTableNotImplemented = "grid table is not implemented",
|
||||
meMarkdownIllformedTable = "illformed delimiter row of a Markdown table",
|
||||
meNewSectionExpected = "new section expected",
|
||||
meNewSectionExpected = "new section expected $1",
|
||||
meGeneralParseError = "general parse error",
|
||||
meInvalidDirective = "invalid directive: '$1'",
|
||||
meFootnoteMismatch = "mismatch in number of footnotes and their refs: $1",
|
||||
mwRedefinitionOfLabel = "redefinition of label '$1'",
|
||||
mwUnknownSubstitution = "unknown substitution '$1'",
|
||||
mwUnsupportedLanguage = "language '$1' not supported",
|
||||
mwUnsupportedField = "field '$1' not supported"
|
||||
mwUnsupportedField = "field '$1' not supported",
|
||||
mwRstStyle = "RST style: $1"
|
||||
|
||||
MsgHandler* = proc (filename: string, line, col: int, msgKind: MsgKind,
|
||||
arg: string) {.closure, gcsafe.} ## what to do in case of an error
|
||||
@@ -1420,16 +1421,42 @@ proc tokenAfterNewline(p: RstParser): int =
|
||||
else: inc result
|
||||
|
||||
proc isAdornmentHeadline(p: RstParser, adornmentIdx: int): bool =
|
||||
## check that underline/overline length is enough for the heading.
|
||||
## No support for Unicode.
|
||||
if p.tok[adornmentIdx].symbol in ["::", "..", "|"]:
|
||||
return false
|
||||
var headlineLen = 0
|
||||
if p.idx < adornmentIdx: # underline
|
||||
var failure = ""
|
||||
if p.idx < adornmentIdx: # check for underline
|
||||
if p.idx > 0:
|
||||
headlineLen = currentTok(p).col - p.tok[adornmentIdx].col
|
||||
if headlineLen > 0:
|
||||
rstMessage(p, mwRstStyle, "indentation of heading text allowed" &
|
||||
" only for overline titles")
|
||||
for i in p.idx ..< adornmentIdx-1: # adornmentIdx-1 is a linebreak
|
||||
headlineLen += p.tok[i].symbol.len
|
||||
else: # overline
|
||||
result = p.tok[adornmentIdx].symbol.len >= headlineLen and headlineLen != 0
|
||||
if not result:
|
||||
failure = "(underline '" & p.tok[adornmentIdx].symbol & "' is too short)"
|
||||
else: # p.idx == adornmentIdx, at overline. Check overline and underline
|
||||
var i = p.idx + 2
|
||||
headlineLen = p.tok[i].col - p.tok[adornmentIdx].col
|
||||
while p.tok[i].kind notin {tkEof, tkIndent}:
|
||||
headlineLen += p.tok[i].symbol.len
|
||||
inc i
|
||||
return p.tok[adornmentIdx].symbol.len >= headlineLen
|
||||
result = p.tok[adornmentIdx].symbol.len >= headlineLen and
|
||||
headlineLen != 0
|
||||
if result:
|
||||
result = result and p.tok[i].kind == tkIndent and
|
||||
p.tok[i+1].kind == tkAdornment and
|
||||
p.tok[i+1].symbol == p.tok[adornmentIdx].symbol
|
||||
if not result:
|
||||
failure = "(underline '" & p.tok[i+1].symbol & "' does not match " &
|
||||
"overline '" & p.tok[adornmentIdx].symbol & "')"
|
||||
else:
|
||||
failure = "(overline '" & p.tok[adornmentIdx].symbol & "' is too short)"
|
||||
if not result:
|
||||
rstMessage(p, meNewSectionExpected, failure)
|
||||
|
||||
proc isLineBlock(p: RstParser): bool =
|
||||
var j = tokenAfterNewline(p)
|
||||
@@ -1941,7 +1968,7 @@ proc parseSection(p: var RstParser, result: PRstNode) =
|
||||
of rnLineBlock: a = parseLineBlock(p)
|
||||
of rnDirective: a = parseDotDot(p)
|
||||
of rnEnumList: a = parseEnumList(p)
|
||||
of rnLeaf: rstMessage(p, meNewSectionExpected)
|
||||
of rnLeaf: rstMessage(p, meNewSectionExpected, "(syntax error)")
|
||||
of rnParagraph: discard
|
||||
of rnDefList: a = parseDefinitionList(p)
|
||||
of rnFieldList:
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
## Another message
|
||||
##
|
||||
## Passing Channels Safely
|
||||
## ----------------------
|
||||
## -----------------------
|
||||
## Note that when passing objects to procedures on another thread by pointer
|
||||
## (for example through a thread's argument), objects created using the default
|
||||
## allocator will use thread-local, GC-managed memory. Thus it is generally
|
||||
|
||||
@@ -261,8 +261,8 @@ Wrong chapter
|
||||
------------
|
||||
|
||||
"""
|
||||
let output4 = rstToHtml(input4, {roSupportMarkdown}, defaultConfig())
|
||||
doAssert "Wrong chapter" in output4 and "<h1" notin output4
|
||||
expect(EParseError):
|
||||
let output4 = rstToHtml(input4, {roSupportMarkdown}, defaultConfig())
|
||||
|
||||
let input5 = """
|
||||
Check that punctuation after adornment and indent are not detected as adornment.
|
||||
@@ -281,6 +281,22 @@ Some chapter
|
||||
let output6 = rstToHtml(input6, {roSupportMarkdown}, defaultConfig())
|
||||
doAssert "<h1 id=\"some-chapter\">Some chapter</h1>" in output6
|
||||
|
||||
# check that overline and underline match
|
||||
let input7 = dedent """
|
||||
------------
|
||||
Some chapter
|
||||
-----------
|
||||
"""
|
||||
expect(EParseError):
|
||||
let output7 = rstToHtml(input7, {roSupportMarkdown}, defaultConfig())
|
||||
|
||||
let input8 = dedent """
|
||||
-----------
|
||||
Overflow
|
||||
-----------
|
||||
"""
|
||||
expect(EParseError):
|
||||
let output8 = rstToHtml(input8, {roSupportMarkdown}, defaultConfig())
|
||||
|
||||
test "RST links":
|
||||
let input1 = """
|
||||
@@ -308,8 +324,8 @@ This is too short to be a transition:
|
||||
|
||||
context2
|
||||
"""
|
||||
let output2 = rstToHtml(input2, {roSupportMarkdown}, defaultConfig())
|
||||
doAssert "<hr" notin output2
|
||||
expect(EParseError):
|
||||
let output2 = rstToHtml(input2, {roSupportMarkdown}, defaultConfig())
|
||||
|
||||
test "RST literal block":
|
||||
let input1 = """
|
||||
|
||||
Reference in New Issue
Block a user