Qt 6.6附带的QML语言服务器(qmlls)的新增功能

What’s new in QML Language Server (qmlls) shipped with Qt 6.6

Qt 6.6附带的QML语言服务器(qmlls)的新增功能

July 24, 2023 by Sami Shalayel | Comments

​2023年7月24日:Sami Shalayel |评论

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?

Qt 6.6附带的QML语言服务器具有令人兴奋的新代码导航功能,我们将在本博客文章中演示这些功能。但首先,什么是QML语言服务器?

What is QML Language Server?

什么是QML语言服务器?

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!

​QML语言服务器是QML的一个语言模型,可用于多种编辑器。这意味着它允许编辑器显示警告或错误,例如支持丰富的代码导航和格式化代码。如果想阅读更多关于QML语言服务器的信息,应该在这里查看它的新文档页面(在撰写本文时)!

Your favorite editor needs to implement the Language Server Protocol (LSP) to support QML Language Server, see here for the official LSP page.

​喜欢的编辑器需要实现语言服务器协议(LSP)来支持QML语言服务器,请参阅此处的官方LSP页面。

Setting up QML Language Server in VS Code

在VS代码中设置QML语言服务器

Let’s set up your favorite (LSP-implementing) editor to explore the new features of the QML Language Server!

让我们设置最喜欢的(LSP实现)编辑器来探索QML语言服务器的新功能!

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!

由于不同编辑器的设置说明各不相同,将在这篇博客文章中解释如何在VS Code中设置QML语言服务器,但如果已经在编辑器中设置并运行了QML语言Server,请跳过这一部分!

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.


请注意,Qt Creator 11是撰写本文时的当前版本,它使用QML语言服务器功能的内部实现。仍然可以在首选项中将QML语言服务器添加到Qt Creator的“语言客户端”列表中,或者通过复选框在“Qt Quick”设置中启用qmlls支持,但这不会覆盖内部实现的使用。随着QML语言服务器实现的进展,这种情况将在未来发生变化。

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.

​对于这篇博客文章,我创建了一个示例项目来尝试QML语言服务器的不同功能。可以在这里找到它。

Clone it using:

使用以下方法进行克隆:

git clone https://git.qt.io/Sami.Shalayel/demoforqmllswhatsnew66.git

Create a build folder, cd into it and configure the project:

创建一个构建文件夹,cd到其中并配置项目:

mkdir build-demoforqmllswhatsnew66-debug
<path/to/QtInstallation>/bin/qt-cmake -S ../demoforqmllswhatsnew66 -B . -G Ninja

Installing the Language Client for VS Code

安装VS代码的语言客户端

I will use VS Code with an experimental and unofficial extension for this blog post, you can download it from here.

​我将使用VS代码作为这篇博客文章的实验性和非官方扩展,可以从这里下载。

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:

首先,需要安装VS Code和npm。然后,可以使用以下方法克隆回购:

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:

进入qmlls-vscode文件夹,下载并安装所需的依赖项,使用:

npm install && npm run compile

Once this step is done, you should be able to start VS Code in the current folder using:

完成此步骤后,应该能够使用以下方法在当前文件夹中启动VS代码:

code .

A VS Code window will open and show you the project for the unofficial extension for VS Code.

将打开一个VS代码窗口,并向显示VS代码的非官方扩展的项目。

Setting up the QML Language Server Extension

设置QML语言服务器扩展

In VS Code, open the client/src/extension.ts file: 

在VS代码中,打开client/src/extension.ts文件:

opening the extension.ts file in VS Code

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.

​此设置需要指向实际的“qmlls”二进制文件。如果您使用官方安装程序安装Qt,您应该能够在<QtInstallationPath>/bin下找到'qmlls'二进制文件。

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 the bin folder of your installation folder, qtbase/bin/qmlls for development builds, for example.

如果自己编译了Qt 6.6或dev分支,则可以通过运行ninja qtdeclarative_src qmlls生成二进制文件。将在安装文件夹的bin文件夹中找到二进制文件,例如,用于开发构建的qtbase/bin/qmlls。

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:

