Policies/Frameworks Coding Style: Difference between revisions

    From KDE TechBase
    (Initial stub for KF5 coding style)
     
    (Add a statement about whitespace in range-based for loops)
    (10 intermediate revisions by one other user not shown)
    Line 1: Line 1:
    {{Note|1=This is a style guide for KDE Frameworks 5. If you write code that is not targeted at KF5, but only at KDE SC 4, refer to [[Policies/Kdelibs_Coding_Style|that style guide]].}}
    {{Note|1=This is a style guide for KDE Frameworks 5. If you write code that is not targeted at KF5, but only at KDE SC 4, refer to [[Policies/Kdelibs_Coding_Style|that style guide]].}}
    {{Note|1=This style guide describes the preferred coding style in KDE Frameworks 5. It is no set of absolute rules. You can break them in particular situations if it improves the readability of the code or you have some other good reason for doing so.}}


    == Indentation ==
    == Indentation ==
    * 4 spaces
    * 4 spaces
    * no tabs
    * No tabs
     
    == Variable Declarations ==
    * Each variable declaration on a new line
    * Each new word in a variable name starts with a capital letter (so-called camelCase)
    * Avoid abbreviations
    * Take useful names. No short names, except:
    ** Single character variable names can denote counters and temporary variables whose purpose is obvious
    * Variables and functions start with a lowercase letter
     
    Example:
    <syntaxhighlight lang="cpp-qt">
    // wrong
    KCategorizedView *catview;
    QString prtxt, Errstr;
     
    // correct
    KCategorizedView *groupedDeviceList;
    QString progressText;
    QString errorString;
    </syntaxhighlight>
     
    == Whitespace ==
    * Use blank lines to group statements
    * Use only one empty line
    * One space after each keyword
    ** Exception: No space between return and ';'
    * No space after left parentheses/before right parentheses
    * For pointers or references, use a single space before '*' or '&', but not after
    * No space after a cast
    * Single spaces around binary arithmetic operators '+', '-', '*', '/', '%'
    * In function headers and calls: No space before and one space after commas
    ** Exception: Normalized SIGNAL/SLOT string descriptors in calls to QObject::connect()
    * Insert a single space before and after the colon in a range-based for loop
     
    Example:
    <syntaxhighlight lang="cpp-qt">
    // wrong
    QString* myString;
    if( a%7 > 3 ){
        setPos( x , y );
        return ;
    }
    for( const QString& fileName: fileNames ){
        showFileContents( fileName );
    }
     
    // correct
    QString *myString;
    if (a % 7 > 3) {
        setPos(x, y);
        return;
    }
    for (const QString &fileName : fileNames) {
        showFileContents(fileName);
    }
    </syntaxhighlight>
     
    == Braces ==
    * As a base rule, the left curly brace goes on the same line as the start of the statement.
     
    Example:
    <syntaxhighlight lang="cpp-qt">
    // wrong
    if (true)
    {
    }
     
    // correct
    if (true) {
    }
    </syntaxhighlight>


    == Qt Includes ==
     
    * Exception: Function implementations, class, struct and namespace declarations always have the opening brace on the start of a line.
     
    Example:
    <syntaxhighlight lang="cpp-qt">
    void debug(int i)
    {
        qDebug("foo: %i", i);
    }
     
    class Debug
    {
    };
    </syntaxhighlight>
     
     
    * Use curly braces even when the body of a conditional statement contains only one line.
    * Put 'else' on the same line as the closing brace of the corresponding if block
     
    Example:
    <syntaxhighlight lang="cpp-qt">
    // wrong
    if (active)
        return true;
    else
        return j == 0;
     
    for (int i = 0; i < 10; ++i)
        qDebug("%i", i);
     
    // correct
    if (active) {
        return true;
    } else {
        return j == 0;
    }
     
    for (int i = 0; i < 10; ++i) {
        qDebug("%i", i);
    }
    </syntaxhighlight>
     
    == Switch Statements ==
    Case labels are on the same column as the switch
     
    Example:
    <syntaxhighlight lang="cpp-qt">
    switch (myEnum) {
    case Value1:
        doSomething();
        break;
    case Value2:
        doSomethingElse();
        // fall through
    default:
        defaultHandling();
        break;
    }
    </syntaxhighlight>
     
    == Line Breaks ==
    Try to keep lines shorter than 100 characters, inserting line breaks as necessary.
     
    ==Includes==
    * If possible use forward declarations in header files and put the corresponding includes in the implementation files.
    * Includes are grouped in sections which come in this order:
    ** In implementation files the corresponding header file (if applicable). This helps catch when you forget to put includes or forward declarations in the header.
    ** Headers from same framework.
    ** Headers from other frameworks.
    ** Qt headers.
    ** Other headers.
    * Each section is sorted alphabetically.
     
    Example:
    <syntaxhighlight lang="cpp-qt">
    // Includes in the implementation of the fictitious class KoolStuffPlugin
    // Own header
    #include "koolstuffplugin.h"
     
    // Own framework
    #include "koollib.h"
    #include "koolstuff.h"
     
    // Other frameworks
    #include <KComboBox>
    #include <KFile>
    #include <KIO/FileJob>
    #include <KNotification>
    #include <KPlotWidget>
     
    // Qt
    #include <QString>
     
    // Other
    #include <stdlib.h>
    </syntaxhighlight>
     
    === Qt Includes and KDE Frameworks Includes ===
    * For Qt #includes omit the module name and only use the class name.  That way chances are good that future migrations of Qt classes between different modules do not need any adjustments in the code.
    * For Qt #includes omit the module name and only use the class name.  That way chances are good that future migrations of Qt classes between different modules do not need any adjustments in the code.


    Line 19: Line 189:


    {{Note|1=This policy applies to KF5 and is the exact opposite of the preferred style for kdelibs in KDE SC 4.}}
    {{Note|1=This policy applies to KF5 and is the exact opposite of the preferred style for kdelibs in KDE SC 4.}}
    Apply the same principle for Frameworks #includes:
    <syntaxhighlight lang="cpp-qt">
    // wrong
    #include <KIOCore/KFileItem>
    #include <KIOCore/KIO/HostInfo>
    // correct
    #include <KFileItem>
    #include <KIO/HostInfo>
    </syntaxhighlight>
    ==Include Guards==
    * Take the name of the header file, make it all upper case, and replace anything that is not a letter or a number with an underscore '_'.
    * If you would include it with a leading directory, use that as part of the include guard.
    * Do not add leading or trailing underscores.
    * Put them below any license text.
    Example for kaboutdata.h:
    <syntaxhighlight lang="cpp-qt">
    #ifndef KABOUTDATA_H
    #define KABOUTDATA_H
    </syntaxhighlight>
    Example for kio/job.h:
    <syntaxhighlight lang="cpp-qt">
    #ifndef KIO_JOB_H
    #define KIO_JOB_H
    </syntaxhighlight>

    Revision as of 11:25, 17 January 2020

    Note
    This is a style guide for KDE Frameworks 5. If you write code that is not targeted at KF5, but only at KDE SC 4, refer to that style guide.


    Note
    This style guide describes the preferred coding style in KDE Frameworks 5. It is no set of absolute rules. You can break them in particular situations if it improves the readability of the code or you have some other good reason for doing so.


    Indentation

    • 4 spaces
    • No tabs

    Variable Declarations

    • Each variable declaration on a new line
    • Each new word in a variable name starts with a capital letter (so-called camelCase)
    • Avoid abbreviations
    • Take useful names. No short names, except:
      • Single character variable names can denote counters and temporary variables whose purpose is obvious
    • Variables and functions start with a lowercase letter

    Example:

    // wrong
    KCategorizedView *catview;
    QString prtxt, Errstr;
    
    // correct
    KCategorizedView *groupedDeviceList;
    QString progressText;
    QString errorString;
    

    Whitespace

    • Use blank lines to group statements
    • Use only one empty line
    • One space after each keyword
      • Exception: No space between return and ';'
    • No space after left parentheses/before right parentheses
    • For pointers or references, use a single space before '*' or '&', but not after
    • No space after a cast
    • Single spaces around binary arithmetic operators '+', '-', '*', '/', '%'
    • In function headers and calls: No space before and one space after commas
      • Exception: Normalized SIGNAL/SLOT string descriptors in calls to QObject::connect()
    • Insert a single space before and after the colon in a range-based for loop

    Example:

    // wrong
    QString* myString;
    if( a%7 > 3 ){
        setPos( x , y );
        return ;
    }
    for( const QString& fileName: fileNames ){
        showFileContents( fileName );
    }
    
    // correct
    QString *myString;
    if (a % 7 > 3) {
        setPos(x, y);
        return;
    }
    for (const QString &fileName : fileNames) {
        showFileContents(fileName);
    }
    

    Braces

    • As a base rule, the left curly brace goes on the same line as the start of the statement.

    Example:

    // wrong
    if (true)
    {
    }
    
    // correct
    if (true) {
    }
    


    • Exception: Function implementations, class, struct and namespace declarations always have the opening brace on the start of a line.

    Example:

    void debug(int i)
    {
        qDebug("foo: %i", i);
    }
    
    class Debug
    {
    };
    


    • Use curly braces even when the body of a conditional statement contains only one line.
    • Put 'else' on the same line as the closing brace of the corresponding if block

    Example:

    // wrong
    if (active)
        return true;
    else
        return j == 0;
    
    for (int i = 0; i < 10; ++i)
        qDebug("%i", i);
    
    // correct
    if (active) {
        return true;
    } else {
        return j == 0;
    }
    
    for (int i = 0; i < 10; ++i) {
        qDebug("%i", i);
    }
    

    Switch Statements

    Case labels are on the same column as the switch

    Example:

    switch (myEnum) {
    case Value1:
        doSomething();
        break;
    case Value2:
        doSomethingElse();
        // fall through
    default:
        defaultHandling();
        break;
    }
    

    Line Breaks

    Try to keep lines shorter than 100 characters, inserting line breaks as necessary.

    Includes

    • If possible use forward declarations in header files and put the corresponding includes in the implementation files.
    • Includes are grouped in sections which come in this order:
      • In implementation files the corresponding header file (if applicable). This helps catch when you forget to put includes or forward declarations in the header.
      • Headers from same framework.
      • Headers from other frameworks.
      • Qt headers.
      • Other headers.
    • Each section is sorted alphabetically.

    Example:

    // Includes in the implementation of the fictitious class KoolStuffPlugin
    // Own header
    #include "koolstuffplugin.h"
    
    // Own framework
    #include "koollib.h"
    #include "koolstuff.h"
    
    // Other frameworks
    #include <KComboBox>
    #include <KFile>
    #include <KIO/FileJob>
    #include <KNotification>
    #include <KPlotWidget>
    
    // Qt
    #include <QString>
    
    // Other
    #include <stdlib.h>
    

    Qt Includes and KDE Frameworks Includes

    • For Qt #includes omit the module name and only use the class name. That way chances are good that future migrations of Qt classes between different modules do not need any adjustments in the code.

    Example:

    // wrong
    #include <QtCore/QString>
    
    // correct
    #include <QString>
    


    Note
    This policy applies to KF5 and is the exact opposite of the preferred style for kdelibs in KDE SC 4.


    Apply the same principle for Frameworks #includes:

    // wrong
    #include <KIOCore/KFileItem>
    #include <KIOCore/KIO/HostInfo>
    
    // correct
    #include <KFileItem>
    #include <KIO/HostInfo>
    

    Include Guards

    • Take the name of the header file, make it all upper case, and replace anything that is not a letter or a number with an underscore '_'.
    • If you would include it with a leading directory, use that as part of the include guard.
    • Do not add leading or trailing underscores.
    • Put them below any license text.


    Example for kaboutdata.h:

    #ifndef KABOUTDATA_H
    #define KABOUTDATA_H
    


    Example for kio/job.h:

    #ifndef KIO_JOB_H
    #define KIO_JOB_H