project: Updating contributing guidelines

This commit is contained in:
Michael Fabian 'Xaymar' Dirks 2022-08-27 19:40:24 +02:00
parent c1b832c03a
commit ed88c4a4d2

View file

@ -1,161 +1,237 @@
# Commits
Commits should always only focus on a single change that is necessary for that commit to work. For example, a commit that changes how something logs messages should not also include a new blur effect. In those cases, the commit should be split up into two, so that they can be reverted independently from another.
# Contributing
This document goes over how you are expected to contribute to the project. This document is softly enforced, and considered a guideline instead of a requirement.
## Commit Subject
The subject line of a commit should begin with the prefix followed by a `: `, and then followed by a summary of what the change does, which should be no longer than 52 alphanumerical characters including whitespace. The prefix is determined by the file being modified, simply remove the extension or find the group that a file belongs to. For example, a modifiation to blur.effect would have the category effects, due to it being re-usable.
## Localization
We use Crowdin to handle translations into many languages. Please join the [StreamFX project on Crowdin](https://crowdin.com/project/obs-stream-effects) if you are interested in improving the translations to your native tongue. Pull Requests therefore should only include changes to `en-US.ini`, and no other localization files should be touched.
### Prefixes
- effects: Anything modifying generic effects like blur.effect, color-conversion.effect, mask.effect, etc.
- locale: Changes in `/data/locale`.
- examples: Changes in `/data/examples` that are not directly influenced by a change to one of the filters, sources or transitions.
- project: Changes to files like README, CONTRIBUTING, AUTHORS, etc.
- cmake: Changes to CMake build scripts.
- ci: Changes to Continuous Integration.
## Commit Guidelines
Commits should focus on a single change, such as formatting, fixing a single bug, a single warning across the code, and similar things. This means that you should not include a fix to color format handling in a commit that implements a new encoder.
All other files should be prefixed with the main file changed, so a change to the translations for Source Mirror would be `source-mirror: commit`.
### Linear History
This project prefers the linear history of `git rebase`, and as such forbids merge commits. This allows all branches to be a single line back to the root, unless viewed as a whole where it becomes a tree. If you are working on a branch for a feature, bug or other thing, you should learn how to rebase back onto the main branch before making a pull request.
## Commit Messages
The commit message should always convey why this change was necessary, what is being changed and how it affects the code when being run. There are rare cases where this can be left out (formatting, refactoring, ...) but it should always be descriptive of what is actually being done.
### Commit Message & Title
As the StreamFX project uses linear history without merge commits, we require a commit message format like this:
# Coding Guidelines
```
prefix: short description
## Naming
The project uses the generally known snake_case for code and the uppercase variant for enumerations and macros:
optional long description
```
### Macros (ELEPHANT_CASE)
- Casing: Uppercase
The `short description` should be no longer than 80 characters, excluding the `prefix: ` part. The `optional long description` should be present if the change is not immediately obvious - however it does not replace proper documentation.
#### The correct `prefix`
Depending on where the file is that you ended up modifying, or if you modified multiple files at once, the prefix changes. Take a look at the list to understand which directories cause which prefix:
- `/CMakeLists.txt`, `/cmake` -> `cmake`
- `/.github/workflows` -> `ci`
- `/data/locale`, `/crowdin.yml` -> `locale`
- `/data/examples` -> `examples`
- `/data` -> `data` (if not part of another prefix)
- `/media` -> `media`
- `/source`, `/include` -> `code`
- `/templates` -> `templates` (or merge with `cmake`)
- `/third-party` -> `third-party`
- `/tools` -> `tools`
- `/ui` -> `ui` (if not part of a `code` change)
- Most other files -> `project`
Multiple prefixes should be separated by `, ` and sorted alphabetically so that a change to `ui` and `code` results in a prefix of `code, ui`. If only a single code file was changed or multiple related file with a common parent were changed, the `code` prefix should be replaced by the path to the file like in these examples:
- `/source/encoders/encoder-ffmpeg` -> `encoder/ffmpeg`
- `/source/filters/filter-shader` -> `filter/shader`
- and so on.
These guidelines are soft requirements and may be extended in the future.
## Coding Guidelines
### Documentation & Comments
Your code should contain the comments where they would save time, as well as documentation for "public" facing functionality. This means that you shouldn't explain things like `1 + 1`, but should provide explanations for complex things. Consider the following:
```c++
int32_t idepth = static_cast<int32_t>(depth);
int32_t size = static_cast<int32_t>(pow(2l, idepth));
int32_t grid_size = static_cast<int32_t>(pow(2l, (idepth / 2)));
int32_t container_size = static_cast<int32_t>(pow(2l, (idepth + (idepth / 2))));
```
This would be much easier to read if it had a an explaination and didn't require parsing the math. Comments are all about saving time to developers not already invested into the code.
### Naming & Casing
Names for anything should describe the purpose or function of the thing, unless the thing is temporary such as iterators.
#### Macros
- Casing: ELEPHANT_CASE
- Separator: `_`
- Prefixes: `S_` for global values, `ST_` for local (this file) values, `D_` for simple functions, `P_` for complex functions
- Prefixes: Optional
- `S_` for global values
- `ST_` for local values
- `D_` for simple functions
- `P_` for complex functions
- Suffixes: No
Example:
```
#define S_PI 3.14141
#define ST_PI2 S_PI / 2.0
#define D_(x) S_PI * x
#define P_(x, y) double_t x(double_t a, double_t b) { return a * b * y; }
##### Example
```c++
#define EXAMPLE FALSE // ❌
#define S_PI 3.14141 // ✔ (in .h and .hpp files)
#define ST_PI2 S_PI / 2.0 // ✔
#define D_(x) S_PI * x // ✔
#define P_(x, y) double_t x(double_t a, double_t b) { return a * b * y; } // ✔
```
### Enumerations (snake_case)
- Casing: Lowercase
#### Namespaces
- Casing: snake_case
- Separator: `_`
- Prefixes: None
- Suffixes: None
Example:
```
enum my_enum {};
enum class my_enum_class {};
enum class my_enum_class_int : int {};
##### Example
```c++
namespace BLA {}; // ❌
namespace a_space {}; // ✔
```
#### Enumeration Entries (ELEPHANT_CASE)
- Casing: Uppercase
- Separator: `_`
Example:
```
enum my_enum {
ENTRY_1,
ENTRY_2
};
```
### Variables (snake_case)
- Casing: Lowercase
- Separator: `_`
- Prefixes: No
- Suffixes: No
Example:
```
int my_var = 0;
```
### Functions (snake_case)
- Casing: Lowercase
- Separator: `_`
- Prefixes: No
- Suffixes: No (differentiate by parameters only)
Example:
```
// This is forbidden.
void func();
int func_int();
// This is okay.
void func();
void func(int& result);
```
### Namespaces (snake_case)
- Casing: Lowercase
- Separator: `_`
Example:
```
namespace a_space {};
```
### Classes, Structs, Unions (snake_case)
- Casing: Lowercase
- Separator: `_`
- Prefixes: No
- Suffixes: No
Example:
```
class a_class {};
class interface_class {};
```
#### Interface Classes
Interface Classes are handled like normal classes. There are no prefixes or suffixes to attach.
#### Methods (snake_case)
- Casing: Lowercase
- Separator: `_`
- Prefixes: No
- Suffixes: No (differentiate by parameters only)
Example:
```
class a_class {
// This is forbidden.
void func();
int func_int();
// This is okay.
void func();
void func(int& result);
};
```
#### Member Variables (snake_case)
- Casing: Lowercase
- Separator: `_`
- Prefixes: `_` if private, otherwise none
- Suffixes: No
Example:
```
class a_class {
int64_t _local_var;
void* _pointer;
int32_t _id;
};
```
### Type Definitions (snake_case)
- Casing: Lowercase
#### Type Definitions
- Casing: snake_case
- Separator: `_`
- Prefixes: No
- Suffixes: `_t`
Example:
```
typedef int32_t my_type_t;
```c++
typedef int32_t my_type; // ❌
typedef int32_t my_type_t; // ✔
```
## Preprocessor Macros
Preprocessor `#define` Macros should be used sparingly, due to their nature of changing code before the compiler gets a chance to work with it. Unless necessary, they should never be in a header file.
#### Enumerations
- Casing: snake_case
- Separator: `_`
- Prefixes: No
- Suffixes: No
##### Entries
- Casing: ELEPHANT_CASE
- Separator: `_`
- Prefixes: Conditional
- `enum`: `STREAMFX_<ENUM_NAME>_`
- `enum class`: None
- Suffixes: No
##### Example
```c++
enum my_enum { // ✔
STREAMFX_MY_ENUM_ENTRY_1, // ✔
ENUM_ENTRY_2 // ❌
};
enum class my_enum : int { // ✔
STREAMFX_MY_ENTRY_1, // ❌
ENUM_ENTRY_2 // ✔
};
enum class my_enum_int : int { // ❌, has `_int` suffix.
};
```
#### Variables
- Casing: snake_case
- Separator: `_`
- Prefixes:
- Locals: None
- Globals: `g_`
- Suffixes: None
##### Example
```c++
float example; // ❌
float g_example; // ✔
function example() {
float _example; // ❌
float example; // ✔
}
```
#### Classes & Structures
- Casing: snake_case
- Separator: `_`
- Prefixes: None
- Suffixes: None
##### Members
- Casing: snake_case
- Separator: `_`
- Prefixes:
- `_` for private, protected
- None for public (prefer set-/get-ters)
- Suffixes: None
##### Methods
- Casing: snake_case
- Separator: `_`
- Prefixes: None
- Suffixes: None
##### Example
```c++
class example {
float example; // ❌
float _example; // ✔
int example_int(); // ❌, has `_int` suffix.
void example(); // ✔
void example(int& result); // ✔
}
struct example {
float _example; // ❌
float example; // ✔
}
```
#### Unions
- Casing: snake_case
- Separator: `_`
- Prefixes: None
- Suffixes: None
##### Union Members
- Casing: snake_case
- Separator: `_`
- Prefixes: None
- Suffixes: None
##### Example
```c++
union {
float _example; // ❌
float example; // ✔
}
```
#### Functions
- Casing: snake_case
- Separator: `_`
- Prefixes: No
- Suffixes: No
##### Example
```c++
void func(); // ✔
void func(int& result); // ✔
int func_int(); // ❌
```
#### Interface Classes
Interface Classes are handled like normal classes. There are no prefixes or suffixes to attach.
### Preprocessor Macros
Pre-processor Macros are a "last stand" option, when all other options fail or would produce worse results. If possible and cleaner to do so, prefer the use of `constexpr` code.
### Classes
#### Members
Members of classes should be private and only accessible via get/set methods.
## Building
Please read [the guide on the wiki](https://github.com/Xaymar/obs-StreamFX/wiki/Building) for building the project.