在我的机器上,二进制文件位于/Users/sami/Qt/6.6.0/macos/bin/qmlls中,其中/Users/sami/Qt/是我用于Qt安装程序的安装路径。此外,QML语言服务器需要知道当前项目的构建文件夹,因此我们得出以下结论:

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.

​请查看文档,了解在无法使用命令行参数时如何将构建目录传递给QML语言服务器。

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.

此外,如果没有使用我上面链接的示例项目,请确保传递将构建QML模块的文件夹,以防它与常规构建文件夹不同!当且仅当可以在路径/to/builddirectory/ModuleName/qmldir下找到它们的qmldir时,才能识别项目中定义的QML模块。QML语言服务器应该打印出一条消息,说明它将使用哪个构建目录来查找项目QML模块。

Now that the QML Language Server extension is configured, install the QML extension by Baptist BENOIST for VS Code as shown in the screenshot: 

现在已经配置了QML语言服务器扩展,请通过Baptist BENOIST为VS Code安装QML扩展,如屏幕截图所示:

Steps to install the QML extension

Thats it! Save the file and run the project using the “play” button: 

就是这样!使用“播放”按钮保存文件并运行项目:

Steps to install the QML extension

Exploring new QML Language Server features on the example project

在示例项目中探索QML语言服务器的新功能

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.

现在,在刚刚为QML语言服务器准备的编辑器中打开一个QML项目。可以使用Ctrl+O或Command+O选择项目的文件夹以在VS代码中打开它。

Showing errors in the editor

在编辑器中显示错误

The first thing you should see, when you open the Main.qml file, is the following warning: 

当您打开Main.qml文件时,应该看到的第一件事是以下警告:

Import cannot be found because module was not imported yet

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文档无效,或者QML语言服务器设置不正确。可能错过了“在VS代码中设置QML语言服务器”中的某些内容。

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.

QML语言服务器通过检查构建目录来查找项目中的QML模块。通过调用Build-demoforqmllswhatsnew66-debug文件夹中的ninja来构建项目。

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: 

构建项目后,可以关闭并重新打开编辑器,以确保QML语言服务器尝试加载丢失的模块,并且关于丢失模块的警告应该消失:

Import can be found now

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:

为了证明QML语言服务器仍在做一些事情,我添加了一个在任何地方都没有定义的QmlComponent,这就是QML语言Server抱怨这个未知组件的原因。可以通过在警告之前添加一个定义来消除警告:

 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.

一旦添加了缺失的一行,可能会意识到,不需要重新编译项目,也不需要手动调用qmllint来检查文件是否有更多错误,如下所示:QML语言服务器负责更新警告。 

Showing off new features of QML Language Server in 6.6

在6.6中展示QML语言服务器的新功能

Note that QML Language Server is still in active development and might crash or be buggy. You can report any crashes or bugs here.

​请注意,QML语言服务器仍在积极开发中,可能会崩溃或出现错误。可以在此处报告任何崩溃或错误。

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.

为了能够进行屏幕截图,我决定从上下文菜单中触发不同的QML语言服务器功能:当然,如果你知道的话,可以使用编辑器提供的快捷键。

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’:

QML语言服务器的一个新功能是能够找到某些对象的定义,它在6.6中出现,并将在6.7中得到进一步改进。假设想知道myItem.i是在哪里定义的,因为有人决定将其所有属性命名为“i”。右键单击myItem.i中的i,然后选择“转到定义”:

Ask for the definition of i.

Ask for the definition of i.

询问i的定义。

And QML Language Server will make your editor jump to the property definition of i:

QML语言服务器将使编辑器跳转到i的属性定义:

The definition of i.

The definition of i.

i的定义。

Over time, as QML Language Server gains in functionality, the number of actions available from the right-click menu will increase.

随着时间的推移,随着QML语言服务器功能的增强,右键单击菜单中可用的操作数量将增加。

This also works for ids, for example:

这也适用于id,例如:

