Styling guidelines

General

The maximum line limit is 80 characters. In the case of a line exceeding 80 charaters, wrapping rules should be applied.

Files & Directories

Files should be in pascalcase. Directories should be in nocase. Used file extensions are .cpp, .hpp, .mm and .hmm.

Comments

For single line comments, there should be a single space padding.

// Correct
/* Correct */

//Wrong
/*Wrong*/

For multiline comments, the contents should start in a next line with a indent.

/*
	This is quite correct.
	Isn't it?
*/

/*This is
wrong lol*/

Constants

For null pointers, nullptr should be used.

// Correct
CCObject* obj = nullptr;

// Wrong
CCObject* obj = 0;
CCObject* obj = NULL;
CCObject* obj = 0.0f;

Floats should be suffixed with f, hexadecimal values should be prefixed with 0x.

// Correct
int hex = 0x1907;
float delta = 0.016667f;

// Wrong
int hex = 1907h;
float delta = 0.016667;

Variables

Local variables should be in camelcase.

// Correct
int myCoolVariable = 1907;

// Wrong
int MyBadVariable = 1907;
int this_is_ugly = 1907;
int _Scary_val = 1907;

No more than 1 variable should be declared in a same line.

// Correct
bool firstVar = false;
bool secondVar = true;

// Wrong
bool firstVar = false, secondVar = true;

Static variables should be prefixed with s_ and in camelcase.

// Correct
static CCNode* s_sharedNode = nullptr;

// Wrong
static CCNode* g_sharedNode = nullptr;
static CCNode* sharedNode = nullptr;

Since global variable initializations between platforms are inconsistent, the use of global variables is entirely discouraged.

Types

Type aliases should always be defined using the using keyword. Types should be in pascalcase without a suffix.

// Correct
using EpicInteger = unsigned long long int;

// Wrong
typedef unsigned long long int EpicInteger;
using EpicInteger_t = unsigned long long int;

Pointers and references should be attached to the type.

// Correct
CCNode* node;
CCNode*& node2 = node;

// Wrong
CCNode *node;
CCNode *&node2 = node;
CCNode* &node3 = node;

Const qualifiers should be always after the qualified type.

// Correct
std::string const& ref = str;
CCNode const* node2 = node;
CCNode* const node3 = node;

// Wrong
const std::string& ref = str;
const CCNode* node2 = node;

In places of ambiguity, typename should be used.

// Correct
typename Something::type test = value;

// Wrong
Something::type test = value;

Statements

If, while and for statements should be on the same line, the scope should start in the same line. One line if, while and for statements shouldn’t use braces.

// Correct
while (thing == 54) {
	thing = 53;
}
if (thing == 54) thing = 53;
for (int thing = 53; thing != 54; ++thing) {
	// Stuff
}

// Wrong
while (thing == 54) 
{
	thing = 53;
}
if (thing == 54) { thing = 53; }

Switch statement labels should be on the same line as the statement. Every fallthrough should be marked with [[fallthrough]]. For enums, every case should be handled.

// Correct
switch (thing) {
	case TestEnum::Xd: [[fallthrough]];
	case TestEnum::Lol:
		value = 5;
		break;
	default:
		value = 6;
		break;
}

// Wrong
switch (thing) {
case TestEnum::Xd: [[fallthrough]];
case TestEnum::Lol:
	value = 5;
	break;
}

Functions

Return type, the function and the parameters should be in the same line. Function name and the parameter names should be in camelcase. There shouldn’t be any space between function name and the parenthesis.

// Correct
CCObject* copyWithMeme(CCMeme* meme);

// Wrong
CCObject* 
copyWithMeme (CCMeme* meme);

Definitions should start on the same line.

// Correct
CCObject* copyWithMeme(CCMeme* meme) {
	return nullptr; // funny meme if i do say so myself
}

// Wrong
CCObject* copyWithMeme(CCMeme* meme)
{
	return nullptr;
}

Unless necessary, the trailing return type shouldn’t be used.

// Correct
CCObject* copyWithMeme(CCMeme* meme) {
	return nullptr;
}

// Wrong
auto copyWithMeme(CCMeme* meme) -> CCObject* {
	return nullptr;
}

Namespaces

Namespaces should be one word lowercase.

// Correct
namespace geode {

}

// Wrong
namespace the_old_lilac_namespace {
	
}

using namespace std; shouldn’t be used.

// Correct
std::string value;

// Wrong
string value;

Classes

Classes should be in pascalcase and the declaration should start on the same line.

// Correct
class BasedButton {

};

// Wrong
class BasedButton 
{

};

Access specifiers should be on the same indentation as the classes.

// Correct
class BasedButton {
public:
	// Stuff
};

// Wrong
class BasedButton {
 public:
	// this one is for you camila
};

// Wrong
class BasedButton {
	public:
	// bad stuff
};

Subclasses should be on the same line.

// Correct
class BasedButton : CCNode, FLAlertDelegate {
public:
	// Stuff
};

// Wrong
class BasedButton
 : CCNode, FLAlertDelegate {
public:
	// Stuff
};

// Wrong
class BasedButton : 
	CCNode, 
	FLAlertDelegate {
public:
	// Stuff
};

Classes which shouldn’t be extended should be marked as final.

// Correct
class BasedButton final : CCNode {
public:
	// I am the last implementer ok
};

// Wrong
class BasedButton : CCNode {
public:
	// pls dont subclass me okthxbai
};

Member functions

Same rules of functions apply for member functions.

// Correct
class BasedButton : CCNode {
public:
	bool init() override {
		return true;
	}
};

// Wrong
class BasedButton : CCNode {
public:
	bool init() override
	{
		return true;
	}
};

Functions should be const qualified whenever they can.

// Correct
class BasedButton : CCNode {
public:
	void baseMyButton(BasedButton const* other) const {
		// basing your button
		// and not modifying you :)
	}
};

// Wrong
class BasedButton : CCNode {
public:
	void baseMyButton(BasedButton const* other) {
		// basing your button
		// and not modifying you :)
	}
};

Virtual overrides should be marked as override.

// Correct
class BasedButton : CCNode {
public:
	bool init() override {
		return true;
	}
};

// Wrong
class BasedButton : CCNode {
public:
	bool init() {
		return true;
	}
};

Outofline definitions of member functions have the same rules applied to them.

// Correct
bool BasedButton::init() {
	return true;
}

// Wrong
bool BasedButton::init() 
{
	return true;
}

Templates

Template parameters should always be in pascalcase, and the types should always use the class keyword.

// Correct
template <class CoolType>

// Wrong
template <typename t>

Template declarations should always be on the previous line.

// Correct
template <class CoolType>
void function(CoolType&& value);

template <int CoolInt>
class EpicClass;

// Wrong
template <class CoolType> void function(CoolType&& value);

template <int CoolInt> class EpicClass;

In places of ambiguity, template should be used.

// Correct
auto value = Something::template function<int>();

// Wrong
auto value = Something::function<int>();

Macros

Syntactical macros should always be prefixed with $ and should use one word lowercase.

// Correct
#define $modify(...) // lol

// Wrong
#define $modifyThisDamnedClass(...) // lol

Other macros should always be uppersnakecase and should be prefixed with GEODE_.

// Correct
#define GEODE_DEFINE_FUNC(...)

// Wrong
#define DEFINEFUNCLOL(...)
#define OrThisOne(...)

Wrapping

TODO