Răsfoiți Sursa

Add a code style guide

Panagiotis Christopoulos Charitos 5 ani în urmă
părinte
comite
0edd903e51
3 a modificat fișierele cu 231 adăugiri și 3 ștergeri
  1. 3 0
      .gitattributes
  2. 8 3
      README.md
  3. 220 0
      docs/code_style.md

+ 3 - 0
.gitattributes

@@ -12,3 +12,6 @@
 *.ankimtl text eol=lf
 *.ankimtl text eol=lf
 *.ankimdl text eol=lf
 *.ankimdl text eol=lf
 *.ankipart text eol=lf
 *.ankipart text eol=lf
+*.ankiskel text eol=lf
+*.ankiankim text eol=lf
+*.ankicl text eol=lf

+ 8 - 3
README.md

@@ -10,7 +10,7 @@ AnKi 3D engine is a Linux and Windows opensource game engine that runs on Vulkan
 AnKi's license is `BSD`. This practically means that you can use the source or parts of the source on proprietary and
 AnKi's license is `BSD`. This practically means that you can use the source or parts of the source on proprietary and
 non proprietary products as long as you follow the conditions of the license.
 non proprietary products as long as you follow the conditions of the license.
 
 
-See `LICENSE` file for more info.
+See the [LICENSE](LICENSE) file for more info.
 
 
 2 Building AnKi
 2 Building AnKi
 ===============
 ===============
@@ -80,11 +80,10 @@ Alternatively, recent Visual Studio versions support building CMake projects fro
 - Visual Studio will automatically understand that AnKi is a CMake project and it will populate the CMake cache
 - Visual Studio will automatically understand that AnKi is a CMake project and it will populate the CMake cache
 - Press "build all"
 - Press "build all"
 
 
-
 3 Next steps
 3 Next steps
 ============
 ============
 
 
-This code repository contains **3 sample projects** that are built by default (`ANKI_BUILD_SAMPLES` CMake option):
+This code repository contains **4 sample projects** that are built by default (`ANKI_BUILD_SAMPLES` CMake option):
 
 
 - `sponza`: The Crytek's Sponza scene
 - `sponza`: The Crytek's Sponza scene
 - `simple_scene`: A simple scene
 - `simple_scene`: A simple scene
@@ -99,3 +98,9 @@ On Linux:
 	$./path/to/build/bin/sponza
 	$./path/to/build/bin/sponza
 
 
 On Windows just find the `sponza.exe` and execute it.
 On Windows just find the `sponza.exe` and execute it.
+
+4 Contributing
+==============
+
+There are no special rules if you want to contribute. Just create a PR. Read the code [style guide](docs/code_style.md)
+before that though.

+ 220 - 0
docs/code_style.md

