From: Matthias Clasen Date: Fri, 24 Sep 2010 02:26:07 +0000 (-0400) Subject: docs: Add a CODING-STYLE document X-Git-Url: http://pileus.org/git/?a=commitdiff_plain;h=3557761fb35dcf94825e8a3df92f3c40da1bde90;p=~andy%2Fgtk docs: Add a CODING-STYLE document This document mostly codifies the existing GTK+ coding style conventions; it is strongly based on the clutter document of the same name. --- diff --git a/docs/CODING-STYLE b/docs/CODING-STYLE new file mode 100644 index 000000000..7b2e8f23f --- /dev/null +++ b/docs/CODING-STYLE @@ -0,0 +1,635 @@ +GTK+ Coding Style +------------------------------------------------------------------------------- + +This document is intended to be a short description of the preferred +coding style to be used for the GTK+ source code. It was strongly +inspired by Clutter's CODING_STYLE. + +Coding style is a matter of consistency, readability and maintainance; +coding style is also completely arbitrary and a matter of taste. This +document will use examples at the very least to provide authoritative +and consistent answers to common questions regarding the coding style, +and will also try to identify the allowed exceptions. + +The examples will show the preferred coding style; the negative examples +will be clearly identified. Please, don't submit code to GTK+ that +looks like any of these. + +Part of the rationales for these coding style rules are available either +in the kernel CodingStyle document or in Cairo's CODING_STYLE one. + +When in doubt, check the surrounding code and try to imitate it. + ++ Line width + +The maximum line width for source files is 80 characters, whenever possible. +Longer lines are usually an indication that you either need a function +or a pre-processor macro. + ++ Indentation + +Each new level is indented 2 or more spaces than the previous level: + + if (condition) + single_statement (); + +This can only be achieved using space characters. It may not be achieved +using tab characters alone, or using a combination of spaces and tabs. + +Do not change the editor's configuration to change the meaning of a +tab character (see below); code using tabs to indent will not be accepted +into GTK+. + +Even if two spaces for each indentation level allows deeper nesting than +8 spaces, GTK+ favours self-documenting function names that can take +quite some space. For this reason you should avoid deeply nested code. + ++ Tab characters + +The tab character must always be expanded to spaces. If a literal +tab must be used inside the source, the tab must always be interpreted +according to its traditional meaning: + + Advance to the next column which is a multiple of 8. + [ these two lines should be aligned ] + ++ Braces + +Curly braces should not be used for single statement blocks: + + if (condition) + single_statement (); + else + another_single_statement (arg1); + +In case of multiple statements, curly braces should be put on another +indentation level: + + if (condition) + { + statement_1 (); + statement_2 (); + statement_3 (); + } + +The "no block for single statements" rule has only four exceptions: + + ① if the single statement covers multiple lines, e.g. for functions with + many arguments, and it is followed by else or else if: + + /* valid */ + if (condition) + { + a_single_statement_with_many_arguments (some_lengthy_argument, + another_lengthy_argument, + and_another_one, + plus_one); + } + else + another_single_statement (arg1, arg2); + + ② if the condition is composed of many lines: + + /* valid */ + if (condition1 || + (condition2 && condition3) || + condition4 || + (condition5 && (condition6 || condition7))) + { + a_single_statement (); + } + + ③ Nested if's, in which case the block should be placed on the + outermost if: + + /* valid */ + if (condition) + { + if (another_condition) + single_statement (); + else + another_single_statement (); + } + + /* invalid */ + if (condition) + if (another_condition) + single_statement (); + else if (yet_another_condition) + another_single_statement (); + + ④ If either side of an if-else statement has braces, both sides + should, to match up indentation: + + /* valid */ + if (condition) + { + foo (); + bar (); + } + else + { + baz (); + } + + /* invalid */ + if (condition) + { + foo (); + bar (); + } + else + baz (); + +In general, new blocks should be placed on a new indentation level, +like: + + int retval = 0; + + statement_1 (); + statement_2 (); + + { + int var1 = 42; + gboolean res = FALSE; + + res = statement_3 (var1); + + retval = res ? -1 : 1; + } + +While curly braces for function definitions should rest on a new line +they should not add an indentation level: + + /* valid */ + static void + my_function (int argument) + { + do_my_things (); + } + + /* invalid */ + static void + my_function (int argument) { + do_my_things (); + } + + /* invalid */ + static void + my_function (int argument) + { + do_my_things (); + } + +Curly braces must not be placed on the same line as a condition: + + /* invalid */ + if (condition) { + statement_1 (); + statement_2 (); + } ++ Conditions + +Do not check boolean values for equality: + + /* invalid */ + if (condition == TRUE) + do_foo (); + + /* valid */ + if (another_condition) + do_bar (); + +Even if C handles NULL equality like a boolean, be explicit: + + /* valid */ + if (some_pointer == NULL) + do_blah (); + + /* invalid */ + if (some_other_pointer) + do_blurp (); + +In case of conditions split over multiple lines, the logical operators should +always go at the end of the line: + + /* invalid */ + if (condition1 + || condition2 + || condition3) + { + do_foo (); + } + + /* valid */ + if (condition1 && + condition2 && + (condition3 || (condition4 && condition5))) + { + do_blah (); + } + ++ Functions + +Functions should be declared by placing the returned value on a separate +line from the function name: + + void + my_function (void) + { + } + +The arguments list must be broken into a new line for each argument, +with the argument names right aligned, taking into account pointers: + + void + my_function (some_type_t type, + another_type_t *a_pointer, + final_type_t another_type) + { + } + +The alignment also holds when invoking a function without breaking the +80 characters limit: + + align_function_arguments (first_argument, + second_argument, + third_argument); + +To respect the 80 characters limit do not break the function name from +the arguments: + + /* invalid */ + a_very_long_function_name_with_long_parameters + (argument_the_first, argument_the_second); + + /* valid */ + first_a = argument_the_first; + second_a = argument_the_second; + a_very_long_function_name_with_long_parameters (first_a, second_a); + ++ Whitespace + +Always put a space before a parenthesis but never after: + + /* valid */ + if (condition) + do_my_things (); + + /* valid */ + switch (condition) + { + } + + /* invalid */ + if(condition) + do_my_things(); + + /* invalid */ + if ( condition ) + do_my_things ( ); + +A switch() should open a block on a new indentation level, and each case +should start on the same indentation level as the curly braces, with the +case block on a new indentation level: + + /* valid */ + switch (condition) + { + case FOO: + do_foo (); + break; + + case BAR: + do_bar (); + break; + } + + /* invalid */ + switch (condition) { + case FOO: do_foo (); break; + case BAR: do_bar (); break; + } + + /* invalid */ + switch (condition) + { + case FOO: do_foo (); + break; + case BAR: do_bar (); + break; + } + + /* invalid */ + switch (condition) + { + case FOO: + do_foo (); + break; + case BAR: + do_bar (); + break; + } + +It is preferable, though not mandatory, to separate the various cases with +a newline: + + switch (condition) + { + case FOO: + do_foo (); + break; + + case BAR: + do_bar (); + break; + + default: + do_default (); + } + +The 'break' statement for the default: case is not mandatory. + +If a case block needs to declare new variables, the same rules as the +inner blocks (see above) apply; the break statement should be placed +outside of the inner block: + + switch (condition) + { + case FOO: + { + int foo; + + foo = do_foo (); + } + break; + + ... + } + +When declaring a structure type use newlines to separate logical sections +of the structure: + + struct _GtkWrapBoxPrivate + { + GtkOrientation orientation; + GtkWrapAllocationMode mode; + + GtkWrapBoxSpreading horizontal_spreading; + GtkWrapBoxSpreading vertical_spreading; + + guint16 vertical_spacing; + guint16 horizontal_spacing; + + guint16 minimum_line_children; + guint16 natural_line_children; + + GList *children; + }; + + +Do not eliminate whitespace and newlines just because something would +fit on 80 characters: + + /* invalid */ + if (condition) foo (); else bar (); + +Do eliminate trailing whitespace on any line, preferably as a separate +patch or commit. Never use empty lines at the beginning or at the end of +a file. + +Do enable the default git pre-commit hook that detect trailing +whitespace for you and help you to avoid corrupting GTK+'s tree with +it. Do that as follows: + + chmod a+x .git/hooks/pre-commit + +You might also find the git-stripspace utility helpful which acts as a +filter to remove trailing whitespace as well as initial, final, and +duplicate blank lines. + ++ Headers + +Headers are special, for GTK+, in that they don't have to obey the +80 characters limit. The only major rule for headers is that the function +definitions should be vertically aligned in three columns: + + return value function_name (type argument, + type argument, + type argument); + +The maximum width of each column is given by the longest element in the +column: + + void gtk_type_set_property (GtkType *type, + const gchar *value, + GError **error); + G_CONST_RETURN gchar *gtk_type_get_property (GtkType *type); + +It is also possible to align the columns to the next tab: + + void gtk_type_set_prop (GtkType *type, + gfloat value); + gfloat gtk_type_get_prop (GtkType *type); + gint gtk_type_update_foobar (GtkType *type); + +Public headers should never be included directly: + + #if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION) + #error "Only can be included directly." + #endif + +All headers should have inclusion guards (for internal usage) +and C++ guards: + + #ifndef __GTK_FOO_H__ + #define __GTK_FOO_H__ + + #include + + G_BEGIN_DECLS + + ... + + G_END_DECLS + + #endif /* __GTK_FOO_H__ */ + ++ Includes + +GTK+ source files should never include the global gtk.h header, but +instead include the individual headers that are needed. Every file must +include config.h first, then its own header, then other GTK+ headers +that it needs, then system and third-party headers that it needs. + + /* valid */ + #include "config.h" + + #include "gtkfoo.h" + + #include "gtkwidget.h" + #include "gtkbutton.h" + + ... + + #include + + ++ GObject + +GObject classes definition and implementation require some additional +coding style notices. + +Typedef declarations should be placed at the beginning of the file: + + typedef struct _GtkFoo GtkFoo; + typedef struct _GtkFooClass GtkFooClass; + typedef struct _GtkFooPrivate GtkFooPrivate; + +This includes enumeration types: + + typedef enum + { + GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT, + GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH + } GtkSizeRequestMode; + +And callback types: + + typedef void (* GtkCallback) (GtkWidget *widget, + gpointer user_data); + +Instance structures should only contain the parent type and a pointer to a +private data structure, and they should be annotated as "private": + + struct _GtkFoo + { + /*< private >*/ + GtkWidget parent_instance; + + GtkFooPrivate *priv; + }; + +All the properties should be stored inside the private data structure, which +is defined inside the source file - or, if needed, inside a private header +file; the private header filename must end with "private.h" and must not be +installed. + +The private data structure should only be accessed internally using the +pointer inside the instance structure, and never using the +G_TYPE_INSTANCE_GET_PRIVATE() macro or the g_type_instance_get_private() +function. + +Always use the G_DEFINE_TYPE(), G_DEFINE_TYPE_WITH_CODE() macros, or +their abstract variants G_DEFINE_ABSTRACT_TYPE() and +G_DEFINE_ABSTRACT_TYPE_WITH_CODE(), and the similar macros for defining +interfaces. + +Interface types should always have the dummy typedef for cast purposes: + + typedef struct _GtkFoo GtkFoo; + +The interface structure should have "Interface" postfixed to the dummy typedef: + + typedef struct _GtkFooInterface GtkFooInterface; + +Interfaces must have the following macros: + + - Macro: - Expands to: + • GTK_TYPE_ _get_type + • GTK_ G_TYPE_CHECK_INSTANCE_CAST + • GTK_IS_ G_TYPE_CHECK_INSTANCE_TYPE + • GTK__GET_IFACE G_TYPE_INSTANCE_GET_INTERFACE + ++ Memory allocation + +When dynamically allocating data on the heap either use g_new() or, +if allocating multiple small data structures, g_slice_new(). + +Public structure types should always be returned after being zero-ed, +either explicitly for each member, or by using g_new0() or g_slice_new0(). + ++ Macros + +Try to avoid private macros unless strictly necessary. Remember to #undef +them at the end of a block or a series of functions needing them. + +Inline functions are usually preferable to private macros. + +Public macros should not be used unless they evaluate to a constant. + ++ Public API + +Avoid exporting variables as public API, since this is cumbersome on some +platforms. It is always preferable to add getters and setters instead. + +All public functions must be listed in the gtk.symbols file. + ++ Private API + +Non-exported functions that are needed in more than one source file +should be named "_gtk_...", and declared in a private header file. + +Underscore-prefixed functions are never exported. + +Non-exported functions that are only needed in one source file +should be declared static. + ++ Documentation + +All public APIs must have gtk-doc comments. For functions, these should +be placed in the source file, directly above the function. + + /* valid */ + /** + * gtk_get_flow: + * @widget: a #GtkWidget + * + * Gets the flow of a widget. + * + * Note that flows may be laminar or turbulent... + * + * Returns: (transfer none): the flow of @widget + */ + GtkFlow * + gtk_get_flow (GtkWidget *widget) + { + + ... + + } + +Doc comments for macros, function types, class structs, etc should be +placed next to the definitions, typically in headers. + +Section introductions should be placed in the source file they describe, +after the license header: + + /* valid */ + /** + * SECTION:gtksizerequest + * @Short_Description: Height-for-width geometry management + * @Title: GtkSizeRequest + * + * The GtkSizeRequest interface is GTK+'s height-for-width (and + * width-for-height) geometry management system. + * ... + */ + +To properly document a new function, macro, function type or struct, +it needs to be listed in the gtk3-sections.txt file. + +To properly document a new class, it needs to be given its own section +in gtk3-sections.txt, needs to be included in gtk-docs.sgml, and the +get_type function needs to listed in gtk3.types. + ++ Old code + +New code that is being added to GTK+ should adhere to the style +explained above. Existing GTK+ code does largely follow these +conventions, but there are some differences, e.g. occurrences +of tabs, etc. + +It is ok to update the style of a code block or function when you +are touching it anyway, but sweeping whitespace changes obscure the +git history and should be avoided.