CodeGuidelines - musescore/MuseScore GitHub Wiki

Code guidelines

To keep the source consistent, readable, modifiable and easy to merge, we use a fairly rigid coding style. All patches will be expected to conform to the style and enforced by a CI job checking against it. The coding style described here is valid for the master branch (and all branches derived from that), for the 3.x branch (and prior to that) the old coding style is used.

MuseScore code style and conventions are based on the Qt code style and conventions, but there are some differences.

C++

Indentation

  • 4 spaces are used for indentation
  • Spaces, not tabs!

Namespace

  • All namespaces must be child to the global namespace mu
  • Namespaces names must be lowercase so they can be easily distinguished from class names
 // Wrong
 namespace Cool {
     ...
 }

 // Correct
 namespace mu::cool {
     ...
 }

Header and implementation

  • Header files have the extension .h, files implementation .cpp
  • Each header and implementation file must have a license text at the top
  • The header file must have a guard named MU_{MODULE}_{CLASSNAME}_H
  • Only declaration should be in the header files, avoid placing the implementation in header files, except when necessary, such as function-template definitions.
  • Important! Don't put the singletons implementation in the header file.

The class declaration should be in this order:

  1. licence
  2. guard
  3. includes
  4. forward declarations
  5. namespace
  6. class declaration
  7. Qt macro (Q_OBJECT, Q_PROPERTY, Q_ENUMS...)
  8. public methods (first constructor and destructor if they public)
  9. public slots
  10. signals
  11. protected
  12. private slots
  13. private methods
  14. private members
 // Correct
{LICENCE}

#ifndef MU_COOL_RECT_H
#define MU_COOL_RECT_H

#include <QObject>
#include <QRect>

namespace mu {
namespace cool {
class Rect : public QObject
{
    Q_OBJECT
public:
    explicit Rect(QObject* parent = nullptr);
    ~Rect();

    int width() const;
    int height() const;

    int square() const;

public slots:
    void setWidth(int w);
    void setHeight(int h);

signals:
    void squareChanged(int sq);

private:
    void updateSquare();

    QRect m_rect;
    int m_square = 0;
};
}
}

#endif // MU_COOL_RECT_H
// Correct

{LICENCE}

#include "rect.h"

Rect::Rect(QObject* parent)
    : QObject(parent)
{
}

Rect::~Rect()
{
}

void Rect::updateSquare()
{
    int s = width() * height();
    if (s != m_square) {
        m_square = s;
        emit squareChanged(s);
    }
}

void Rect::setWidth(int w)
{
    m_rect.setWidth(w);
    updateSquare();
}

int Rect::width() const
{
    return m_rect.width();
}

void Rect::setHeight(int h)
{
    m_rect.setHeight(h);
    updateSquare();
}

int Rect::height() const
{
    return m_rect.height();
}

int Rect::square() const
{
    return m_square;
}
  • If there is initialization in constructors, always put a colon on a new line
// Wrong
ClassName::ClassName(int arg) : Base(), m_param(arg) {}

ClassName::ClassName(int arg) : Base(), m_param(arg)
{}

ClassName::ClassName(int arg) :
    Base(), m_param(arg)
{
}

// Correct
ClassName::ClassName(int arg)
    : Base(), m_param(arg)
{  
}

Declaring variables

  • Declare each variable on a separate line
  • Avoid short or meaningless names (e.g. "a", "rbarr", "nughdeget")
  • Single character variable names are only okay for counters and temporaries, where the purpose of the variable is obvious
  • Wait when declaring a variable until it is needed
  • For pointers or references, no space between the '*' or '&' and type (different from Qt)
  • Always initialize the variable with the initial value.
  • Use nullptr, rather than 0, to initialize pointers.
 // Wrong
 int a, b;
 char *c, *d;
 const Type &val = ...
 void func(const Type &val);

 // Correct
 int height = 0;
 int width = 0;
 char* nameOfThis = nullptr;
 char* nameOfThat = nullptr;
 const Type& val = ...
 void foo(const Type& val);
  • Variables and functions start with a lower-case letter. Each consecutive word in a variable's name starts with an upper-case letter (camelCase)
  • Constants all uppercase letters and underscore to separate words
  • Avoid abbreviations
 // Wrong
 short Cntr;
 int panel_height = 0;
 char ITEM_DELIM = ' ';

 // Correct
 short counter = 0;
 int panelHeight = 0;
 const char ITEM_DELIMITER = ' ';
  • Classes and structures always start with an upper-case letter.
  • Acronyms are camel-cased (e.g. XmlReader, not XMLReader).
  • Data members of classes are named like ordinary nonmember variables, but with a prefix m_.
  • Public members of struct (POD) are named like ordinary nonmember variables, with out any prefix.
 // Wrong
 class counter
 {
 ...
 private:
     int count;
 }

 class HTMLParser
 {
 ...
 private:
     char* _data;
 }

 // Correct
 class Counter
 {
 ...
 private:
     int m_count = 0;
 }

 class HtmlParser
 {
 ...
 private:
     char* m_data = nullptr;
 }

