Skip to content

Improve errors for modules without functionality#232

Merged
pedjaradenkovic merged 5 commits into
mainfrom
fix/handle-modules-without-functionality
Jul 2, 2026
Merged

Improve errors for modules without functionality#232
pedjaradenkovic merged 5 commits into
mainfrom
fix/handle-modules-without-functionality

Conversation

@pedjaradenkovic

@pedjaradenkovic pedjaradenkovic commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Context

Fixes: https://github.com/Codeplain-ai/next-microsoft/issues/100

When a .plain module has no functionality to render, the renderer produced misleading errors. This PR fixes those messages and, more importantly, draws a clean line between parse-time (syntax) errors — intrinsic to the file, independent of how it's used — and usage errors — where an otherwise-valid file is wrong for the role it's playing (render target vs. imported dependency).

The discriminating test: does the file's validity flip depending on its role? If the same bytes are valid in one role and invalid in another, it's a usage error; if invalid in every role, it's a syntax error.

Error classification

Condition Category Exception
No ***functional specs*** section at all usage (valid as an import, not renderable) MissingFunctionalitiesError (new)
***functional specs*** section present but empty syntax (invalid in every role) PlainSyntaxError
Has functionalities but no implementation reqs syntax (intrinsic) PlainSyntaxError (unchanged)
Imported module contains functionalities usage (valid to render, not to import) ImportedModuleWithFunctionalitiesError (new)

Messages

  • No functional specs (not renderable): Module <name> does not have any functionality specified. At least one functionality is required for rendering. (no Plain syntax error: prefix — it isn't one)
  • Empty functional specs section: Plain syntax error: Module '<name>' has an empty 'functional specs' section. At least one functionality must be specified.
  • Imported module with functionalities: Module <name> is imported but contains functional specs. Imported modules may only provide definitions, implementation reqs, and test reqs.

Changes

  • plain2code_exceptions.py — new user-facing exceptions MissingFunctionalitiesError and ImportedModuleWithFunctionalitiesError.

  • plain2code.py — both added to EXPECTED_EXCEPTIONS (reported to the user directly, never sent to Sentry as crashes).

  • plain_file.py — retired the misnamed check_if_functional_requirements_are_specified (it mutated a caller-passed buffer, raised a validation error, and returned header presence) and split it into three single-purpose helpers:

    • has_functional_specs_section — pure presence predicate
    • count_functionalities — functionality count
    • validate_functionalities_have_implementation_reqs — the impl-reqs validation

    The render path (plain_file_parser) and the import path (process_imports) now read as the parse-vs-usage layering described above.

Notable behavior fix

Reclassifying the import check also fixes prior mislabeling: an imported module that carried functional specs and lacked implementation reqs used to surface the misleading "no implementation reqs" syntax error first. It now reports the correct import usage error regardless of impl reqs.

Testing

  • New tests: test_no_functional_specs_section, test_empty_functional_specs_section (tests/test_plainfileparser.py) and test_imported_module_with_functionalities (tests/test_imports.py), plus supporting fixtures under tests/data/.
  • Existing test_missing_non_functional_requirements / test_without_non_functional_requirement still pass (≥1 functionality → preserved impl-reqs check).
  • Full suite green; black / isort / flake8 / mypy all clean.
  • Both no-functionality cases verified end-to-end via --dry-run.

Distinguish two cases when a module has no functionality to render:

- No ***functional specs*** header at all: raise the new non-syntax
  MissingFunctionalitiesError with a clear, actionable message instead
  of the misleading 'was required but does not contain functional
  requirements' PlainSyntaxError.
- Empty ***functional specs*** section: raise a PlainSyntaxError naming
  the empty section, instead of silently rendering zero functionalities
  or reporting a misleading 'no implementation reqs' error.

Modules with at least one functionality still flow through the existing
implementation-reqs validation.
Split the misnamed check_if_functional_requirements_are_specified (which
mutated a caller-passed buffer, raised a validation error, and returned
header presence) into three single-purpose helpers:

- has_functional_specs_section: pure presence predicate
- count_functionalities: functionality count
- validate_functionalities_have_implementation_reqs: the impl-reqs validation

Reclassify 'imported module must not contain functionalities' from a
PlainSyntaxError to the new usage error ImportedModuleWithFunctionalitiesError.
The file is syntactically valid and would be fine as a render target; it is
only wrong for the import role, so it is a usage error, not a syntax error.
This also fixes the prior mislabeling where such a module could surface the
misleading 'no implementation reqs' syntax error first.

Behavior preserved: missing functional specs (usage), empty functional specs
section (syntax), and functionalities-without-impl-reqs (syntax) are unchanged.
@pedjaradenkovic pedjaradenkovic force-pushed the fix/handle-modules-without-functionality branch from 842c612 to fc001e5 Compare June 30, 2026 12:02
@pedjaradenkovic pedjaradenkovic requested a review from NejcS June 30, 2026 12:02
Comment thread plain_file.py Outdated
Comment on lines +171 to +180
def validate_functionalities_have_implementation_reqs(plain_source) -> None:
"""Raise if the module has functionalities but no implementation reqs are specified."""
implementation_reqs = plain_source[plain_spec.NON_FUNCTIONAL_REQUIREMENTS]
has_implementation_reqs = (
implementation_reqs is not None
and hasattr(implementation_reqs, "children")
and len(implementation_reqs.children) > 0
)
if not has_implementation_reqs:
raise PlainSyntaxError("Plain syntax error: functionality with no implementation reqs specified.")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be worded better. What this does is it checks if the plain file has any implementation reqs but the comment, function name and error message (at least to me) make it sound like each functionality must have an implementation requirement.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I'll reword this!

@NejcS

NejcS commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

@pedjaradenkovic in general I think the change is good but I left a small comment

@NejcS NejcS left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@pedjaradenkovic pedjaradenkovic merged commit e1c4447 into main Jul 2, 2026
10 checks passed
@pedjaradenkovic pedjaradenkovic deleted the fix/handle-modules-without-functionality branch July 2, 2026 21:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants