Skip to content

Formatting the source code

Peter Jonas edited this page Jun 17, 2024 · 1 revision

C++ and friends

We have strict style guidelines for the C++ code, and any files written in similar languages like plain C or Objective C, but not to third-party code.

The guidelines are enforced in pull requests by the codestyle CI check, which uses Uncrustify to format the code, and gives an error if any style violations were detected.

You can save time by running Uncrustify on your local machine before you push code to GitHub.

Download Uncrustify

Make sure you get Uncrustify version 0.73, as this is the version used by the codestyle check.

Don't try to install Uncrustify from a package manager as this will give you the wrong version.

Add Uncrustify to PATH

Once extracted/compiled, you'll need to add the location of the uncrustify binary to your PATH environment variable, or move it to a location that's already in PATH.

Run Uncrustify manually

You could use the scripts in tools/codestyle to run Uncrustify on a single file, a directory of files, or the entire repository.

You'd need to do this every time you change the code, so it's probably better to use the automatic methods given below.

Run Uncrustify on every commit

This method uses a pre-commit hook to ensure that code is formatted with Uncrustify before it gets committed. This works regardless of how you edit the code, but you won't see the benefit in your IDE until you create a commit. Also, when you create the commit, the modification timestamp will update on any files that Uncrustify changes, which means these files will get recompiled on the next build. For best results, use this method in combination with running Uncrustify in your IDE.

Run this command once in MuseScore's source folder to enable our pre-commit hook:

# Linux and macOS
ln -s ../../hooks/pre-commit .git/hooks/pre-commit

# Git Bash with sudo (creates a real symbolic link)
MSYS=winsymlinks:nativestrict sudo ln -s ../../hooks/pre-commit .git/hooks/pre-commit

# Git Bash without sudo (creates a Windows .lnk shortcut that simulates a symlink)
MSYS=winsymlinks:lnk ln -s ../../hooks/pre-commit .git/hooks/pre-commit

# CMD (Administrator prompt or sudo required)
mklink .git\hooks\pre-commit ..\..\hooks\pre-commit

# PowerShell (Administrator prompt or sudo required)
cmd /c mklink .git\hooks\pre-commit ..\..\hooks\pre-commit

Now Git will run Uncrustify for you each time you commit code, so you never have to think about it!

If you need to disable the pre-commit hook later on, run this command:

# CMD and PowerShell
del .git\hooks\pre-commit

# All other shells (also works in PowerShell)
rm .git/hooks/pre-commit

Or you can disable the hook temporarily by passing the -n/--no-verify option to git commit.

Run Uncrustify in your IDE

Many IDEs provide an option to reformat code every time you save a file. This means you don't have to create a commit to see the improvements, and the modification timestamp is never updated unnecessarily. However, this method won't format files edited outside the IDE, so for best results you should use this method in combination with the pre-commit hook.

Run Uncrustify in Qt Creator

  1. Go to Help → About Plugins → C++.
    1. Enable Beautifier (experimental).
    2. Click OK and restart Qt Creator.
  2. Go to Edit → Preferences → Beautifier.
    1. Enable Automatic Formatting on File Save.
    2. Below this, change the Tool dropdown to "Uncrustify".
  3. Go to the Uncrustify tab.
    1. In Uncrustify command, enter the full path to your Uncrustify binary (or browse to it).
    2. Disable Use file uncrustify.cfg defined in project files.
    3. Enable Use file specific uncrustify.cfg and browse to tools/codestyle/uncrustify_musescore.cfg.

Run Uncrustify in VSCode

  1. Install the "Uncrustify" extension.
  2. Open VS Code Settings and find Uncrustify.
  3. Set Config Path to /path/to/MuseScore/tools/codestyle/uncrustify_musescore.cfg
  4. Go to Format.
  5. Enable Editor: Format On Save.
  6. Restart VS Code.

Other languages

We don't have automatic style checks for any languages besides C++ and friends, but we do have recommendations for other languages.

New files

We recommend that you enable the following settings in your IDE as the default for all newly created files:

  • Encoding: UTF-8
  • Line ending: Unix-style (LF - linefeed, \n)
  • Indentation: 4 spaces (not tabs)
  • Trim trailing whitespace
  • Insert newline at end of file

In general, we recommend that you adopt whatever style conventions are commonly used in each language, or when there is no consensus, do whatever is most similar to our C++ style. The CodeGuidelines provide more explicit rules for certain languages.

Existing files

Existing files should continue to use whatever style is already most prevalent in that file. See Editing without changing style.

If you're rewriting substantial portions of a file anyway then you could consider reformatting the entire file to follow our recommendations for new files.

If you find several files that are not following the recommendations, you could consider reformatting them all in one big PR that is free of any semantic changes. Create a commit with the style change then add this commit's SHA to .git-blame-ignore-revs in a second commit on the same PR. Make sure you update the SHA when rebasing.

Similarly, if you want to move lots of files or rename a directory, it's best to do this in a separate PR that is free of other changes.

Editing without changing style

When making semantic changes, sometimes it's best to disable automatic formatting in your IDE so that the important changes are not obscured by lots of whitespace changes elsewhere in the file. This makes it easier for team members to review your PR.

In VS Code, you can use the shortcut Ctrl+K followed by Ctrl+Shift+S to save a file without reformatting it. Or you could edit the file in a simple text editor that doesn't support automatic formatting, such as Notepad or nano. Make sure you don't leave any trailing whitespace on the lines you edit.

Alternatively, you can allow your IDE to reformat the file, then you can filter out unwanted changes with git add -p [file]. When prompted by Git, type y to accept a change, n to reject it, s to split the change into smaller changes (if possible), or e to edit manually. This enables you to commit the semantic changes (with git commit), then you can use git checkout -- [file] to discard the unwanted style changes.

Third-party code

Ideally we wouldn't change third-party code at all, but it is sometimes necessary to make small changes in order to integrate it with MuseScore Studio. If this happens, we need to be able to compare our version to the original to see what we changed. Also, when pulling in new upstream code, we want to see what changed upstream, and whether our own patches are still required.

To make this comparison straightforward, code borrowed from other open source projects must be added verbatim. Any semantic changes must be made in separate commits after the initial import. No style changes are allowed.

To prevent our Uncrustify scripts from modifying these files, add an empty file called .untidy to the directory of the third-party library/module (which should be named after the library/module) or to the parent directory (which should be named thirdparty).

If you need to edit the third-party files, see editing without changing style.

Clone this wiki locally