What’s new in QML Language Server (qmlls) shipped with Qt 6.6
July 24, 2023 by Sami Shalayel | Comments
The QML Language Server shipped with Qt 6.6 comes with exciting new code-navigation features that we will demonstrate in this blog post. But first things first, what is QML Language Server?
What is QML Language Server?
QML Language Server is a language model for QML that can be used for a wide variety of editors. That means it allows an editor to display warnings or errors, support rich code navigation, and format code, for example. If you want to read more about QML Language Server, you should check out its new (at the time of writing) documentation page here!
Your favorite editor needs to implement the Language Server Protocol (LSP) to support QML Language Server, see here for the official LSP page.
Setting up QML Language Server in VS Code
Let’s set up your favorite (LSP-implementing) editor to explore the new features of the QML Language Server!
As the setup instructions vary from editor to editor, I will also explain in this blog post how to set up QML Language Server in VS Code, but feel free to skip this part if you already have QML Language Server set up and running in your editor!
Note that Qt Creator 11, which is the current version at the time of writing, uses an internal implementation for the functionality of the QML Language Server. You can still add the QML Language Server to Qt Creator's list of "Language Clients" in Preferences or enable the qmlls support in the "Qt Quick" settings via the checkbox, but this will not override the use of the internal implementation. This will change in the future as the implementation of QML Language Server progresses.
Getting an Example Project
For this blog post, I created an example project to try out the different functionality of QML Language Server. You can find it here.
Clone it using:
git clone https://git.qt.io/Sami.Shalayel/demoforqmllswhatsnew66.git
Create a build folder, cd into it and configure the project:
mkdir build-demoforqmllswhatsnew66-debug
<path/to/QtInstallation>/bin/qt-cmake -S ../demoforqmllswhatsnew66 -B . -G Ninja
Installing the Language Client for VS Code
I will use VS Code with an experimental and unofficial extension for this blog post, you can download it from here.
Note that some editors do not require an extension to use language servers. Some just require the path to the binary and the file extensions to use with the language server. In this case you can skip this step and go to the setup part.
First, you will need to install VS Code and npm. Then, you can clone the repo using:
git clone https://git.qt.io/Sami.Shalayel/qmlls-vscode.git
Go inside the qmlls-vscode folder and download and install the required dependencies using:
npm install && npm run compile
Once this step is done, you should be able to start VS Code in the current folder using:
code .
A VS Code window will open and show you the project for the unofficial extension for VS Code.
Setting up the QML Language Server Extension
In VS Code, open the client/src/extension.ts
file:
You should be able to find some code that looks like this:
const serverExecutable : Executable = {
command: "sh",
args: [ '-c', 'tee /tmp/qmllsInput | $HOME/projects/qt5-build/qtbase/bin/qmlls | tee /tmp/qmllsOutput'],
// prints VSCode commands to qmlls into qmllsInput file and
// qmlls responses into qmllsOutput file
};
This setting needs to point to your actual ‘qmlls’ binary. If you installed Qt using the official installer, you should be able to find the ‘qmlls’ binary under <QtInstallationPath>/bin
.
If you compiled Qt 6.6 or the dev branch yourself, you can generate the binary by running
ninja qtdeclarative_src qmlls
. You will find the binary in thebin
folder of your installation folder,qtbase/bin/qmlls
for development builds, for example.
On my machine, the binary is located in /Users/sami/Qt/6.6.0/macos/bin/qmlls
, where /Users/sami/Qt/
is the installation path that I used for the Qt installer. Furthermore, QML Language Server needs to know the build folder of the current project, so we end up with the following lines:
const serverExecutable : Executable = {
command: "/Users/sami/Qt/6.6.0/macos/bin/qmlls",
args: [ '--build-dir', '<path/to/build-demoforqmllswhatsnew66-debug>'],
};
Have a look at the documentation to see how to pass the build directory to QML Language Server when command-line arguments cannot be used.
Also, if you are not using the example project I linked above, make sure to pass the folder where your QML modules will be built, in case it differs from your general build folder! QML Modules defined in your project are recognized if and only if their qmldir can be found under path/to/build-directory/ModuleName/qmldir
. QML Language Server should print out a message about which build directory it will use to find project QML modules.
Now that the QML Language Server extension is configured, install the QML extension by Baptist BENOIST for VS Code as shown in the screenshot:
Thats it! Save the file and run the project using the “play” button:
Exploring new QML Language Server features on the example project
Now, open a QML project in the editor you have just prepared for QML Language Server. You can select the folder of the project using Ctrl+O or Command+O to open it in VS Code.
Showing errors in the editor
The first thing you should see, when you open the Main.qml file, is the following warning:
If you do not see any warning, you might either have an invalid QML document or QML Language Server might not have been set up correctly. You might have missed something from ‘Setting up QML Language Server in VS Code’.
QML Language Server finds QML module in your project by inspecting the build directory. Build your project by calling ninja
inside of the build-demoforqmllswhatsnew66-debug
folder.
Once you have built the project, you can close and reopen the editor to make sure that QML Language Server attempts to load the missing module, and the warning about the missing module should be gone:
As proof that QML Language Server is still doing something, I added a QmlComponent that was not defined anywhere, and that is why QML Language Server complains about this UnknownComponent
. You can make the warning go away by adding a definition before it:
component UnknownComponent: Item {} // add this line before the line with 'UnknownComponent {}'
Once you added the missing line, you might realize that you did not need to recompile the project, or call qmllint by hand, to check if the file had more errors like this: QML Language Server took care of updating the warnings for you.
Showing off new features of QML Language Server in 6.6
Note that QML Language Server is still in active development and might crash or be buggy. You can report any crashes or bugs here.
To be able to take screenshots, I decided to trigger the different QML Language Server features from the context menu: of course you can instead use the shortkeys provided by your editor if you know them.
Go to definition
One of the new features of QML Language Server that arrived in 6.6 and will get refined further in 6.7 is the ability to find the definition of certain objects. Lets say you would like to know where that myItem.i
was defined because someone decided to name all of their properties to ‘i’. Right-click on the i
in myItem.i
and choose ‘Go to definition’:
And QML Language Server will make your editor jump to the property definition of i:
Over time, as QML Language Server gains in functionality, the number of actions available from the right-click menu will increase.
This also works for ids, for example:
will find the definition of myItems
which is somewhere above:
Try it out yourself! Write some QML code and let QML Language Server find its definition for. You can report any unexpected behavior here.
Go to type definition
While this feature sounds quite similar to the previous one, it allows you to find the definition of the type of a property, like myComponent
, for example:
and it will take you to the definition of the type of the myComponent
property:
Full text formatting support
To format your code with qmlformat
without leaving your editor, right-click anywhere in the code and select ‘Format Document’:
You should see a beautifully formatted QML file now:
Finding usages
Another new feature in QML Language Server in 6.6 is the ability to find usages of symbols. Function f
seems to use the property i
a lot, for example. Lets ask QML Language Server to find all occurences of the property i
in the current QML file!
You should see following list of usages:
Note that the definition of i
is also included in the list of usages, and that QML Language Server managed to distinguish between the JavaScript Identifier i
defined inside f
and the JavaScript Idenfifier i
defined inside the block of the while-loop. The latter i
shadows the first i
. If you are curious, you can also take a look at the inner identifier’s usages, and see that those do not get mixed up with the homonymous property:
And the result is:
You can also find usages of a certain id, for example with myItems
:
And the results are:
Known Limitations
QML Language Server has some known limitations in 6.6, here is an (non-exhaustive) list of them.
Method names
Currently, method names are not supported, QML Language Server cannot find references or go to the definition of a method.
Unimplemented JavaScript Language Constructs
Some JavaScript language constructs like loops (for, while, etc…) did not make it into 6.6 and are not supported by QML Language Server. In such case, it might crash (you can report it here) or show incomplete or no information when asking for definitions, usages, and so on.
If your code uses unimplemented constructs, consider using the version of QML Language Server from dev as it already supports most JavaScript constructs.
Renaming Symbols
The LSP-feature renaming symbol will be available on from QML Language Server in 6.7. You can get a peek of its current functionality if you use the QML Language Server from dev.
Partial Text Formatting Support
While the current QML Language Server version allows to format the entire file, it is not possible yet to format parts of a file. In the future, it should be possible to format only selected code instead of the entire file.
Conclusion
I hope you learned a lot about the QML Language Server and that I could motivate you to take a look at QML Language Server, try it out on your own code, and to open bugs here when encountering bugs or crashes, either for QML Language Server from 6.6 or from dev.
Blog Topics:
Comments
Subscribe to our newsletter
Subscribe Newsletter
Try Qt 6.7 Now!
Download the latest release here: www.qt.io/download.
Qt 6.7 focuses on the expansion of supported platforms and industry standards. This makes code written with Qt more sustainable and brings more value in Qt as a long-term investment.
We're Hiring
Check out all our open positions here and follow us on Instagram to see what it's like to be #QtPeople.