Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-131296

qmlls fails to parse some QML modules and C++ types when there is more than one QML module in a directory

    XMLWordPrintable

Details

    • Windows
    • 33b5854f6 (dev), 751743489 (6.9), 4538cdb18 (6.8)

    Description

      When you have more than one QML module and more than one CMake target in a directory, qmlls gets confused and fails to parse the QML module (and C++ header files).

      # CMakeLists.txt
      
      cmake_minimum_required(VERSION 3.16)
      
      set(CMAKE_CXX_STANDARD 23)
      set(CMAKE_CXX_STANDARD_REQUIRED ON)
      set(CMAKE_AUTOMOC ON)
      set(CMAKE_INCLUDE_CURRENT_DIR ON)
      
      project(
        qmlls_import_bug_toplevel
        VERSION 0.1
        LANGUAGES CXX)
      
      find_package(Qt6 6.8 REQUIRED COMPONENTS Core Widgets Gui Quick)
      
      qt_standard_project_setup(REQUIRES 6.8)
      
      qt_add_library(MyModule STATIC)
      qt_add_qml_module(
        MyModule
        URI "MyModule"
        VERSION 1.0
        DEPENDENCIES QtQuick)
      
      target_link_libraries(MyModule PUBLIC Qt6::Quick Qt6::Core)
      
      qt_add_executable(MyModule_tests tst_main.cpp Something.h)
      
      qt_add_qml_module(
        MyModule_tests
        URI "MyModule_tests"
        VERSION 1.0
        DEPENDENCIES QtQuick
        QML_FILES Main.qml)
      
      target_link_libraries(MyModule_tests PRIVATE MyModule MyModuleplugin)
      
      // Something.h
      #pragma once
      
      #include <QObject>
      #include <QtQmlIntegration>
      
      class Something : public QObject
      {
          Q_OBJECT
          QML_ELEMENT
      public:
          inline explicit Something(QObject *parent = nullptr) { qDebug() << "Something created"; }
      
      signals:
      };
      
      // tst_main.cpp
      #include <QGuiApplication>
      #include <QQmlApplicationEngine>
      
      int main(int argc, char **argv)
      {
          QGuiApplication app{argc, argv};
          QQmlApplicationEngine engine;
          QObject::connect(
              &engine,
              &QQmlApplicationEngine::objectCreationFailed,
              &app,
              []() { QCoreApplication::exit(-1); },
              Qt::QueuedConnection);
          engine.loadFromModule("MyModule_tests", "Main");
      
          return app.exec();
      }
      
      
      // Main.qml
      
      import QtQuick 2.15
      import MyModule_tests
      
      Window {
          id: root
          width: 640
          height: 480
          visible: true
      
          QtObject {
              id: obj
              property var obj: Something {}
          }
      
          Component.onCompleted: {
              if (obj.obj) {
                  console.log("There is something in obj");
              }
          }
      }
      

      qmlls warns:

      Failed to import MyModule_tests. Are your import paths set up properly? [import] 

      Warnings occurred while importing module "MyModule_tests": [import]

      Something was not found. Did you add all imports and dependencies? [import] 

      Type Something is used but it is not resolved [unresolved-type]

      There is no defect in runtime behavior. When running the program, the message "qml: There is something in obj" is printed to the console.

      If you remove MyModule target from CMakeLists.txt, rebuild the target, and restart qmlls, then qmlls is able to find the import again:

      # CMakeLists.txt
      
      cmake_minimum_required(VERSION 3.16)
      
      set(CMAKE_CXX_STANDARD 23)
      set(CMAKE_CXX_STANDARD_REQUIRED ON)
      set(CMAKE_AUTOMOC ON)
      set(CMAKE_INCLUDE_CURRENT_DIR ON)
      
      project(
        qmlls_import_bug_toplevel
        VERSION 0.1
        LANGUAGES CXX)
      
      find_package(Qt6 6.8 REQUIRED COMPONENTS Core Widgets Gui Quick)
      
      qt_standard_project_setup(REQUIRES 6.8)
      
      qt_add_executable(MyModule_tests tst_main.cpp Something.h)
      
      qt_add_qml_module(
        MyModule_tests
        URI "MyModule_tests"
        VERSION 1.0
        DEPENDENCIES QtQuick
        QML_FILES Main.qml)
      
      target_link_libraries(MyModule_tests PRIVATE Qt6::Quick Qt6::Core)
      
      

      My usecase of creating multiple targets in the same directory (with shared sources) is to allow unit-testing the QML module. The actual setup is more complicated and uses mock objects to verify the modules functionality and are not reflected in this trimmed-down reproducible example.

      Either this setup should be rejected at CMake configure time (with a clear error message), or qmlls should correctly handle multiple QML modules in a single directory.

      Attachments

        1. Archive.zip
          4 kB
          Sami Shalayel

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              sami.shalayel Sami Shalayel
              jclink Jessia Clinkscale
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes