このブログは「What's new in QML tooling in Qt 6.11, part 2: new qmllint warnings」を翻訳したものです。
最新のQtリリースであるQt 6.11の公開が間近に迫っています。この短いブログ記事シリーズでは、Qt 6.11でQMLツール群がもたらす新機能をご紹介します。Qmllsの新機能に関する第1部はこちら、コンテキストプロパティのサポートに関する第3部はこちらでご覧いただけます。
qmllintは、前回のqmllintの警告に関するブログ記事以来、多くの新機能を追加しました。そこで、本記事では、Qt 6.6からQt 6.11の間に追加されたqmllintの警告一覧について解説します。既存のqmllintの警告一覧(例を含む)は、ドキュメントでご確認いただけます。ここでは、各警告についてその詳細なドキュメントへのリンクを掲載しますので、警告が発生する原因や修正方法に関する詳細情報や例を簡単に確認していただけます。
QMLメンバーのシャドウイング
シャドウイングとは、QMLコンポーネントが基底クラスにすでに存在するID、プロパティ、シグナル、またはメソッドを再定義した際に発生します。これは強力であると同時に危険な仕組みでもあり、予期せぬ奇妙な動作を引き起こしたり、パフォーマンスを低下させたりする可能性があります。
Qt 6.11では、シャドウされる、またはシャドウ可能なプロパティを指定するために、virtualおよびoverrideキーワードが追加されました。Qt 6.10では、シャドウできないプロパティを指定するために、finalキーワードが追加されました。これらを合わせると、以下のようになります:
- シャドウ化可能なプロパティに対する
virtual
- 別のプロパティをシャドウする必要があるプロパティに対する
override
- シャドウされてはならないプロパティに対する
final
virtuaもoverrideも指定されていないプロパティは、警告なしにシャドウイングされる可能性があります。QMLランタイムやqmllintからは警告が出力されません。以下のコードスニペットで、どのプロパティがシャドウイングされているかおわかりになりますか?
// Building.qml
import QtQuick
Item {
property int floors
property string rotation // like CSS rotate, "-120deg"
property date constructionDate
}
もし私がそのプロパティがあると言わなければ、shadowingプロパティに気づきましたか?rotationプロパティは、すでに基底型に存在しています。基底型のrotationプロパティを期待しているコードは、代わりに文字列を認識してしまい、おそらくBuildingコンポーネントでは動作しないでしょう。これを修正するには、例えばBuilding.qml内のrotationプロパティの名前をcssRotationに変更することができます。
// Building.qml
import QtQuick
Item {
property int floors
property string cssRotation // like CSS rotate, "-120deg"
property date constructionDate
}
次のコードスニペットがどのような出力を返すか、お分かりになりますか?
import QtQuick
Item {
clip: true
Component.onCompleted: console.log(clip) // what does this print?
/* ... */
function clip() { return 123; }
}
このスニペットは次のように出力されます
function clip() { [native code] }
実行時には、期待されるtrueではなく、clipメソッドが同名のプロパティをシャドウイングしてしまうため、別の値が返されます。この例は、シャドウイングがプロパティ間だけで起こるわけではないことを示しています。プロパティ、シグナル、メソッド、IDのあらゆる組み合わせの間でも発生する可能性があります。特にIDによるシャドウイングは混乱を招きやすいです。このスニペットの出力がどうなるか、お分かりになりますか?
import QtQuick
Item {
x: 42
Component.onCompleted: console.log(x) // what does this print?
/* ... */
Item { id: x }
}
おそらくお気づきでしょうが、出力は42ではないと思われます。x への参照では、プロパティよりも ID が優先されるため、console.log(x)は ID が xである Item を出力してしまいます。これは見つけにくく、デバッグも困難です。幸いなことに、Qt 6.12 では、新しい [id-shadows-member] qmllint 警告により、この問題は解消されます。
qmllintは、次のような状況で警告を表示します:
- あるプロパティが別のプロパティを誤って上書きしています。 ([property-override])
- 複数のインラインコンポーネントに同じ名前が付けられています。 ([duplicate-inline-components])
- 同じ型内で定義された複数のメンバーが、同じ名前を持っています。 ([duplicated-name])
- そのメンバーが使用中の場合、IDはそのメンバーをシャドウします。 ([id-shadows-member]*)
- あるメンバーが別のメンバーをシャドウします。 ([shadow]**)
(*) この警告は、Qt 6.12 以降で利用可能になります。
(**) シャドウイングに関する警告をすべて表示するには、設定ファイル .qmllint.ini 内に Shadow=warning を追加して、[shadow] カテゴリを有効にしてください。現在、すべてのシャドウイングのケースを修正できるわけではないため、このカテゴリはデフォルトで無効になっています。例えば、QML では現在、メソッドがプロパティをシャドウイングしていることを明示する方法がありません。各発生箇所での警告を無効にするには、// qmllint disable shadow というコメントを追加してください。
JavaScript に関する新しい警告
qmllintに、組み込みのQt Creator QMLコードモデルと同等の機能を提供するため、JavaScript固有の新しい警告を追加しました。これらの警告は、厳密にはQML固有のものではなく、JavaScriptの一般的な使用法に関するものです:
(*) この警告は、デフォルトでは有効になっていません。
新しい列挙型の警告
QMLにおける列挙型の使用法と定義について、いくつかの警告を追加しました:
C++で定義されたスコープのない列挙型([restricted-type])に関する警告を削除しました。この警告は、ComponentName.EnumName.keyのような列挙型のアクセスに対して表示されていました。Qt 6.11 では、QML での列挙型の名前によるアクセスが許可されており、これは https://codereview.qt-project.org/c/qt/qtdeclarative/+/646544 によって追加されました。
新しいプロパティに関する注意喚起
また、プロパティに値を代入またはバインドする際に、いくつかの警告を追加しました:
その他の新しい警告
最後に、これまでの分類には当てはまらない警告も追加しました:
(*) この警告は、デフォルトでは有効になっていません
まとめ
Qt 6.11で新たに導入されたシャドウイングに関する警告について解説し、6.12への展望を簡単に触れた上で、Qt 6.6以降に追加された数多くの警告について確認しました。
すべての警告に関するドキュメントは、こちらのリストでご確認いただけます。期待通りに動作しない警告や、ドキュメントが不十分な警告に遭遇した場合は、お気軽にJIRAでバグ報告を作成してください。
コンテキストプロパティに関する第3部は、こちらからご覧いただけます。