1. CodingStyle
Contents
1.1. C
1.1.1. Introduction
The coding style is based on a number of reference models.
First and foremost, we recommend reading Linus' Linux Kernel Coding Style. We take almost everything from that and it highlights all of our practises and things we try to avoid. It is also quite amusing in places.
The GNOME Coding Style also expands on #1 and we also embrace these values.
Everything that follows is modification upon these existing styles. Some of what we mention below is already mentioned in the guides above, however, we will re-iterate them here for completeness.
We encourage you to follow the Tracker coding style throughout the Tracker project. For the core components (application and libs) this coding style is enforced.
1.1.2. Includes
NOTE: Some of these principles are taken from the GIMP documentation and have been in use for some time.
1. All .h files should not include anything, with two exceptions:
- Objects include their immediate parent class
If the header uses types like time_t (or off_t), it includes <time.h> (or <sys/types.h>). This only applies to system includes!
2. All .c files should have the following include order and have adequate spacing between groups:
#include "config.h" /* alyways and first */ #include <glib.h> /* *only* needed if the file needs stuff */ /* like G_OS_WIN32 for conditional inclusion */ /* of system headers */ #include <system headers> /* like <stdio.h> */ #include <glib-object.h> #include <libtracker-sparql/tracker-sparql.h> /* see next section for when to include */ /* top level header or specific headers */ #include "module/foo.h" /* files from modules below this one */ #include "module/bar.h" #include "gimp.h" /* files from this module */ #include "gimpimage.h" #include "gimpwhatever.h"
3. Each library has a top level include file, e.g. tracker-sparql.h. This includes all other headers needed for the library. For future compatibility:
For cases where the library is used, only this header should be included.
For cases where the library is dependent on building (e.g. libtracker-bus is required for libtracker-sparql) specific includes are fine.
1.1.3. Indentation & Spacing
- We use tabs for indentation and spaces for alignment
- We try to avoid ALL whitespace where possible.
Before sending in a patch you can check if you're changes have added any whitespace by using git diff --check.
For Emacs users, there is a whitespace-mode you can use with the whitespace and smarttab extensions. This make things a lot easier here).
- One tab should be used for the initial indentation, the editor should know how to align this based on the code. The rest of any alignment needed should use spaces.
Below the example illustrates tabs with ">>" and spaces with ".".
e.g.
static void tracker_miner_web_class_init (TrackerMinerWebClass *klass) { >> GObjectClass *object_class = G_OBJECT_CLASS (klass); >> object_class->set_property = miner_web_set_property; >> object_class->get_property = miner_web_get_property; >> object_class->constructed = miner_web_constructed; >> g_object_class_install_property (object_class, >> .................................PROP_ASSOCIATED, >> .................................g_param_spec_boolean ("associated", >> ......................................................."Associated", >> ......................................................."Tells if the miner is associated with the remote service", >> .......................................................FALSE, >> .......................................................G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); >> g_type_class_add_private (object_class, sizeof (TrackerMinerWebPrivate)); }
- Opening brackets are on a new line and inline with the above statement's starting column.
1.1.4. Functions
1.1.4.1. Declarations
- Function names are lowercase and words are separated by underscores.
- Function return types are on their own line as illustrated below.
- Parameters are separated by new lines and aligned.
e.g.
static gboolean parse_list_indexes (const gchar *option_name, const gchar *value, gpointer data, GError **error) { ... return TRUE; }
1.1.4.2. Prototypes
This includes in header files or prototyping in the same file:
- Function types are on the same line as the function name.
- All arguments are aligned according to all functions prototyped.
e.g.
static gchar * get_class_from_prefix (TrackerSparqlConnection *connection, const gchar *prefix); static gboolean parse_list_indexes (const gchar *option_name, const gchar *value, gpointer data, GError **error); static gboolean parse_list_notifies (const gchar *option_name, const gchar *value, gpointer data, GError **error); ...
1.1.5. Macros & Enums
- Macros and enums are all uppercase, words separated by underscores.
- Macros and enums are all aligned with values beginning on the same column.
- Enum names don't have to be in uppercase as below, only the definitions in the enum.
e.g.
#define TRACKER_DB_CACHE_SIZE_DEFAULT 250 #define TRACKER_DB_CACHE_SIZE_UPDATE 2000 typedef enum { TRACKER_DB_UNKNOWN, TRACKER_DB_METADATA, TRACKER_DB_FULLTEXT, } TrackerDB; typedef enum { TRACKER_DB_MANAGER_FORCE_REINDEX = 1 << 1, TRACKER_DB_MANAGER_REMOVE_CACHE = 1 << 2, /* 1 << 3 Was low mem mode */ TRACKER_DB_MANAGER_REMOVE_ALL = 1 << 4, TRACKER_DB_MANAGER_READONLY = 1 << 5 } TrackerDBManagerFlags;
1.1.6. Structures & Types
Types are all word capitalized with no separators between words, e.g. TrackerLanguagePriv and TrackerMinerWebClass below.
- Structs don't need to have their variables lined up, we used to do this, but stopped more recently.
- Structs should use spacing to make variable grouping clearer.
- Structs which have virtual methods should be aligned like function prototypes mentioned earlier.
e.g. Basic
typedef struct { GHashTable *stop_words; gboolean enable_stemmer; gchar *language_code; GMutex *stemmer_mutex; gpointer stemmer; } TrackerLanguagePriv;
e.g. Advanced
typedef struct { TrackerMinerClass parent_class; /* vmethods */ void (* authenticate) (TrackerMinerWeb *miner, GError **error); GHashTable* (* get_association_data) (TrackerMinerWeb *miner, GError **error); void (* associate) (TrackerMinerWeb *miner, const GHashTable *association_data, GError **error); void (* dissociate) (TrackerMinerWeb *miner, GError **error); } TrackerMinerWebClass;
1.1.7. Conditions
Braces should always be used for if statements, there is only one exception:
There is only 1 line that is run if TRUE and there are no else conditions. The reason for this is, else conditions made it harder to see if proceeding lines are part of the condition or not and adding lines can sometimes be done erroneously as a result.
- Operators should be at the end of the line, not at the beginning of the next line for multi-line conditions.
e.g. One line condition
if (foo == TRUE) return TRUE;
e.g. Multiple conditions
if (!list && show_files) { failed_str = _("The --list option is required for --show-files"); } else if (add_tag && remove_tag) { failed_str = _("Add and delete actions can not be used together"); } else if (!list && !add_tag && !remove_tag && !files) { failed_str = _("No arguments were provided"); } else if (description && !add_tag) { failed_str = _("The --description option can only be used with --add"); }
e.g. Multiple conditions on separate lines
if (strcmp (baz, "sliff") == 0 || strcmp (baz, "sloff") == 0) { return TRUE; } else { return FALSE; }
1.1.8. Switches
- Switch statements should avoid using assertions in default cases for several reasons (unless there is good reason):
- This hides new additions to enums which would be warned by the compiler in most cases
- Binaries should not abort because of an unhandled enum
e.g.
switch (signo) { case SIGABRT: case SIGALRM: _exit (EXIT_FAILURE); break; case SIGTERM: case SIGINT: in_loop = TRUE; disable_shutdown = FALSE; quit_timeout_cb (NULL); /* Fall through */ default: if (g_strsignal (signo)) { g_print ("\n"); g_print ("Received signal:%d->'%s'\n", signo, g_strsignal (signo)); } break; }
1.2. Vala
The coding style for Vala isn't too dissimilar to C. We stick to the Vala Coding Style as documented.