mirror of
https://github.com/OPM/ResInsight.git
synced 2026-11-01 08:38:00 -06:00
* Completions: Apply perforation cell filter to COMPDAT and MSW export * PerforationInterval: Limit Cell Filter dropdown to case-level filters * PerforationInterval: Prefix Cell Filter entries with case name when multiple cases * Completions: Use std::format for cell filter suppression log messages
145 lines
4.7 KiB
Markdown
145 lines
4.7 KiB
Markdown
# Coding Style Guidelines
|
||
|
||
This document describes the coding style and formatting conventions for ResInsight.
|
||
|
||
## Code Formatting
|
||
|
||
### clang-format
|
||
|
||
ResInsight uses clang-format for C++ code formatting:
|
||
- **Configuration**: `.clang-format` file in repository root
|
||
- **Version**: Use clang-format-19 to enforce style
|
||
|
||
### Python Formatting
|
||
|
||
Python code should be formatted using `ruff`:
|
||
|
||
```bash
|
||
# Format source code
|
||
python -m ruff format test_polygons.py
|
||
|
||
# Check code style
|
||
python -m ruff check --fix test_polygons.py
|
||
```
|
||
|
||
## Copyright Headers
|
||
|
||
- New files must use the **current year** (the year the file is created) in the copyright header
|
||
- Never change the copyright year in existing files — the year reflects when the file was originally created
|
||
- Example header for a file created in 2026:
|
||
|
||
```cpp
|
||
/////////////////////////////////////////////////////////////////////////////////
|
||
//
|
||
// Copyright (C) 2026- Equinor ASA
|
||
//
|
||
```
|
||
|
||
## Language Standards
|
||
|
||
- **C++**: C++23 standard
|
||
- **Python**: Python 3.11+
|
||
|
||
## Best Practices
|
||
|
||
### General Guidelines
|
||
|
||
1. **Minimal Changes**: Make the smallest possible changes to achieve the goal
|
||
2. **Preserve Formatting**: Do not reformat unrelated code
|
||
3. **Comments**: Match the style of existing comments in the file
|
||
4. **Libraries**: Use existing libraries whenever possible; only add new libraries or update versions if absolutely necessary
|
||
|
||
### Code Quality
|
||
|
||
1. Always validate changes don't break existing behavior
|
||
2. Always validate changes don't introduce security vulnerabilities
|
||
3. Fix any vulnerabilities related to your changes
|
||
4. Run linters, builds and tests before making code changes to understand any existing issues
|
||
5. Always try to lint, build and test code changes as soon as possible after making them
|
||
|
||
### Testing
|
||
|
||
1. Only run linters, builds and tests that already exist
|
||
2. Do not add new linting, building or testing tools unless necessary to fix the issue
|
||
3. It is unacceptable to remove or edit unrelated tests
|
||
4. Documentation changes do not need to be linted, built or tested unless there are specific tests for documentation
|
||
|
||
### Header / Implementation Split (C++)
|
||
|
||
Put function bodies in the `.cpp` file, not inline in the header.
|
||
|
||
- Declare member functions in the header; define them in the matching `.cpp`.
|
||
- This applies even to one-line bodies (`return false;`, `return m_field;`, trivial forwarders).
|
||
- Exceptions: function templates that must stay in the header, and `constexpr` functions where the compiler requires the definition to be visible.
|
||
|
||
```cpp
|
||
// Bad – inline body in the header
|
||
class RimFoo
|
||
{
|
||
public:
|
||
bool canAddSubCollection() const override { return false; }
|
||
};
|
||
|
||
// Good – declared in the header, defined in the .cpp
|
||
// RimFoo.h
|
||
class RimFoo
|
||
{
|
||
public:
|
||
bool canAddSubCollection() const override;
|
||
};
|
||
|
||
// RimFoo.cpp
|
||
bool RimFoo::canAddSubCollection() const
|
||
{
|
||
return false;
|
||
}
|
||
```
|
||
|
||
Why: keeps headers light (faster builds, smaller include surface), keeps the implementation file as the single source of truth for behavior, and matches the existing style across `ApplicationLibCode`.
|
||
|
||
### Logging
|
||
|
||
Use `std::format` to build log messages — not `QString(...).arg(...)`.
|
||
|
||
- `RiaLogging::info` / `warning` / `error` take `std::string_view`. Passing a `QString` requires a trailing `.toStdString()`; `std::format` avoids that and reads better.
|
||
- `QString` arguments can be passed directly to `std::format` — include `RiaQStringFormatter.h`, which provides a `std::formatter<QString>` specialization.
|
||
|
||
```cpp
|
||
// Bad – QString with positional placeholders, manual conversion
|
||
RiaLogging::info( QString( "Exported %1 cells for well '%2'." ).arg( count ).arg( wellName ).toStdString() );
|
||
|
||
// Good – std::format, QString passed directly
|
||
RiaLogging::info( std::format( "Exported {} cells for well '{}'.", count, wellName ) );
|
||
```
|
||
|
||
### Lambda Functions
|
||
|
||
Keep lambdas short and readable:
|
||
|
||
- **1–3 lines**: keep inline
|
||
- **4+ lines or contains control flow** (if/for/while): extract to a named method (e.g. `onApplyClicked()`) and call it from a single-line lambda
|
||
|
||
```cpp
|
||
// Good – short inline lambda
|
||
addNewButton( "Show Report", [this]() { showReport(); } );
|
||
|
||
// Good – multi-statement, no control flow, still inline
|
||
addNewButton( "Clear Data",
|
||
[this]()
|
||
{
|
||
clearData();
|
||
updateConnectedEditors();
|
||
} );
|
||
|
||
// Good – complex logic extracted to a named method
|
||
addNewButton( "Apply", [this]() { onApplyClicked(); } );
|
||
void MyClass::onApplyClicked() { /* complex logic here */ }
|
||
```
|
||
|
||
## Commit Conventions
|
||
|
||
When creating commits:
|
||
- Use issue number at the start of the title: `#12773 Python: Add API for creating valve templates`
|
||
- Follow git conventions for commit messages
|
||
- Always run python formatting/check on changed files before commits
|