@@ -0,0 +1,220 @@
+This document describes the code style of AnKi 3D Engine.
+
+
+Comments
+========
+
+All comments are C++ like:
+
+	// Some comment
+
+And for doxygen comments:
+
+	/// @brief blah blah
+	/// @param blah blah
+
+Naming Conventions
+==================
+
+**Variables, functions and methods** are lower camelCase.
+
+	functionDoSomething(someVariableA, someVariableB);
+
+All **types** are PascalCase and that includes classes, structs, typedefs and enums.
+
+	enum MyEnum {...};
+	class MyClass {...};
+	using MyType = int;
+
+All **constant expressions** are SCREAMING_SNAKE_CASE and that includes enumerants.
+
+	constexpr int MY_CONSTANT = ...;
+
+	enum MyEnum
+	{
+		ENUMERANT_A
+	};
+
+All **macros and defines** should be SCREAMING_SNAKE_CASE and they should have an `ANKI_` prefix.
+
+	ANKI_ASSERT(...);
+
+	#define ANKI_MAX_SOMETHING ...
+
+All **template arguments** should start with `T`.
+
+	template<typename TSomething, typename TOther, U32 T_SOME_CONST>
+
+The **source files** are always PascalCase.
+
+	ThreadHive.h
+	MyShaderProgram.ankiprog
+
+All **function and method names** should form a sentence with at least one verb.
+
+	doSomething(...);
+	getSomething();
+	calculateSomething(...);
+
+**No hungarian notations** with 2 exceptions.
+
+- All member variables have the `m_` prefix.
+- All global variables have the `g_` prefix.
+
+C++ rules
+=========
+
+**Always use strongly typed enums**. If you need to relax the rules use the `ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS` macro.
+
+	enum class MyEnum : uint {...};
+	ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(MyEnum, inline);
+
+**Never use `typedef`** to define types. Use `using` instead.
+
+	using U32 = uint32_t;
+	using Func = void(*)(int, int);
+
+**Never use C-style casting**. Use static_cast, reinterpret_cast or const_cast for most cases and constructor-like cast for fudmental types.
+
+	Derived* d = static_cast<Derived*>(base);
+
+	uint i = uint(1.1f); // uint is fudmental type
+
+**Always use `constexpr`** when applicable. Never use defines for constants.
+
+	constexpr uint SOME_CONST = ...;
+
+**Never use `struct`** and always use `class` instead. Since it's difficult to come up with rules on when to use struct over class always use class and be done with it.
+
+	class MyTrivialType
+	{
+	public:
+		int m_x;
+		int m_y;
+	};
+
+**Avoid using `auto`**. It's only allowed in some templates and in iterators. auto makes reading code difficult.
+
+**Includes should always have the full file path**. This avoids issues with files of similar name. Non-AnKi includes follow AnKi includes.
+
+	#include <anki/util/Thread.h>
+	#include <anki/util/WeakArray.h>
+	#include <anki/util/Allocator.h>
+	#include <cstdio>
+
+**Never use public nested classes**. Only private nested classes are allowed. Nested classes cannot be forward declared.
+
+	class MyClass
+	{
+	public:
+		// NO!!!!!!!!!!!
+		class Nested {...};
+
+	private:
+		// It's fine
+		class Nested {...};
+
+		// Also fine
+		class
+		{
+			...
+		} m_myUnamedThing;
+	};
+
+Try to **use `explicit`** in constructors for extra safety. Don't use explicit on copy constructors.
+
+AnKi uses **const correctness** throughout and that's mandatory. Always use `const`. The only place where you don't have to is for function and method parameters.
+
+	uint doSomething(uint noNeedForConst)
+	{
+		const uint bla = noNeedForConst + 10;
+		return blah;
+	}
+
+**Access types in a class have a specified order**. First `public` then `protected` and last `private`. There are some exceptions where this rule has to break.
+
+	class MyClass
+	{
+	public:
+		...
+	protected:
+		...
+	private:
+		...
+	};
+
+Always **use AnKi's fudmental types** (U32, I32, F32, Bool etc etc). For integers and if you don't care about the size of the integer you can use the type `U` for unsinged or `I` for signed. Both of them are at least 32bit.
+
+	for(U32 i = 0; i < 10; ++i) {...}
+
+If you have to overload the operator Bool always use **`explicit operator Bool` operator** overloading.
+
+	explicit operator Bool() const {...}
+
+The use of **references and pointers** is govern by some rules. Always use references except when you transfer or share ownership where you should use pointers. Pointers are also allowed for optional data that can be nullptr.
+
+	// ptr is a pointer so you CAN NOT destroy it after a call to doSomething is done
+	// ref is a reference so you CAN destroy it after a call to doSomething is done
+	void Foo::doSomething(TypeA* ptr, TypeB& ref)
+	{
+		// Store the ptr somewhere
+		m_someMember = ptr;
+
+		// Won't store the ref
+		ref += ...;
+	}
+
+Always **use `nullptr`**.
+
+	void* ptr = nullptr;
+
+**Never use C style arrays**. Use the `Array<>` template instead.
+
+	Array<MyType, 10> myArray;
+
+**Don't use STL**. AnKi has a replacement for most STL templates. There are some exceptions though.
+
+- Can use `type_traights`.
+- Some from `utility` eg std::move.
+- Some from `algorithm` eg std::sort.
+
+Always try to **comment parts of the source code**. Self documenting code is never enough.
+
+Always use `override` or `final` on virtual methods and try to use `final` on classes when applicable.
+
+	class Foo final
+	{
+	public:
+		void myVirtual(...) override {...}
+	};
+
+Code formatting
+===============
+
+clang-format deals with code formatting. To format the whole source tree type the following in a terminal:
+
+	$ cd /path/to/anki
+	$ ./tools/format_source.sh
+
+If you need to format on Windows do the same from a WSL terminal.
+
+Some cases that are not handled by clang-format follow.
+
+**Always use curly braces** on single line expressions.
+
+	// NO!!!!!!!!!!!
+	if(something) doSomething();
+
+	// YES!!!!!!!!!!!!!!
+	if(something)
+	{
+		doSomething();
+	}
+
+Always place the **condition of a conditional ternary operator** inside parenthesis.
+
+	// NO!!!!!!!!!!!
+	a = b ? 1 : 0;
+
+	// YES!!!!!!!!!!!!!!
+	a = (b) ? 1 : 0;