Read CONTRIBUTING.rst for the architecture (parse → intermediate → generators), the layout of dev/test_data/ and the full coding style guide.
Prefer functional programming instead of object hierarchy.
If a function is called only once from somewhere and is shorter than 30-40 lines OR has a lot of arguments, inline it. We want to keep complexity down!
Always analyze for efficiency -- for example, avoid unnecessary copies of arrays.
Keep the state minimal! Don't introduce state (stateful properties) in classes just because.
Make all global constants Final[...] in Python. Use readonly containers (Mapping, Sequence etc.).
While programming, run fast-fail tests first: mypy and black on code generators. Once the code is ready, re-record the goldens over the unit tests. Summarize the changes with the function signatures, class interfaces and state, and concrete code snippets -- then ask for approval before you run live tests.
- Fast checks:
python dev/continuous_integration/precommit.py --select reformat ssort mypy ruff(--overwritereformats and re-sorts in place). - One test module:
python -m unittest dev/tests/cpp/test_main.py - Re-record golden data: set
AAS_CORE_CODEGEN_TESTS_RERECORD=1, then review withgit diff dev/test_data/. - The tests cache the pickled symbol tables in
/tmp/aas-core-codegen-*/, keyed on the meta-model source and the code ofparseandintermediate, so parallel worktrees never share stale pickles. Old pickles pile up; remove them now and then withrm -f /tmp/aas-core-codegen-*/model-*.pickle. - Live-test fast checks (compile, type-check and lint only; no test runs):
python dev/live_tests/fast_check_<language>.py --select <case> --output_dir <dir>forcpp,csharp,golang,java,pythonandtypescript. Always run them first, and run the live tests only once they pass. Pass the same--output_dirto the live test to re-use the prepared projects. - Live test:
python dev/live_tests/live_test_cpp.py --select <case> --output_dir <dir>(C++: clang with-DDEBUGonly,VCPKG_ROOTmust be set).
These aren't written down anywhere, and Claude tends to break them:
- Never hand-edit files under
dev/test_data/**/expected*. Change the generator and re-record. - Test a new feature with one common meta-model in
dev/test_data/common_meta_models/, never one per small case. Each one generates full SDKs for every target. Error cases go todev/test_data/parse/unexpected/ortest_type_inference.py. - Generated C++ must stay C++11-compatible, even though the tests compile as C++17.
-
Annotate the variables (
lst: List[str] = []), never with type comments (# type: List[str]): ruff does not see them and reports the imports as unused. This applies to the code generators, not to the generated code. -
Import with a module alias prefix (
cpp_common,golang_naming). The only allowed symbol aliases areI,II, … -
In
Strippedblocks, use one placeholder per indentation level:{IIIII}, never{IIII}{I}. -
Write multi-line generated code as a
f"""\string, never with\nescapes:.. code-block:: python
header = f"""\ {keyword} ( {I}{indent_but_first_line(condition, I)} )""" -
Use icontract
@require/@ensureinstead ofassert. Use aUnion[...]type hint instead of anisinstanceprecondition. -
No
get_prefix. Use_by_for mappings and_setfor sets. No_utils/_helpers. -
No
# TODO. Notes are# NOTE (mristin):(wheremristinis your GitHub username). No code in comments. Usepathlib, notos.path. No**keyword arguments.
We follow Chris Beams' guidelines on commit messages_:
- Separate subject from body with a blank line
- Limit the subject line to 50 characters
- Capitalize the subject line
- Do not end the subject line with a period
- Use the imperative mood in the subject line, full sentences in the body with a subject ("We ...")
- Wrap the body at 72 characters
- Use the body to explain what and why vs. how
.. _guidelines on commit messages: https://chris.beams.io/posts/git-commit/
Keep the commit messages succinct! 1-2 sentences per important point accompanied with a concrete code snippet.
Do not append Co-authored by Claude line in commit messages!
Inline code fragments should be marked with ....
Split work in atomic units in feature branches; prepend mristin/ prefix to the branch name.