Whitespace

  • Use blank lines to group statements together where suited
  • Always use only one blank line
  • Always use a single space after a keyword and before a curly brace:
 // Wrong
 if(foo){
     ...
 }

 // Correct
 if (foo) {
     ...
 }
  • Surround binary operators with spaces
  • Leave a space after each comma
  • No space after a cast, avoid C-style casts when possible
 // Wrong
 char *blockOfMemory = (char* ) malloc(data.size());

 // Correct
 char* blockOfMemory = reinterpret_cast<char*>(malloc(data.size()));

Use safer type conversion when possible:

// Wrong
Chord* chord = static_cast<Chord*>(e);

// Correct
Chord* chord = toChord(e);

Braces

  • Use attached braces: The opening brace goes on the same line as the start of the statement. If the closing brace is followed by another keyword, it goes into the same line as well:
 // Wrong
 if (codec)
 {
     ...
 }
 else
 {
     ...
 }

 if (codec) {
     ...
     }

 // Correct
 if (codec) {
     ...
 } else {
     ...
 }
  • Exception: Function implementations (but not lambdas) and class declarations always have the left brace on the start of a line:
 static void foo(int g)
 {
     ...
 }

 class Moo
 {
     ...
 };
  • Do not put multiple statements on one line
  • If the body of the expression consists of one line, add braces anyway (different from Qt)
 // Wrong
 if (foo) bar();

 if (foo)
     bar();

 // Correct
 if (foo) {
     bar();
 }
  • Do not put 'else' after jump statements:
 // Wrong
 if (thisOrThat)
     return;
 else
     somethingElse();

 // Correct
 if (thisOrThat) {
     return;
 }

 somethingElse();

Parentheses

  • Use parentheses to group expressions:
 // Wrong
 if (a && b || c)

 // Correct
 if ((a && b) || c)

 // Wrong
 a + b & c

 // Correct
 (a + b) & c

Line breaks

  • Keep lines shorter than 120 characters; wrap if necessary
  • Commas go at the end of wrapped lines; operators start at the beginning of the new lines. An operator at the end of the line is easy to miss if the editor is too narrow.
 // Wrong
 if (longExpression +
     otherLongExpression +
     otherOtherLongExpression) {
 }

 // Correct
 if (longExpression
     + otherLongExpression
     + otherOtherLongExpression) {
 }

General exceptions

  • When strictly following a rule makes your code look bad, feel free to break it.
  • If there is a dispute in any given code, create a pull request with the proposed changes to the style code.

Qml

In general, the same style as for C++

  • Property names as well as C ++ variable names
  • Private property must be a separate object
 // Wrong
 Item {
     property var cntr
     property var internal_data

     ...
 }

 // Correct
 Item {

     property var counter: 0

     QObject {
         id: prv
         property var data: null
     }

     ...
 }
  • The opening brace goes on the same line as the start of the statement (with no exceptions)
 // Wrong
 Rectangle
 {
     width: 40
     height: 20
     ...
 }

 function do_something()
 {
     ...
 }

 // Correct
 Rectangle {

     width: 40
     height: 20
     ...
 }

 function doSomeThing() {
     ...
 }
  • This is the order of properties in a QML item
Object {
    id: someID

    // newline here
    
    anchors.someProperty: ...
    anchors.another: ...
    // Or:
    Layout.someProperty: ...

    // newline here

    someRegularProperty: ...
    anotherOne: ...

    // newline here

    navigation.someProperty: ...

    // newline here

    onSomeSignal: {
        doSomething()
    }

    onSomeSignalWithParameter: function(param) {
        soSomethingWith(param)
    }
}

CMake

//! TODO need to write like this

⚠️ **GitHub.com Fallback** ⚠️