mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
798 lines
12 KiB
Markdown
798 lines
12 KiB
Markdown
# 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 2 */
|
|
|
|
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. */
|
|
}
|
|
```
|