diff --git a/docs/07.CODING-STANDARDS.md b/docs/07.CODING-STANDARDS.md new file mode 100644 index 0000000000..46fa98375f --- /dev/null +++ b/docs/07.CODING-STANDARDS.md @@ -0,0 +1,797 @@ +# JerryScript Coding Standards + +This text is a brief overview of JerryScript Coding Standards. +Each rule starts with a short description followed by several +examples. We believe examples are better than long explanations. +Please follow these guidelines when you submit a patch for +review. + +## General rules + +* Indentation is two spaces. +* Tab characters are not allowed. +* Maximum line length is 120 characters (excluding newline). +* No trailing white space is allowed. +* Run `tools/run-tests.py --check-vera` to check several + of the coding conventions automatically. + +## Comments + +Only block comments (`/* */`) are allowed in JerryScript. +Comments should be complete sentences (e.g. start with an +upper case letter), except for return value, field and +argument descriptions (see the exceptions below). The +text part of a comment should focus on explaining *why* +the code is doing something rather than *what* the code +is doing. + +```diff ++++ Good +++ +``` + +```c + /* A perfect comment. */ + + /* A perfect multiline + * comment. Each line should + * start with an asterisk. */ +``` + +```diff +--- Bad --- +``` + +```c + // Double slash comments are not allowed. + + /* not a complete sentence */ + + /* A bad mulitiline + comment. */ +``` + +All types, constants and functions require a description in +JerryScript. These comments should start with `/**`. The starting +`/**` and ending `*/` must be on separate lines. + +```diff ++++ Good +++ +``` + +```c +/** + * A correct description. + */ +``` + +```diff +--- Bad --- +``` + +```c +/** An incorrect description. */ +``` + +## Preprocessor defines + +The name of a preprocessor macro must be an uppercase string +and these macros must be preceded by a description. +Abbreviations are allowed but not preferred in new code. + +```diff ++++ Good +++ +``` + +```c +/** + * Short description about the constant. + */ +#define JERRY_VALUE_SEVEN 7 + +/** + * Short description about the macro function. + */ +#define JERRY_ADD_TWO_NUMBERS(arg1, arg2) \ + ((arg1) + (arg2)) + +/** + * Although this is correct, a reviewer might request + * to change NUMS to NUMBERS. Hence it is recommended + * to use NUMBERS in the first place. + */ +#define JERRY_ADD_TWO_NUMS(arg1, arg2) \ + ((arg1) + (arg2)) +``` + +```diff +--- Bad --- +``` + +```c +#define JERRY_CONSTANT_WITHOUT_DESCRIPTION 5 + +#define JeRrY_mIxEd_CaSe_NaMe "str" +``` + +## Conditional preprocessor directives + +A comment is required after `#else` and `#endif` in JerryScript. +The defined keyword should be omitted from these comments. + +```diff ++++ Good +++ +``` + +```c +#ifdef JERRY_A + +#else /* !JERRY_A */ + +#endif /* JERRY_A */ + +#ifdef JERRY_A +#if defined JERRY_B && defined JERRY_C && (JERRY_C > 6) + +#else /* !(JERRY_B && JERRY_C && (JERRY_C > 6)) */ + +#endif /* JERRY_B && JERRY_C && (JERRY_C > 6) */ +#endif /* JERRY_A */ +``` + +```diff +--- Bad --- +``` + +```c +#ifdef JERRY_A + +#endif + +#ifdef JERRY_A + +#endif /* defined JERRY_A */ + +#ifdef JERRY_B + /* Missing comment after else. */ +#else + +#endif /* JERRY_B */ +``` + +## Code blocks + +Each code block must be enclosed in curly braces even +if it is a single line statement. These braces must +be on separate lines. There must be a single space +before the opening parenthesis of the expression +after if/while/switch keywords. + +```diff ++++ Good +++ +``` + +```c +if (value > 6) +{ + function_call (); +} + +if (value > 1) +{ + function_call_a (); +} +else +{ + function_call_b (); +} + +do +{ + function_call (); + value++; +} +while (value < 6); + +switch (value) +{ + case A: + { + /* FALLTHRU comment is allowed if a + * switch-case is not terminated by + * break/continue/return. */ + + /* FALLTHRU */ + } + case B: + case C: + { + break; + } + case D: + { + /* We can use continue if we are in a loop. */ + continue; + } + default: + { + return; + } +} +``` + +```diff +--- Bad --- +``` + +```c +if (value > 6) + function_call_a (); +else + function_call_b (); + +if (value > 6) { + function_call_a (); +} + +if (value > 6) function_call_a (); +else { function_call_b (); } + +if +(value > 6) +{ +} + +switch (value) { + case 0: break; + default: { + return 5; + } +} + +switch (value) +{ + case A: + { + if (value > 6) + { + CASE B: + { + /* This is allowed in C but + * not in JerryScript. */ + break; + } + } + } +} + +do + value++; +while (value < 5); + +do { + value++; +} while (value < 5); + +do +{ + value++; +} while (value < 5); +``` + +## Newlines + +A newline in JerryScript is a separator which separates different +parts of the source code. Its primary purpose is to improve +readability. Unlike other rules developers have some freedom +to add newlines to their code. However there are some rules. + +* Only a single newline separator is allowed. +* Source files must be terminated by a newline. +* Global declarations must be separated by a newline. +* Newlines are not allowed after an opening curly brace or before + a closing curly brace +* No newlines are allowed between control statements (if-else, while, + for, switch, etc.) and their code blocks. +* There should be a newline after the variable declarations + if they are the first statements of a block. + +```diff ++++ Good +++ +``` + +```c +if (a > 5) +{ + /* Newline must be present after the first + * variable declarations of a code block. */ + int j = a - 1; + int k = a * 2; + + return j + k; +} + +while (a < 5) +{ + a++; + + /* It is recommended to put a newline after + * intermediate variable declarations. */ + int i = a * 2; + + b = i - 3; +} + +/* It is a recommended to put newlines around asserts. */ +a = b + 5; + +JERRY_ASSERT (a < 20); + +c = a + 7; + +/* It is a good practice to put a newline after a multiline + * function call (see Function calls later). */ +f (a, + b, + c); + +a = 6; +``` + +```diff +--- Bad --- +``` + +```c +/* No newlines are allowed after an opening curly + * brace or before a closing curly brace */ + +while (a > 0) +{ + + a = 6; + +} + +if (a > 5) +{ + while (b < 6) + { + + b++; + } + +} + + +/* Two or more newlines are not allowed. */ +a = 6; + + +b = 7; + +/* No newlines are allowed between control staments + * and their code blocks. */ + +if (a > 6) + +{ +} + +else + +{ +} + +do + +{ +} + +while (a < 6); +``` + +## Expressions + +Spaces are required around binary operators. No space is +needed otherwise. + +```diff ++++ Good +++ +``` + +```c +a = b + c; +a = (b + c) << 3; +a = b = c + ~d; +a += ++c + d++; +call_function (a * (b + !!c) - d + (e % f)); +if (a) +{ +} +``` + +```diff +--- Bad --- +``` + +```c +a=b+c; +a = b+c; +a += c + ( d ); +/* Introduce temporary variables or macros + * if the expression is too long. Occures rarely.. */ +a = b + + c; +if ( a + b > 0 ) +{ +} +``` + +## Logical operators + +All expressions with && and || logical operators must be +enclosed in parentheses. A single and multiline form is +allowed for these expressions. In the latter case each +line must start with the logical operator and each line +must be aligned to the column right after the opening +parenthesis. + +```diff ++++ Good +++ +``` + +```c +/* Single line form. */ +a = ((c && d) || (e && f)); + +a = (c + && d); + +a = (c + && (d || e) + && f); + +do +{ +} +while (a + && b); + +/* This form is rarely used but it is ok. */ +if (a + && (b + || c + || d) + && e) +{ +} +``` + +```diff +--- Bad --- +``` + +```c +if (a || b || + c) +{ +} + +/* Parentheses are missing. */ +a = b || c; + +/* Misaligned &&. */ +if (a + && b) +{ +} +``` + +## Ternary conditional operators + +A special form of ternary conditional operators are allowed +in JerryScript where the ? and : operators are on separate +lines in the same column. + +```diff ++++ Good +++ +``` + +```c +a = (b ? c + : d); + +/* Single line form is accepted as well. */ +a = (b ? c : d); + +/* This form is rarely used but it is ok. */ +if (a ? b + : (c ? d + : e)) +{ +} +``` + +```diff +--- Bad --- +``` + +```c +a = b ? + c : d; + +while (a ? b + : c) +{ +} + +if (a + ? b + : c) +{ +} +``` + +## Function calls + +There must be a space after the function name. Each argument +must be in the same or separated lines. In the former case +there must be a space before the next argument and in the +latter case all arguments must be aligned to the same column. + +```diff ++++ Good +++ +``` + +```c +function_a (); +function_b (a); +function_c (a, b, c); + +function_c (a, + b, + c); + +function_c (a, + b, + function_c (a, + b, + c); +``` + +```diff +--- Bad --- +``` + +```c +/* No space before the opening parenthesis. */ +function_f(); + +function_f ( +); + +function_g(a); + +function_g + (a + ); + +/* Two arguments on the same line. */ +function_h (a, b, + c); + +function_h (a, + b, c); + +/* Misaligned arguments. */ +function_h (a, + b, + c); +``` + +## Variable declarations + +JerryScript is a pure C99 codebase so variable +declarations can be anywhere in the code including +inside for-loops. It is recommended to declare a +variable before the first use. + +```diff ++++ Good +++ +``` + +```c +for (int i = 0; i < 10; i++) +{ + int j = i + 1; + while (j < 10) + { + ++j; + } +} + +/* Multiline form of for loops. */ +for (int i = 0; + i < 10; + i++) +{ +} +``` + +## Type casting + +There must be a space after the closing parenthesis +of the type cast. Type casting has no multiline form +in JerryScript. + +```diff ++++ Good +++ +``` + +```c +int a = (int) double_variable; + +int a = (int) (long) (float) double_variable; +``` + +```diff +--- Bad --- +``` + +```c +/* Wrong spaces. */ +int a = ( int )double_variable; + +/* No multiline form. */ +int a = (int) + double_variable; +``` + +## Pointers and asterisk character + +Each pointer in JerryScript must be a lowercase string +which is ending with a `_p` suffix. Furthermore there +must be a space before the asterisk character. + +```diff ++++ Good +++ +``` + +```c + int *int_p; + + /* No need to add multiple _p-s for multiple indirections. + * It is recommended to avoid these constructs using typedef + * declarations. A reviewer might request such a change. */ + int ***int_p; + + /* This rule applies for type casting as well. */ + char = *(char *) type_p; +``` + +```diff +--- Bad --- +``` + +```c + /* No _p after the name. */ + int *ptr; + + /* Wrong asterisk position. */ + int* ptr_p; + + char_p = * (char*)type_p; +``` + +## Types + +Each type in JerryScript must be a lowercase string +which ends with a `_t` suffix. Furthermore each type +declaration must be preceded by a short description +of the type and each field must have a short description +as well. + +```diff ++++ Good +++ +``` + +```c +/** + * Short description of the following structure. + */ +typedef struct +{ + /* Field descriptions do not start with capital letters + * and there is no full stop at the end. */ + field1_t field1; /**< description of field 1 */ + field2_t field2; /**< description of field 1 */ + + field_n_t field_n; /**< description of field n */ +} structure_name_t; + +/** + * Another integer type. + */ +typedef int jerry_int; +``` + +```diff +--- Bad --- +``` + +```c +typedef struct +{ + field_t field_without_description; +} structure_without_description_t; + +typedef struct { int a; } single_line_struct; + +typedef +union { +} +wrong_newlines_t; + +/* + * Bad comment format. + */ +typedef +char wrong_newlines_again_t; +``` + +## Function declarations + +Function declarations in JerryScript are verbose but this format +reduces the maintenance cost and allows faster understanding of +the code. + +```diff ++++ Good +++ +``` + +```c +/** + * Short overview about the purpose of this function. + * + * A more detailed explanation if needed. + * + * Note: + * Extra notes if needed. + * + * @return short description about the value + * returned by the function + */ +return_value_type_t +function_name (argument1, /**< description of argument1 */ + argument2, /**< description of argument2 */ + ... + argument_n, /**< description of argument n */ +{ + + /* Function body. */ + +} /* function_name */ +``` + +```diff +--- Bad --- +``` + +```c +static int +print (char *text) /**< description of text argument */ +{ + /* Missing comment before the function. */ +} /* print */ + +/** + * Prints the text received by the function. + * + * @return number of characters printed by the function + */ +int print(char *text) +{ + /* No description of text argument. */ + /* Missing comment at the end of the function. */ +} +```