diff --git a/scripts/isolate_tests.py b/scripts/isolate_tests.py index 67234ac1b..ef755e699 100755 --- a/scripts/isolate_tests.py +++ b/scripts/isolate_tests.py @@ -38,19 +38,34 @@ def extract_test_cases(path): # Look for `pragma solidity`, `contract`, `library` or `interface` # and abort a line not indented properly. def extract_docs_cases(path): - inside = False + insideBlock = False + insideBlockParameters = False + pastBlockParameters = False extractedLines = [] tests = [] # Collect all snippets of indented blocks for l in open(path, mode='r', errors='ignore', encoding='utf8', newline='').read().splitlines(): if l != '': - if not inside and l.startswith(' '): + if not insideBlock and l.startswith(' '): # start new test extractedLines += [''] - inside = l.startswith(' ') - if inside: - extractedLines[-1] += l + '\n' + insideBlockParameters = False + pastBlockParameters = False + insideBlock = l.startswith(' ') + if insideBlock: + if not pastBlockParameters: + # NOTE: For simplicity this allows blank lines between block parameters even + # though Sphinx does not. This does not matter since the first non-empty line in + # a Solidity file cannot start with a colon anyway. + if not l.strip().startswith(':') and (l != '' or not insideBlockParameters): + insideBlockParameters = False + pastBlockParameters = True + else: + insideBlockParameters = True + + if not insideBlockParameters: + extractedLines[-1] += l + '\n' codeStart = "(// SPDX-License-Identifier:|pragma solidity|contract.*{|library.*{|interface.*{)" diff --git a/test/scripts/fixtures/code_block.rst b/test/scripts/fixtures/code_block.rst new file mode 100644 index 000000000..f97967b93 --- /dev/null +++ b/test/scripts/fixtures/code_block.rst @@ -0,0 +1,22 @@ +Some text + + +.. code-block:: solidity + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity >=0.7.0 <0.9.0; + + contract C { + function foo() public view {} + } + + +.. warning:: + + A Warning. + +:: + + contract C {} + +More text. diff --git a/test/scripts/fixtures/code_block_with_directives.rst b/test/scripts/fixtures/code_block_with_directives.rst new file mode 100644 index 000000000..ff52d5b0e --- /dev/null +++ b/test/scripts/fixtures/code_block_with_directives.rst @@ -0,0 +1,48 @@ +A normal block with parameters. + +.. code-block:: solidity + :force: + :language: Solidity + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity >=0.7.0 <0.9.0; + + contract C { + function foo() public view {} + } + + +.. warning:: + A Warning. + +.. code-block:: solidity + + uint constant x = 42; + +Text. + +:: + + contract C {} + +A block with blank lines between block parameters. +Sphinx will treat the second one as a part of the code. + +.. code-block:: solidity + :force: + + :language: Solidity + + contract D {} + :linenos: + +Block with parameters indented less than code. +Sphinx does not complain about these. + +.. code-block:: solidity + :force: + :linenos: + + contract E {} + +More text. diff --git a/test/scripts/test_isolate_tests.py b/test/scripts/test_isolate_tests.py new file mode 100644 index 000000000..15c375a82 --- /dev/null +++ b/test/scripts/test_isolate_tests.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +import unittest + +from unittest_helpers import FIXTURE_DIR, load_fixture + +# NOTE: This test file file only works with scripts/ added to PYTHONPATH so pylint can't find the imports +# pragma pylint: disable=import-error +from isolate_tests import extract_docs_cases +# pragma pylint: enable=import-error + + +CODE_BLOCK_RST_PATH = FIXTURE_DIR / 'code_block.rst' +CODE_BLOCK_RST_CONTENT = load_fixture(CODE_BLOCK_RST_PATH) +CODE_BLOCK_WITH_DIRECTIVES_RST_PATH = FIXTURE_DIR / 'code_block_with_directives.rst' +CODE_BLOCK_WITH_DIRECTIVES_RST_CONTENT = load_fixture(CODE_BLOCK_WITH_DIRECTIVES_RST_PATH) + + +class TestExtractDocsCases(unittest.TestCase): + def setUp(self): + self.maxDiff = 10000 + + def test_solidity_block(self): + expected_cases = [ + " // SPDX-License-Identifier: GPL-3.0\n" + " pragma solidity >=0.7.0 <0.9.0;\n" + "\n" + " contract C {\n" + " function foo() public view {}\n" + " }\n" + "\n" + "\n", + + " contract C {}\n" + "\n", + ] + + self.assertEqual(extract_docs_cases(CODE_BLOCK_RST_PATH), expected_cases) + + def test_solidity_block_with_directives(self): + expected_cases = [ + " // SPDX-License-Identifier: GPL-3.0\n" + " pragma solidity >=0.7.0 <0.9.0;\n" + "\n" + " contract C {\n" + " function foo() public view {}\n" + " }\n" + "\n" + "\n", + + " contract C {}\n" + "\n", + + " contract D {}\n" + " :linenos:\n" + "\n", + + " contract E {}\n" + "\n", + ] + + self.assertEqual(extract_docs_cases(CODE_BLOCK_WITH_DIRECTIVES_RST_PATH), expected_cases)