From 18979a64c3ff7e7345e2fd5a81deee0e238779e4 Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Tue, 24 Jun 2025 13:56:28 -0700 Subject: [PATCH 01/14] ensure that all docs have code samples that are tested with a new CI check Signed-off-by: Jade Abraham --- modules/standard/Sort.chpl | 3 + util/buildRelease/smokeTest | 11 ++++ util/devel/lookForCodeBlocks | 123 +++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100755 util/devel/lookForCodeBlocks diff --git a/modules/standard/Sort.chpl b/modules/standard/Sort.chpl index 4bf606d1ab63..e7f46cea5cfe 100644 --- a/modules/standard/Sort.chpl +++ b/modules/standard/Sort.chpl @@ -105,6 +105,7 @@ array being sorted. The default key method would look like this: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel proc defaultComparator.key(elt) { @@ -125,6 +126,7 @@ operator, which is used by the base compare method of all sort routines. If the ``<`` operator is not defined for the return type, the user may define it themselves like so: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel operator <(x: returnType, y: returnType): bool { @@ -157,6 +159,7 @@ indicating how x and y compare to each other. The conditions between ``x`` and The default compare method for a signed integral type can look like this: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel proc defaultComparator.compare(x, y) { diff --git a/util/buildRelease/smokeTest b/util/buildRelease/smokeTest index b550da635a2d..ad06151a90e2 100755 --- a/util/buildRelease/smokeTest +++ b/util/buildRelease/smokeTest @@ -142,6 +142,17 @@ if [ $LINT -eq 1 ]; then exit 1 fi + # check that the docs have don't use literal .. code-block:: chpl + # TODO: improve the script so it does not have to ignore the spec explicitly + echo "Checking for literal .. code-block:: chpl" + $($CHPL_HOME/util/config/find-python.sh) \ + $CHPL_HOME/util/devel/lookForCodeBlocks modules doc/rst/ \ + --ignore doc/rst/language/spec + if [ $? -ne 0 ] ; then + echo "Found literal code blocks" + exit 1 + fi + # done with lint checks fi diff --git a/util/devel/lookForCodeBlocks b/util/devel/lookForCodeBlocks new file mode 100755 index 000000000000..c9b5d730e5cc --- /dev/null +++ b/util/devel/lookForCodeBlocks @@ -0,0 +1,123 @@ +#!/usr/bin/env python3 +import sys +import os +import glob +from itertools import chain +import pathlib +import argparse + + +def check_file(filename): + """ + Open a file and check for '.. code-block:: [chapel|chpl]' directives. + Return a list of tuples with the filename and linenumber + + if the previous line is '.. BLOCK-test-allowCodeBlock', then skip this line. + """ + code_blocks = [] + with open(filename, "rb") as fp: + lines = fp.readlines() + for linenum, line in enumerate(lines): + line = line.strip() + prevline = lines[linenum - 1].strip() if linenum > 0 else b"" + if ( + line.startswith(b".. code-block:: chapel") + or line.startswith(b".. code-block:: chpl") + ) and not prevline.startswith(b".. BLOCK-test-allowCodeBlock"): + code_blocks.append((filename, linenum + 1)) + + return code_blocks + + +def check_files(filenames): + result = chain.from_iterable(check_file(fn) for fn in filenames) + return sorted(result, key=lambda x: (x[0], x[1])) + + +def ignore_files(filenames, ignore_patterns=[]): + """ + filter out files that match any of the ignore patterns. + """ + if not ignore_patterns: + return filenames + + ignored_files = set() + for filename in filenames: + resolved_filename = pathlib.Path(filename).resolve() + for pattern in ignore_patterns: + if resolved_filename.is_relative_to(pattern): + ignored_files.add(filename) + if resolved_filename.match(pattern): + ignored_files.add(filename) + + return [fn for fn in filenames if fn not in ignored_files] + + +def get_gitignore_patterns(chplhome: pathlib.Path): + """ + Read the .gitignore file for the docs and return a list of patterns. + """ + + directory = chplhome / "doc" + gitignore_path = directory / ".gitignore" + if not gitignore_path.exists(): + patterns = [] + else: + with gitignore_path.open("r") as f: + patterns = [ + line.strip() + for line in f + if line.strip() and not line.startswith("#") + ] + + resolve_patterns = [] + for p in patterns: + if p.startswith("/"): + p = str(directory / p[1:]) + elif not p.startswith("*"): + p = str(directory / p) + resolve_patterns.append(p) + return resolve_patterns + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "files", + nargs="*", + help="Files or directories to check for code blocks. " + "If a directory is provided, all files in it will be checked.", + ) + parser.add_argument('--ignore', action='append', default=[], + help='Patterns to ignore, e.g., "*.rst" or "docs/*"') + + args = parser.parse_args() + filenames = [] + for a in args.files: + if os.path.isdir(a): + filenames.extend( + str(p) for p in pathlib.Path(a).rglob("*") if p.is_file() + ) + elif os.path.isfile(a): + filenames.append(a) + else: + filenames.extend(glob.glob(a, recursive=True)) + + chplhome = pathlib.Path(__file__).parent.parent.parent + ignore_patterns = get_gitignore_patterns(chplhome) + for p in args.ignore: + ignore_patterns.append(str(pathlib.Path(p).resolve())) + filenames = ignore_files(filenames, ignore_patterns) + + results = check_files(filenames) + if len(results) != 0: + print("Found plain code blocks!") + print("Please turn these into testable code blocks") + print(*(" {}:{}".format(*r) for r in results), sep="\n") + return 1 + else: + return 0 + + +if __name__ == "__main__": + exit(main()) From 826bff967daaf4d07f5a7ed63e9c62c9190bd0af Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Wed, 2 Jul 2025 09:11:44 -0700 Subject: [PATCH 02/14] add report function to extract-rst-tests Signed-off-by: Jade Abraham --- doc/util/extract-rst-tests.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/doc/util/extract-rst-tests.py b/doc/util/extract-rst-tests.py index df7240e236ba..053a1ebd2d32 100755 --- a/doc/util/extract-rst-tests.py +++ b/doc/util/extract-rst-tests.py @@ -13,6 +13,7 @@ import argparse import re +import json capture_space = re.compile(r"(\s*)\S.*") capture_chapter = re.compile(r"\s*.. _Chapter-([a-zA-Z0-9._-]+):\s*") @@ -29,6 +30,7 @@ match_prediff = re.compile(r"\s*.. BLOCK-test-chapelprediff\s*") match_function = re.compile(r"\s*.. function::\s*") total_tests = 0 +test_sources = dict() def get_arguments(): """ @@ -46,6 +48,8 @@ def get_arguments(): help='destination directory of output') parser.add_argument('--verbose', '-v', action='store_true', default=False, help='verbosity') + parser.add_argument('--report', type=str, default=None, + help='create a report of the tests found') return parser.parse_args() @@ -145,6 +149,7 @@ def extract_tests(rstfile, outdir): execopts = "" compopts = "" prediff = "" + code_block_lines = [] example_start = i-1 example_end = -1 @@ -227,12 +232,14 @@ def extract_tests(rstfile, outdir): # .. BLOCK-test-chapelpost # .. BLOCK-test-chapelpre elif re.match(match_code, line): + linenum = i (i, block) = read_block(lines, i) # Filter out request for line numbers if block.startswith(":linenos:"): block = block.replace(":linenos:", "", 1) chpl += block + code_block_lines += [linenum] #print ("Adding to chpl ", block) @@ -255,6 +262,12 @@ def extract_tests(rstfile, outdir): global total_tests total_tests += 1 + global test_sources + test_sources[os.path.abspath(f"{outdir}/{chapter}/{testname}.chpl")] = { + "rstfile": os.path.abspath(rstfile), + "lines": code_block_lines, + } + def main(**kwargs): """Driver function""" @@ -263,6 +276,10 @@ def main(**kwargs): rstfiles = kwargs['rstfiles'] output = kwargs['output'] verbose = kwargs['verbose'] + report = kwargs['report'] + + if report and os.path.exists(report): + os.remove(report) for rstfile in rstfiles: if os.path.isfile(rstfile): @@ -275,6 +292,11 @@ def main(**kwargs): else: print("File not found ", rstfile) + if report: + global test_sources + with open(report, 'w') as fp: + json.dump(test_sources, fp, indent=2) + global total_tests print("DONE - created", total_tests, "tests") From 1e83c032445d69144ac1ae27e16a0b68cc4adffc Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Wed, 2 Jul 2025 09:12:00 -0700 Subject: [PATCH 03/14] allow lookForCodeBlocks to read spec report Signed-off-by: Jade Abraham --- util/devel/lookForCodeBlocks | 64 +++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/util/devel/lookForCodeBlocks b/util/devel/lookForCodeBlocks index c9b5d730e5cc..54fd017f5ae9 100755 --- a/util/devel/lookForCodeBlocks +++ b/util/devel/lookForCodeBlocks @@ -4,10 +4,13 @@ import os import glob from itertools import chain import pathlib +from pathlib import Path import argparse +import re +import json -def check_file(filename): +def check_file(filename, reports): """ Open a file and check for '.. code-block:: [chapel|chpl]' directives. Return a list of tuples with the filename and linenumber @@ -20,17 +23,21 @@ def check_file(filename): for linenum, line in enumerate(lines): line = line.strip() prevline = lines[linenum - 1].strip() if linenum > 0 else b"" - if ( - line.startswith(b".. code-block:: chapel") - or line.startswith(b".. code-block:: chpl") - ) and not prevline.startswith(b".. BLOCK-test-allowCodeBlock"): + is_code_block = line.startswith( + b".. code-block:: chapel" + ) or line.startswith(b".. code-block:: chpl") + is_allowed = prevline.startswith(b".. BLOCK-test-allowCodeBlock") + is_in_report = any( + r.contains(filename, linenum + 1) for r in reports + ) + if is_code_block and not is_allowed and not is_in_report: code_blocks.append((filename, linenum + 1)) return code_blocks -def check_files(filenames): - result = chain.from_iterable(check_file(fn) for fn in filenames) +def check_files(filenames, reports): + result = chain.from_iterable(check_file(fn, reports) for fn in filenames) return sorted(result, key=lambda x: (x[0], x[1])) @@ -80,16 +87,43 @@ def get_gitignore_patterns(chplhome: pathlib.Path): return resolve_patterns +class CreatedTestReport: + def __init__(self, report_file): + self.report_file = report_file + self.report = json.loads(self.report_file.read_text()) + self.lines_per_rst = {} + for entry in self.report.values(): + rstfile = entry["rstfile"] + if rstfile not in self.lines_per_rst: + self.lines_per_rst[rstfile] = set() + self.lines_per_rst[rstfile].update(entry["lines"]) + + def contains(self, file, line): + p = str(pathlib.Path(file).resolve()) + r = line in self.lines_per_rst.get(p, set()) + return r + + def main(): parser = argparse.ArgumentParser() parser.add_argument( "files", nargs="*", help="Files or directories to check for code blocks. " - "If a directory is provided, all files in it will be checked.", + "If a directory is provided, all files in it will be checked.", + ) + parser.add_argument( + "--ignore", + action="append", + default=[], + help='Patterns to ignore, e.g., "*.rst" or "docs/*"', + ) + parser.add_argument( + "--read-report", + action="append", + default=[], + help="Read a report file of created tests and use it to check if docs are tested", ) - parser.add_argument('--ignore', action='append', default=[], - help='Patterns to ignore, e.g., "*.rst" or "docs/*"') args = parser.parse_args() filenames = [] @@ -109,7 +143,15 @@ def main(): ignore_patterns.append(str(pathlib.Path(p).resolve())) filenames = ignore_files(filenames, ignore_patterns) - results = check_files(filenames) + reports = [] + for report_file in args.read_report: + report_file = pathlib.Path(report_file) + if not report_file.exists(): + print(f"Report file {report_file} does not exist, skipping") + continue + reports.append(CreatedTestReport(report_file)) + + results = check_files(filenames, reports) if len(results) != 0: print("Found plain code blocks!") print("Please turn these into testable code blocks") From a5ddfa4e1925ef4c686fa401853ca997c66913b2 Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Wed, 2 Jul 2025 09:12:09 -0700 Subject: [PATCH 04/14] update smoketest Signed-off-by: Jade Abraham --- util/buildRelease/smokeTest | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/util/buildRelease/smokeTest b/util/buildRelease/smokeTest index ad06151a90e2..150342231c17 100755 --- a/util/buildRelease/smokeTest +++ b/util/buildRelease/smokeTest @@ -143,11 +143,11 @@ if [ $LINT -eq 1 ]; then fi # check that the docs have don't use literal .. code-block:: chpl - # TODO: improve the script so it does not have to ignore the spec explicitly - echo "Checking for literal .. code-block:: chpl" + echo "Checking for literal '.. code-block:: chpl'" + make $chpl_make_args spectests >/dev/null 2>/dev/null || exit 1 $($CHPL_HOME/util/config/find-python.sh) \ $CHPL_HOME/util/devel/lookForCodeBlocks modules doc/rst/ \ - --ignore doc/rst/language/spec + --read-report $CHPL_HOME/examples/spec/report.json if [ $? -ne 0 ] ; then echo "Found literal code blocks" exit 1 From 8ab6a95d6afb5b3638128de6188ce1d3ba6728c8 Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Wed, 2 Jul 2025 13:49:26 -0700 Subject: [PATCH 05/14] always generate report Signed-off-by: Jade Abraham --- Makefile.devel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.devel b/Makefile.devel index 633efad3773d..f453a7c5b0f4 100644 --- a/Makefile.devel +++ b/Makefile.devel @@ -103,4 +103,4 @@ run-dyno-linters: run-frontend-linters FORCE SPECTEST_DIR = ./test/release/examples/spec spectests: FORCE rm -rf $(SPECTEST_DIR) - doc/util/extract-rst-tests.py doc/rst/language/spec/ --output $(SPECTEST_DIR) + doc/util/extract-rst-tests.py doc/rst/language/spec/ --output $(SPECTEST_DIR) --report $(SPECTEST_DIR)/report.json From f59950bccba0dc18f39c03ae6eca5b909a322785 Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Wed, 9 Jul 2025 09:56:28 -0700 Subject: [PATCH 06/14] ignore developer docs Signed-off-by: Jade Abraham --- util/buildRelease/smokeTest | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/util/buildRelease/smokeTest b/util/buildRelease/smokeTest index 150342231c17..dd65febca5f1 100755 --- a/util/buildRelease/smokeTest +++ b/util/buildRelease/smokeTest @@ -147,7 +147,8 @@ if [ $LINT -eq 1 ]; then make $chpl_make_args spectests >/dev/null 2>/dev/null || exit 1 $($CHPL_HOME/util/config/find-python.sh) \ $CHPL_HOME/util/devel/lookForCodeBlocks modules doc/rst/ \ - --read-report $CHPL_HOME/examples/spec/report.json + --read-report $CHPL_HOME/examples/spec/report.json \ + --ignore doc/rst/developer if [ $? -ne 0 ] ; then echo "Found literal code blocks" exit 1 From d0e032dc1251dca435a6aee6fc81ab29f82fdbf1 Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Wed, 9 Jul 2025 10:04:56 -0700 Subject: [PATCH 07/14] add a whole bunch of .. BLOCK-test-allowCodeBlock Signed-off-by: Jade Abraham --- doc/rst/language/spec/expressions.rst | 21 +++++++++++++++++---- doc/rst/language/spec/locales.rst | 1 + doc/rst/language/spec/methods.rst | 1 + doc/rst/language/spec/ranges.rst | 1 + doc/rst/language/spec/records.rst | 2 +- doc/rst/language/spec/statements.rst | 2 +- doc/rst/language/spec/tuples.rst | 6 ++++-- doc/rst/technotes/subquery.rst | 6 ++++++ 8 files changed, 32 insertions(+), 8 deletions(-) diff --git a/doc/rst/language/spec/expressions.rst b/doc/rst/language/spec/expressions.rst index da4c0f02ab33..edbacc5c5a40 100644 --- a/doc/rst/language/spec/expressions.rst +++ b/doc/rst/language/spec/expressions.rst @@ -603,6 +603,7 @@ Unary Plus Operators The unary plus operators are predefined as follows: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel operator +(a: int(8)): int(8) @@ -637,6 +638,7 @@ Unary Minus Operators The unary minus operators are predefined as follows: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel operator -(a: int(8)): int(8) @@ -673,6 +675,7 @@ Addition Operators The addition operators are predefined as follows: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel operator +(a: int(8), b: int(8)): int(8) @@ -731,6 +734,7 @@ Subtraction Operators The subtraction operators are predefined as follows: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel operator -(a: int(8), b: int(8)): int(8) @@ -786,6 +790,7 @@ Multiplication Operators The multiplication operators are predefined as follows: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel operator *(a: int(8), b: int(8)): int(8) @@ -842,6 +847,7 @@ Division Operators The division operators are predefined as follows: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel operator /(a: int(8), b: int(8)): int(8) @@ -904,6 +910,7 @@ Modulus Operators The modulus operators are predefined as follows: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel operator %(a: int(8), b: int(8)): int(8) @@ -1182,8 +1189,7 @@ The Logical Negation Operator The logical negation operator is predefined for booleans and integers as follows: - - +.. BLOCK-test-allowCodeBlock .. code-block:: chapel operator !(a: bool): bool @@ -1296,6 +1302,7 @@ Ordered Comparison Operators The “less than” comparison operators are predefined over numeric types as follows: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel operator <(a: int(8), b: int(8)): bool @@ -1320,6 +1327,7 @@ the result is false. The “greater than” comparison operators are predefined over numeric types as follows: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel operator >(a: int(8), b: int(8)): bool @@ -1344,6 +1352,7 @@ otherwise the result is false. The “less than or equal to” comparison operators are predefined over numeric types as follows: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel operator <=(a: int(8), b: int(8)): bool @@ -1368,6 +1377,7 @@ The result of ``a <= b`` is true if ``a`` is less than or equal to The “greater than or equal to” comparison operators are predefined over numeric types as follows: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel operator >=(a: int(8), b: int(8)): bool @@ -1392,6 +1402,7 @@ The result of ``a >= b`` is true if ``a`` is greater than or equal to The ordered comparison operators are predefined over strings as follows: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel operator <(a: string, b: string): bool @@ -1422,6 +1433,7 @@ Equality Comparison Operators The equality comparison operators ``==`` and ``!=`` are predefined over bool and the numeric types as follows: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel operator ==(a: int(8), b: int(8)): bool @@ -1475,6 +1487,7 @@ equivalent to ``!(a == b)``. The equality comparison operators are predefined over classes as follows: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel operator ==(a: RootClass, b: RootClass): bool @@ -1491,6 +1504,7 @@ in :ref:`Record_Comparison_Operators`. The equality comparison operators are predefined over strings as follows: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel operator ==(a: string, b: string): bool @@ -1537,8 +1551,7 @@ The string concatenation operator ``+`` is predefined for string arguments and returns a new string that is the concatenation of its arguments: - - +.. BLOCK-test-allowCodeBlock .. code-block:: chapel operator +(s0: string, s1: string): string diff --git a/doc/rst/language/spec/locales.rst b/doc/rst/language/spec/locales.rst index 992c927676ba..8abcc5166710 100644 --- a/doc/rst/language/spec/locales.rst +++ b/doc/rst/language/spec/locales.rst @@ -78,6 +78,7 @@ contains definitions for the array of locales on which the program is executing (``Locales``), a domain for that array (``LocaleSpace``), and the number of locales (``numLocales``). +.. BLOCK-test-allowCodeBlock .. code-block:: chapel config const numLocales: int; diff --git a/doc/rst/language/spec/methods.rst b/doc/rst/language/spec/methods.rst index a73591c353ef..5c0d66ad07b1 100644 --- a/doc/rst/language/spec/methods.rst +++ b/doc/rst/language/spec/methods.rst @@ -440,6 +440,7 @@ Operators may be overloaded (see :ref:`Function_Overloading`) to support new behavior on one or more types using the ``operator`` keyword. Such overloads may be defined as standalone functions, e.g. +.. BLOCK-test-allowCodeBlock .. code-block:: chapel operator +(lhs: t1, rhs: t2) { ... } diff --git a/doc/rst/language/spec/ranges.rst b/doc/rst/language/spec/ranges.rst index 5bf5b7014cbc..ee20513c3a8d 100644 --- a/doc/rst/language/spec/ranges.rst +++ b/doc/rst/language/spec/ranges.rst @@ -938,6 +938,7 @@ Arithmetic Operators The following arithmetic operators are defined on ranges and integral types: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel proc +(r: range, s: integral): range diff --git a/doc/rst/language/spec/records.rst b/doc/rst/language/spec/records.rst index 74ad7322d460..05b7d6d60b73 100644 --- a/doc/rst/language/spec/records.rst +++ b/doc/rst/language/spec/records.rst @@ -764,7 +764,7 @@ records if none are explicitly defined. ``==`` and ``!=`` functions have the following signatures for a record ``R``: - +.. BLOCK-test-allowCodeBlock .. code-block:: chapel operator ==(lhs:R, rhs:R) : bool where lhs.type == rhs.type; diff --git a/doc/rst/language/spec/statements.rst b/doc/rst/language/spec/statements.rst index 2b3c384fe15b..6b3eb75327c8 100644 --- a/doc/rst/language/spec/statements.rst +++ b/doc/rst/language/spec/statements.rst @@ -214,7 +214,7 @@ For all other compound assignments, Chapel provides a completely generic catch-all implementation defined in the obvious way. For example: - +.. BLOCK-test-allowCodeBlock .. code-block:: chapel inline proc +=(ref lhs, rhs) { diff --git a/doc/rst/language/spec/tuples.rst b/doc/rst/language/spec/tuples.rst index 079e24960aa3..cdabe8a01f4a 100644 --- a/doc/rst/language/spec/tuples.rst +++ b/doc/rst/language/spec/tuples.rst @@ -261,7 +261,7 @@ and ``coforall`` loops. These loops iterate over all of the tuple’s elements. A loop of the form: - +.. BLOCK-test-allowCodeBlock .. code-block:: chapel [for|forall|coforall] e in t do @@ -271,7 +271,7 @@ where t is a homogeneous tuple of size ``n``, is semantically equivalent to: - +.. BLOCK-test-allowCodeBlock .. code-block:: chapel [for|forall|coforall] i in 0..n-1 do @@ -288,6 +288,7 @@ elements, giving each iteration its own index variable that is a future to include ``const`` or ``ref`` index variables). Thus, a loop of the form: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel for e in t do @@ -296,6 +297,7 @@ loop of the form: where t is a heterogeneous tuple of size ``n`` is semantically equivalent to: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel { // iteration 0 diff --git a/doc/rst/technotes/subquery.rst b/doc/rst/technotes/subquery.rst index 7f83cacb461b..afa10a4013a6 100644 --- a/doc/rst/technotes/subquery.rst +++ b/doc/rst/technotes/subquery.rst @@ -19,6 +19,7 @@ Functions Supported on Array and Domain Types hasSingleLocalSubdomain ----------------------- +.. BLOCK-test-allowCodeBlock .. code-block:: chapel proc array.hasSingleLocalSubdomain() : bool; @@ -44,6 +45,7 @@ To support this function on a custom domain map, write a param function named localSubdomain -------------- +.. BLOCK-test-allowCodeBlock .. code-block:: chapel proc array.localSubdomain(loc: locale = here) : domain; @@ -60,6 +62,7 @@ used to modify the index set owned by the locale. To support this function on a custom domain map, write a function named ``dsiLocalSubdomain``. For example: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel proc BlockArr.dsiLocalSubdomain(loc: locale) : domain; @@ -67,6 +70,7 @@ To support this function on a custom domain map, write a function named localSubdomains --------------- +.. BLOCK-test-allowCodeBlock .. code-block:: chapel iter array.localSubdomains(loc: locale = here) : domain; @@ -83,6 +87,7 @@ Currently, this is a serial iterator. To support this iterator on a custom domain map, write an iterator named ``dsiLocalSubdomains``. For example: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel iter BlockCyclicArr.dsiLocalSubdomains(loc: locale) : domain; @@ -93,6 +98,7 @@ Functions Supported on Arrays, Domains, and Distributions targetLocales ------------- +.. BLOCK-test-allowCodeBlock .. code-block:: chapel proc array.targetLocales() : [] locale; From 6a3a0bde3f64334de35b633e4627ba640dee78f7 Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Wed, 9 Jul 2025 10:30:51 -0700 Subject: [PATCH 08/14] ignore evolution Signed-off-by: Jade Abraham --- util/buildRelease/smokeTest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/buildRelease/smokeTest b/util/buildRelease/smokeTest index dd65febca5f1..d090f4b7fd56 100755 --- a/util/buildRelease/smokeTest +++ b/util/buildRelease/smokeTest @@ -148,7 +148,7 @@ if [ $LINT -eq 1 ]; then $($CHPL_HOME/util/config/find-python.sh) \ $CHPL_HOME/util/devel/lookForCodeBlocks modules doc/rst/ \ --read-report $CHPL_HOME/examples/spec/report.json \ - --ignore doc/rst/developer + --ignore doc/rst/developer --ignore doc/rst/language/evolution.rst if [ $? -ne 0 ] ; then echo "Found literal code blocks" exit 1 From dda57c994dc9e8359164b5f5e8cdeb33feff2a60 Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Tue, 26 Aug 2025 08:55:49 -0700 Subject: [PATCH 09/14] dont test code in deprecated module Signed-off-by: Jade Abraham --- modules/packages/HDFS.chpl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/packages/HDFS.chpl b/modules/packages/HDFS.chpl index b9324f1b0897..7e9a955033fc 100644 --- a/modules/packages/HDFS.chpl +++ b/modules/packages/HDFS.chpl @@ -35,6 +35,7 @@ Using HDFS Support in Chapel To open an HDFS file in Chapel, first create an :class:`HDFSFileSystem` by connecting to an HDFS name node. +.. BLOCK-test-allowCodeBlock .. code-block:: chapel import HDFS; @@ -49,6 +50,7 @@ Once you have a :record:`hdfs`, you can open files within that filesystem using :proc:`HDFSFileSystem.open` and perform I/O on them using the usual functionality in the :mod:`IO` module: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel var f = fs.open("/tmp/testfile.txt", ioMode.cw); From d90c9db2b0dc487dadd31d33d855c80ba4d51077 Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Tue, 26 Aug 2025 08:56:03 -0700 Subject: [PATCH 10/14] dont test code in deprecated module Signed-off-by: Jade Abraham --- modules/packages/DistributedBagDeprecated.chpl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/packages/DistributedBagDeprecated.chpl b/modules/packages/DistributedBagDeprecated.chpl index f24b24b7457e..ddd2bce89e0c 100644 --- a/modules/packages/DistributedBagDeprecated.chpl +++ b/modules/packages/DistributedBagDeprecated.chpl @@ -88,6 +88,7 @@ properly initialize the structure. Using the default state without initializing will result in a halt. + .. BLOCK-test-allowCodeBlock .. code-block:: chapel var bag = new DistBag(int, targetLocales=ourTargetLocales); @@ -99,6 +100,7 @@ desired, and likely will more memory consumption on a single node. We offer a way for the user to invoke a more static load balancing approach, called :proc:`DistributedBagImpl.balance`, which will redistributed work. + .. BLOCK-test-allowCodeBlock .. code-block:: chapel bag.addBulk(1..N); From a1f20ef4b20a5a20e072ac78a5b361d1c9fab106 Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Tue, 26 Aug 2025 08:57:48 -0700 Subject: [PATCH 11/14] ignore a bunch of code that should not be tested Signed-off-by: Jade Abraham --- modules/dists/BlockCycDist.chpl | 1 + modules/dists/BlockDist.chpl | 1 + modules/dists/CyclicDist.chpl | 1 + modules/dists/HashedDist.chpl | 1 + modules/dists/PrivateDist.chpl | 1 + modules/dists/ReplicatedDist.chpl | 1 + modules/dists/StencilDist.chpl | 1 + modules/dists/dims/BlockCycDim.chpl | 1 + modules/dists/dims/BlockDim.chpl | 1 + modules/dists/dims/ReplicatedDim.chpl | 1 + 10 files changed, 10 insertions(+) diff --git a/modules/dists/BlockCycDist.chpl b/modules/dists/BlockCycDist.chpl index 734fe46b4ac1..3e78522b0f38 100644 --- a/modules/dists/BlockCycDist.chpl +++ b/modules/dists/BlockCycDist.chpl @@ -118,6 +118,7 @@ When run on 6 locales, the output is: The ``blockCycDist`` initializer is defined as follows: + .. BLOCK-test-allowCodeBlock .. code-block:: chapel proc blockCycDist.init( diff --git a/modules/dists/BlockDist.chpl b/modules/dists/BlockDist.chpl index b746241f5790..f583eb4ba177 100644 --- a/modules/dists/BlockDist.chpl +++ b/modules/dists/BlockDist.chpl @@ -214,6 +214,7 @@ as possible between those tasks. The ``blockDist`` initializer is defined as follows: + .. BLOCK-test-allowCodeBlock .. code-block:: chapel proc blockDist.init( diff --git a/modules/dists/CyclicDist.chpl b/modules/dists/CyclicDist.chpl index 664edd337bb1..990ea4b0bfa2 100644 --- a/modules/dists/CyclicDist.chpl +++ b/modules/dists/CyclicDist.chpl @@ -123,6 +123,7 @@ as evenly as possible between those tasks. The ``cyclicDist`` initializer is defined as follows: + .. BLOCK-test-allowCodeBlock .. code-block:: chapel proc cyclicDist.init( diff --git a/modules/dists/HashedDist.chpl b/modules/dists/HashedDist.chpl index 553a71be908d..5575c44be6f2 100644 --- a/modules/dists/HashedDist.chpl +++ b/modules/dists/HashedDist.chpl @@ -100,6 +100,7 @@ When run on 6 locales, the output is: The ``hashedDist`` domain map initializer is defined as follows: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel proc init(type idxType, diff --git a/modules/dists/PrivateDist.chpl b/modules/dists/PrivateDist.chpl index 01812c12c321..f2a16b459a00 100644 --- a/modules/dists/PrivateDist.chpl +++ b/modules/dists/PrivateDist.chpl @@ -42,6 +42,7 @@ This module declares a module-level constant of type ``privateDist`` named ``PrivateSpace`` for use as a convenience (so that user programs do not need to declare their own). + .. BLOCK-test-allowCodeBlock .. code-block:: chapel const PrivateSpace: domain(1) dmapped new privateDist(); diff --git a/modules/dists/ReplicatedDist.chpl b/modules/dists/ReplicatedDist.chpl index a3dfadf49bbf..1593fad6384b 100644 --- a/modules/dists/ReplicatedDist.chpl +++ b/modules/dists/ReplicatedDist.chpl @@ -92,6 +92,7 @@ distribution. The ``replicatedDist`` initializer is defined as follows: + .. BLOCK-test-allowCodeBlock .. code-block:: chapel proc replicatedDist.init( diff --git a/modules/dists/StencilDist.chpl b/modules/dists/StencilDist.chpl index 7480795b56a0..6756dde102ea 100644 --- a/modules/dists/StencilDist.chpl +++ b/modules/dists/StencilDist.chpl @@ -156,6 +156,7 @@ config param disableStencilLazyRAD = defaultDisableLazyRADOpt; The ``stencilDist`` initializer is defined as follows: + .. BLOCK-test-allowCodeBlock .. code-block:: chapel proc stencilDist.init( diff --git a/modules/dists/dims/BlockCycDim.chpl b/modules/dists/dims/BlockCycDim.chpl index 28452a1cfa97..17aeec3867f3 100644 --- a/modules/dists/dims/BlockCycDim.chpl +++ b/modules/dists/dims/BlockCycDim.chpl @@ -54,6 +54,7 @@ that would be produced by a 1D :class:`~BlockCycDist.blockCycDist` distribution. The ``BlockCyclicDim`` record initializer is defined as follows: + .. BLOCK-test-allowCodeBlock .. code-block:: chapel proc init( diff --git a/modules/dists/dims/BlockDim.chpl b/modules/dists/dims/BlockDim.chpl index 0c6cac3f8282..5d9365e95d47 100644 --- a/modules/dists/dims/BlockDim.chpl +++ b/modules/dists/dims/BlockDim.chpl @@ -40,6 +40,7 @@ that would be produced by a 1D :class:`~BlockDist.blockDist` distribution. The following ``BlockDim`` record initializers are available: + .. BLOCK-test-allowCodeBlock .. code-block:: chapel proc BlockDim.init( diff --git a/modules/dists/dims/ReplicatedDim.chpl b/modules/dists/dims/ReplicatedDim.chpl index 17f88efcdb04..1e1b9cba1925 100644 --- a/modules/dists/dims/ReplicatedDim.chpl +++ b/modules/dists/dims/ReplicatedDim.chpl @@ -46,6 +46,7 @@ distribution accesses all replicands in certain cases, as specified there. The ``ReplicatedDim`` record initializer is available as follows: + .. BLOCK-test-allowCodeBlock .. code-block:: chapel proc ReplicatedDim.init(numLocales:int) From 620d6fbeb7c7e40ae8e0ec3629c8a76516257751 Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Tue, 26 Aug 2025 08:58:04 -0700 Subject: [PATCH 12/14] ignore spec code that does not need to be tested Signed-off-by: Jade Abraham --- doc/rst/language/spec/arrays.rst | 4 ++++ doc/rst/language/spec/data-parallelism.rst | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/doc/rst/language/spec/arrays.rst b/doc/rst/language/spec/arrays.rst index 8b5205f1e545..81c58aae86ba 100644 --- a/doc/rst/language/spec/arrays.rst +++ b/doc/rst/language/spec/arrays.rst @@ -567,6 +567,7 @@ as described by its domain. A loop of the form: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel [for|forall|coforall] a in A do @@ -576,6 +577,7 @@ is semantically equivalent to: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel [for|forall|coforall] i in A.domain do @@ -1111,6 +1113,7 @@ set manipulations. The supported set operators are: Consider the following code where ``A`` and ``B`` are associative arrays: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel var C = A op B; @@ -1122,6 +1125,7 @@ There are also ``op=`` variants that store the result into the first operand. Consider the following code where ``A`` and ``B`` are associative arrays: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel A op= B; diff --git a/doc/rst/language/spec/data-parallelism.rst b/doc/rst/language/spec/data-parallelism.rst index 02ad2fc65157..016423bb693e 100644 --- a/doc/rst/language/spec/data-parallelism.rst +++ b/doc/rst/language/spec/data-parallelism.rst @@ -235,6 +235,7 @@ of the loop, and yields each resulting value. When a forall expression is used to initialize a variable, such as +.. BLOCK-test-allowCodeBlock .. code-block:: chapel var X = forall iterableExpression() do computeValue(); @@ -710,12 +711,14 @@ Consider a function ``f`` with formal arguments ``s1``, ``s2``, ... that are promoted and formal arguments ``a1``, ``a2``, ... that are not promoted. The call +.. BLOCK-test-allowCodeBlock .. code-block:: chapel f(s1, s2, ..., a1, a2, ...) is equivalent to +.. BLOCK-test-allowCodeBlock .. code-block:: chapel [(e1, e2, ...) in zip(s1, s2, ...)] f(e1, e2, ..., a1, a2, ...) @@ -726,12 +729,14 @@ the promoted actuals must have the same shape. Formal arguments that are not promoted are evaluated once and stored in a temporary variable. If formal ``a1`` is an expression, then the call +.. BLOCK-test-allowCodeBlock .. code-block:: chapel f(s1, s2, ..., a1, a2, ...) is equivalent to +.. BLOCK-test-allowCodeBlock .. code-block:: chapel var tmp = a1; @@ -785,12 +790,14 @@ rather than functions. Whole array assignment is one example. It is is implicitly parallel. The array assignment statement: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel LHS = RHS; is equivalent to +.. BLOCK-test-allowCodeBlock .. code-block:: chapel forall (e1,e2) in zip(LHS,RHS) do From 86ef09099b5f3b3b26233d4eaeebd5e144a71dba Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Tue, 26 Aug 2025 09:06:11 -0700 Subject: [PATCH 13/14] more ignores for code blocks Signed-off-by: Jade Abraham --- doc/rst/language/spec/data-parallelism.rst | 1 - doc/rst/technotes/dsi.rst | 9 +++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/doc/rst/language/spec/data-parallelism.rst b/doc/rst/language/spec/data-parallelism.rst index 016423bb693e..2d2b2b564687 100644 --- a/doc/rst/language/spec/data-parallelism.rst +++ b/doc/rst/language/spec/data-parallelism.rst @@ -235,7 +235,6 @@ of the loop, and yields each resulting value. When a forall expression is used to initialize a variable, such as -.. BLOCK-test-allowCodeBlock .. code-block:: chapel var X = forall iterableExpression() do computeValue(); diff --git a/doc/rst/technotes/dsi.rst b/doc/rst/technotes/dsi.rst index 3bac824a8972..cdba3a48c0ba 100644 --- a/doc/rst/technotes/dsi.rst +++ b/doc/rst/technotes/dsi.rst @@ -173,6 +173,7 @@ class ``GlobalDomain`` .. class:: GlobalDomain + .. BLOCK-test-allowCodeBlock .. code-block:: chapel class GlobalDomain: BaseRectangularDom { @@ -231,6 +232,7 @@ class ``GlobalDomain`` The same as the other ``dsiSetIndices``. Could be implemented like this: + .. BLOCK-test-allowCodeBlock .. code-block:: chapel { dsiSetIndices([(...rangesArg)]); } @@ -426,6 +428,7 @@ class ``GlobalArray`` The DSI requirements apply to each of those classes. Here ``GlobalArray`` refers to each such class. + .. BLOCK-test-allowCodeBlock .. code-block:: chapel class GlobalArray ... { @@ -727,6 +730,7 @@ class that chooses to support privatization. NOTE: do not specify the return type (due to a bug in the compiler). +.. BLOCK-test-allowCodeBlock .. code-block:: chapel class Global ... { @@ -845,9 +849,10 @@ the former needs to reference a privatized copy of the latter. To obtain a privatized copy of an object, e.g. for use within ``dsiPrivatize()``, use the following procedure: - .. code-block:: chapel +.. BLOCK-test-allowCodeBlock +.. code-block:: chapel - proc chpl_getPrivatizedCopy(type objectType, objectPid:int): objectType + proc chpl_getPrivatizedCopy(type objectType, objectPid:int): objectType Notes: From 50ca4b492d18f3d32effb8214dc9872909d3d21c Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Tue, 26 Aug 2025 09:14:42 -0700 Subject: [PATCH 14/14] add more ignores Signed-off-by: Jade Abraham --- doc/rst/tools/chpldoc/chpldoc.rst | 2 ++ modules/packages/UnitTest.chpl | 2 ++ modules/standard/GMP.chpl | 1 + 3 files changed, 5 insertions(+) diff --git a/doc/rst/tools/chpldoc/chpldoc.rst b/doc/rst/tools/chpldoc/chpldoc.rst index 08f6308d1159..5a0758f8300c 100644 --- a/doc/rst/tools/chpldoc/chpldoc.rst +++ b/doc/rst/tools/chpldoc/chpldoc.rst @@ -225,6 +225,7 @@ Stifling documentation To mark a particular symbol to not be output as part of the documentation, preface the symbol with the attribute ``@chpldoc.nodoc``. For example: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel @chpldoc.nodoc @@ -232,6 +233,7 @@ preface the symbol with the attribute ``@chpldoc.nodoc``. For example: Private symbols are not documented by default. +.. BLOCK-test-allowCodeBlock .. code-block:: chapel private proc foo() { ... } diff --git a/modules/packages/UnitTest.chpl b/modules/packages/UnitTest.chpl index ef8a4b631d85..ef9afbc84bf0 100644 --- a/modules/packages/UnitTest.chpl +++ b/modules/packages/UnitTest.chpl @@ -27,6 +27,7 @@ automates execution of any test function. A unit test function is defined as any function with the following signature: +.. BLOCK-test-allowCodeBlock .. code-block:: chapel proc funcName(test: borrowed Test) throws {} @@ -1228,6 +1229,7 @@ module UnitTest { Call this as + .. BLOCK-test-allowCodeBlock .. code-block:: chapel UnitTest.main(); diff --git a/modules/standard/GMP.chpl b/modules/standard/GMP.chpl index 0f0cc2540c9b..82431a4a88ea 100644 --- a/modules/standard/GMP.chpl +++ b/modules/standard/GMP.chpl @@ -58,6 +58,7 @@ Step 1: Step 2: Have your Chapel program ``use`` the standard GMP module + .. BLOCK-test-allowCodeBlock .. code-block:: chapel use GMP; // put this statement in your Chapel program