Ask for the definition of myItems.

Ask for the definition of myItems.

询问myItems的定义。

will find the definition of myItems which is somewhere above:

将在上面找到myItems的定义:

The definition of myItems.

The definition of myItems.

myItems的定义。

Try it out yourself! Write some QML code and let QML Language Server find its definition for. You can report any unexpected behavior here.


自己试试吧!编写一些QML代码,让QML语言服务器找到它的定义。可以在此处报告任何意外行为。

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:

虽然此功能听起来与上一个功能非常相似,但它允许查找属性类型的定义,例如myComponent:

Ask for the definition of myComponent.

Ask for the definition of myComponent.

询问myComponent的定义。

and it will take you to the definition of the type of the myComponent property:

它将带您了解myComponent属性类型的定义:

The definition of myComponent.

The definition of myComponent.

myComponent的定义。

Full text formatting support
支持全文格式

To format your code with qmlformat without leaving your editor, right-click anywhere in the code and select ‘Format Document’:

要在不离开编辑器的情况下使用qmlformat格式化代码,请右键单击代码中的任何位置,然后选择“格式化文档”:

Format document from context menu.

Format document from context menu.

从上下文菜单设置文档格式。

You should see a beautifully formatted QML file now:

现在应该看到一个格式优美的QML文件:

Formatted document.

Formatted document.

格式化的文档。

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!

6.6中QML语言服务器的另一个新功能是能够查找符号的用法。例如,函数f似乎经常使用属性i。让我们让QML语言服务器在当前QML文件中查找所有出现的属性i!

Ask for usages of i.

Ask for usages of i.

询问i的用法。

You should see following list of usages:

应该看到以下用法列表:

Usages of i.

Usages of i.

i的用法。

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:

请注意,i的定义也包括在用法列表中,QML语言服务器设法区分了在f中定义的JavaScript标识符i和在while循环的块中定义的JavaScriptIdenfier i。后一个i遮蔽了前一个i。如果很好奇,也可以看看内部标识符的用法,看看这些用法不会与同音异义属性混淆:

Ask for usages of i.

Ask for usages of i.

询问i的用法。

And the result is:

结果是:

Usages of i.

Usages of i.

i的用法。

You can also find usages of a certain id, for example with myItems:

还可以找到某个id的用法,例如myItems:

Usages of myItems.

Usages of myItems.

myItems的用法。

And the results are:

结果是:

Usages of myItems.

Usages of myItems.

myItems的用法。

Known Limitations

已知限制

QML Language Server has some known limitations in 6.6, here is an (non-exhaustive) list of them.

QML语言服务器在6.6中有一些已知的限制,这里是一个(非详尽的)列表。

Method names
方法名称

Currently, method names are not supported, QML Language Server cannot find references or go to the definition of a method.

目前,不支持方法名称,QML语言服务器无法找到引用或转到方法的定义。

Unimplemented JavaScript Language Constructs
未实现的JavaScript语言构造

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.

​一些JavaScript语言构造,如循环(for、while等),没有进入6.6,也不受QML语言服务器的支持。在这种情况下,它可能会崩溃(可以在此处报告它),或者在询问定义、用法等时显示不完整或没有信息。

If your code uses unimplemented constructs, consider using the version of QML Language Server from dev as it already supports most JavaScript constructs.

如果代码使用未实现的构造,请考虑使用dev中的QML语言服务器版本,因为它已经支持大多数JavaScript构造。

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.

LSP功能重命名符号将在6.7中的QML语言服务器上提供。如果使用来自dev的QML语言服务器,可以了解它的当前功能。

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.

虽然当前QML语言服务器版本允许格式化整个文件,但还不可能格式化文件的部分内容。将来,应该可以只格式化选定的代码,而不是格式化整个文件。

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.

​希望你学到了很多关于QML语言服务器的知识,我可以激励你看看QML语言服务,在你自己的代码上试用它,并在遇到错误或崩溃时在这里打开错误,无论是6.6版的QML语言服务器还是dev版的。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值