diff options
Diffstat (limited to 'src/libs')
240 files changed, 4631 insertions, 1520 deletions
diff --git a/src/libs/3rdparty/CMakeLists.txt b/src/libs/3rdparty/CMakeLists.txt new file mode 100644 index 0000000000..7cf97ab87f --- /dev/null +++ b/src/libs/3rdparty/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(cplusplus) +add_subdirectory(syntax-highlighting) diff --git a/src/libs/3rdparty/cplusplus/CMakeLists.txt b/src/libs/3rdparty/cplusplus/CMakeLists.txt new file mode 100644 index 0000000000..a33e96a197 --- /dev/null +++ b/src/libs/3rdparty/cplusplus/CMakeLists.txt @@ -0,0 +1,46 @@ +add_qtc_library(3rd_cplusplus OBJECT + PUBLIC_DEPENDS Qt5::Core Utils + DEFINES CPLUSPLUS_BUILD_LIB + INCLUDES "${CMAKE_SOURCE_DIR}/src/libs" + SOURCES + AST.cpp AST.h + ASTClone.cpp + ASTMatch0.cpp + ASTMatcher.cpp ASTMatcher.h + ASTPatternBuilder.h + ASTVisit.cpp + ASTVisitor.cpp ASTVisitor.h + ASTfwd.h + Bind.cpp Bind.h + CPlusPlus.h + CPlusPlusForwardDeclarations.h + Control.cpp Control.h + CoreTypes.cpp CoreTypes.h + DiagnosticClient.cpp DiagnosticClient.h + FullySpecifiedType.cpp FullySpecifiedType.h + Keywords.cpp + Lexer.cpp Lexer.h + LiteralTable.h + Literals.cpp Literals.h + Matcher.cpp Matcher.h + MemoryPool.cpp MemoryPool.h + Name.cpp Name.h + NameVisitor.cpp NameVisitor.h + Names.cpp Names.h + ObjectiveCAtKeywords.cpp + ObjectiveCTypeQualifiers.cpp ObjectiveCTypeQualifiers.h + Parser.cpp Parser.h + QtContextKeywords.cpp QtContextKeywords.h + SafeMatcher.cpp SafeMatcher.h + Scope.cpp Scope.h + Symbol.cpp Symbol.h + SymbolVisitor.h + Symbols.cpp Symbols.h + Templates.cpp Templates.h + Token.cpp Token.h + TranslationUnit.cpp TranslationUnit.h + Type.cpp Type.h + TypeVisitor.cpp TypeVisitor.h + cppassert.h + PROPERTIES POSITION_INDEPENDENT_CODE ON +) diff --git a/src/libs/3rdparty/syntax-highlighting/.gitignore b/src/libs/3rdparty/syntax-highlighting/.gitignore index 02ba11c78a..52f10e28a5 100644 --- a/src/libs/3rdparty/syntax-highlighting/.gitignore +++ b/src/libs/3rdparty/syntax-highlighting/.gitignore @@ -7,3 +7,6 @@ CMakeLists.txt.user callgrind.* heaptrack.* +/build*/ +*.unc-backup* + diff --git a/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt b/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt index 49923fb26e..27cc408223 100644 --- a/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt +++ b/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt @@ -1,134 +1,47 @@ -cmake_minimum_required(VERSION 3.0) - -set(KF5_VERSION "5.52.0") -project(KSyntaxHighlighting VERSION ${KF5_VERSION}) - -find_package(ECM 5.51.0 REQUIRED NO_MODULE) -set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) -if(POLICY CMP0063) - cmake_policy(SET CMP0063 NEW) -endif() - -include(FeatureSummary) -include(GenerateExportHeader) -include(ECMSetupVersion) -include(ECMGenerateHeaders) -include(ECMGeneratePriFile) -include(CMakePackageConfigHelpers) -include(ECMPoQmTools) -include(ECMQtDeclareLoggingCategory) -include(KDEInstallDirs) -include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) -include(KDECMakeSettings) -include(ECMMarkNonGuiExecutable) -include(ECMAddQch) - - -ecm_setup_version(PROJECT - VARIABLE_PREFIX SyntaxHighlighting - VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/ksyntaxhighlighting_version.h" - PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5SyntaxHighlightingConfigVersion.cmake" +add_qtc_library(KSyntaxHighlighting STATIC + PUBLIC_INCLUDES autogenerated/ autogenerated/src/lib src/lib + PUBLIC_DEFINES KSYNTAXHIGHLIGHTING_LIBRARY + DEPENDS Qt5::Network Qt5::Gui + SOURCES + autogenerated/src/lib/ksyntaxhighlighting_logging.cpp autogenerated/src/lib/ksyntaxhighlighting_logging.h + autogenerated/ksyntaxhighlighting_version.h + + data/themes/theme-data.qrc + + src/lib/abstracthighlighter.cpp src/lib/abstracthighlighter.h src/lib/abstracthighlighter_p.h + src/lib/context.cpp src/lib/context_p.h + src/lib/contextswitch.cpp src/lib/contextswitch_p.h + src/lib/definition.cpp src/lib/definition.h + src/lib/definitiondownloader.cpp src/lib/definitiondownloader.h + src/lib/definitionref_p.h + src/lib/definition_p.h + src/lib/foldingregion.cpp src/lib/foldingregion.h + src/lib/format.cpp src/lib/format.h src/lib/format_p.h + src/lib/htmlhighlighter.cpp src/lib/htmlhighlighter.h + src/lib/keywordlist.cpp src/lib/keywordlist_p.h + src/lib/ksyntaxhighlighting_export.h + src/lib/matchresult_p.h + src/lib/repository.cpp src/lib/repository.h src/lib/repository_p.h + src/lib/rule.cpp src/lib/rule_p.h + src/lib/state.cpp src/lib/state.h src/lib/state_p.h + src/lib/syntaxhighlighter.cpp src/lib/syntaxhighlighter.h + src/lib/textstyledata_p.h + src/lib/theme.cpp src/lib/theme.h + src/lib/themedata.cpp src/lib/themedata_p.h + src/lib/wildcardmatcher.cpp src/lib/wildcardmatcher_p.h + src/lib/xml_p.h ) -# -# Dependencies -# -set(REQUIRED_QT_VERSION 5.8.0) -find_package(Qt5 ${REQUIRED_QT_VERSION} NO_MODULE REQUIRED COMPONENTS Core Network Test) -option(KSYNTAXHIGHLIGHTING_USE_GUI "Build components depending on Qt5Gui" ON) -if(KSYNTAXHIGHLIGHTING_USE_GUI) - find_package(Qt5 ${REQUIRED_QT_VERSION} NO_MODULE REQUIRED COMPONENTS Gui) -endif() -find_package(Qt5 ${REQUIRED_QT_VERSION} NO_MODULE QUIET OPTIONAL_COMPONENTS Widgets XmlPatterns) -set_package_properties(Qt5 PROPERTIES URL "http://qt-project.org/") -set_package_properties(Qt5Widgets PROPERTIES PURPOSE "Example application.") -set_package_properties(Qt5XmlPatterns PROPERTIES PURPOSE "Compile-time validation of syntax definition files.") - -find_package(Perl REQUIRED) -set_package_properties(Perl PROPERTIES PURPOSE "Auto-generate PHP syntax definition files.") - -# -# allow to install the "differently" licensed syntax xml files instead of putting them in a QRC and link them in -# -option(QRC_SYNTAX "Bundle the syntax definition files inside the library as resources" ON) -add_feature_info(SYNTAX_RESOURCE ${QRC_SYNTAX} "Bundle the syntax definition files inside the library as resources") - -# -# allow to turn of lookup for syntax files and themes via QStandardPaths -# -option(NO_STANDARD_PATHS "Skip lookup of syntax and theme definitions in QStandardPaths locations" OFF) -add_feature_info(FEATURE_NO_STANDARD_PATHS ${NO_STANDARD_PATHS} "Skip lookup of syntax and theme definitions in QStandardPaths locations") - -# -# API documentation -# -option(BUILD_QCH "Build API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)" OFF) -add_feature_info(QCH ${BUILD_QCH} "API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)") - -# -# Translations -# -if (IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/po") - ecm_install_po_files_as_qm(po) -endif() - -# tell the framework if it shall use the syntax files from the resource -if (QRC_SYNTAX) - add_definitions(-DHAS_SYNTAX_RESOURCE) -endif() - -# skip standard paths? -if (NO_STANDARD_PATHS) - add_definitions(-DNO_STANDARD_PATHS) -endif() - -# -# Actually build the stuff -# -include_directories(${CMAKE_CURRENT_BINARY_DIR}) -add_subdirectory(data) -add_subdirectory(src) -if(TARGET Qt5::Gui) - add_subdirectory(examples) -endif() - -# -# CMake package config file generation -# -set(CMAKECONFIG_INSTALL_DIR "${CMAKECONFIG_INSTALL_PREFIX}/KF5SyntaxHighlighting") - -if (BUILD_QCH) - ecm_install_qch_export( - TARGETS KF5SyntaxHighlighting_QCH - FILE KF5SyntaxHighlightingQchTargets.cmake - DESTINATION "${CMAKECONFIG_INSTALL_DIR}" - COMPONENT Devel - ) - set(PACKAGE_INCLUDE_QCHTARGETS "include(\"\${CMAKE_CURRENT_LIST_DIR}/KF5SyntaxHighlightingQchTargets.cmake\")") -endif() - -configure_package_config_file( - "${CMAKE_CURRENT_SOURCE_DIR}/KF5SyntaxHighlightingConfig.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/KF5SyntaxHighlightingConfig.cmake" - INSTALL_DESTINATION "${CMAKECONFIG_INSTALL_DIR}" +install( + DIRECTORY data/syntax + DESTINATION "${IDE_DATA_PATH}/generic-highlighter/" ) -install(FILES - "${CMAKE_CURRENT_BINARY_DIR}/KF5SyntaxHighlightingConfig.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/KF5SyntaxHighlightingConfigVersion.cmake" - DESTINATION "${CMAKECONFIG_INSTALL_DIR}" - COMPONENT Devel) - -if(TARGET KF5SyntaxHighlighting) - install(EXPORT KF5SyntaxHighlightingTargets - DESTINATION "${CMAKECONFIG_INSTALL_DIR}" - FILE KF5SyntaxHighlightingTargets.cmake - NAMESPACE KF5::) -endif() - -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ksyntaxhighlighting_version.h" - DESTINATION "${KDE_INSTALL_INCLUDEDIR_KF5}" - COMPONENT Devel) -install(FILES org_kde_ksyntaxhighlighting.categories DESTINATION ${KDE_INSTALL_CONFDIR}) - -feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) +add_custom_target(copy_generic_highligher_to_builddir ALL VERBATIM) +add_custom_command(TARGET copy_generic_highligher_to_builddir POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy_directory data/syntax + "${PROJECT_BINARY_DIR}/${IDE_DATA_PATH}/generic-highlighter/syntax" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT Copy files into build directory + VERBATIM +) diff --git a/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt.kde b/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt.kde new file mode 100644 index 0000000000..4f88fcf84a --- /dev/null +++ b/src/libs/3rdparty/syntax-highlighting/CMakeLists.txt.kde @@ -0,0 +1,140 @@ +cmake_minimum_required(VERSION 3.5) + +set(KF5_VERSION "5.59.0") +project(KSyntaxHighlighting VERSION ${KF5_VERSION}) + +find_package(ECM 5.59.0 REQUIRED NO_MODULE) +set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) +if(POLICY CMP0063) + cmake_policy(SET CMP0063 NEW) +endif() + +include(FeatureSummary) +include(GenerateExportHeader) +include(ECMSetupVersion) +include(ECMGenerateHeaders) +include(ECMGeneratePriFile) +include(CMakePackageConfigHelpers) +include(ECMPoQmTools) +include(ECMQtDeclareLoggingCategory) +include(KDEInstallDirs) +include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) +include(KDECMakeSettings) +include(ECMMarkNonGuiExecutable) +include(ECMAddQch) +include(ECMOptionalAddSubdirectory) + + +ecm_setup_version(PROJECT + VARIABLE_PREFIX SyntaxHighlighting + VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/ksyntaxhighlighting_version.h" + PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5SyntaxHighlightingConfigVersion.cmake" +) + +# +# Dependencies +# +set(REQUIRED_QT_VERSION 5.10.0) +find_package(Qt5 ${REQUIRED_QT_VERSION} NO_MODULE REQUIRED COMPONENTS Core Network Test) +option(KSYNTAXHIGHLIGHTING_USE_GUI "Build components depending on Qt5Gui" ON) +if(KSYNTAXHIGHLIGHTING_USE_GUI) + find_package(Qt5 ${REQUIRED_QT_VERSION} NO_MODULE REQUIRED COMPONENTS Gui) +endif() +find_package(Qt5 ${REQUIRED_QT_VERSION} NO_MODULE QUIET OPTIONAL_COMPONENTS PrintSupport Widgets XmlPatterns) +set_package_properties(Qt5 PROPERTIES URL "http://qt-project.org/") +set_package_properties(Qt5Widgets PROPERTIES PURPOSE "Example application.") +set_package_properties(Qt5PrintSupport PROPERTIES PURPOSE "Example application.") +set_package_properties(Qt5XmlPatterns PROPERTIES PURPOSE "Compile-time validation of syntax definition files.") + +find_package(Perl REQUIRED) +set_package_properties(Perl PROPERTIES PURPOSE "Auto-generate PHP syntax definition files.") + +# +# allow to install the "differently" licensed syntax xml files instead of putting them in a QRC and link them in +# +option(QRC_SYNTAX "Bundle the syntax definition files inside the library as resources" ON) +add_feature_info(SYNTAX_RESOURCE ${QRC_SYNTAX} "Bundle the syntax definition files inside the library as resources") + +# +# allow to turn of lookup for syntax files and themes via QStandardPaths +# +option(NO_STANDARD_PATHS "Skip lookup of syntax and theme definitions in QStandardPaths locations" OFF) +add_feature_info(FEATURE_NO_STANDARD_PATHS ${NO_STANDARD_PATHS} "Skip lookup of syntax and theme definitions in QStandardPaths locations") + +# +# API documentation +# +option(BUILD_QCH "Build API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)" OFF) +add_feature_info(QCH ${BUILD_QCH} "API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)") + +# +# Translations +# +if (IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/po") + ecm_install_po_files_as_qm(po) +endif() + +# tell the framework if it shall use the syntax files from the resource +if (QRC_SYNTAX) + add_definitions(-DHAS_SYNTAX_RESOURCE) +endif() + +# skip standard paths? +if (NO_STANDARD_PATHS) + add_definitions(-DNO_STANDARD_PATHS) +endif() +add_definitions(-DQT_NO_FOREACH) + +# +# Actually build the stuff +# +include_directories(${CMAKE_CURRENT_BINARY_DIR}) +add_subdirectory(data) +add_subdirectory(src) +if(TARGET Qt5::Gui) + add_subdirectory(examples) + if (BUILD_TESTING) + add_subdirectory(autotests) + endif() +endif() + +# +# CMake package config file generation +# +set(CMAKECONFIG_INSTALL_DIR "${CMAKECONFIG_INSTALL_PREFIX}/KF5SyntaxHighlighting") + +if (BUILD_QCH) + ecm_install_qch_export( + TARGETS KF5SyntaxHighlighting_QCH + FILE KF5SyntaxHighlightingQchTargets.cmake + DESTINATION "${CMAKECONFIG_INSTALL_DIR}" + COMPONENT Devel + ) + set(PACKAGE_INCLUDE_QCHTARGETS "include(\"\${CMAKE_CURRENT_LIST_DIR}/KF5SyntaxHighlightingQchTargets.cmake\")") +endif() + +configure_package_config_file( + "${CMAKE_CURRENT_SOURCE_DIR}/KF5SyntaxHighlightingConfig.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/KF5SyntaxHighlightingConfig.cmake" + INSTALL_DESTINATION "${CMAKECONFIG_INSTALL_DIR}" +) + +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/KF5SyntaxHighlightingConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/KF5SyntaxHighlightingConfigVersion.cmake" + DESTINATION "${CMAKECONFIG_INSTALL_DIR}" + COMPONENT Devel) + +if(TARGET KF5SyntaxHighlighting) + install(EXPORT KF5SyntaxHighlightingTargets + DESTINATION "${CMAKECONFIG_INSTALL_DIR}" + FILE KF5SyntaxHighlightingTargets.cmake + NAMESPACE KF5::) +endif() + +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ksyntaxhighlighting_version.h" + DESTINATION "${KDE_INSTALL_INCLUDEDIR_KF5}" + COMPONENT Devel) +install(FILES org_kde_ksyntaxhighlighting.categories DESTINATION ${KDE_INSTALL_CONFDIR}) + +feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/src/libs/3rdparty/syntax-highlighting/README.md b/src/libs/3rdparty/syntax-highlighting/README.md index 1eedc0af7f..c1b82c63d1 100644 --- a/src/libs/3rdparty/syntax-highlighting/README.md +++ b/src/libs/3rdparty/syntax-highlighting/README.md @@ -30,3 +30,20 @@ out of scope: * management of text buffers or documents If you need any of this, check out [KTextEditor](https://api.kde.org/frameworks/ktexteditor/html/). + +## Adding unit tests for a syntax definition + +* add an input file into the autotests/input/ folder, lets call it test.<language-extension> + +* if the file extension is not sufficient to trigger the right syntax definition, you can add an + second file testname.<language-extension>.syntax that contains the syntax definition name + to enforce the use of the right extension + +* do "make && make test" + +* inspect the outputs found in your binary directory autotests/folding.out, autotests/html.output and autotests/output + +* if ok, run in the binary folder "./autotests/update-reference-data.sh" to copy the results to the right location + +* add the result references after the copying to the git + diff --git a/src/libs/3rdparty/syntax-highlighting/autogenerated/ksyntaxhighlighting_version.h b/src/libs/3rdparty/syntax-highlighting/autogenerated/ksyntaxhighlighting_version.h index bd31a4d407..70795908d6 100644 --- a/src/libs/3rdparty/syntax-highlighting/autogenerated/ksyntaxhighlighting_version.h +++ b/src/libs/3rdparty/syntax-highlighting/autogenerated/ksyntaxhighlighting_version.h @@ -3,10 +3,10 @@ #ifndef SyntaxHighlighting_VERSION_H #define SyntaxHighlighting_VERSION_H -#define SyntaxHighlighting_VERSION_STRING "5.52.0" +#define SyntaxHighlighting_VERSION_STRING "5.59.0" #define SyntaxHighlighting_VERSION_MAJOR 5 -#define SyntaxHighlighting_VERSION_MINOR 52 +#define SyntaxHighlighting_VERSION_MINOR 59 #define SyntaxHighlighting_VERSION_PATCH 0 -#define SyntaxHighlighting_VERSION ((5<<16)|(52<<8)|(0)) +#define SyntaxHighlighting_VERSION ((5<<16)|(59<<8)|(0)) #endif diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/cmake.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/cmake.xml index 2a9088b46c..6d170e4eaa 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/cmake.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/cmake.xml @@ -31,7 +31,7 @@ <language name="CMake" - version="11" + version="12" kateversion="2.4" section="Other" extensions="CMakeLists.txt;*.cmake;*.cmake.in" @@ -317,6 +317,7 @@ <item>PATTERN</item> <item>PERMISSIONS</item> <item>READ</item> + <item>READ_SYMLINK</item> <item>REGEX</item> <item>RELATIVE</item> <item>RELATIVE_PATH</item> @@ -335,6 +336,7 @@ <item>SHA3_512</item> <item>SHA512</item> <item>SHOW_PROGRESS</item> + <item>SIZE</item> <item>STATUS</item> <item>STRINGS</item> <item>TIMEOUT</item> @@ -484,8 +486,10 @@ <item>CACHE</item> <item>DIRECTORY</item> <item>EXT</item> + <item>LAST_EXT</item> <item>NAME</item> <item>NAME_WE</item> + <item>NAME_WLE</item> <item>PATH</item> <item>PROGRAM</item> <item>PROGRAM_ARGS</item> @@ -1054,6 +1058,7 @@ <item>COPY_FILE</item> <item>COPY_FILE_ERROR</item> <item>LINK_LIBRARIES</item> + <item>LINK_OPTIONS</item> <item>OUTPUT_VARIABLE</item> <item>RESULT_VAR</item> <item>SOURCES</item> @@ -1065,6 +1070,7 @@ <item>COMPILE_OUTPUT_VARIABLE</item> <item>COMPILE_RESULT_VAR</item> <item>LINK_LIBRARIES</item> + <item>LINK_OPTIONS</item> <item>OUTPUT_VARIABLE</item> <item>RUN_OUTPUT_VARIABLE</item> <item>RUN_RESULT_VAR</item> @@ -1209,6 +1215,7 @@ <item>CMAKE_ARCHIVE_OUTPUT_DIRECTORY</item> <item>CMAKE_ARGC</item> <item>CMAKE_ARGV0</item> + <item>CMAKE_AUTOGEN_ORIGIN_DEPENDS</item> <item>CMAKE_AUTOGEN_PARALLEL</item> <item>CMAKE_AUTOGEN_VERBOSE</item> <item>CMAKE_AUTOMOC</item> @@ -1223,6 +1230,7 @@ <item>CMAKE_BACKWARDS_COMPATIBILITY</item> <item>CMAKE_BINARY_DIR</item> <item>CMAKE_BUILD_RPATH</item> + <item>CMAKE_BUILD_RPATH_USE_ORIGIN</item> <item>CMAKE_BUILD_TOOL</item> <item>CMAKE_BUILD_TYPE</item> <item>CMAKE_BUILD_WITH_INSTALL_NAME_DIR</item> @@ -1297,6 +1305,7 @@ <item>CMAKE_FIND_PACKAGE_NAME</item> <item>CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY</item> <item>CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY</item> + <item>CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS</item> <item>CMAKE_FIND_PACKAGE_SORT_DIRECTION</item> <item>CMAKE_FIND_PACKAGE_SORT_ORDER</item> <item>CMAKE_FIND_PACKAGE_WARN_NO_MODULE</item> @@ -1316,6 +1325,10 @@ <item>CMAKE_GENERATOR_INSTANCE</item> <item>CMAKE_GENERATOR_PLATFORM</item> <item>CMAKE_GENERATOR_TOOLSET</item> + <item>CMAKE_GLOBAL_AUTOGEN_TARGET</item> + <item>CMAKE_GLOBAL_AUTOGEN_TARGET_NAME</item> + <item>CMAKE_GLOBAL_AUTORCC_TARGET</item> + <item>CMAKE_GLOBAL_AUTORCC_TARGET_NAME</item> <item>CMAKE_GNUtoMS</item> <item>CMAKE_HAS_ANSI_STRING_STREAM</item> <item>CMAKE_HOME_DIRECTORY</item> @@ -1412,6 +1425,7 @@ <item>CMAKE_MAJOR_VERSION</item> <item>CMAKE_MAKE_PROGRAM</item> <item>CMAKE_MATCH_COUNT</item> + <item>CMAKE_MAXIMUM_RECURSION_DEPTH</item> <item>CMAKE_MFC_FLAG</item> <item>CMAKE_MINIMUM_REQUIRED_VERSION</item> <item>CMAKE_MINOR_VERSION</item> @@ -1884,6 +1898,7 @@ <item>CTEST_SCP_COMMAND</item> <item>CTEST_SITE</item> <item>CTEST_SOURCE_DIRECTORY</item> + <item>CTEST_SUBMIT_URL</item> <item>CTEST_SVN_COMMAND</item> <item>CTEST_SVN_OPTIONS</item> <item>CTEST_SVN_UPDATE_OPTIONS</item> @@ -1964,6 +1979,8 @@ <item>PROJECT_VERSION_PATCH</item> <item>PROJECT_VERSION_TWEAK</item> <item>QTIFWDIR</item> + <item>SWIG_OUTFILE_DIR</item> + <item>SWIG_SOURCE_FILE_EXTENSIONS</item> <item>THREADS_PREFER_PTHREAD_FLAG</item> <item>UNIX</item> <item>WIN32</item> @@ -1982,6 +1999,7 @@ <item>AUTORCC_SOURCE_GROUP</item> <item>CMAKE_CXX_KNOWN_FEATURES</item> <item>CMAKE_C_KNOWN_FEATURES</item> + <item>CMAKE_ROLE</item> <item>DEBUG_CONFIGURATIONS</item> <item>DISABLED_FEATURES</item> <item>ECLIPSE_EXTRA_NATURES</item> @@ -2067,17 +2085,24 @@ <item>ARCHIVE_OUTPUT_DIRECTORY</item> <item>ARCHIVE_OUTPUT_NAME</item> <item>AUTOGEN_BUILD_DIR</item> + <item>AUTOGEN_ORIGIN_DEPENDS</item> <item>AUTOGEN_TARGET_DEPENDS</item> <item>AUTOMOC</item> + <item>AUTOMOC_COMPILER_PREDEFINES</item> <item>AUTOMOC_DEPEND_FILTERS</item> + <item>AUTOMOC_EXECUTABLE</item> + <item>AUTOMOC_MACRO_NAMES</item> <item>AUTOMOC_MOC_OPTIONS</item> <item>AUTORCC</item> + <item>AUTORCC_EXECUTABLE</item> <item>AUTORCC_OPTIONS</item> <item>AUTOUIC</item> + <item>AUTOUIC_EXECUTABLE</item> <item>AUTOUIC_OPTIONS</item> <item>AUTOUIC_SEARCH_PATHS</item> <item>BINARY_DIR</item> <item>BUILD_RPATH</item> + <item>BUILD_RPATH_USE_ORIGIN</item> <item>BUILD_WITH_INSTALL_NAME_DIR</item> <item>BUILD_WITH_INSTALL_RPATH</item> <item>BUNDLE</item> diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/doxygen.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/doxygen.xml index 99b1d79c02..a6abda9204 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/doxygen.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/doxygen.xml @@ -4,7 +4,7 @@ <!ENTITY wordsep "([][,?;()]|\.$|\.?\s)"> <!-- things that end a TagWord --> ]> <language name="Doxygen" - version="5" + version="6" kateversion="5.0" section="Markup" extensions="*.dox;*.doxygen" @@ -463,7 +463,7 @@ <itemData name="Tags" defStyleNum="dsAnnotation" bold="1" /> <itemData name="Custom Tags" defStyleNum="dsAnnotation" /> <itemData name="Word" defStyleNum="dsCommentVar" bold="1" italic="0" /> - <itemData name="HTML Tag" defStyleNum="dsKeyword" color="#000000" bold="1" italic="0" /> + <itemData name="HTML Tag" defStyleNum="dsKeyword" bold="1" italic="0" /> <itemData name="Entities" defStyleNum="dsOthers" color="#4086C0" bold="1" italic="1" /> <itemData name="Description" defStyleNum="dsDocumentation" /> <itemData name="Comment" defStyleNum="dsComment" /> diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/html.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/html.xml index 4f9eb962d7..107e1067da 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/html.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/html.xml @@ -5,7 +5,7 @@ <!ENTITY attributeName "[A-Za-z_:*#\(\[][\)\]\w.:_-]*"> <!ENTITY entref "&(#[0-9]+|#[xX][0-9A-Fa-f]+|&name;);"> ]> -<language name="HTML" version="5" kateversion="3.4" section="Markup" extensions="*.htm;*.html;*.shtml;*.shtm" mimetype="text/html" author="Wilbert Berendsen (wilbert@kde.nl)" license="LGPL" priority="10"> +<language name="HTML" version="7" kateversion="3.4" section="Markup" extensions="*.htm;*.html;*.shtml;*.shtm" mimetype="text/html" author="Wilbert Berendsen (wilbert@kde.nl)" license="LGPL" priority="10"> <highlighting> <contexts> @@ -163,16 +163,23 @@ </context> <context name="JS" attribute="Other Text" lineEndContext="#stay"> - <Detect2Chars attribute="Element" context="#pop" char="/" char1=">" endRegion="script" /> + <RegExpr attribute="Attribute" context="Script-Type" String="(\s+|^)type(?=\=|\s|$)" insensitive="true"/> <DetectChar attribute="Element" context="JS content" char=">" /> + <IncludeRules context="DefaultJS" /> + </context> + <context name="DefaultJS" attribute="Other Text" lineEndContext="#stay"> + <Detect2Chars attribute="Element" context="#pop" char="/" char1=">" endRegion="script" /> <IncludeRules context="FindAttributes" /> <RegExpr attribute="Error" context="#stay" String="\S" /> </context> <context name="JS content" attribute="Other Text" lineEndContext="#stay"> + <IncludeRules context="Default JS content"/> + <IncludeRules context="Normal##JavaScript" includeAttrib="true"/> + </context> + <context name="Default JS content" attribute="Other Text" lineEndContext="#stay"> <RegExpr attribute="Element" context="El Close 2" String="</script\b" insensitive="true" endRegion="script" /> <RegExpr attribute="Comment" context="JS comment close" String="//(?=.*</script\b)" insensitive="true" /> - <IncludeRules context="Normal##JavaScript" includeAttrib="true"/> </context> <context name="JS comment close" attribute="Comment" lineEndContext="#pop"> @@ -202,6 +209,79 @@ <IncludeRules context="FindEntityRefs" /> </context> + <!-- Read content from the "type" attribute to change the language to + highlight in the <script> tag. The default language is JavaScript. --> + + <context name="Script-Type" attribute="Other Text" lineEndContext="#stay" fallthrough="true" fallthroughContext="#pop"> + <DetectSpaces /> + <DetectChar attribute="Attribute" context="#pop!Script-Type Value" char="=" /> + </context> + <context name="Script-Type Value" attribute="Other Text" lineEndContext="#stay" fallthrough="true" fallthroughContext="#pop!Value"> + <DetectSpaces /> + <!-- TypeScript --> + <StringDetect attribute="Value" context="#pop#pop!TypeScript" String=""text/typescript""/> + <StringDetect attribute="Value" context="#pop#pop!TypeScript" String="'text/typescript'"/> + <!-- JSX (JavaScript React) --> + <StringDetect attribute="Value" context="#pop#pop!JSX" String=""text/jsx""/> + <StringDetect attribute="Value" context="#pop#pop!JSX" String="'text/jsx'"/> + <StringDetect attribute="Value" context="#pop#pop!JSX" String=""text/babel""/> + <StringDetect attribute="Value" context="#pop#pop!JSX" String="'text/babel'"/> + <!-- MustacheJS / HandlebarsJS / RactiveJS --> + <StringDetect attribute="Value" context="#pop#pop!MustacheJS" String=""x-tmpl-mustache""/> + <StringDetect attribute="Value" context="#pop#pop!MustacheJS" String="'x-tmpl-mustache'"/> + <StringDetect attribute="Value" context="#pop#pop!MustacheJS" String=""text/mustache""/> + <StringDetect attribute="Value" context="#pop#pop!MustacheJS" String="'text/mustache'"/> + <StringDetect attribute="Value" context="#pop#pop!MustacheJS" String=""text/x-mustache-template""/> + <StringDetect attribute="Value" context="#pop#pop!MustacheJS" String="'text/x-mustache-template'"/> + <StringDetect attribute="Value" context="#pop#pop!MustacheJS" String=""text/x-handlebars-template""/> + <StringDetect attribute="Value" context="#pop#pop!MustacheJS" String="'text/x-handlebars-template'"/> + <StringDetect attribute="Value" context="#pop#pop!MustacheJS" String=""text/ractive""/> + <StringDetect attribute="Value" context="#pop#pop!MustacheJS" String="'text/ractive'"/> + <!-- HTML templates --> + <StringDetect attribute="Value" context="#pop#pop!Script HTML template" String=""text/html""/> + <StringDetect attribute="Value" context="#pop#pop!Script HTML template" String="'text/html'"/> + </context> + + <context name="JSX" attribute="Other Text" lineEndContext="#stay"> + <DetectChar attribute="Element" context="JSX content" char=">" /> + <IncludeRules context="DefaultJS" /> + </context> + <context name="JSX content" attribute="Other Text" lineEndContext="#stay"> + <IncludeRules context="Default JS content"/> + <IncludeRules context="Normal##JavaScript React" includeAttrib="true"/> + </context> + + <context name="TypeScript" attribute="Other Text" lineEndContext="#stay"> + <DetectChar attribute="Element" context="TypeScript content" char=">" /> + <IncludeRules context="DefaultJS" /> + </context> + <context name="TypeScript content" attribute="Other Text" lineEndContext="#stay"> + <IncludeRules context="Default JS content"/> + <IncludeRules context="Normal##TypeScript" includeAttrib="true"/> + </context> + + <context name="MustacheJS" attribute="Other Text" lineEndContext="#stay"> + <DetectChar attribute="Element" context="MustacheJS content" char=">" /> + <IncludeRules context="DefaultJS" /> + </context> + <context name="MustacheJS content" attribute="Other Text" lineEndContext="#stay"> + <RegExpr attribute="Element" context="El Close 2" String="</script\b" insensitive="true" endRegion="script" /> + <StringDetect attribute="Error" context="#stay" String="<script>" insensitive="true" /> + <RegExpr attribute="Error" context="#stay" String="<script\b" insensitive="true" /> + <IncludeRules context="Base##Mustache/Handlebars (HTML)" includeAttrib="true"/> + </context> + + <context name="Script HTML template" attribute="Other Text" lineEndContext="#stay"> + <DetectChar attribute="Element" context="Script HTML template content" char=">" /> + <IncludeRules context="DefaultJS" /> + </context> + <context name="Script HTML template content" attribute="Other Text" lineEndContext="#stay"> + <RegExpr attribute="Element" context="El Close 2" String="</script\b" insensitive="true" endRegion="script" /> + <StringDetect attribute="Error" context="#stay" String="<script>" insensitive="true" /> + <RegExpr attribute="Error" context="#stay" String="<script\b" insensitive="true" /> + <IncludeRules context="FindHTML" /> + </context> + </contexts> <itemDatas> <itemData name="Normal Text" defStyleNum="dsNormal" /> diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/ini.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/ini.xml index 465422f0b0..ce300fff47 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/ini.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/ini.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE language SYSTEM "language.dtd"> -<language name="INI Files" section="Configuration" extensions="*.ini;*.pls;*.kcfgc;*.conf" mimetype="" version="4" kateversion="2.4" author="Jan Janssen (medhefgo@web.de)" license="LGPL"> +<language name="INI Files" section="Configuration" extensions="*.ini;*.pls;*.kcfgc" mimetype="" version="5" kateversion="2.4" author="Jan Janssen (medhefgo@web.de)" license="LGPL"> <highlighting> <list name="keywords"> diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/markdown.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/markdown.xml index 39ffaf77af..f88848729f 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/markdown.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/markdown.xml @@ -35,7 +35,7 @@ <!ENTITY strikeoutregex "[~]{2}[^~].*[^~][~]{2}"> <!-- pandoc style --> ]> -<language name="Markdown" version="3" kateversion="3.8" section="Markup" extensions="*.md;*.mmd;*.markdown" priority="15" author="Darrin Yeager, Claes Holmerson" license="GPL,BSD"> +<language name="Markdown" version="6" kateversion="5.0" section="Markup" extensions="*.md;*.mmd;*.markdown" priority="15" author="Darrin Yeager, Claes Holmerson" license="GPL,BSD"> <highlighting> <contexts> <context attribute="Normal Text" lineEndContext="#stay" name="Normal Text"> @@ -74,13 +74,57 @@ <context attribute="comment" lineEndContext="#stay" name="comment"> <RegExpr String="-->" attribute="comment" context="#pop" endRegion="comment"/> </context> + <context attribute="code" lineEndContext="#stay" name="bash-code"> + <WordDetect attribute="code" context="#pop" String="```"/> + <IncludeRules context="##Bash" includeAttrib="true"/> + </context> + <context attribute="code" lineEndContext="#stay" name="cmake-code"> + <WordDetect attribute="code" context="#pop" String="```"/> + <IncludeRules context="##CMake" includeAttrib="true"/> + </context> + <context attribute="code" lineEndContext="#stay" name="cpp-code"> + <WordDetect attribute="code" context="#pop" String="```"/> + <IncludeRules context="##C++" includeAttrib="true"/> + </context> + <context attribute="code" lineEndContext="#stay" name="css-code"> + <WordDetect attribute="code" context="#pop" String="```"/> + <IncludeRules context="##CSS" includeAttrib="true"/> + </context> + <context attribute="code" lineEndContext="#stay" name="email-code"> + <WordDetect attribute="code" context="#pop" String="```"/> + <IncludeRules context="##Email" includeAttrib="true"/> + </context> + <context attribute="code" lineEndContext="#stay" name="haskell-code"> + <WordDetect attribute="code" context="#pop" String="```"/> + <IncludeRules context="##Haskell" includeAttrib="true"/> + </context> + <context attribute="code" lineEndContext="#stay" name="html-code"> + <WordDetect attribute="code" context="#pop" String="```"/> + <IncludeRules context="##HTML" includeAttrib="true"/> + </context> + <context attribute="code" lineEndContext="#stay" name="json-code"> + <WordDetect attribute="code" context="#pop" String="```"/> + <IncludeRules context="##JSON" includeAttrib="true"/> + </context> <context attribute="code" lineEndContext="#stay" name="php-code"> <WordDetect attribute="code" context="#pop" String="```"/> - <IncludeRules context="phpsource##PHP/PHP"/> + <IncludeRules context="phpsource##PHP/PHP" includeAttrib="true"/> </context> <context attribute="code" lineEndContext="#stay" name="python-code"> <WordDetect attribute="code" context="#pop" String="```"/> - <IncludeRules context="##Python"/> + <IncludeRules context="##Python" includeAttrib="true"/> + </context> + <context attribute="code" lineEndContext="#stay" name="qml-code"> + <WordDetect attribute="code" context="#pop" String="```"/> + <IncludeRules context="##QML" includeAttrib="true"/> + </context> + <context attribute="code" lineEndContext="#stay" name="rust-code"> + <WordDetect attribute="code" context="#pop" String="```"/> + <IncludeRules context="##Rust" includeAttrib="true"/> + </context> + <context attribute="code" lineEndContext="#stay" name="xml-code"> + <WordDetect attribute="code" context="#pop" String="```"/> + <IncludeRules context="##XML" includeAttrib="true"/> </context> <context attribute="code" lineEndContext="#stay" name="code"> <WordDetect attribute="code" context="#pop" String="```"/> @@ -98,8 +142,19 @@ <RegExpr attribute="mailtolink" String="&mailtolinkregex;"/> <RegExpr attribute="strikeout" minimal="true" String="&strikeoutregex;"/> <RegExpr attribute="linebreak" minimal="true" String="&linebreakregex;"/> + <WordDetect attribute="code" context="bash-code" String="```bash"/> + <WordDetect attribute="code" context="cmake-code" String="```cmake"/> + <WordDetect attribute="code" context="cpp-code" String="```cpp"/> + <WordDetect attribute="code" context="css-code" String="```css"/> + <WordDetect attribute="code" context="email-code" String="```email"/> + <WordDetect attribute="code" context="haskell-code" String="```haskell"/> + <WordDetect attribute="code" context="html-code" String="```html"/> + <WordDetect attribute="code" context="json-code" String="```json"/> <WordDetect attribute="code" context="php-code" String="```php"/> <WordDetect attribute="code" context="python-code" String="```python"/> + <WordDetect attribute="code" context="qml-code" String="```qml"/> + <WordDetect attribute="code" context="rust-code" String="```rust"/> + <WordDetect attribute="code" context="xml-code" String="```xml"/> <StringDetect attribute="code" context="code" String="```"/> </context> </contexts> @@ -121,12 +176,12 @@ <itemData name="blockquote" defStyleNum="dsDataType"/> <itemData name="bq-emphasis" defStyleNum="dsDataType" italic="true"/> <itemData name="bq-strong" defStyleNum="dsDataType" bold="true"/> - <itemData name="bullet" defStyleNum="dsFloat"/> - <itemData name="bl-emphasis" defStyleNum="dsFloat" italic="true"/> - <itemData name="bl-strong" defStyleNum="dsFloat" bold="true"/> - <itemData name="numlist" defStyleNum="dsFloat"/> - <itemData name="nl-emphasis" defStyleNum="dsFloat" italic="true"/> - <itemData name="nl-strong" defStyleNum="dsFloat" bold="true"/> + <itemData name="bullet" defStyleNum="dsString"/> + <itemData name="bl-emphasis" defStyleNum="dsString" italic="true"/> + <itemData name="bl-strong" defStyleNum="dsString" bold="true"/> + <itemData name="numlist" defStyleNum="dsString"/> + <itemData name="nl-emphasis" defStyleNum="dsString" italic="true"/> + <itemData name="nl-strong" defStyleNum="dsString" bold="true"/> <itemData name="comment" defStyleNum="dsComment"/> <itemData name="code" defStyleNum="dsBaseN"/> <itemData name="reflink" defStyleNum="dsOthers" underline="true"/> diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/perl.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/perl.xml index cd3d3ce65c..0d1931649c 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/perl.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/perl.xml @@ -39,7 +39,7 @@ Enhance tr/// and y/// support. --> -<language name="Perl" version="7" kateversion="2.4" section="Scripts" extensions="*.pl;*.PL;*.pm;*.pl6;*.PL6;*.p6;*.pm6;" mimetype="application/x-perl;text/x-perl" priority="5" author="Anders Lund (anders@alweb.dk)" license="LGPLv2"> +<language name="Perl" version="8" kateversion="2.4" section="Scripts" extensions="*.pl;*.PL;*.pm;*.pl6;*.PL6;*.p6;*.pm6;" mimetype="application/x-perl;text/x-perl" priority="5" author="Anders Lund (anders@alweb.dk)" license="LGPLv2"> <highlighting> <list name="keywords"> <item>if</item> @@ -383,8 +383,11 @@ <RegExpr attribute="Operator" context="find_pattern" String="\b(?:m|qr)(?=\s*[^\w\s\]})])" /> - <RegExpr attribute="Normal Text" context="#stay" String="[\w_]+\s*/" /> - <RegExpr attribute="Normal Text" context="#stay" String="[<>"':]/" /> + <RegExpr attribute="Normal Text" context="#stay" String="[\w_]+\s*//?\=?" /> + <RegExpr attribute="Normal Text" context="#stay" String="[<>"':]//?\=?" /> + <!-- Avoid conflicts between operators / and // --> + <StringDetect attribute="Normal Text" context="#stay" String="//=" /> + <Detect2Chars attribute="Normal Text" context="#stay" char="/" char1="/" /> <DetectChar attribute="Operator" context="pattern_slash" char="/" beginRegion="Pattern" /> <RegExpr attribute="Operator" context="#stay" String="-[rwxoRWXOeszfdlpSbctugkTBMAC]\b" /> diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/ruby.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/ruby.xml index 754dfdc5fe..a451e1442f 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/ruby.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/ruby.xml @@ -31,7 +31,7 @@ <!-- Hold the "language" opening tag on a single line, as mentioned in "language.dtd". --> <language name="Ruby" section="Scripts" - version="9" kateversion="3.3" + version="10" kateversion="3.3" extensions="*.rb;*.rjs;*.rxml;*.xml.erb;*.js.erb;*.rake;Rakefile;Gemfile;*.gemspec;Vagrantfile" mimetype="application/x-ruby" style="ruby" indenter="ruby" @@ -179,11 +179,11 @@ <item>warn</item> </list> - <list name="mixin-methods"> - <item>extend</item> - <item>include</item> - <item>prepend</item> - </list> + <list name="mixin-methods"> + <item>extend</item> + <item>include</item> + <item>prepend</item> + </list> <contexts> <context name="Normal" attribute="Normal Text" lineEndContext="#stay"> @@ -204,7 +204,7 @@ <RegExpr attribute="Keyword" String="\;\s*(while|until)\b(?!.*\bdo\b)" context="#stay" beginRegion="def block"/> <RegExpr attribute="Keyword" String="(if|unless)\b" context="#stay" beginRegion="def block" firstNonSpace="true"/> <RegExpr attribute="Keyword" String="\;\s*(if|unless)\b" context="#stay" beginRegion="def block"/> - <WordDetect attribute="Keyword" String="class" context="#stay" beginRegion="def block"/> + <WordDetect attribute="Keyword" String="class" context="no_heredoc" beginRegion="def block"/> <WordDetect attribute="Keyword" String="module" context="#stay" beginRegion="def block"/> <WordDetect attribute="Keyword" String="begin" context="#stay" beginRegion="def block"/> <RegExpr attribute="Keyword" String="\bfor\b(?!.*\bdo\b)" context="#stay" beginRegion="def block"/> @@ -231,7 +231,7 @@ <keyword attribute="Pseudo variable" String="pseudo-variables" context="check_div_1"/> <keyword attribute="Default globals" String="default-globals" context="check_div_2"/> <keyword attribute="Kernel methods" String="kernel-methods" context="check_div_2"/> - <keyword attribute="Module mixin methods" String="mixin-methods" context="check_div_2"/> + <keyword attribute="Module mixin methods" String="mixin-methods" context="check_div_2"/> <!-- (global) vars starting with $ Match them before $_. @@ -263,8 +263,8 @@ push operator '<<' than requiring to put space between the operator and the string. --> - <RegExpr attribute="Operator" context="find_indented_heredoc" String="\s*<<-(?=\w+|["'])" beginRegion="HereDocument" /> - <RegExpr attribute="Operator" context="find_heredoc" String="\s*<<(?=\w+|["'])" beginRegion="HereDocument" /> + <RegExpr attribute="Operator" context="find_indented_heredoc" String="\s*<<[-~](?=\w+|["'`])" beginRegion="HereDocument" /> + <RegExpr attribute="Operator" context="find_heredoc" String="\s*<<(?=\w+|["'`])" beginRegion="HereDocument" /> <DetectChar attribute="Operator" char="." context="#stay"/> <Detect2Chars attribute="Operator" char="&" char1="&" context="#stay"/> @@ -280,8 +280,10 @@ <RegExpr attribute="Symbol" String=":(@{1,2}|\$)?[a-zA-Z_][a-zA-Z0-9_]*[=?!]?" context="check_div_1"/> <RegExpr attribute="Symbol" String=":\[\]=?" context="check_div_1"/> - <RegExpr attribute="Symbol" String="(@{1,2}|\$)?[a-zA-Z_][a-zA-Z0-9_]*[=?!]?: " context="check_div_1"/> - <RegExpr attribute="Symbol" String="\[\]=?: " context="check_div_1"/> + <!-- Do not send to "check_div_1" context!: + after detecting these rules (": ") there can be a regular expression (see bug: #361875) --> + <RegExpr attribute="Symbol" String="(@{1,2}|\$)?[a-zA-Z_][a-zA-Z0-9_]*[=?!]?: " context="#stay"/> + <RegExpr attribute="Symbol" String="\[\]=?: " context="#stay"/> <DetectChar attribute="String" char=""" context="Quoted String"/> <DetectChar attribute="Raw String" char="'" context="Apostrophed String"/> @@ -436,13 +438,17 @@ The contexts below support both normal and indented heredocs --> <!-- here we markup the heredoc markers --> - <context name="find_heredoc" attribute="Normal Text" lineEndContext="#pop" > + <context name="find_heredoc" attribute="Normal Text" lineEndContext="#pop" fallthrough="true" fallthroughContext="#pop"> <RegExpr attribute="Keyword" context="apostrophed_normal_heredoc" String="'(\w+)'" /> - <RegExpr attribute="Keyword" context="normal_heredoc" String=""?(\w+)"?" /> + <RegExpr attribute="Keyword" context="normal_heredoc" String="(\w+)" /> + <RegExpr attribute="Keyword" context="normal_heredoc" String=""(\w+)"" /> + <RegExpr attribute="Keyword" context="normal_heredoc" String="`(\w+)`" /> </context> - <context name="find_indented_heredoc" attribute="Normal Text" lineEndContext="#pop" > + <context name="find_indented_heredoc" attribute="Normal Text" lineEndContext="#pop" fallthrough="true" fallthroughContext="#pop"> <RegExpr attribute="Keyword" context="apostrophed_indented_heredoc" String="'(\w+)'" /> - <RegExpr attribute="Keyword" context="indented_heredoc" String=""?(\w+)"?" /> + <RegExpr attribute="Keyword" context="indented_heredoc" String="(\w+)" /> + <RegExpr attribute="Keyword" context="indented_heredoc" String=""(\w+)"" /> + <RegExpr attribute="Keyword" context="indented_heredoc" String="`(\w+)`" /> </context> <!-- these are the real heredoc contexts --> <context name="indented_heredoc" attribute="Here Document" lineEndContext="#stay" dynamic="true"> @@ -467,6 +473,16 @@ <Detect2Chars attribute="Substitution" char="#" char1="{" context="Subst"/> </context> + <!-- avoid highlighting heredoc markers, for example, in singleton class definition (see bug: #358273) --> + <context name="no_heredoc" attribute="Normal Text" lineEndContext="#stay" fallthrough="true" fallthroughContext="#pop"> + <DetectSpaces /> + <Detect2Chars attribute="Operator" char="<" char1="<" context="#pop"/> + <!-- comments --> + <RegExpr attribute="Comment" String="#\s*BEGIN.*$" context="#stay" beginRegion="marker" column="0"/> + <RegExpr attribute="Comment" String="#\s*END.*$" context="#stay" endRegion="marker" column="0"/> + <DetectChar attribute="Comment" char="#" context="General Comment"/> + </context> + <!-- General delimited input support The contexts below handle the various gdl formats --> @@ -892,7 +908,7 @@ <itemData name="Constant" defStyleNum="dsDataType"/> <itemData name="Constant Value" defStyleNum="dsDataType" color="#bb1188"/> <itemData name="Kernel methods" defStyleNum="dsNormal" color="#000080" selColor="#ffffff"/> <!-- #CC0E86 --> - <itemData name="Module mixin methods" defStyleNum="dsNormal" color="#000080" selColor="#ffffff"/> <!-- #CC0E86 --> + <itemData name="Module mixin methods" defStyleNum="dsNormal" color="#000080" selColor="#ffffff"/> <!-- #CC0E86 --> <itemData name="Member" defStyleNum="dsNormal"/> <itemData name="Instance Variable" defStyleNum="dsOthers"/> <itemData name="Class Variable" defStyleNum="dsOthers"/> @@ -913,3 +929,5 @@ <keywords casesensitive="1" weakDeliminator="!?"/> </general> </language> + +<!-- kate: replace-tabs off; --> diff --git a/src/libs/3rdparty/syntax-highlighting/data/syntax/yacc.xml b/src/libs/3rdparty/syntax-highlighting/data/syntax/yacc.xml index 6936c7a2de..06d6492ff1 100644 --- a/src/libs/3rdparty/syntax-highlighting/data/syntax/yacc.xml +++ b/src/libs/3rdparty/syntax-highlighting/data/syntax/yacc.xml @@ -32,7 +32,7 @@ This code is released under the LGPL as part of kdelibs/kate. ======================================================================== --> -<language name="Yacc/Bison" version="4" kateversion="2.4" section="Sources" extensions="*.y;*.yy;*.ypp;*.y++" mimetype="text/x-yacc;text/x-bison" priority="5" author="Jan Villat (jan.villat@net2000.ch)" license="LGPL"> +<language name="Yacc/Bison" version="5" kateversion="5.0" section="Sources" extensions="*.y;*.yy;*.ypp;*.y++" mimetype="text/x-yacc;text/x-bison" priority="5" author="Jan Villat (jan.villat@net2000.ch)" license="LGPL"> <highlighting> <contexts> @@ -200,9 +200,12 @@ This code is released under the LGPL as part of kdelibs/kate. </context> <context name="CommentStar" attribute="Comment" lineEndContext="#stay"> <Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" /> + <IncludeRules context="##Alerts" /> + <IncludeRules context="##Modelines" /> </context> - <context name="CommentSlash" attribute="Comment" lineEndContext="#stay"> - <RegExpr attribute="Comment" context="#pop" String="[^\\]$" /> + <context name="CommentSlash" attribute="Comment" lineEndContext="#pop"> + <IncludeRules context="##Alerts" /> + <IncludeRules context="##Modelines" /> </context> <context name="StringOrChar" attribute="Normal Text" lineEndContext="#stay"> diff --git a/src/libs/3rdparty/syntax-highlighting/src/cli/kate-syntax-highlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/cli/kate-syntax-highlighter.cpp index 80a15d2589..8334dd32e9 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/cli/kate-syntax-highlighter.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/cli/kate-syntax-highlighter.cpp @@ -92,14 +92,14 @@ int main(int argc, char **argv) Repository repo; if (parser.isSet(listDefs)) { - foreach (const auto &def, repo.definitions()) { + for (const auto &def : repo.definitions()) { std::cout << qPrintable(def.name()) << std::endl; } return 0; } if (parser.isSet(listThemes)) { - foreach (const auto &theme, repo.themes()) + for (const auto &theme : repo.themes()) std::cout << qPrintable(theme.name()) << std::endl; return 0; } diff --git a/src/libs/3rdparty/syntax-highlighting/src/indexer/katehighlightingindexer.cpp b/src/libs/3rdparty/syntax-highlighting/src/indexer/katehighlightingindexer.cpp index 489fbec160..3534cfde90 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/indexer/katehighlightingindexer.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/indexer/katehighlightingindexer.cpp @@ -194,6 +194,82 @@ bool checkLookAhead(const QString &hlFilename, QXmlStreamReader &xml) } /** + * Helper class to search for non-existing keyword include. + */ +class KeywordIncludeChecker +{ +public: + void processElement(const QString &hlFilename, const QString &hlName, QXmlStreamReader &xml) + { + if (xml.name() == QLatin1String("list")) { + auto &keywords = m_keywordMap[hlName]; + keywords.filename = hlFilename; + auto name = xml.attributes().value(QLatin1String("name")).toString(); + m_currentIncludes = &keywords.includes[name]; + } + else if (xml.name() == QLatin1String("include")) { + if (!m_currentIncludes) { + qWarning() << hlFilename << "line" << xml.lineNumber() << "<include> tag ouside <list>"; + m_success = false; + } else { + m_currentIncludes->push_back({xml.lineNumber(), xml.readElementText()}); + } + } + } + + bool check() const + { + bool success = m_success; + for (auto &keywords : m_keywordMap) { + QMapIterator<QString, QVector<Keywords::Include>> includes(keywords.includes); + while (includes.hasNext()) { + includes.next(); + for (auto &include : includes.value()) { + bool containsKeywordName = true; + int const idx = include.name.indexOf(QStringLiteral("##")); + if (idx == -1) { + auto &keywordName = includes.key(); + containsKeywordName = keywords.includes.contains(keywordName); + } + else { + auto defName = include.name.mid(idx + 2); + auto listName = include.name.left(idx); + auto it = m_keywordMap.find(defName); + if (it == m_keywordMap.end()) { + qWarning() << keywords.filename << "line" << include.line << "unknown definition in" << include.name; + success = false; + } else { + containsKeywordName = it->includes.contains(listName); + } + } + + if (!containsKeywordName) { + qWarning() << keywords.filename << "line" << include.line << "unknown keyword name in" << include.name; + success = false; + } + } + } + } + return success; + } + +private: + struct Keywords + { + QString filename; + struct Include + { + qint64 line; + QString name; + }; + QMap<QString, QVector<Include>> includes; + }; + QHash<QString, Keywords> m_keywordMap; + QVector<Keywords::Include> *m_currentIncludes = nullptr; + bool m_success = true; +}; + +/** * Helper class to search for non-existing or unreferenced keyword lists. */ class KeywordChecker @@ -296,6 +372,7 @@ public: const auto unusedNames = language.existingContextNames - language.usedContextNames; if (!unusedNames.isEmpty()) { qWarning() << language.hlFilename << "Unused contexts:" << unusedNames; + success = false; } } @@ -457,9 +534,10 @@ int main(int argc, char *argv[]) // index all given highlightings ContextChecker contextChecker; + KeywordIncludeChecker keywordIncludeChecker; QVariantMap hls; int anyError = 0; - foreach (const QString &hlFilename, hlFilenames) { + for (const QString &hlFilename : qAsConst(hlFilenames)) { QFile hlFile(hlFilename); if (!hlFile.open(QIODevice::ReadOnly)) { qWarning ("Failed to open %s", qPrintable(hlFilename)); @@ -493,7 +571,7 @@ int main(int argc, char *argv[]) QVariantMap hl; // transfer text attributes - Q_FOREACH (const QString &attribute, textAttributes) { + for (const QString &attribute : qAsConst(textAttributes)) { hl[attribute] = xml.attributes().value(attribute).toString(); } @@ -528,6 +606,9 @@ int main(int argc, char *argv[]) // search for used/existing contexts if applicable contextChecker.processElement(hlFilename, hlName, xml); + // search for existing keyword includes + keywordIncludeChecker.processElement(hlFilename, hlName, xml); + // search for used/existing attributes if applicable attributeChecker.processElement(xml); @@ -571,6 +652,9 @@ int main(int argc, char *argv[]) if (!contextChecker.check()) anyError = 7; + if (!keywordIncludeChecker.check()) + anyError = 7; + // bail out if any problem was seen if (anyError) diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt b/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt index bf729fca71..95bf4c349e 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/CMakeLists.txt @@ -40,6 +40,7 @@ ecm_generate_headers(SyntaxHighlighting_HEADERS HEADER_NAMES AbstractHighlighter Definition + DefinitionDownloader FoldingRegion Format Repository diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp index f69944debd..c4ef86a771 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/abstracthighlighter.cpp @@ -53,7 +53,7 @@ void AbstractHighlighterPrivate::ensureDefinitionLoaded() defData = DefinitionData::get(m_definition); } - if (Q_UNLIKELY(!defData->repo && !defData->name.isEmpty())) + if (Q_UNLIKELY(!defData->repo && !defData->fileName.isEmpty())) qCCritical(Log) << "Repository got deleted while a highlighter is still active!"; if (m_definition.isValid()) @@ -118,13 +118,13 @@ State AbstractHighlighter::highlightLine(const QString& text, const State &state // verify definition, deal with no highlighting being enabled d->ensureDefinitionLoaded(); - if (!d->m_definition.isValid()) { + const auto defData = DefinitionData::get(d->m_definition); + if (!d->m_definition.isValid() || !defData->isLoaded()) { applyFormat(0, text.size(), Format()); return State(); } // verify/initialize state - auto defData = DefinitionData::get(d->m_definition); auto newState = state; auto stateData = StateData::get(newState); const DefinitionRef currentDefRef(d->m_definition); @@ -139,9 +139,37 @@ State AbstractHighlighter::highlightLine(const QString& text, const State &state // process empty lines if (text.isEmpty()) { - while (!stateData->topContext()->lineEmptyContext().isStay()) { - if (!d->switchContext(stateData, stateData->topContext()->lineEmptyContext(), QStringList())) + /** + * handle line empty context switches + * guard against endless loops + * see https://phabricator.kde.org/D18509 + */ + int endlessLoopingCounter = 0; + while (!stateData->topContext()->lineEmptyContext().isStay() || (stateData->topContext()->lineEmptyContext().isStay() && !stateData->topContext()->lineEndContext().isStay())) { + /** + * line empty context switches + */ + if (!stateData->topContext()->lineEmptyContext().isStay()) { + if (!d->switchContext(stateData, stateData->topContext()->lineEmptyContext(), QStringList())) { + /** + * end when trying to #pop the main context + */ + break; + } + /** + * line end context switches only when lineEmptyContext is #stay. This avoids + * skipping empty lines after a line continuation character (see bug 405903) + */ + } else if (!stateData->topContext()->lineEndContext().isStay() && + !d->switchContext(stateData, stateData->topContext()->lineEndContext(), QStringList())) break; + + // guard against endless loops + ++endlessLoopingCounter; + if (endlessLoopingCounter > 1024) { + qCDebug(Log) << "Endless switch context transitions for line empty context, aborting highlighting of line."; + break; + } } auto context = stateData->topContext(); applyFormat(0, 0, context->attributeFormat()); @@ -238,11 +266,18 @@ State AbstractHighlighter::highlightLine(const QString& text, const State &state if (newOffset <= offset) continue; - // apply folding - if (rule->endRegion().isValid()) - applyFolding(offset, newOffset - offset, rule->endRegion()); + /** + * apply folding. + * special cases: + * - rule with endRegion + beginRegion: in endRegion, the length is 0 + * - rule with lookAhead: length is 0 + */ + if (rule->endRegion().isValid() && rule->beginRegion().isValid()) + applyFolding(offset, 0, rule->endRegion()); + else if (rule->endRegion().isValid()) + applyFolding(offset, rule->isLookAhead() ? 0 : newOffset - offset, rule->endRegion()); if (rule->beginRegion().isValid()) - applyFolding(offset, newOffset - offset, rule->beginRegion()); + applyFolding(offset, rule->isLookAhead() ? 0 : newOffset - offset, rule->beginRegion()); if (rule->isLookAhead()) { Q_ASSERT(!rule->context().isStay()); @@ -293,12 +328,30 @@ State AbstractHighlighter::highlightLine(const QString& text, const State &state } while (offset < text.size()); + /** + * apply format for remaining text, if any + */ if (beginOffset < offset) applyFormat(beginOffset, text.size() - beginOffset, *currentFormat); - while (!stateData->topContext()->lineEndContext().isStay() && !lineContinuation) { - if (!d->switchContext(stateData, stateData->topContext()->lineEndContext(), QStringList())) - break; + /** + * handle line end context switches + * guard against endless loops + * see https://phabricator.kde.org/D18509 + */ + { + int endlessLoopingCounter = 0; + while (!stateData->topContext()->lineEndContext().isStay() && !lineContinuation) { + if (!d->switchContext(stateData, stateData->topContext()->lineEndContext(), QStringList())) + break; + + // guard against endless loops + ++endlessLoopingCounter; + if (endlessLoopingCounter > 1024) { + qCDebug(Log) << "Endless switch context transitions for line end context, aborting highlighting of line."; + break; + } + } } return newState; diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp index c03d23dc48..ae95a6b235 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/definition.cpp @@ -31,6 +31,7 @@ #include "context_p.h" #include "format.h" #include "format_p.h" +#include "repository.h" #include "repository_p.h" #include "rule_p.h" #include "ksyntaxhighlighting_logging.h" @@ -222,13 +223,13 @@ QStringList Definition::foldingIgnoreList() const QStringList Definition::keywordLists() const { - d->load(); + d->load(DefinitionData::OnlyKeywords(true)); return d->keywordLists.keys(); } QStringList Definition::keywordList(const QString& name) const { - d->load(); + d->load(DefinitionData::OnlyKeywords(true)); const auto list = d->keywordList(name); return list ? list->keywords() : QStringList(); } @@ -323,18 +324,18 @@ Context* DefinitionData::initialContext() const return contexts.first(); } -Context* DefinitionData::contextByName(const QString& name) const +Context* DefinitionData::contextByName(const QString& wantedName) const { - foreach (auto context, contexts) { - if (context->name() == name) + for (const auto context : contexts) { + if (context->name() == wantedName) return context; } return nullptr; } -KeywordList *DefinitionData::keywordList(const QString& name) +KeywordList *DefinitionData::keywordList(const QString& wantedName) { - auto it = keywordLists.find(name); + auto it = keywordLists.find(wantedName); return (it == keywordLists.end()) ? nullptr : &it.value(); } @@ -343,9 +344,9 @@ bool DefinitionData::isWordDelimiter(QChar c) const return std::binary_search(wordDelimiters.constBegin(), wordDelimiters.constEnd(), c); } -Format DefinitionData::formatByName(const QString& name) const +Format DefinitionData::formatByName(const QString& wantedName) const { - const auto it = formats.constFind(name); + const auto it = formats.constFind(wantedName); if (it != formats.constEnd()) return it.value(); @@ -357,7 +358,7 @@ bool DefinitionData::isLoaded() const return !contexts.isEmpty(); } -bool DefinitionData::load() +bool DefinitionData::load(OnlyKeywords onlyKeywords) { if (fileName.isEmpty()) return false; @@ -365,6 +366,9 @@ bool DefinitionData::load() if (isLoaded()) return true; + if (bool(onlyKeywords) && keywordIsLoaded) + return true; + QFile file(fileName); if (!file.open(QFile::ReadOnly)) return false; @@ -375,17 +379,22 @@ bool DefinitionData::load() if (token != QXmlStreamReader::StartElement) continue; - if (reader.name() == QLatin1String("highlighting")) - loadHighlighting(reader); + if (reader.name() == QLatin1String("highlighting")) { + loadHighlighting(reader, onlyKeywords); + if (bool(onlyKeywords)) { + return true; + } + } else if (reader.name() == QLatin1String("general")) loadGeneral(reader); } - for (auto it = keywordLists.begin(); it != keywordLists.end(); ++it) - (*it).setCaseSensitivity(caseSensitive); + for (auto it = keywordLists.begin(); it != keywordLists.end(); ++it) { + it->setCaseSensitivity(caseSensitive); + } - foreach (auto context, contexts) { + for (const auto context : qAsConst(contexts)) { context->resolveContexts(); context->resolveIncludes(); context->resolveAttributeFormat(); @@ -454,10 +463,10 @@ bool DefinitionData::loadMetaData(const QString &file, const QJsonObject &obj) fileName = file; const auto exts = obj.value(QLatin1String("extensions")).toString(); - foreach (const auto &ext, exts.split(QLatin1Char(';'), QString::SkipEmptyParts)) + for (const auto &ext : exts.split(QLatin1Char(';'), QString::SkipEmptyParts)) extensions.push_back(ext); const auto mts = obj.value(QLatin1String("mimetype")).toString(); - foreach (const auto &mt, mts.split(QLatin1Char(';'), QString::SkipEmptyParts)) + for (const auto &mt : mts.split(QLatin1Char(';'), QString::SkipEmptyParts)) mimetypes.push_back(mt); return true; @@ -482,29 +491,42 @@ bool DefinitionData::loadLanguage(QXmlStreamReader &reader) author = reader.attributes().value(QStringLiteral("author")).toString(); license = reader.attributes().value(QStringLiteral("license")).toString(); const auto exts = reader.attributes().value(QStringLiteral("extensions")).toString(); - foreach (const auto &ext, exts.split(QLatin1Char(';'), QString::SkipEmptyParts)) + for (const auto &ext : exts.split(QLatin1Char(';'), QString::SkipEmptyParts)) extensions.push_back(ext); const auto mts = reader.attributes().value(QStringLiteral("mimetype")).toString(); - foreach (const auto &mt, mts.split(QLatin1Char(';'), QString::SkipEmptyParts)) + for (const auto &mt : mts.split(QLatin1Char(';'), QString::SkipEmptyParts)) mimetypes.push_back(mt); if (reader.attributes().hasAttribute(QStringLiteral("casesensitive"))) caseSensitive = Xml::attrToBool(reader.attributes().value(QStringLiteral("casesensitive"))) ? Qt::CaseSensitive : Qt::CaseInsensitive; return true; } -void DefinitionData::loadHighlighting(QXmlStreamReader& reader) +void DefinitionData::loadHighlighting(QXmlStreamReader& reader, OnlyKeywords onlyKeywords) { Q_ASSERT(reader.name() == QLatin1String("highlighting")); Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement); + // skip highlighting + reader.readNext(); + while (!reader.atEnd()) { switch (reader.tokenType()) { case QXmlStreamReader::StartElement: if (reader.name() == QLatin1String("list")) { - KeywordList keywords; - keywords.load(reader); - keywordLists.insert(keywords.name(), keywords); + if (!keywordIsLoaded) { + KeywordList keywords; + keywords.load(reader); + keywordLists.insert(keywords.name(), keywords); + } + else { + reader.skipCurrentElement(); + reader.readNext(); // Skip </list> + } + } else if (bool(onlyKeywords)) { + resolveIncludeKeywords(); + return; } else if (reader.name() == QLatin1String("contexts")) { + resolveIncludeKeywords(); loadContexts(reader); reader.readNext(); } else if (reader.name() == QLatin1String("itemDatas")) { @@ -522,6 +544,19 @@ void DefinitionData::loadHighlighting(QXmlStreamReader& reader) } } +void DefinitionData::resolveIncludeKeywords() +{ + if (keywordIsLoaded) { + return; + } + + keywordIsLoaded = true; + + for (auto it = keywordLists.begin(); it != keywordLists.end(); ++it) { + it->resolveIncludeKeywords(*this); + } +} + void DefinitionData::loadContexts(QXmlStreamReader& reader) { Q_ASSERT(reader.name() == QLatin1String("contexts")); @@ -598,7 +633,7 @@ void DefinitionData::loadGeneral(QXmlStreamReader& reader) std::sort(wordDelimiters.begin(), wordDelimiters.end()); auto it = std::unique(wordDelimiters.begin(), wordDelimiters.end()); wordDelimiters.truncate(std::distance(wordDelimiters.begin(), it)); - foreach (const auto c, reader.attributes().value(QLatin1String("weakDeliminator"))) + for (const auto c : reader.attributes().value(QLatin1String("weakDeliminator"))) wordDelimiters.remove(c); // adaptWordWrapDelimiters, and sort diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/definition_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/definition_p.h index ab95a9552c..9bbf59691c 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/definition_p.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/definition_p.h @@ -46,6 +46,9 @@ public: DefinitionData(); ~DefinitionData(); + DefinitionData(const DefinitionData &) = delete; + DefinitionData &operator=(const DefinitionData &) = delete; + static DefinitionData* get(const Definition &def); bool isLoaded() const; @@ -54,9 +57,11 @@ public: void clear(); - bool load(); + enum class OnlyKeywords : bool; + + bool load(OnlyKeywords onlyKeywords = OnlyKeywords(false)); bool loadLanguage(QXmlStreamReader &reader); - void loadHighlighting(QXmlStreamReader &reader); + void loadHighlighting(QXmlStreamReader &reader, OnlyKeywords onlyKeywords); void loadContexts(QXmlStreamReader &reader); void loadItemData(QXmlStreamReader &reader); void loadGeneral(QXmlStreamReader &reader); @@ -65,6 +70,8 @@ public: void loadSpellchecking(QXmlStreamReader &reader); bool checkKateVersion(const QStringRef &verStr); + void resolveIncludeKeywords(); + KeywordList *keywordList(const QString &name); bool isWordDelimiter(QChar c) const; @@ -83,6 +90,7 @@ public: QHash<QString, Format> formats; QString wordDelimiters; QString wordWrapDelimiters; + bool keywordIsLoaded = false; bool hasFoldingRegions = false; bool indentationBasedFolding = false; QStringList foldingIgnoreList; diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp index 397da6d700..d1808cafef 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/format.cpp @@ -213,52 +213,52 @@ void FormatPrivate::load(QXmlStreamReader& reader) name = reader.attributes().value(QStringLiteral("name")).toString(); defaultStyle = stringToDefaultFormat(reader.attributes().value(QStringLiteral("defStyleNum"))); - QStringRef ref = reader.attributes().value(QStringLiteral("color")); - if (!ref.isEmpty()) { - style.textColor = QColor(ref.toString()).rgba(); + QStringRef attribute = reader.attributes().value(QStringLiteral("color")); + if (!attribute.isEmpty()) { + style.textColor = QColor(attribute.toString()).rgba(); } - ref = reader.attributes().value(QStringLiteral("selColor")); - if (!ref.isEmpty()) { - style.selectedTextColor = QColor(ref.toString()).rgba(); + attribute = reader.attributes().value(QStringLiteral("selColor")); + if (!attribute.isEmpty()) { + style.selectedTextColor = QColor(attribute.toString()).rgba(); } - ref = reader.attributes().value(QStringLiteral("backgroundColor")); - if (!ref.isEmpty()) { - style.backgroundColor = QColor(ref.toString()).rgba(); + attribute = reader.attributes().value(QStringLiteral("backgroundColor")); + if (!attribute.isEmpty()) { + style.backgroundColor = QColor(attribute.toString()).rgba(); } - ref = reader.attributes().value(QStringLiteral("selBackgroundColor")); - if (!ref.isEmpty()) { - style.selectedBackgroundColor = QColor(ref.toString()).rgba(); + attribute = reader.attributes().value(QStringLiteral("selBackgroundColor")); + if (!attribute.isEmpty()) { + style.selectedBackgroundColor = QColor(attribute.toString()).rgba(); } - ref = reader.attributes().value(QStringLiteral("italic")); - if (!ref.isEmpty()) { + attribute = reader.attributes().value(QStringLiteral("italic")); + if (!attribute.isEmpty()) { style.hasItalic = true; - style.italic = Xml::attrToBool(ref); + style.italic = Xml::attrToBool(attribute); } - ref = reader.attributes().value(QStringLiteral("bold")); - if (!ref.isEmpty()) { + attribute = reader.attributes().value(QStringLiteral("bold")); + if (!attribute.isEmpty()) { style.hasBold = true; - style.bold = Xml::attrToBool(ref); + style.bold = Xml::attrToBool(attribute); } - ref = reader.attributes().value(QStringLiteral("underline")); - if (!ref.isEmpty()) { + attribute = reader.attributes().value(QStringLiteral("underline")); + if (!attribute.isEmpty()) { style.hasUnderline = true; - style.underline = Xml::attrToBool(ref); + style.underline = Xml::attrToBool(attribute); } - ref = reader.attributes().value(QStringLiteral("strikeOut")); - if (!ref.isEmpty()) { + attribute = reader.attributes().value(QStringLiteral("strikeOut")); + if (!attribute.isEmpty()) { style.hasStrikeThrough = true; - style.strikeThrough = Xml::attrToBool(ref); + style.strikeThrough = Xml::attrToBool(attribute); } - ref = reader.attributes().value(QStringLiteral("spellChecking")); - if (!ref.isEmpty()) { - spellCheck = Xml::attrToBool(ref); + attribute = reader.attributes().value(QStringLiteral("spellChecking")); + if (!attribute.isEmpty()) { + spellCheck = Xml::attrToBool(attribute); } } diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp index fe5f77586a..f042baac27 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist.cpp @@ -22,6 +22,9 @@ */ #include "keywordlist_p.h" +#include "repository.h" +#include "definition_p.h" +#include "ksyntaxhighlighting_logging.h" #include <QDebug> #include <QXmlStreamReader> @@ -58,6 +61,11 @@ void KeywordList::load(QXmlStreamReader& reader) reader.readNextStartElement(); break; } + else if (reader.name() == QLatin1String("include")) { + m_includes.append(reader.readElementText().trimmed()); + reader.readNextStartElement(); + break; + } reader.readNext(); break; case QXmlStreamReader::EndElement: @@ -102,3 +110,40 @@ void KeywordList::initLookupForCaseSensitivity(Qt::CaseSensitivity caseSensitive */ std::sort(vectorToSort.begin(), vectorToSort.end(), [caseSensitive] (const QStringRef &a, const QStringRef &b) { return a.compare(b, caseSensitive) < 0; }); } + +void KeywordList::resolveIncludeKeywords(DefinitionData &def) +{ + while (!m_includes.isEmpty()) { + const auto kw_include = std::move(m_includes.back()); + m_includes.pop_back(); + + const auto idx = kw_include.indexOf(QLatin1String("##")); + KeywordList *keywords = nullptr; + + if (idx >= 0) { + auto listName = kw_include.left(idx); + auto defName = kw_include.mid(idx + 2); + auto includeDef = def.repo->definitionForName(defName); + if (includeDef.isValid()) { + auto defData = DefinitionData::get(includeDef); + defData->load(DefinitionData::OnlyKeywords(true)); + keywords = defData->keywordList(listName); + } + else { + qCWarning(Log) << "Unable to resolve external include keyword for definition" << defName << "in" << def.name; + } + } else { + keywords = def.keywordList(kw_include); + } + + if (keywords) { + if (this != keywords) { + keywords->resolveIncludeKeywords(def); + } + m_keywords += keywords->m_keywords; + } + else { + qCWarning(Log) << "Unresolved include keyword" << kw_include << "in" << def.name; + } + } +} diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist_p.h b/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist_p.h index 8c41aabe0c..25d0022dbe 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist_p.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/keywordlist_p.h @@ -36,6 +36,9 @@ QT_END_NAMESPACE namespace KSyntaxHighlighting { +class Repository; +class DefinitionData; + class KeywordList { public: @@ -69,6 +72,7 @@ public: void load(QXmlStreamReader &reader); void setCaseSensitivity(Qt::CaseSensitivity caseSensitive); void initLookupForCaseSensitivity(Qt::CaseSensitivity caseSensitive); + void resolveIncludeKeywords(DefinitionData &def); private: /** @@ -82,6 +86,11 @@ private: QStringList m_keywords; /** + * raw list of include keywords, as seen in XML (but trimmed) + */ + QStringList m_includes; + + /** * default case-sensitivity setting */ Qt::CaseSensitivity m_caseSensitive = Qt::CaseSensitive; diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp index 922225a7e1..aaba9616dc 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.cpp @@ -69,7 +69,7 @@ Repository::~Repository() { // reset repo so we can detect in still alive definition instances // that the repo was deleted - foreach (const auto &def, d->m_sortedDefs) + for (const auto &def : qAsConst(d->m_sortedDefs)) DefinitionData::get(def)->repo = nullptr; } @@ -78,21 +78,16 @@ Definition Repository::definitionForName(const QString& defName) const return d->m_defs.value(defName); } -static Definition bestCandidate(QVector<Definition> &&candidates) +static void sortDefinitions(QVector<Definition> &definitions) { - if (candidates.isEmpty()) - return Definition(); - - std::partial_sort(candidates.begin(), candidates.begin() + 1, candidates.end(), [](const Definition &lhs, const Definition &rhs) { + std::stable_sort(definitions.begin(), definitions.end(), [](const Definition &lhs, const Definition &rhs) { return lhs.priority() > rhs.priority(); }); - - return candidates.at(0); } Definition Repository::definitionForFileName(const QString& fileName) const { - return bestCandidate(definitionsForFileName(fileName)); + return definitionsForFileName(fileName).value(0); } QVector<Definition> Repository::definitionsForFileName(const QString &fileName) const @@ -101,9 +96,8 @@ QVector<Definition> Repository::definitionsForFileName(const QString &fileName) const auto name = fi.fileName(); QVector<Definition> candidates; - for (auto it = d->m_defs.constBegin(); it != d->m_defs.constEnd(); ++it) { - auto def = it.value(); - foreach (const auto &pattern, def.extensions()) { + for (const Definition &def : qAsConst(d->m_sortedDefs)) { + for (const auto &pattern : def.extensions()) { if (WildcardMatcher::exactMatch(name, pattern)) { candidates.push_back(def); break; @@ -111,26 +105,28 @@ QVector<Definition> Repository::definitionsForFileName(const QString &fileName) } } + sortDefinitions(candidates); return candidates; } Definition Repository::definitionForMimeType(const QString& mimeType) const { - return bestCandidate(definitionsForMimeType(mimeType)); + return definitionsForMimeType(mimeType).value(0); } QVector<Definition> Repository::definitionsForMimeType(const QString &mimeType) const { QVector<Definition> candidates; - for (auto it = d->m_defs.constBegin(); it != d->m_defs.constEnd(); ++it) { - auto def = it.value(); - foreach (const auto &matchType, def.mimeTypes()) { + for (const Definition &def : qAsConst(d->m_sortedDefs)) { + for (const auto &matchType : def.mimeTypes()) { if (mimeType == matchType) { candidates.push_back(def); break; } } } + + sortDefinitions(candidates); return candidates; } @@ -169,11 +165,11 @@ void RepositoryPrivate::load(Repository *repo) // do lookup in standard paths, if not disabled #ifndef NO_STANDARD_PATHS - foreach (const auto &dir, QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("org.kde.syntax-highlighting/syntax"), QStandardPaths::LocateDirectory)) + for (const auto &dir : QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("org.kde.syntax-highlighting/syntax"), QStandardPaths::LocateDirectory)) loadSyntaxFolder(repo, dir); // backward compatibility with Kate - foreach (const auto &dir, QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("katepart5/syntax"), QStandardPaths::LocateDirectory)) + for (const auto &dir : QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("katepart5/syntax"), QStandardPaths::LocateDirectory)) loadSyntaxFolder(repo, dir); #endif @@ -181,7 +177,7 @@ void RepositoryPrivate::load(Repository *repo) loadSyntaxFolder(repo, QStringLiteral(":/org.kde.syntax-highlighting/syntax")); // user given extra paths - foreach (const auto &path, m_customSearchPaths) + for (const auto &path : qAsConst(m_customSearchPaths)) loadSyntaxFolder(repo, path + QStringLiteral("/syntax")); m_sortedDefs.reserve(m_defs.size()); @@ -198,7 +194,7 @@ void RepositoryPrivate::load(Repository *repo) // do lookup in standard paths, if not disabled #ifndef NO_STANDARD_PATHS - foreach (const auto &dir, QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("org.kde.syntax-highlighting/themes"), QStandardPaths::LocateDirectory)) + for (const auto &dir : QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("org.kde.syntax-highlighting/themes"), QStandardPaths::LocateDirectory)) loadThemeFolder(dir); #endif @@ -206,7 +202,7 @@ void RepositoryPrivate::load(Repository *repo) loadThemeFolder(QStringLiteral(":/org.kde.syntax-highlighting/themes")); // user given extra paths - foreach (const auto &path, m_customSearchPaths) + for (const auto &path : qAsConst(m_customSearchPaths)) loadThemeFolder(path + QStringLiteral("/themes")); } @@ -307,7 +303,7 @@ quint16 RepositoryPrivate::nextFormatId() void Repository::reload() { qCDebug(Log) << "Reloading syntax definitions!"; - foreach (const auto &def, d->m_sortedDefs) + for (const auto &def : qAsConst(d->m_sortedDefs)) DefinitionData::get(def)->clear(); d->m_defs.clear(); d->m_sortedDefs.clear(); diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h index e4e9bed69f..2bc66965cf 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/repository.h @@ -167,9 +167,11 @@ public: Definition definitionForFileName(const QString &fileName) const; /** - * Returns all Definition%s for the file named @p fileName. + * Returns all Definition%s for the file named @p fileName sorted by priority. * The match is performed based on the \e extensions and @e mimetype of * the definition files. + * + * @since 5.56 */ QVector<Definition> definitionsForFileName(const QString &fileName) const; @@ -184,7 +186,9 @@ public: Definition definitionForMimeType(const QString &mimeType) const; /** - * Returns all Definition%s to the type named @p mimeType + * Returns all Definition%s to the type named @p mimeType sorted by priority + * + * @since 5.56 */ QVector<Definition> definitionsForMimeType(const QString &mimeType) const; diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp index c48753bf0c..d9cf5eb211 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/rule.cpp @@ -59,7 +59,8 @@ static int matchEscapedChar(const QString &text, int offset) if (controlChars.contains(c)) return offset + 2; - if (c == QLatin1Char('x')) { // hex encoded character + // hex encoded character + if (c == QLatin1Char('x')) { auto newOffset = offset + 2; for (int i = 0; i < 2 && newOffset + i < text.size(); ++i, ++newOffset) { if (!isHexChar(text.at(newOffset))) @@ -70,14 +71,13 @@ static int matchEscapedChar(const QString &text, int offset) return newOffset; } - if (isOctalChar(c)) { // octal encoding + // octal encoding, simple \0 is OK, too, unlike simple \x above + if (isOctalChar(c)) { auto newOffset = offset + 2; for (int i = 0; i < 2 && newOffset + i < text.size(); ++i, ++newOffset) { if (!isOctalChar(text.at(newOffset))) break; } - if (newOffset == offset + 2) - return offset; return newOffset; } diff --git a/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp b/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp index 2bb61a7ae6..4987dc95f0 100644 --- a/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp +++ b/src/libs/3rdparty/syntax-highlighting/src/lib/syntaxhighlighter.cpp @@ -156,15 +156,15 @@ void SyntaxHighlighter::highlightBlock(const QString& text) void SyntaxHighlighter::applyFormat(int offset, int length, const KSyntaxHighlighting::Format& format) { - if (format.isDefaultTextStyle(theme()) || length == 0) + if (length == 0) return; QTextCharFormat tf; - if (format.hasTextColor(theme())) - tf.setForeground(format.textColor(theme())); + // always set the foreground color to avoid palette issues + tf.setForeground(format.textColor(theme())); + if (format.hasBackgroundColor(theme())) tf.setBackground(format.backgroundColor(theme())); - if (format.isBold(theme())) tf.setFontWeight(QFont::Bold); if (format.isItalic(theme())) diff --git a/src/libs/3rdparty/variant/variant.hpp b/src/libs/3rdparty/variant/variant.hpp index 29d7feb29f..dca26986c9 100644 --- a/src/libs/3rdparty/variant/variant.hpp +++ b/src/libs/3rdparty/variant/variant.hpp @@ -8,6 +8,11 @@ #ifndef MPARK_VARIANT_HPP #define MPARK_VARIANT_HPP +#if defined(__GNUC__) && __GNUC__ >= 9 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-copy" +#endif + /* variant synopsis @@ -2453,4 +2458,8 @@ namespace std { } // namespace std +#if defined(__GNUC__) && __GNUC__ >= 9 +#pragma GCC diagnostic pop +#endif + #endif // MPARK_VARIANT_HPP diff --git a/src/libs/CMakeLists.txt b/src/libs/CMakeLists.txt new file mode 100644 index 0000000000..52cc1d35a9 --- /dev/null +++ b/src/libs/CMakeLists.txt @@ -0,0 +1,21 @@ +add_subdirectory(3rdparty) + +add_subdirectory(aggregation) +add_subdirectory(extensionsystem) +add_subdirectory(utils) +add_subdirectory(languageutils) +add_subdirectory(cplusplus) +add_subdirectory(modelinglib) +add_subdirectory(qmljs) +add_subdirectory(qmldebug) +add_subdirectory(qmleditorwidgets) +add_subdirectory(glsl) +add_subdirectory(languageserverprotocol) +add_subdirectory(ssh) +add_subdirectory(sqlite) +add_subdirectory(clangsupport) +add_subdirectory(tracing) + +if (WIN32) + add_subdirectory(qtcreatorcdbext) +endif() diff --git a/src/libs/aggregation/CMakeLists.txt b/src/libs/aggregation/CMakeLists.txt new file mode 100644 index 0000000000..6871c9ab35 --- /dev/null +++ b/src/libs/aggregation/CMakeLists.txt @@ -0,0 +1,6 @@ +add_qtc_library(Aggregation + DEPENDS Qt5::Core + SOURCES + aggregate.cpp aggregate.h + aggregation_global.h +) diff --git a/src/libs/aggregation/examples/text/main.cpp b/src/libs/aggregation/examples/text/main.cpp index c205ccb838..043196ab78 100644 --- a/src/libs/aggregation/examples/text/main.cpp +++ b/src/libs/aggregation/examples/text/main.cpp @@ -31,7 +31,7 @@ MyMain::MyMain(QWidget *parent, Qt::WFlags flags) : QWidget(parent, flags) { ui.setupUi(this); - connect(ui.comboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), + connect(ui.comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &MyMain::select); } diff --git a/src/libs/clangsupport/CMakeLists.txt b/src/libs/clangsupport/CMakeLists.txt new file mode 100644 index 0000000000..84cdbaf8b9 --- /dev/null +++ b/src/libs/clangsupport/CMakeLists.txt @@ -0,0 +1,137 @@ +add_qtc_library(ClangSupport + PUBLIC_DEPENDS Utils Sqlite Qt5::Core Qt5::Network + PUBLIC_INCLUDES "${CMAKE_CURRENT_LIST_DIR}" + PUBLIC_DEFINES + CLANG_VERSION="${CLANG_VERSION}" + CLANG_RESOURCE_DIR="${CLANG_RESOURCE_DIR}" + CLANG_BINDIR="${CLANG_BIN_DIR}" + DEFINES CLANGSUPPORT_BUILD_LIB + SOURCES + alivemessage.cpp alivemessage.h + annotationsmessage.cpp annotationsmessage.h + baseserverproxy.cpp baseserverproxy.h + cancelmessage.cpp cancelmessage.h + changedfilepathcompressor.h + clangcodemodelclientinterface.cpp clangcodemodelclientinterface.h + clangcodemodelclientmessages.h + clangcodemodelclientproxy.cpp clangcodemodelclientproxy.h + clangcodemodelconnectionclient.cpp clangcodemodelconnectionclient.h + clangcodemodelserverinterface.cpp clangcodemodelserverinterface.h + clangcodemodelservermessages.h + clangcodemodelserverproxy.cpp clangcodemodelserverproxy.h + clangpathwatcher.h + clangpathwatcherinterface.h + clangpathwatchernotifier.h + clangrefactoringclientmessages.h + clangrefactoringmessages.h + clangrefactoringservermessages.h + clangsupport_global.h + clangsupportdebugutils.cpp clangsupportdebugutils.h + clangsupportexceptions.h + codecompletion.cpp codecompletion.h + codecompletionchunk.cpp codecompletionchunk.h + commandlinebuilder.h + compilermacro.h + completionsmessage.cpp completionsmessage.h + connectionclient.cpp connectionclient.h + connectionserver.cpp connectionserver.h + diagnosticcontainer.cpp diagnosticcontainer.h + documentschangedmessage.cpp documentschangedmessage.h + documentsclosedmessage.cpp documentsclosedmessage.h + documentsopenedmessage.cpp documentsopenedmessage.h + documentvisibilitychangedmessage.cpp documentvisibilitychangedmessage.h + dynamicastmatcherdiagnosticcontainer.cpp dynamicastmatcherdiagnosticcontainer.h + dynamicastmatcherdiagnosticcontextcontainer.cpp dynamicastmatcherdiagnosticcontextcontainer.h + dynamicastmatcherdiagnosticmessagecontainer.cpp dynamicastmatcherdiagnosticmessagecontainer.h + dynamicmatcherdiagnostics.h + echomessage.cpp echomessage.h + endmessage.cpp endmessage.h + environment.h + executeinloop.h + filecontainer.cpp filecontainer.h + filecontainerv2.cpp filecontainerv2.h + filepath.cpp filepath.h + filepathcache.h + filepathcaching.cpp filepathcaching.h + filepathcachingfwd.h + filepathcachinginterface.h + filepathexceptions.h + filepathid.cpp filepathid.h + filepathstorage.h + filepathstoragesources.h + filepathstoragesqlitestatementfactory.h + filepathview.h + fixitcontainer.cpp fixitcontainer.h + followsymbolmessage.cpp followsymbolmessage.h + generatedfiles.cpp generatedfiles.h + generatedfilesinterface.h + idpaths.h + includesearchpath.h + ipcclientinterface.h + ipcclientprovider.h + ipcinterface.h + ipcserverinterface.h + lineprefixer.cpp lineprefixer.h + messageenvelop.cpp messageenvelop.h + modifiedtimechecker.h + modifiedtimecheckerinterface.h + nativefilepath.h + pchmanagerclientinterface.cpp pchmanagerclientinterface.h + pchmanagerclientproxy.cpp pchmanagerclientproxy.h + pchmanagerserverinterface.cpp pchmanagerserverinterface.h + pchmanagerserverproxy.cpp pchmanagerserverproxy.h + pchpaths.h + precompiledheadersupdatedmessage.cpp precompiledheadersupdatedmessage.h + processcreator.cpp processcreator.h + processexception.cpp processexception.h + processhandle.h + processstartedevent.cpp processstartedevent.h + progresscounter.h + progressmessage.h + projectmanagementserverinterface.h + projectpartartefact.cpp projectpartartefact.h + projectpartcontainer.cpp projectpartcontainer.h + projectpartid.h + projectpartpch.cpp projectpartpch.h + projectpartsstorage.h + projectpartsstorageinterface.h + readmessageblock.cpp readmessageblock.h + refactoringclientinterface.cpp refactoringclientinterface.h + refactoringclientproxy.cpp refactoringclientproxy.h + refactoringdatabaseinitializer.h + refactoringserverinterface.cpp refactoringserverinterface.h + refactoringserverproxy.cpp refactoringserverproxy.h + referencesmessage.cpp referencesmessage.h + removegeneratedfilesmessage.cpp removegeneratedfilesmessage.h + removeprojectpartsmessage.h + requestannotationsmessage.cpp requestannotationsmessage.h + requestcompletionsmessage.cpp requestcompletionsmessage.h + requestfollowsymbolmessage.cpp requestfollowsymbolmessage.h + requestreferencesmessage.cpp requestreferencesmessage.h + requestsourcelocationforrenamingmessage.cpp requestsourcelocationforrenamingmessage.h + requestsourcerangesanddiagnosticsforquerymessage.cpp requestsourcerangesanddiagnosticsforquerymessage.h + requestsourcerangesforquerymessage.cpp requestsourcerangesforquerymessage.h + requesttooltipmessage.cpp requesttooltipmessage.h + sourceentry.h + sourcelocationcontainer.cpp sourcelocationcontainer.h + sourcelocationcontainerv2.cpp sourcelocationcontainerv2.h + sourcelocationscontainer.cpp sourcelocationscontainer.h + sourcelocationsforrenamingmessage.cpp sourcelocationsforrenamingmessage.h + sourcerangecontainer.cpp sourcerangecontainer.h + sourcerangecontainerv2.cpp sourcerangecontainerv2.h + sourcerangesanddiagnosticsforquerymessage.cpp sourcerangesanddiagnosticsforquerymessage.h + sourcerangescontainer.cpp sourcerangescontainer.h + sourcerangesforquerymessage.cpp sourcerangesforquerymessage.h + sourcerangewithtextcontainer.cpp sourcerangewithtextcontainer.h + stringcache.h + stringcachealgorithms.h + stringcachefwd.h + tokeninfocontainer.cpp tokeninfocontainer.h + tooltipinfo.cpp tooltipinfo.h + tooltipmessage.cpp tooltipmessage.h + unsavedfilesremovedmessage.cpp unsavedfilesremovedmessage.h + unsavedfilesupdatedmessage.cpp unsavedfilesupdatedmessage.h + updategeneratedfilesmessage.cpp updategeneratedfilesmessage.h + updateprojectpartsmessage.cpp updateprojectpartsmessage.h + writemessageblock.cpp writemessageblock.h +) diff --git a/src/libs/clangsupport/clangsupport-lib.pri b/src/libs/clangsupport/clangsupport-lib.pri index 0668382803..df537f5848 100644 --- a/src/libs/clangsupport/clangsupport-lib.pri +++ b/src/libs/clangsupport/clangsupport-lib.pri @@ -110,6 +110,7 @@ HEADERS += \ $$PWD/clangsupportexceptions.h \ $$PWD/completionsmessage.h \ $$PWD/executeinloop.h \ + $$PWD/pchpaths.h \ $$PWD/projectpartid.h \ $$PWD/projectpartsstorage.h \ $$PWD/projectpartsstorageinterface.h \ @@ -203,7 +204,6 @@ HEADERS += \ $$PWD/nativefilepath.h \ $$PWD/filepathview.h \ $$PWD/compilermacro.h \ - $$PWD/projectpartpchproviderinterface.h \ $$PWD/updategeneratedfilesmessage.h \ $$PWD/removegeneratedfilesmessage.h \ $$PWD/generatedfiles.h \ @@ -213,6 +213,10 @@ HEADERS += \ $$PWD/includesearchpath.h \ $$PWD/commandlinebuilder.h \ $$PWD/projectpartartefact.h \ - $$PWD/projectpartcontainer.h + $$PWD/projectpartcontainer.h \ + $$PWD/sourceentry.h \ + $$PWD/modifiedtimecheckerinterface.h \ + $$PWD/environment.h \ + $$PWD/modifiedtimechecker.h contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols diff --git a/src/libs/clangsupport/commandlinebuilder.h b/src/libs/clangsupport/commandlinebuilder.h index 9de1da68d3..dedcf1c518 100644 --- a/src/libs/clangsupport/commandlinebuilder.h +++ b/src/libs/clangsupport/commandlinebuilder.h @@ -33,6 +33,9 @@ #include <utils/smallstringvector.h> #include <utils/cpplanguage_details.h> +#include <QCoreApplication> +#include <QDir> + namespace ClangBackEnd { enum class InputFileType : unsigned char { Header, Source }; @@ -46,7 +49,8 @@ public: InputFileType sourceType = InputFileType::Header, FilePathView sourcePath = {}, FilePathView outputPath = {}, - FilePathView includePchPath = {}) + FilePathView includePchPath = {}, + NativeFilePathView preIncludeSearchPath = {}) { commandLine.reserve(1024); @@ -58,6 +62,7 @@ public: addLanguageVersion(projectInfo); addNoStdIncAndNoStdLibInc(projectInfo.language); addCompilerMacros(projectInfo.compilerMacros); + addPreIncludeSearchPath(preIncludeSearchPath); addProjectIncludeSearchPaths( sortedIncludeSearchPaths(projectInfo.projectIncludeSearchPaths)); addSystemAndBuiltInIncludeSearchPaths( @@ -97,9 +102,12 @@ public: if (projectInfo.languageExtension && Utils::LanguageExtension::ObjectiveC) return sourceType == InputFileType::Header ? "objective-c++-header" : "objective-c++"; + return sourceType == InputFileType::Header ? "c++-header" : "c++"; + case Utils::Language::None: + return "none"; } - return sourceType == InputFileType::Header ? "c++-header" : "c++"; + return "none"; } void addLanguage(const ProjectInfo &projectInfo, InputFileType sourceType) @@ -131,6 +139,8 @@ public: return "-std=c++17"; case Utils::LanguageVersion::CXX2a: return "-std=c++2a"; + case Utils::LanguageVersion::None: + return ""; } return "-std=c++2a"; @@ -159,6 +169,8 @@ public: return "-std=gnu++17"; case Utils::LanguageVersion::CXX2a: return "-std=gnu++2a"; + case Utils::LanguageVersion::None: + return ""; } return "-std=gnu++2a"; @@ -209,6 +221,14 @@ public: commandLine.emplace_back(Utils::SmallString{"-D", macro.key, "=", macro.value}); } + void addPreIncludeSearchPath(NativeFilePathView preIncludeSearchPath) + { + if (!preIncludeSearchPath.empty()) { + commandLine.emplace_back("-isystem"); + commandLine.emplace_back(preIncludeSearchPath); + } + } + IncludeSearchPaths sortedIncludeSearchPaths(const IncludeSearchPaths &unsortedPaths) { IncludeSearchPaths paths = unsortedPaths; diff --git a/src/libs/clangsupport/connectionclient.cpp b/src/libs/clangsupport/connectionclient.cpp index bdbedab5c0..b3025baeea 100644 --- a/src/libs/clangsupport/connectionclient.cpp +++ b/src/libs/clangsupport/connectionclient.cpp @@ -325,7 +325,7 @@ void ConnectionClient::connectStandardOutputAndError(QProcess *process) const void ConnectionClient::connectLocalSocketError() const { connect(m_localSocket, - static_cast<void (QLocalSocket::*)(QLocalSocket::LocalSocketError)>(&QLocalSocket::error), + QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error), this, &ConnectionClient::printLocalSocketError); } diff --git a/src/libs/clangsupport/connectionserver.h b/src/libs/clangsupport/connectionserver.h index 8f13e631c5..b60083c4f8 100644 --- a/src/libs/clangsupport/connectionserver.h +++ b/src/libs/clangsupport/connectionserver.h @@ -72,11 +72,17 @@ public: } + void ensureAliveMessageIsSent() + { + if (m_aliveTimer.remainingTime() == 0) + sendAliveMessage(); + } + private: void connectToLocalServer(const QString &connectionName) { QObject::connect(&m_localSocket, - static_cast<void (QLocalSocket::*)(QLocalSocket::LocalSocketError)>(&QLocalSocket::error), + QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error), [&] (QLocalSocket::LocalSocketError) { qWarning() << "ConnectionServer error:" << m_localSocket.errorString() << connectionName; }); diff --git a/src/libs/clangsupport/ipcserverinterface.cpp b/src/libs/clangsupport/environment.h index fbc92de52e..ffa4d907cc 100644 --- a/src/libs/clangsupport/ipcserverinterface.cpp +++ b/src/libs/clangsupport/environment.h @@ -23,9 +23,25 @@ ** ****************************************************************************/ -#include "ipcserverinterface.h" +#pragma once + +#include <nativefilepath.h> namespace ClangBackEnd { +class Environment +{ +public: + Environment() = default; + Environment(const Environment &) = delete; + Environment &operator=(const Environment &) = delete; + + virtual Utils::PathString pchBuildDirectory() const = 0; + virtual uint hardwareConcurrency() const = 0; + virtual NativeFilePathView preIncludeSearchPath() const = 0; + +protected: + ~Environment() = default; +}; } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/executeinloop.h b/src/libs/clangsupport/executeinloop.h index 9c3eddeb4d..3642c3ccd3 100644 --- a/src/libs/clangsupport/executeinloop.h +++ b/src/libs/clangsupport/executeinloop.h @@ -29,38 +29,6 @@ #include <QCoreApplication> #include <QThread> -#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) -template<typename CallableType> -class CallableEvent : public QEvent -{ -public: - using Callable = std::decay_t<CallableType>; - CallableEvent(Callable &&callable) - : QEvent(QEvent::None) - , callable(std::move(callable)) - {} - CallableEvent(const Callable &callable) - : QEvent(QEvent::None) - , callable(callable) - {} - - ~CallableEvent() { callable(); } - -public: - Callable callable; -}; - -template<typename Callable> -void executeInLoop(Callable &&callable, QObject *object = QCoreApplication::instance()) -{ - if (QThread *thread = qobject_cast<QThread *>(object)) - object = QAbstractEventDispatcher::instance(thread); - - QCoreApplication::postEvent(object, - new CallableEvent<Callable>(std::forward<Callable>(callable)), - Qt::HighEventPriority); -} -#else template<typename Callable> void executeInLoop(Callable &&callable, QObject *object = QCoreApplication::instance()) { @@ -69,4 +37,3 @@ void executeInLoop(Callable &&callable, QObject *object = QCoreApplication::inst QMetaObject::invokeMethod(object, std::forward<Callable>(callable)); } -#endif diff --git a/src/libs/clangsupport/generatedfiles.cpp b/src/libs/clangsupport/generatedfiles.cpp index f4863baba5..644137886b 100644 --- a/src/libs/clangsupport/generatedfiles.cpp +++ b/src/libs/clangsupport/generatedfiles.cpp @@ -25,6 +25,8 @@ #include "generatedfiles.h" +#include <utils/algorithm.h> + namespace ClangBackEnd { void GeneratedFiles::update(V2::FileContainers &&fileContainers) @@ -32,16 +34,16 @@ void GeneratedFiles::update(V2::FileContainers &&fileContainers) V2::FileContainers unionFileContainers; unionFileContainers.reserve(m_fileContainers.size() + fileContainers.size()); - auto compare = [] (const V2::FileContainer &first, const V2::FileContainer &second) { + auto compare = [](const V2::FileContainer &first, const V2::FileContainer &second) { return first.filePath < second.filePath; }; - std::set_union(std::make_move_iterator(fileContainers.begin()), - std::make_move_iterator(fileContainers.end()), - std::make_move_iterator(m_fileContainers.begin()), - std::make_move_iterator(m_fileContainers.end()), - std::back_inserter(unionFileContainers), - compare); + Utils::set_union(std::make_move_iterator(fileContainers.begin()), + std::make_move_iterator(fileContainers.end()), + std::make_move_iterator(m_fileContainers.begin()), + std::make_move_iterator(m_fileContainers.end()), + std::back_inserter(unionFileContainers), + compare); m_fileContainers = std::move(unionFileContainers); } @@ -55,12 +57,12 @@ void GeneratedFiles::update(const V2::FileContainers &fileContainers) return first.filePath < second.filePath; }; - std::set_union(fileContainers.begin(), - fileContainers.end(), - std::make_move_iterator(m_fileContainers.begin()), - std::make_move_iterator(m_fileContainers.end()), - std::back_inserter(unionFileContainers), - compare); + Utils::set_union(fileContainers.begin(), + fileContainers.end(), + std::make_move_iterator(m_fileContainers.begin()), + std::make_move_iterator(m_fileContainers.end()), + std::back_inserter(unionFileContainers), + compare); m_fileContainers = std::move(unionFileContainers); } diff --git a/src/libs/clangsupport/modifiedtimechecker.h b/src/libs/clangsupport/modifiedtimechecker.h new file mode 100644 index 0000000000..c9b62c4673 --- /dev/null +++ b/src/libs/clangsupport/modifiedtimechecker.h @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "filepathcachinginterface.h" +#include "modifiedtimecheckerinterface.h" + +#include <algorithm> +#include <iterator> + +namespace ClangBackEnd { +template<typename SourceEntries = ::ClangBackEnd::SourceEntries> +class ModifiedTimeChecker final : public ModifiedTimeCheckerInterface<SourceEntries> +{ + using SourceEntry = typename SourceEntries::value_type; + +public: + using GetModifiedTime = std::function<ClangBackEnd::TimeStamp(ClangBackEnd::FilePathView filePath)>; + ModifiedTimeChecker(GetModifiedTime &getModifiedTime, FilePathCachingInterface &filePathCache) + : m_getModifiedTime(getModifiedTime) + , m_filePathCache(filePathCache) + {} + + bool isUpToDate(const SourceEntries &sourceEntries) const + { + if (sourceEntries.empty()) + return false; + + updateCurrentSourceTimeStamps(sourceEntries); + + return compareEntries(sourceEntries); + } + + void pathsChanged(const FilePathIds &filePathIds) + { + using SourceTimeStampReferences = std::vector<std::reference_wrapper<SourceTimeStamp>>; + + SourceTimeStampReferences timeStampsToUpdate; + timeStampsToUpdate.reserve(filePathIds.size()); + + std::set_intersection(m_currentSourceTimeStamps.begin(), + m_currentSourceTimeStamps.end(), + filePathIds.begin(), + filePathIds.end(), + std::back_inserter(timeStampsToUpdate)); + + for (SourceTimeStamp &sourceTimeStamp : timeStampsToUpdate) { + sourceTimeStamp.timeStamp = m_getModifiedTime( + m_filePathCache.filePath(sourceTimeStamp.sourceId)); + } + } + +private: + bool compareEntries(const SourceEntries &sourceEntries) const + { + class CompareSourceId + { + public: + bool operator()(SourceTimeStamp first, SourceTimeStamp second) + { + return first.sourceId < second.sourceId; + } + + bool operator()(::ClangBackEnd::SourceEntry first, ::ClangBackEnd::SourceEntry second) + { + return first.sourceId < second.sourceId; + } + + bool operator()(SourceTimeStamp first, ::ClangBackEnd::SourceEntry second) + { + return first.sourceId < second.sourceId; + } + + bool operator()(::ClangBackEnd::SourceEntry first, SourceTimeStamp second) + { + return first.sourceId < second.sourceId; + } + }; + + SourceTimeStamps currentSourceTimeStamp; + currentSourceTimeStamp.reserve(sourceEntries.size()); + std::set_intersection(m_currentSourceTimeStamps.begin(), + m_currentSourceTimeStamps.end(), + sourceEntries.begin(), + sourceEntries.end(), + std::back_inserter(currentSourceTimeStamp), + CompareSourceId{}); + + class CompareTime + { + public: + bool operator()(SourceTimeStamp first, SourceTimeStamp second) + { + return first.timeStamp <= second.timeStamp; + } + + bool operator()(::ClangBackEnd::SourceEntry first, ::ClangBackEnd::SourceEntry second) + { + return first.timeStamp <= second.timeStamp; + } + + bool operator()(SourceTimeStamp first, ::ClangBackEnd::SourceEntry second) + { + return first.timeStamp <= second.timeStamp; + } + + bool operator()(::ClangBackEnd::SourceEntry first, SourceTimeStamp second) + { + return first.timeStamp <= second.timeStamp; + } + }; + + return std::lexicographical_compare(currentSourceTimeStamp.begin(), + currentSourceTimeStamp.end(), + sourceEntries.begin(), + sourceEntries.end(), + CompareTime{}); + } + + void updateCurrentSourceTimeStamps(const SourceEntries &sourceEntries) const + { + SourceTimeStamps sourceTimeStamps = newSourceTimeStamps(sourceEntries); + + for (SourceTimeStamp &newSourceTimeStamp : sourceTimeStamps) { + newSourceTimeStamp.timeStamp = m_getModifiedTime( + m_filePathCache.filePath(newSourceTimeStamp.sourceId)); + } + + auto split = sourceTimeStamps.insert(sourceTimeStamps.end(), + m_currentSourceTimeStamps.begin(), + m_currentSourceTimeStamps.end()); + std::inplace_merge(sourceTimeStamps.begin(), split, sourceTimeStamps.end()); + + m_currentSourceTimeStamps = sourceTimeStamps; + } + + SourceTimeStamps newSourceTimeStamps(const SourceEntries &sourceEntries) const + { + SourceEntries newSourceEntries; + newSourceEntries.reserve(sourceEntries.size()); + + class CompareSourceId + { + public: + bool operator()(SourceTimeStamp first, SourceTimeStamp second) + { + return first.sourceId < second.sourceId; + } + + bool operator()(::ClangBackEnd::SourceEntry first, ::ClangBackEnd::SourceEntry second) + { + return first.sourceId < second.sourceId; + } + + bool operator()(SourceTimeStamp first, ::ClangBackEnd::SourceEntry second) + { + return first.sourceId < second.sourceId; + } + + bool operator()(::ClangBackEnd::SourceEntry first, SourceTimeStamp second) + { + return first.sourceId < second.sourceId; + } + }; + + std::set_difference(sourceEntries.begin(), + sourceEntries.end(), + m_currentSourceTimeStamps.begin(), + m_currentSourceTimeStamps.end(), + std::back_inserter(newSourceEntries), + CompareSourceId{}); + + SourceTimeStamps newTimeStamps; + newTimeStamps.reserve(newSourceEntries.size()); + + std::transform(newSourceEntries.begin(), + newSourceEntries.end(), + std::back_inserter(newTimeStamps), + [](SourceEntry entry) { + return SourceTimeStamp{entry.sourceId, {}}; + }); + + return newTimeStamps; + } + +private: + mutable SourceTimeStamps m_currentSourceTimeStamps; + GetModifiedTime &m_getModifiedTime; + FilePathCachingInterface &m_filePathCache; +}; + +} // namespace ClangBackEnd diff --git a/src/libs/clangsupport/projectpartpchproviderinterface.h b/src/libs/clangsupport/modifiedtimecheckerinterface.h index 282e541cfd..a0e79b0701 100644 --- a/src/libs/clangsupport/projectpartpchproviderinterface.h +++ b/src/libs/clangsupport/modifiedtimecheckerinterface.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -25,26 +25,23 @@ #pragma once -#include "projectpartpch.h" - -#include <utils/optional.h> +#include "sourceentry.h" namespace ClangBackEnd { -class ProjectPartPchProviderInterface +template<typename SourceEntries = ::ClangBackEnd::SourceEntries> +class ModifiedTimeCheckerInterface { public: - ProjectPartPchProviderInterface() = default; - ProjectPartPchProviderInterface(const ProjectPartPchProviderInterface &) = delete; - ProjectPartPchProviderInterface &operator=(const ProjectPartPchProviderInterface &) = delete; - - virtual Utils::optional<ClangBackEnd::ProjectPartPch> projectPartPch( - ClangBackEnd::ProjectPartId projectPartId) const = 0; - virtual const ClangBackEnd::ProjectPartPchs &projectPartPchs() const = 0; + ModifiedTimeCheckerInterface() = default; + ModifiedTimeCheckerInterface(const ModifiedTimeCheckerInterface &) = delete; + ModifiedTimeCheckerInterface &operator=(const ModifiedTimeCheckerInterface &) = delete; + virtual bool isUpToDate(const SourceEntries &sourceEntries) const = 0; protected: - ~ProjectPartPchProviderInterface() = default; + ~ModifiedTimeCheckerInterface() = default; }; } // namespace ClangBackEnd + diff --git a/src/libs/clangsupport/pchmanagerclientproxy.h b/src/libs/clangsupport/pchmanagerclientproxy.h index 516b2e3a86..6dec4ecfca 100644 --- a/src/libs/clangsupport/pchmanagerclientproxy.h +++ b/src/libs/clangsupport/pchmanagerclientproxy.h @@ -42,9 +42,6 @@ public: PchManagerClientProxy(const PchManagerClientProxy&) = delete; const PchManagerClientProxy &operator=(const PchManagerClientProxy&) = delete; - PchManagerClientProxy(PchManagerClientProxy &&other) = default; - PchManagerClientProxy &operator=(PchManagerClientProxy &&other) = default; - void readMessages(); void alive() override; diff --git a/src/libs/clangsupport/pchpaths.h b/src/libs/clangsupport/pchpaths.h new file mode 100644 index 0000000000..048ec9da8d --- /dev/null +++ b/src/libs/clangsupport/pchpaths.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "filepath.h" + +namespace ClangBackEnd { + +class PchPaths +{ +public: + PchPaths() = default; + PchPaths(Utils::SmallStringView projectPchPath, Utils::SmallStringView systemPchPath) + : projectPchPath(FilePathView{projectPchPath}) + , systemPchPath(FilePathView{systemPchPath}) + {} + + friend bool operator==(const PchPaths &first, const PchPaths &second) + { + return first.projectPchPath == second.projectPchPath + && first.systemPchPath == second.systemPchPath; + } + +public: + FilePath projectPchPath; + FilePath systemPchPath; +}; + +} // namespace ClangBackEnd diff --git a/src/libs/clangsupport/precompiledheadersupdatedmessage.h b/src/libs/clangsupport/precompiledheadersupdatedmessage.h index 5a21b995df..5bd24dcd49 100644 --- a/src/libs/clangsupport/precompiledheadersupdatedmessage.h +++ b/src/libs/clangsupport/precompiledheadersupdatedmessage.h @@ -25,7 +25,10 @@ #pragma once -#include "projectpartpch.h" +#include "clangsupport_global.h" +#include "projectpartid.h" + +#include <utils/smallstringio.h> namespace ClangBackEnd { @@ -33,25 +36,26 @@ class PrecompiledHeadersUpdatedMessage { public: PrecompiledHeadersUpdatedMessage() = default; - PrecompiledHeadersUpdatedMessage(std::vector<ProjectPartPch> &&projectPartPchs) - : projectPartPchs(std::move(projectPartPchs)) - {} - - ProjectPartPchs takeProjectPartPchs() const + PrecompiledHeadersUpdatedMessage(ProjectPartId projectPartId) { - return std::move(projectPartPchs); + projectPartIds.push_back(projectPartId); } + PrecompiledHeadersUpdatedMessage(ProjectPartIds &&projectPartIds) + : projectPartIds(std::move(projectPartIds)) + {} + + ProjectPartIds takeProjectPartIds() const { return std::move(projectPartIds); } friend QDataStream &operator<<(QDataStream &out, const PrecompiledHeadersUpdatedMessage &message) { - out << message.projectPartPchs; + out << message.projectPartIds; return out; } friend QDataStream &operator>>(QDataStream &in, PrecompiledHeadersUpdatedMessage &message) { - in >> message.projectPartPchs; + in >> message.projectPartIds; return in; } @@ -59,16 +63,13 @@ public: friend bool operator==(const PrecompiledHeadersUpdatedMessage &first, const PrecompiledHeadersUpdatedMessage &second) { - return first.projectPartPchs == second.projectPartPchs; + return first.projectPartIds == second.projectPartIds; } - PrecompiledHeadersUpdatedMessage clone() const - { - return PrecompiledHeadersUpdatedMessage(Utils::clone(projectPartPchs)); - } + PrecompiledHeadersUpdatedMessage clone() const { return *this; } public: - std::vector<ProjectPartPch> projectPartPchs; + ProjectPartIds projectPartIds; }; CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const PrecompiledHeadersUpdatedMessage &message); diff --git a/src/libs/clangsupport/projectpartartefact.cpp b/src/libs/clangsupport/projectpartartefact.cpp index 7623f38796..56551693e1 100644 --- a/src/libs/clangsupport/projectpartartefact.cpp +++ b/src/libs/clangsupport/projectpartartefact.cpp @@ -33,8 +33,6 @@ namespace ClangBackEnd { - - Utils::SmallStringVector ProjectPartArtefact::toStringVector(Utils::SmallStringView jsonText) { if (jsonText.isEmpty()) diff --git a/src/libs/clangsupport/projectpartartefact.h b/src/libs/clangsupport/projectpartartefact.h index ac8c44a891..0d9bcf5c39 100644 --- a/src/libs/clangsupport/projectpartartefact.h +++ b/src/libs/clangsupport/projectpartartefact.h @@ -113,8 +113,8 @@ public: CompilerMacros compilerMacros; IncludeSearchPaths systemIncludeSearchPaths; IncludeSearchPaths projectIncludeSearchPaths; - Utils::Language language = Utils::Language::Cxx; - Utils::LanguageVersion languageVersion = Utils::LanguageVersion::CXX98; + Utils::Language language = Utils::Language::None; + Utils::LanguageVersion languageVersion = Utils::LanguageVersion::None; Utils::LanguageExtension languageExtension = Utils::LanguageExtension::None; }; diff --git a/src/libs/clangsupport/projectpartcontainer.h b/src/libs/clangsupport/projectpartcontainer.h index f1c64bd237..b2133dcaa2 100644 --- a/src/libs/clangsupport/projectpartcontainer.h +++ b/src/libs/clangsupport/projectpartcontainer.h @@ -147,7 +147,8 @@ public: first.sourcePathIds, first.language, first.languageVersion, - first.languageExtension) + first.languageExtension, + first.hasPrecompiledHeader) < std::tie(second.projectPartId, second.toolChainArguments, second.compilerMacros, @@ -157,7 +158,8 @@ public: second.sourcePathIds, second.language, second.languageVersion, - second.languageExtension); + second.languageExtension, + second.hasPrecompiledHeader); } ProjectPartContainer clone() const @@ -169,6 +171,7 @@ public: FilePathIds headerPathIds; FilePathIds sourcePathIds; bool updateIsDeferred = false; + bool hasPrecompiledHeader = true; }; using ProjectPartContainerReference = std::reference_wrapper<ProjectPartContainer>; diff --git a/src/libs/clangsupport/projectpartid.h b/src/libs/clangsupport/projectpartid.h index c372682baf..fc5f659605 100644 --- a/src/libs/clangsupport/projectpartid.h +++ b/src/libs/clangsupport/projectpartid.h @@ -54,7 +54,7 @@ public: return first.projectPathId < second.projectPathId; } - friend QDataStream &operator<<(QDataStream &out, const ProjectPartId &projectPathId) + friend QDataStream &operator<<(QDataStream &out, ProjectPartId projectPathId) { out << projectPathId.projectPathId; diff --git a/src/libs/clangsupport/projectpartpch.cpp b/src/libs/clangsupport/projectpartpch.cpp index aac672441c..9c870ac572 100644 --- a/src/libs/clangsupport/projectpartpch.cpp +++ b/src/libs/clangsupport/projectpartpch.cpp @@ -29,8 +29,7 @@ namespace ClangBackEnd { QDebug operator<<(QDebug debug, const ProjectPartPch &projectPartPch) { - debug.nospace() << "FileContainer(" << projectPartPch.projectPartId.projectPathId << ", " - << projectPartPch.pchPath << ")"; + debug.nospace() << "FileContainer(" << projectPartPch.projectPartId.projectPathId << ")"; return debug; } diff --git a/src/libs/clangsupport/projectpartpch.h b/src/libs/clangsupport/projectpartpch.h index c471b46b16..213247ae42 100644 --- a/src/libs/clangsupport/projectpartpch.h +++ b/src/libs/clangsupport/projectpartpch.h @@ -74,8 +74,7 @@ public: friend bool operator==(const ProjectPartPch &first, const ProjectPartPch &second) { - return first.projectPartId == second.projectPartId - && first.pchPath == second.pchPath; + return first.projectPartId == second.projectPartId && first.pchPath == second.pchPath; } ProjectPartPch clone() const diff --git a/src/libs/clangsupport/projectpartsstorage.h b/src/libs/clangsupport/projectpartsstorage.h index c91291bca2..e71bb0d51e 100644 --- a/src/libs/clangsupport/projectpartsstorage.h +++ b/src/libs/clangsupport/projectpartsstorage.h @@ -74,6 +74,14 @@ public: .template values<FilePathId>(1024, projectPartId.projectPathId); } + bool hasPrecompiledHeader(ProjectPartId projectPartId) const + { + auto value = fetchProjectPrecompiledHeaderPathStatement.template value<Utils::SmallString>( + projectPartId.projectPathId); + + return value && value->hasContent(); + } + ProjectPartContainers fetchProjectParts(const ProjectPartIds &projectPartIds) const override { try { @@ -88,6 +96,7 @@ public: if (value) { value->headerPathIds = fetchHeaders(projectPartId); value->sourcePathIds = fetchSources(projectPartId); + value->hasPrecompiledHeader = hasPrecompiledHeader(projectPartId); projectParts.push_back(*std::move(value)); } } @@ -125,7 +134,7 @@ public: } } - Utils::PathString fetchProjectPartName(ProjectPartId projectPartId) const + Utils::PathString fetchProjectPartName(ProjectPartId projectPartId) const override { try { Sqlite::DeferredTransaction transaction{database}; @@ -236,6 +245,22 @@ public: return statement.template value<ProjectPartArtefact, 8>(projectPartId.projectPathId); } + void resetIndexingTimeStamps(const ProjectPartContainers &projectsParts) override + { + try { + Sqlite::ImmediateTransaction transaction{database}; + + for (const ProjectPartContainer &projectPart : projectsParts) { + for (FilePathId sourcePathId : projectPart.sourcePathIds) + resetDependentIndexingTimeStampsStatement.write(sourcePathId.filePathId); + } + + transaction.commit(); + } catch (const Sqlite::StatementIsBusy &) { + resetIndexingTimeStamps(projectsParts); + } + } + Sqlite::TransactionInterface &transactionBackend() override { return database; } static Utils::SmallString toJson(const Utils::SmallStringVector &strings) @@ -332,5 +357,13 @@ public: "SELECT sourceId FROM projectPartsHeaders WHERE projectPartId = ?", database}; mutable ReadStatement fetchProjectPartsSourcesByIdStatement{ "SELECT sourceId FROM projectPartsSources WHERE projectPartId = ?", database}; + mutable ReadStatement fetchProjectPrecompiledHeaderPathStatement{ + "SELECT projectPchPath FROM precompiledHeaders WHERE projectPartId = ?", database}; + WriteStatement resetDependentIndexingTimeStampsStatement{ + "WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION SELECT " + "dependencySourceId FROM sourceDependencies, collectedDependencies WHERE " + "sourceDependencies.sourceId == collectedDependencies.sourceId) UPDATE fileStatuses SET " + "indexingTimeStamp = NULL WHERE sourceId IN (SELECT sourceId FROM collectedDependencies)", + database}; }; } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/projectpartsstorageinterface.h b/src/libs/clangsupport/projectpartsstorageinterface.h index 1127f70b1f..2d0675e657 100644 --- a/src/libs/clangsupport/projectpartsstorageinterface.h +++ b/src/libs/clangsupport/projectpartsstorageinterface.h @@ -63,6 +63,7 @@ public: virtual Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(FilePathId sourceId) const = 0; virtual Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact( ProjectPartId projectPartId) const = 0; + virtual void resetIndexingTimeStamps(const ProjectPartContainers &projectsParts) = 0; virtual Sqlite::TransactionInterface &transactionBackend() = 0; diff --git a/src/libs/clangsupport/refactoringdatabaseinitializer.h b/src/libs/clangsupport/refactoringdatabaseinitializer.h index efca925413..a7058d3204 100644 --- a/src/libs/clangsupport/refactoringdatabaseinitializer.h +++ b/src/libs/clangsupport/refactoringdatabaseinitializer.h @@ -177,6 +177,7 @@ public: Sqlite::Contraint::PrimaryKey); table.addColumn("size", Sqlite::ColumnType::Integer); table.addColumn("lastModified", Sqlite::ColumnType::Integer); + table.addColumn("indexingTimeStamp", Sqlite::ColumnType::Integer); table.initialize(database); } @@ -188,6 +189,7 @@ public: const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer); const Sqlite::Column &dependencySourceIdColumn = table.addColumn("dependencySourceId", Sqlite::ColumnType::Integer); table.addIndex({sourceIdColumn, dependencySourceIdColumn}); + table.addIndex({dependencySourceIdColumn, sourceIdColumn}); table.initialize(database); } diff --git a/src/libs/clangsupport/sourceentry.h b/src/libs/clangsupport/sourceentry.h new file mode 100644 index 0000000000..c593f1fcd3 --- /dev/null +++ b/src/libs/clangsupport/sourceentry.h @@ -0,0 +1,152 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <filepathid.h> + +#include <vector> + +namespace ClangBackEnd { + +enum class SourceType : unsigned char { + TopProjectInclude, + TopSystemInclude, + UserInclude, + ProjectInclude, + SystemInclude, + Source +}; + +enum class HasMissingIncludes : unsigned char { No, Yes }; + +class TimeStamp +{ + using int64 = long long; +public: + TimeStamp() = default; + TimeStamp(int64 value) + : value(value) + {} + + operator int64() const + { + return value; + } + + int64 value = -1; +}; + +class SourceTimeStamp +{ + using int64 = long long; +public: + SourceTimeStamp(int sourceId, int64 lastModified) + : timeStamp(lastModified) + , sourceId(sourceId) + {} + + SourceTimeStamp(FilePathId sourceId, TimeStamp lastModified) + : timeStamp(lastModified) + , sourceId(sourceId) + {} + + friend bool operator<(SourceTimeStamp first, SourceTimeStamp second) + { + return first.sourceId < second.sourceId; + } + + friend bool operator<(SourceTimeStamp first, FilePathId second) + { + return first.sourceId < second; + } + + friend bool operator<(FilePathId first, SourceTimeStamp second) + { + return first < second.sourceId; + } + + friend bool operator==(SourceTimeStamp first, SourceTimeStamp second) + { + return first.sourceId == second.sourceId && first.timeStamp == second.timeStamp; + } + + friend bool operator!=(SourceTimeStamp first, SourceTimeStamp second) + { + return !(first == second); + } + +public: + TimeStamp timeStamp; + FilePathId sourceId; +}; + +using SourceTimeStamps = std::vector<SourceTimeStamp>; + +class SourceEntry +{ + using int64 = long long; + +public: + SourceEntry(int sourceId, int64 timeStamp, int sourceType, int hasMissingIncludes) + : timeStamp(timeStamp) + , sourceId(sourceId) + , sourceType(static_cast<SourceType>(sourceType)) + , hasMissingIncludes(static_cast<HasMissingIncludes>(hasMissingIncludes)) + {} + + SourceEntry(FilePathId sourceId, + SourceType sourceType, + TimeStamp timeStamp, + HasMissingIncludes hasMissingIncludes = HasMissingIncludes::No) + : timeStamp(timeStamp) + , sourceId(sourceId) + , sourceType(sourceType) + , hasMissingIncludes(hasMissingIncludes) + {} + + friend bool operator<(SourceEntry first, SourceEntry second) { + return first.sourceId < second.sourceId; + } + + friend bool operator==(SourceEntry first, SourceEntry second) + { + return first.sourceId == second.sourceId && first.sourceType == second.sourceType + && first.timeStamp == second.timeStamp; + } + + friend bool operator!=(SourceEntry first, SourceEntry second) { return !(first == second); } + +public: + TimeStamp timeStamp; + FilePathId sourceId; + SourceType sourceType = SourceType::UserInclude; + HasMissingIncludes hasMissingIncludes = HasMissingIncludes::No; +}; + +using SourceEntries = std::vector<SourceEntry>; +using SourceEntryReference = std::reference_wrapper<SourceEntry>; +using SourceEntryReferences = std::vector<SourceEntryReference>; +} // namespace ClangBackEnd diff --git a/src/libs/cplusplus/CMakeLists.txt b/src/libs/cplusplus/CMakeLists.txt new file mode 100644 index 0000000000..593d809394 --- /dev/null +++ b/src/libs/cplusplus/CMakeLists.txt @@ -0,0 +1,44 @@ +# TODO: Support static build, currently being done with CPLUSPLUS_BUILD_STATIC_LIB +# -- if really needed that is. +# TODO: Make Qt5::Gui optional -- if really needed that is. + +add_qtc_library(CPlusPlus + DEPENDS Utils + DEFINES CPLUSPLUS_BUILD_LIB + PUBLIC_DEPENDS 3rd_cplusplus Qt5::Concurrent Qt5::Gui + PUBLIC_INCLUDES "${CMAKE_SOURCE_DIR}/src/libs/3rdparty" + SOURCES + ASTParent.cpp ASTParent.h + ASTPath.cpp ASTPath.h + AlreadyConsideredClassContainer.h + BackwardsScanner.cpp BackwardsScanner.h + CppDocument.cpp CppDocument.h + CppRewriter.cpp CppRewriter.h + DependencyTable.cpp DependencyTable.h + DeprecatedGenTemplateInstance.cpp DeprecatedGenTemplateInstance.h + ExpressionUnderCursor.cpp ExpressionUnderCursor.h + FastPreprocessor.cpp FastPreprocessor.h + FindUsages.cpp FindUsages.h + Icons.cpp Icons.h + LookupContext.cpp LookupContext.h + LookupItem.cpp LookupItem.h + Macro.cpp Macro.h + MatchingText.cpp MatchingText.h + NamePrettyPrinter.cpp NamePrettyPrinter.h + Overview.cpp Overview.h + PPToken.cpp PPToken.h + PreprocessorClient.cpp PreprocessorClient.h + PreprocessorEnvironment.cpp PreprocessorEnvironment.h + ResolveExpression.cpp ResolveExpression.h + SimpleLexer.cpp SimpleLexer.h + SnapshotSymbolVisitor.cpp SnapshotSymbolVisitor.h + SymbolNameVisitor.cpp SymbolNameVisitor.h + TypeOfExpression.cpp TypeOfExpression.h + TypePrettyPrinter.cpp TypePrettyPrinter.h + cppmodelmanagerbase.cpp cppmodelmanagerbase.h + findcdbbreakpoint.cpp findcdbbreakpoint.h + pp-cctype.h pp-engine.cpp + pp-engine.h pp-scanner.cpp + pp-scanner.h + pp.h +) diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp index d892948468..73cc06f26a 100644 --- a/src/libs/cplusplus/CppDocument.cpp +++ b/src/libs/cplusplus/CppDocument.cpp @@ -228,8 +228,7 @@ public: if (fileName != doc->fileName()) return; - QString message; - message.vsprintf(format, ap); + const QString message = QString::vasprintf(format, ap); #ifndef DO_NOT_DUMP_ALL_PARSER_ERRORS { @@ -756,17 +755,17 @@ bool Snapshot::isEmpty() const return _documents.isEmpty(); } -Snapshot::const_iterator Snapshot::find(const Utils::FileName &fileName) const +Snapshot::const_iterator Snapshot::find(const Utils::FilePath &fileName) const { return _documents.find(fileName); } -void Snapshot::remove(const Utils::FileName &fileName) +void Snapshot::remove(const Utils::FilePath &fileName) { _documents.remove(fileName); } -bool Snapshot::contains(const Utils::FileName &fileName) const +bool Snapshot::contains(const Utils::FilePath &fileName) const { return _documents.contains(fileName); } @@ -774,7 +773,7 @@ bool Snapshot::contains(const Utils::FileName &fileName) const void Snapshot::insert(Document::Ptr doc) { if (doc) { - _documents.insert(Utils::FileName::fromString(doc->fileName()), doc); + _documents.insert(Utils::FilePath::fromString(doc->fileName()), doc); m_deps.files.clear(); // Will trigger re-build when accessed. } } @@ -794,7 +793,7 @@ static QList<Macro> macrosDefinedUntilLine(const QList<Macro> ¯os, int line) } Document::Ptr Snapshot::preprocessedDocument(const QByteArray &source, - const Utils::FileName &fileName, + const Utils::FilePath &fileName, int withDefinedMacrosFromDocumentUntilLine) const { Document::Ptr newDoc = Document::create(fileName.toString()); @@ -858,7 +857,7 @@ QList<Snapshot::IncludeLocation> Snapshot::includeLocationsOfDocument(const QStr return result; } -Utils::FileNameList Snapshot::filesDependingOn(const Utils::FileName &fileName) const +Utils::FilePathList Snapshot::filesDependingOn(const Utils::FilePath &fileName) const { updateDependencyTable(); return m_deps.filesDependingOn(fileName); @@ -887,7 +886,7 @@ void Snapshot::allIncludesForDocument_helper(const QString &fileName, QSet<QStri } } -Document::Ptr Snapshot::document(const Utils::FileName &fileName) const +Document::Ptr Snapshot::document(const Utils::FilePath &fileName) const { return _documents.value(fileName); } diff --git a/src/libs/cplusplus/CppDocument.h b/src/libs/cplusplus/CppDocument.h index 006f17aba6..74205f1625 100644 --- a/src/libs/cplusplus/CppDocument.h +++ b/src/libs/cplusplus/CppDocument.h @@ -389,7 +389,7 @@ private: class CPLUSPLUS_EXPORT Snapshot { - typedef QHash<Utils::FileName, Document::Ptr> Base; + typedef QHash<Utils::FilePath, Document::Ptr> Base; public: Snapshot(); @@ -403,36 +403,36 @@ public: bool isEmpty() const; void insert(Document::Ptr doc); // ### remove - void remove(const Utils::FileName &fileName); // ### remove + void remove(const Utils::FilePath &fileName); // ### remove void remove(const QString &fileName) - { remove(Utils::FileName::fromString(fileName)); } + { remove(Utils::FilePath::fromString(fileName)); } const_iterator begin() const { return _documents.begin(); } const_iterator end() const { return _documents.end(); } - bool contains(const Utils::FileName &fileName) const; + bool contains(const Utils::FilePath &fileName) const; bool contains(const QString &fileName) const - { return contains(Utils::FileName::fromString(fileName)); } + { return contains(Utils::FilePath::fromString(fileName)); } - Document::Ptr document(const Utils::FileName &fileName) const; + Document::Ptr document(const Utils::FilePath &fileName) const; Document::Ptr document(const QString &fileName) const - { return document(Utils::FileName::fromString(fileName)); } + { return document(Utils::FilePath::fromString(fileName)); } - const_iterator find(const Utils::FileName &fileName) const; + const_iterator find(const Utils::FilePath &fileName) const; const_iterator find(const QString &fileName) const - { return find(Utils::FileName::fromString(fileName)); } + { return find(Utils::FilePath::fromString(fileName)); } Snapshot simplified(Document::Ptr doc) const; Document::Ptr preprocessedDocument(const QByteArray &source, - const Utils::FileName &fileName, + const Utils::FilePath &fileName, int withDefinedMacrosFromDocumentUntilLine = -1) const; Document::Ptr preprocessedDocument(const QByteArray &source, const QString &fileName, int withDefinedMacrosFromDocumentUntilLine = -1) const { return preprocessedDocument(source, - Utils::FileName::fromString(fileName), + Utils::FilePath::fromString(fileName), withDefinedMacrosFromDocumentUntilLine); } @@ -442,9 +442,9 @@ public: QSet<QString> allIncludesForDocument(const QString &fileName) const; QList<IncludeLocation> includeLocationsOfDocument(const QString &fileName) const; - Utils::FileNameList filesDependingOn(const Utils::FileName &fileName) const; - Utils::FileNameList filesDependingOn(const QString &fileName) const - { return filesDependingOn(Utils::FileName::fromString(fileName)); } + Utils::FilePathList filesDependingOn(const Utils::FilePath &fileName) const; + Utils::FilePathList filesDependingOn(const QString &fileName) const + { return filesDependingOn(Utils::FilePath::fromString(fileName)); } void updateDependencyTable() const; bool operator==(const Snapshot &other) const; diff --git a/src/libs/cplusplus/DependencyTable.cpp b/src/libs/cplusplus/DependencyTable.cpp index f9c17c0b61..8ddc9801d0 100644 --- a/src/libs/cplusplus/DependencyTable.cpp +++ b/src/libs/cplusplus/DependencyTable.cpp @@ -29,9 +29,9 @@ using namespace CPlusPlus; -Utils::FileNameList DependencyTable::filesDependingOn(const Utils::FileName &fileName) const +Utils::FilePathList DependencyTable::filesDependingOn(const Utils::FilePath &fileName) const { - Utils::FileNameList deps; + Utils::FilePathList deps; int index = fileIndex.value(fileName, -1); if (index == -1) @@ -66,14 +66,14 @@ void DependencyTable::build(const Snapshot &snapshot) } for (int i = 0; i < files.size(); ++i) { - const Utils::FileName &fileName = files.at(i); + const Utils::FilePath &fileName = files.at(i); if (Document::Ptr doc = snapshot.document(fileName)) { QBitArray bitmap(files.size()); QList<int> directIncludes; const QStringList documentIncludes = doc->includedFiles(); foreach (const QString &includedFile, documentIncludes) { - int index = fileIndex.value(Utils::FileName::fromString(includedFile)); + int index = fileIndex.value(Utils::FilePath::fromString(includedFile)); if (index == -1) continue; diff --git a/src/libs/cplusplus/DependencyTable.h b/src/libs/cplusplus/DependencyTable.h index 508ae297c5..3e888c59db 100644 --- a/src/libs/cplusplus/DependencyTable.h +++ b/src/libs/cplusplus/DependencyTable.h @@ -44,10 +44,10 @@ class CPLUSPLUS_EXPORT DependencyTable private: friend class Snapshot; void build(const Snapshot &snapshot); - Utils::FileNameList filesDependingOn(const Utils::FileName &fileName) const; + Utils::FilePathList filesDependingOn(const Utils::FilePath &fileName) const; - QVector<Utils::FileName> files; - QHash<Utils::FileName, int> fileIndex; + QVector<Utils::FilePath> files; + QHash<Utils::FilePath, int> fileIndex; QHash<int, QList<int> > includes; QVector<QBitArray> includeMap; }; diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp index 173a6e2a5e..638fba451b 100644 --- a/src/libs/cplusplus/FindUsages.cpp +++ b/src/libs/cplusplus/FindUsages.cpp @@ -170,7 +170,7 @@ void FindUsages::reportResult(unsigned tokenIndex) const int len = tk.utf16chars(); - const Usage u(Utils::FileName::fromString(_doc->fileName()), lineText, line, col, len); + const Usage u(Utils::FilePath::fromString(_doc->fileName()), lineText, line, col, len); _usages.append(u); _references.append(tokenIndex); } diff --git a/src/libs/cplusplus/FindUsages.h b/src/libs/cplusplus/FindUsages.h index deed69276a..2b6880a55c 100644 --- a/src/libs/cplusplus/FindUsages.h +++ b/src/libs/cplusplus/FindUsages.h @@ -40,11 +40,11 @@ class CPLUSPLUS_EXPORT Usage { public: Usage() = default; - Usage(const Utils::FileName &path, const QString &lineText, int line, int col, int len) + Usage(const Utils::FilePath &path, const QString &lineText, int line, int col, int len) : path(path), lineText(lineText), line(line), col(col), len(len) {} public: - Utils::FileName path; + Utils::FilePath path; QString lineText; int line = 0; int col = 0; diff --git a/src/libs/cplusplus/MatchingText.cpp b/src/libs/cplusplus/MatchingText.cpp index c22d3fe89c..59440813a7 100644 --- a/src/libs/cplusplus/MatchingText.cpp +++ b/src/libs/cplusplus/MatchingText.cpp @@ -358,6 +358,32 @@ static bool isAfterRecordLikeDefinition(const BackwardsScanner &tokens, int inde return false; } +static bool isControlFlowKeywordRequiringParentheses(const Token &token) +{ + return token.is(T_IF) + || token.is(T_WHILE) + || token.is(T_FOR) + || token.is(T_SWITCH) + || token.is(T_CATCH); +} + +static bool isAfterControlFlow(const BackwardsScanner &tokens, int index) +{ + const Token &token = tokens[index]; + if (token.is(T_DO) || token.is(T_ELSE) || token.is(T_TRY)) + return true; + + if (token.is(T_RPAREN)) { + const int startIndex = index + 1; + const int matchingBraceIndex = tokens.startOfMatchingBrace(startIndex); + if (matchingBraceIndex == startIndex) + return false; // No matching paren found. + return isControlFlowKeywordRequiringParentheses(tokens[matchingBraceIndex - 1]); + } + + return false; +} + static bool allowAutoClosingBrace(const QTextCursor &cursor, MatchingText::IsNextBlockDeeperIndented isNextIndented) { @@ -370,6 +396,9 @@ static bool allowAutoClosingBrace(const QTextCursor &cursor, if (tokens[index].isStringLiteral()) return false; + if (isAfterControlFlow(tokens, index)) + return false; + if (isAfterNamespaceDefinition(tokens, index)) return false; diff --git a/src/libs/extensionsystem/CMakeLists.txt b/src/libs/extensionsystem/CMakeLists.txt new file mode 100644 index 0000000000..864c57c1ae --- /dev/null +++ b/src/libs/extensionsystem/CMakeLists.txt @@ -0,0 +1,16 @@ +add_qtc_library(ExtensionSystem + DEPENDS Aggregation Utils Qt5::Core Qt5::Widgets + PUBLIC_DEPENDS Qt5::Core + SOURCES + extensionsystem_global.h + invoker.cpp invoker.h + iplugin.cpp iplugin.h iplugin_p.h + optionsparser.cpp optionsparser.h + plugindetailsview.cpp plugindetailsview.h plugindetailsview.ui + pluginerroroverview.cpp pluginerroroverview.h pluginerroroverview.ui + pluginerrorview.cpp pluginerrorview.h pluginerrorview.ui + pluginmanager.cpp pluginmanager.h pluginmanager_p.h + pluginspec.cpp pluginspec.h pluginspec_p.h + pluginview.cpp pluginview.h + SKIP_AUTOMOC pluginmanager.cpp +) diff --git a/src/libs/extensionsystem/iplugin.cpp b/src/libs/extensionsystem/iplugin.cpp index 76704be823..90b4e86672 100644 --- a/src/libs/extensionsystem/iplugin.cpp +++ b/src/libs/extensionsystem/iplugin.cpp @@ -193,7 +193,7 @@ IPlugin::~IPlugin() } /*! - \fn QList<QObject *> IPlugin::createTestObjects() const + \fn QVector<QObject *> IPlugin::createTestObjects() const Returns objects that are meant to be passed on to QTest::qExec(). @@ -201,9 +201,9 @@ IPlugin::~IPlugin() The ownership of returned objects is transferred to caller. */ -QList<QObject *> IPlugin::createTestObjects() const +QVector<QObject *> IPlugin::createTestObjects() const { - return QList<QObject *>(); + return {}; } /*! diff --git a/src/libs/extensionsystem/iplugin.h b/src/libs/extensionsystem/iplugin.h index 4b14ecd92b..9b7489ce0f 100644 --- a/src/libs/extensionsystem/iplugin.h +++ b/src/libs/extensionsystem/iplugin.h @@ -60,7 +60,7 @@ public: virtual QObject *remoteCommand(const QStringList & /* options */, const QString & /* workingDirectory */, const QStringList & /* arguments */) { return nullptr; } - virtual QList<QObject *> createTestObjects() const; + virtual QVector<QObject *> createTestObjects() const; PluginSpec *pluginSpec() const; diff --git a/src/libs/extensionsystem/optionsparser.cpp b/src/libs/extensionsystem/optionsparser.cpp index c3daed5daa..22c45df31f 100644 --- a/src/libs/extensionsystem/optionsparser.cpp +++ b/src/libs/extensionsystem/optionsparser.cpp @@ -115,10 +115,10 @@ bool OptionsParser::checkForTestOptions() if (m_currentArg == QLatin1String(TEST_OPTION)) { if (nextToken(RequiredToken)) { if (m_currentArg == QLatin1String("all")) { - m_pmPrivate->testSpecs = - Utils::transform(m_pmPrivate->loadQueue(), [](PluginSpec *spec) { - return PluginManagerPrivate::TestSpec(spec); - }); + m_pmPrivate->testSpecs + = Utils::transform<std::vector>(m_pmPrivate->loadQueue(), [](PluginSpec *spec) { + return PluginManagerPrivate::TestSpec(spec); + }); } else { QStringList args = m_currentArg.split(QLatin1Char(',')); const QString pluginName = args.takeFirst(); @@ -129,7 +129,7 @@ bool OptionsParser::checkForTestOptions() "The plugin \"%1\" is specified twice for testing.").arg(pluginName); m_hasError = true; } else { - m_pmPrivate->testSpecs.append(PluginManagerPrivate::TestSpec(spec, args)); + m_pmPrivate->testSpecs.emplace_back(spec, args); } } else { if (m_errorString) @@ -265,7 +265,7 @@ bool OptionsParser::checkForUnknownOption() void OptionsParser::forceDisableAllPluginsExceptTestedAndForceEnabled() { - for (const PluginManagerPrivate::TestSpec &testSpec : qAsConst(m_pmPrivate->testSpecs)) + for (const PluginManagerPrivate::TestSpec &testSpec : m_pmPrivate->testSpecs) testSpec.pluginSpec->d->setForceEnabled(true); for (PluginSpec *spec : qAsConst(m_pmPrivate->pluginSpecs)) { if (!spec->isForceEnabled() && !spec->isRequired()) diff --git a/src/libs/extensionsystem/pluginerroroverview.cpp b/src/libs/extensionsystem/pluginerroroverview.cpp index 828bd013f4..74e7ac73b0 100644 --- a/src/libs/extensionsystem/pluginerroroverview.cpp +++ b/src/libs/extensionsystem/pluginerroroverview.cpp @@ -45,7 +45,7 @@ PluginErrorOverview::PluginErrorOverview(QWidget *parent) : // only show errors on startup if plugin is enabled. if (spec->hasError() && spec->isEffectivelyEnabled()) { QListWidgetItem *item = new QListWidgetItem(spec->name()); - item->setData(Qt::UserRole, qVariantFromValue(spec)); + item->setData(Qt::UserRole, QVariant::fromValue(spec)); m_ui->pluginList->addItem(item); } } diff --git a/src/libs/extensionsystem/pluginmanager.cpp b/src/libs/extensionsystem/pluginmanager.cpp index 956f6f01eb..6fbda8e4ec 100644 --- a/src/libs/extensionsystem/pluginmanager.cpp +++ b/src/libs/extensionsystem/pluginmanager.cpp @@ -319,7 +319,7 @@ void PluginManager::removeObject(QObject *obj) \sa PluginManager::getObject() */ -QList<QObject *> PluginManager::allObjects() +QVector<QObject *> PluginManager::allObjects() { return d->allObjects; } @@ -376,10 +376,11 @@ QSet<PluginSpec *> PluginManager::pluginsRequiredByPlugin(PluginSpec *spec) { QSet<PluginSpec *> recursiveDependencies; recursiveDependencies.insert(spec); - QList<PluginSpec *> queue; - queue.append(spec); - while (!queue.isEmpty()) { - PluginSpec *checkSpec = queue.takeFirst(); + std::queue<PluginSpec *> queue; + queue.push(spec); + while (!queue.empty()) { + PluginSpec *checkSpec = queue.front(); + queue.pop(); QHashIterator<PluginDependency, PluginSpec *> depIt(checkSpec->dependencySpecs()); while (depIt.hasNext()) { depIt.next(); @@ -388,7 +389,7 @@ QSet<PluginSpec *> PluginManager::pluginsRequiredByPlugin(PluginSpec *spec) PluginSpec *depSpec = depIt.value(); if (!recursiveDependencies.contains(depSpec)) { recursiveDependencies.insert(depSpec); - queue.append(depSpec); + queue.push(depSpec); } } } @@ -536,12 +537,12 @@ QStringList PluginManager::arguments() \sa setPluginPaths() */ -const QList<PluginSpec *> PluginManager::plugins() +const QVector<PluginSpec *> PluginManager::plugins() { return d->pluginSpecs; } -QHash<QString, QList<PluginSpec *> > PluginManager::pluginCollections() +QHash<QString, QVector<PluginSpec *>> PluginManager::pluginCollections() { return d->pluginCategories; } @@ -752,7 +753,7 @@ void PluginManager::formatPluginVersions(QTextStream &str) */ bool PluginManager::testRunRequested() { - return !d->testSpecs.isEmpty(); + return !d->testSpecs.empty(); } /*! @@ -769,7 +770,7 @@ void PluginManager::profilingReport(const char *what, const PluginSpec *spec) /*! Returns a list of plugins in load order. */ -QList<PluginSpec *> PluginManager::loadQueue() +QVector<PluginSpec *> PluginManager::loadQueue() { return d->loadQueue(); } @@ -818,15 +819,16 @@ PluginSpecPrivate *PluginManagerPrivate::privateSpec(PluginSpec *spec) void PluginManagerPrivate::nextDelayedInitialize() { - while (!delayedInitializeQueue.isEmpty()) { - PluginSpec *spec = delayedInitializeQueue.takeFirst(); + while (!delayedInitializeQueue.empty()) { + PluginSpec *spec = delayedInitializeQueue.front(); + delayedInitializeQueue.pop(); profilingReport(">delayedInitialize", spec); bool delay = spec->d->delayedInitialize(); profilingReport("<delayedInitialize", spec); if (delay) break; // do next delayedInitialize after a delay } - if (delayedInitializeQueue.isEmpty()) { + if (delayedInitializeQueue.empty()) { m_isInitializationDone = true; delete delayedInitializeTimer; delayedInitializeTimer = nullptr; @@ -903,7 +905,7 @@ void PluginManagerPrivate::stopAll() delete delayedInitializeTimer; delayedInitializeTimer = nullptr; } - QList<PluginSpec *> queue = loadQueue(); + QVector<PluginSpec *> queue = loadQueue(); foreach (PluginSpec *spec, queue) { loadPlugin(spec, PluginSpec::Stopped); } @@ -926,8 +928,10 @@ using TestPlanIterator = QMapIterator<QObject *, QStringList>; static bool isTestFunction(const QMetaMethod &metaMethod) { - static const QList<QByteArray> blackList = QList<QByteArray>() - << "initTestCase()" << "cleanupTestCase()" << "init()" << "cleanup()"; + static const QVector<QByteArray> blackList = {"initTestCase()", + "cleanupTestCase()", + "init()", + "cleanup()"}; if (metaMethod.methodType() != QMetaMethod::Slot) return false; @@ -991,7 +995,7 @@ static QStringList matchingTestFunctions(const QStringList &testFunctions, return matchingFunctions; } -static QObject *objectWithClassName(const QList<QObject *> &objects, const QString &className) +static QObject *objectWithClassName(const QVector<QObject *> &objects, const QString &className) { return Utils::findOr(objects, nullptr, [className] (QObject *object) -> bool { QString candidate = QString::fromUtf8(object->metaObject()->className()); @@ -1034,7 +1038,7 @@ static int executeTestPlan(const TestPlan &testPlan) /// Resulting plan consists of all test functions of the plugin object and /// all test functions of all test objects of the plugin. -static TestPlan generateCompleteTestPlan(IPlugin *plugin, const QList<QObject *> &testObjects) +static TestPlan generateCompleteTestPlan(IPlugin *plugin, const QVector<QObject *> &testObjects) { TestPlan testPlan; @@ -1054,7 +1058,8 @@ static TestPlan generateCompleteTestPlan(IPlugin *plugin, const QList<QObject *> /// /// Since multiple match texts can match the same function, a test function might /// be included multiple times for a test object. -static TestPlan generateCustomTestPlan(IPlugin *plugin, const QList<QObject *> &testObjects, +static TestPlan generateCustomTestPlan(IPlugin *plugin, + const QVector<QObject *> &testObjects, const QStringList &matchTexts) { TestPlan testPlan; @@ -1062,7 +1067,7 @@ static TestPlan generateCustomTestPlan(IPlugin *plugin, const QList<QObject *> & const QStringList testFunctionsOfPluginObject = testFunctions(plugin->metaObject()); QStringList matchedTestFunctionsOfPluginObject; QStringList remainingMatchTexts = matchTexts; - QList<QObject *> remainingTestObjectsOfPlugin = testObjects; + QVector<QObject *> remainingTestObjectsOfPlugin = testObjects; while (!remainingMatchTexts.isEmpty()) { const QString matchText = remainingMatchTexts.takeFirst(); @@ -1127,11 +1132,12 @@ void PluginManagerPrivate::startTests() if (!plugin) continue; // plugin not loaded - const QList<QObject *> testObjects = plugin->createTestObjects(); + const QVector<QObject *> testObjects = plugin->createTestObjects(); ExecuteOnDestruction deleteTestObjects([&]() { qDeleteAll(testObjects); }); Q_UNUSED(deleteTestObjects) - const bool hasDuplicateTestObjects = testObjects.size() != testObjects.toSet().size(); + const bool hasDuplicateTestObjects = testObjects.size() + != Utils::filteredUnique(testObjects).size(); QTC_ASSERT(!hasDuplicateTestObjects, continue); QTC_ASSERT(!testObjects.contains(plugin), continue); @@ -1205,7 +1211,7 @@ void PluginManagerPrivate::removeObject(QObject *obj) */ void PluginManagerPrivate::loadPlugins() { - QList<PluginSpec *> queue = loadQueue(); + QVector<PluginSpec *> queue = loadQueue(); Utils::setMimeStartupPhase(MimeStartupPhase::PluginsLoading); foreach (PluginSpec *spec, queue) { loadPlugin(spec, PluginSpec::Loaded); @@ -1218,7 +1224,7 @@ void PluginManagerPrivate::loadPlugins() Utils::reverseForeach(queue, [this](PluginSpec *spec) { loadPlugin(spec, PluginSpec::Running); if (spec->state() == PluginSpec::Running) { - delayedInitializeQueue.append(spec); + delayedInitializeQueue.push(spec); } else { // Plugin initialization failed, so cleanup after it spec->d->kill(); @@ -1261,7 +1267,7 @@ void PluginManagerPrivate::asyncShutdownFinished() { auto *plugin = qobject_cast<IPlugin *>(sender()); Q_ASSERT(plugin); - asynchronousPlugins.removeAll(plugin->pluginSpec()); + asynchronousPlugins.remove(plugin->pluginSpec()); if (asynchronousPlugins.isEmpty()) shutdownEventLoop->exit(); } @@ -1269,11 +1275,11 @@ void PluginManagerPrivate::asyncShutdownFinished() /*! \internal */ -QList<PluginSpec *> PluginManagerPrivate::loadQueue() +QVector<PluginSpec *> PluginManagerPrivate::loadQueue() { - QList<PluginSpec *> queue; + QVector<PluginSpec *> queue; foreach (PluginSpec *spec, pluginSpecs) { - QList<PluginSpec *> circularityCheckQueue; + QVector<PluginSpec *> circularityCheckQueue; loadQueue(spec, queue, circularityCheckQueue); } return queue; @@ -1282,8 +1288,9 @@ QList<PluginSpec *> PluginManagerPrivate::loadQueue() /*! \internal */ -bool PluginManagerPrivate::loadQueue(PluginSpec *spec, QList<PluginSpec *> &queue, - QList<PluginSpec *> &circularityCheckQueue) +bool PluginManagerPrivate::loadQueue(PluginSpec *spec, + QVector<PluginSpec *> &queue, + QVector<PluginSpec *> &circularityCheckQueue) { if (queue.contains(spec)) return true; @@ -1433,7 +1440,7 @@ void PluginManagerPrivate::readPluginPaths() pluginCategories.clear(); // default - pluginCategories.insert(QString(), QList<PluginSpec *>()); + pluginCategories.insert(QString(), QVector<PluginSpec *>()); foreach (const QString &pluginFile, pluginFiles(pluginPaths)) { auto *spec = new PluginSpec; @@ -1477,7 +1484,7 @@ void PluginManagerPrivate::enableDependenciesIndirectly() foreach (PluginSpec *spec, pluginSpecs) spec->d->enabledIndirectly = false; // cannot use reverse loadQueue here, because test dependencies can introduce circles - QList<PluginSpec *> queue = Utils::filtered(pluginSpecs, &PluginSpec::isEffectivelyEnabled); + QVector<PluginSpec *> queue = Utils::filtered(pluginSpecs, &PluginSpec::isEffectivelyEnabled); while (!queue.isEmpty()) { PluginSpec *spec = queue.takeFirst(); queue += spec->d->enableDependenciesIndirectly(containsTestSpec(spec)); diff --git a/src/libs/extensionsystem/pluginmanager.h b/src/libs/extensionsystem/pluginmanager.h index 411a5205b4..c926d07f4a 100644 --- a/src/libs/extensionsystem/pluginmanager.h +++ b/src/libs/extensionsystem/pluginmanager.h @@ -55,14 +55,14 @@ public: // Object pool operations static void addObject(QObject *obj); static void removeObject(QObject *obj); - static QList<QObject *> allObjects(); + static QVector<QObject *> allObjects(); static QReadWriteLock *listLock(); // This is useful for soft dependencies using pure interfaces. template <typename T> static T *getObject() { QReadLocker lock(listLock()); - QList<QObject *> all = allObjects(); + QVector<QObject *> all = allObjects(); foreach (QObject *obj, all) { if (T *result = qobject_cast<T *>(obj)) return result; @@ -72,7 +72,7 @@ public: template <typename T, typename Predicate> static T *getObject(Predicate predicate) { QReadLocker lock(listLock()); - QList<QObject *> all = allObjects(); + QVector<QObject *> all = allObjects(); foreach (QObject *obj, all) { if (T *result = qobject_cast<T *>(obj)) if (predicate(result)) @@ -84,14 +84,14 @@ public: static QObject *getObjectByName(const QString &name); // Plugin operations - static QList<PluginSpec *> loadQueue(); + static QVector<PluginSpec *> loadQueue(); static void loadPlugins(); static QStringList pluginPaths(); static void setPluginPaths(const QStringList &paths); static QString pluginIID(); static void setPluginIID(const QString &iid); - static const QList<PluginSpec *> plugins(); - static QHash<QString, QList<PluginSpec *>> pluginCollections(); + static const QVector<PluginSpec *> plugins(); + static QHash<QString, QVector<PluginSpec *>> pluginCollections(); static bool hasError(); static QSet<PluginSpec *> pluginsRequiringPlugin(PluginSpec *spec); static QSet<PluginSpec *> pluginsRequiredByPlugin(PluginSpec *spec); diff --git a/src/libs/extensionsystem/pluginmanager_p.h b/src/libs/extensionsystem/pluginmanager_p.h index b21a3f7ce4..d67ce28c11 100644 --- a/src/libs/extensionsystem/pluginmanager_p.h +++ b/src/libs/extensionsystem/pluginmanager_p.h @@ -35,6 +35,8 @@ #include <QScopedPointer> #include <QReadWriteLock> +#include <queue> + QT_BEGIN_NAMESPACE class QTime; class QTimer; @@ -65,13 +67,13 @@ public: void loadPlugins(); void shutdown(); void setPluginPaths(const QStringList &paths); - QList<PluginSpec *> loadQueue(); + QVector<ExtensionSystem::PluginSpec *> loadQueue(); void loadPlugin(PluginSpec *spec, PluginSpec::State destState); void resolveDependencies(); void enableDependenciesIndirectly(); void initProfiling(); void profilingSummary() const; - void profilingReport(const char *what, const PluginSpec *spec = 0); + void profilingReport(const char *what, const PluginSpec *spec = nullptr); void setSettings(QSettings *settings); void setGlobalSettings(QSettings *settings); void readSettings(); @@ -80,8 +82,10 @@ public: class TestSpec { public: TestSpec(PluginSpec *pluginSpec, const QStringList &testFunctionsOrObjects = QStringList()) - : pluginSpec(pluginSpec), testFunctionsOrObjects(testFunctionsOrObjects) {} - PluginSpec *pluginSpec; + : pluginSpec(pluginSpec) + , testFunctionsOrObjects(testFunctionsOrObjects) + {} + PluginSpec *pluginSpec = nullptr; QStringList testFunctionsOrObjects; }; @@ -95,21 +99,21 @@ public: testSpecs = Utils::filtered(testSpecs, [pluginSpec](const TestSpec &s) { return s.pluginSpec != pluginSpec; }); } - QHash<QString, QList<PluginSpec *>> pluginCategories; - QList<PluginSpec *> pluginSpecs; - QList<TestSpec> testSpecs; + QHash<QString, QVector<PluginSpec *>> pluginCategories; + QVector<PluginSpec *> pluginSpecs; + std::vector<TestSpec> testSpecs; QStringList pluginPaths; QString pluginIID; - QList<QObject *> allObjects; // ### make this a QList<QPointer<QObject> > > ? + QVector<QObject *> allObjects; // ### make this a QVector<QPointer<QObject> > > ? QStringList defaultDisabledPlugins; // Plugins/Ignored from install settings QStringList defaultEnabledPlugins; // Plugins/ForceEnabled from install settings QStringList disabledPlugins; QStringList forceEnabledPlugins; // delayed initialization QTimer *delayedInitializeTimer = nullptr; - QList<PluginSpec *> delayedInitializeQueue; + std::queue<PluginSpec *> delayedInitializeQueue; // ansynchronous shutdown - QList<PluginSpec *> asynchronousPlugins; // plugins that have requested async shutdown + QSet<PluginSpec *> asynchronousPlugins; // plugins that have requested async shutdown QEventLoop *shutdownEventLoop = nullptr; // used for async shutdown QStringList arguments; @@ -140,8 +144,8 @@ private: void readPluginPaths(); bool loadQueue(PluginSpec *spec, - QList<PluginSpec *> &queue, - QList<PluginSpec *> &circularityCheckQueue); + QVector<ExtensionSystem::PluginSpec *> &queue, + QVector<ExtensionSystem::PluginSpec *> &circularityCheckQueue); void stopAll(); void deleteAll(); diff --git a/src/libs/extensionsystem/pluginspec.cpp b/src/libs/extensionsystem/pluginspec.cpp index ef9ac19ea2..b8d0643982 100644 --- a/src/libs/extensionsystem/pluginspec.cpp +++ b/src/libs/extensionsystem/pluginspec.cpp @@ -885,7 +885,7 @@ int PluginSpecPrivate::versionCompare(const QString &version1, const QString &ve /*! \internal */ -bool PluginSpecPrivate::resolveDependencies(const QList<PluginSpec *> &specs) +bool PluginSpecPrivate::resolveDependencies(const QVector<PluginSpec *> &specs) { if (hasError) return false; @@ -924,11 +924,11 @@ bool PluginSpecPrivate::resolveDependencies(const QList<PluginSpec *> &specs) } // returns the plugins that it actually indirectly enabled -QList<PluginSpec *> PluginSpecPrivate::enableDependenciesIndirectly(bool enableTestDependencies) +QVector<PluginSpec *> PluginSpecPrivate::enableDependenciesIndirectly(bool enableTestDependencies) { if (!q->isEffectivelyEnabled()) // plugin not enabled, nothing to do return {}; - QList<PluginSpec *> enabled; + QVector<PluginSpec *> enabled; QHashIterator<PluginDependency, PluginSpec *> it(dependencySpecs); while (it.hasNext()) { it.next(); diff --git a/src/libs/extensionsystem/pluginspec_p.h b/src/libs/extensionsystem/pluginspec_p.h index 9d37ed9923..fc6c0c2ff2 100644 --- a/src/libs/extensionsystem/pluginspec_p.h +++ b/src/libs/extensionsystem/pluginspec_p.h @@ -52,7 +52,7 @@ public: bool read(const QString &fileName); bool provides(const QString &pluginName, const QString &version) const; - bool resolveDependencies(const QList<PluginSpec *> &specs); + bool resolveDependencies(const QVector<PluginSpec *> &specs); bool loadLibrary(); bool initializePlugin(); bool initializeExtensions(); @@ -103,7 +103,7 @@ public: static bool isValidVersion(const QString &version); static int versionCompare(const QString &version1, const QString &version2); - QList<PluginSpec *> enableDependenciesIndirectly(bool enableTestDependencies = false); + QVector<PluginSpec *> enableDependenciesIndirectly(bool enableTestDependencies = false); bool readMetaData(const QJsonObject &pluginMetaData); diff --git a/src/libs/extensionsystem/pluginview.cpp b/src/libs/extensionsystem/pluginview.cpp index 39a39643cb..bb5d6b98ed 100644 --- a/src/libs/extensionsystem/pluginview.cpp +++ b/src/libs/extensionsystem/pluginview.cpp @@ -212,8 +212,10 @@ public: class CollectionItem : public TreeItem { public: - CollectionItem(const QString &name, QList<PluginSpec *> plugins, PluginView *view) - : m_name(name), m_plugins(plugins), m_view(view) + CollectionItem(const QString &name, QVector<PluginSpec *> plugins, PluginView *view) + : m_name(name) + , m_plugins(plugins) + , m_view(view) { foreach (PluginSpec *spec, plugins) appendChild(new PluginItem(spec, view)); @@ -254,9 +256,11 @@ public: bool setData(int column, const QVariant &data, int role) override { if (column == LoadedColumn && role == Qt::CheckStateRole) { - const QList<PluginSpec *> affectedPlugins = - Utils::filtered(m_plugins, [](PluginSpec *spec) { return !spec->isRequired(); }); - if (m_view->setPluginsEnabled(affectedPlugins.toSet(), data.toBool())) { + const QVector<PluginSpec *> affectedPlugins + = Utils::filtered(m_plugins, [](PluginSpec *spec) { return !spec->isRequired(); }); + if (m_view->setPluginsEnabled(Utils::transform<QSet>(affectedPlugins, + [](PluginSpec *s) { return s; }), + data.toBool())) { update(); return true; } @@ -274,7 +278,7 @@ public: public: QString m_name; - QList<PluginSpec *> m_plugins; + QVector<PluginSpec *> m_plugins; PluginView *m_view; // Not owned. }; @@ -408,13 +412,13 @@ void PluginView::updatePlugins() // Model. m_model->clear(); - - QList<CollectionItem *> collections; - const QHash<QString, QList<PluginSpec *>> pluginCollections = PluginManager::pluginCollections(); + const QHash<QString, QVector<PluginSpec *>> pluginCollections + = PluginManager::pluginCollections(); + std::vector<CollectionItem *> collections; const auto end = pluginCollections.cend(); for (auto it = pluginCollections.cbegin(); it != end; ++it) { const QString name = it.key().isEmpty() ? tr("Utilities") : it.key(); - collections.append(new CollectionItem(name, it.value(), this)); + collections.push_back(new CollectionItem(name, it.value(), this)); } Utils::sort(collections, &CollectionItem::m_name); diff --git a/src/libs/glsl/CMakeLists.txt b/src/libs/glsl/CMakeLists.txt new file mode 100644 index 0000000000..e5fcb3692b --- /dev/null +++ b/src/libs/glsl/CMakeLists.txt @@ -0,0 +1,19 @@ +add_qtc_library(GLSL + DEPENDS Qt5::Core + SOURCES + glsl.h + glslast.cpp glslast.h + glslastdump.cpp glslastdump.h + glslastvisitor.cpp glslastvisitor.h + glslengine.cpp glslengine.h + glslkeywords.cpp + glsllexer.cpp glsllexer.h + glslmemorypool.cpp glslmemorypool.h + glslparser.cpp glslparser.h + glslparsertable.cpp glslparsertable_p.h + glslsemantic.cpp glslsemantic.h + glslsymbol.cpp glslsymbol.h + glslsymbols.cpp glslsymbols.h + glsltype.cpp glsltype.h + glsltypes.cpp glsltypes.h +) diff --git a/src/libs/glsl/glslparser.h b/src/libs/glsl/glslparser.h index f0ccf82cb9..5e148c298b 100644 --- a/src/libs/glsl/glslparser.h +++ b/src/libs/glsl/glslparser.h @@ -26,6 +26,8 @@ ** ****************************************************************************/ +#pragma once + #include "glslparsertable_p.h" #include "glsllexer.h" #include "glslast.h" diff --git a/src/libs/languageserverprotocol/CMakeLists.txt b/src/libs/languageserverprotocol/CMakeLists.txt new file mode 100644 index 0000000000..9ad446817f --- /dev/null +++ b/src/libs/languageserverprotocol/CMakeLists.txt @@ -0,0 +1,23 @@ +add_qtc_library(LanguageServerProtocol + DEPENDS Utils + SOURCES + basemessage.cpp basemessage.h + client.cpp client.h + clientcapabilities.cpp clientcapabilities.h + completion.cpp completion.h + diagnostics.cpp diagnostics.h + icontent.h + initializemessages.cpp initializemessages.h + jsonkeys.h + jsonobject.cpp jsonobject.h + jsonrpcmessages.cpp jsonrpcmessages.h + languagefeatures.cpp languagefeatures.h + languageserverprotocol_global.h + lsptypes.cpp lsptypes.h + lsputils.cpp lsputils.h + messages.cpp messages.h + servercapabilities.cpp servercapabilities.h + shutdownmessages.cpp shutdownmessages.h + textsynchronization.cpp textsynchronization.h + workspace.cpp workspace.h +) diff --git a/src/libs/languageserverprotocol/basemessage.cpp b/src/libs/languageserverprotocol/basemessage.cpp index 1ee17e3eee..950976549e 100644 --- a/src/libs/languageserverprotocol/basemessage.cpp +++ b/src/libs/languageserverprotocol/basemessage.cpp @@ -37,6 +37,8 @@ namespace LanguageServerProtocol { +Q_LOGGING_CATEGORY(parseLog, "qtc.languageserverprotocol.parse", QtWarningMsg) + BaseMessage::BaseMessage() : mimeType(JsonRpcMessageHandler::jsonRpcMimeType()) { } @@ -68,8 +70,7 @@ bool BaseMessage::operator==(const BaseMessage &other) const return true; } -static QPair<QByteArray, QByteArray> splitHeaderFieldLine( - const QByteArray &headerFieldLine, QString &parseError) +static QPair<QByteArray, QByteArray> splitHeaderFieldLine(const QByteArray &headerFieldLine) { static const int fieldSeparatorLength = int(std::strlen(headerFieldSeparator)); int assignmentIndex = headerFieldLine.indexOf(headerFieldSeparator); @@ -77,8 +78,7 @@ static QPair<QByteArray, QByteArray> splitHeaderFieldLine( return {headerFieldLine.mid(0, assignmentIndex), headerFieldLine.mid(assignmentIndex + fieldSeparatorLength)}; } - parseError = BaseMessage::tr("Unexpected header line \"%1\".") - .arg(QLatin1String(headerFieldLine)); + qCWarning(parseLog) << "Unexpected header line:" << QLatin1String(headerFieldLine); return {}; } @@ -134,8 +134,7 @@ void BaseMessage::parse(QBuffer *data, QString &parseError, BaseMessage &message message.content = data->read(message.contentLength); return; } - const QPair<QByteArray, QByteArray> nameAndValue = - splitHeaderFieldLine(headerFieldLine, parseError); + const QPair<QByteArray, QByteArray> nameAndValue = splitHeaderFieldLine(headerFieldLine); const QByteArray &headerFieldName = nameAndValue.first.trimmed(); const QByteArray &headerFieldValue = nameAndValue.second.trimmed(); @@ -146,9 +145,8 @@ void BaseMessage::parse(QBuffer *data, QString &parseError, BaseMessage &message } else if (headerFieldName == contentTypeFieldName) { parseContentType(message, headerFieldValue, parseError); } else { - parseError = tr("Unexpected header field \"%1\" in \"%2\".") - .arg(QLatin1String(headerFieldName), - QLatin1String(headerFieldLine)); + qCWarning(parseLog) << "Unexpected header field" << QLatin1String(headerFieldName) + << "in" << QLatin1String(headerFieldLine); } } diff --git a/src/libs/languageserverprotocol/basemessage.h b/src/libs/languageserverprotocol/basemessage.h index ba8238291a..b2835aa7d7 100644 --- a/src/libs/languageserverprotocol/basemessage.h +++ b/src/libs/languageserverprotocol/basemessage.h @@ -31,6 +31,7 @@ #include <QByteArray> #include <QCoreApplication> +#include <QLoggingCategory> QT_BEGIN_NAMESPACE class QBuffer; @@ -39,6 +40,8 @@ QT_END_NAMESPACE namespace LanguageServerProtocol { +LANGUAGESERVERPROTOCOL_EXPORT Q_DECLARE_LOGGING_CATEGORY(parseLog) + class LANGUAGESERVERPROTOCOL_EXPORT BaseMessage { Q_DECLARE_TR_FUNCTIONS(BaseMessage) diff --git a/src/libs/languageserverprotocol/clientcapabilities.cpp b/src/libs/languageserverprotocol/clientcapabilities.cpp index 0200250444..f73c4ee04c 100644 --- a/src/libs/languageserverprotocol/clientcapabilities.cpp +++ b/src/libs/languageserverprotocol/clientcapabilities.cpp @@ -27,19 +27,6 @@ namespace LanguageServerProtocol { -SymbolCapabilities::SymbolKindCapabilities::SymbolKindCapabilities() -{ - setValueSet({SymbolKind::File, SymbolKind::Module, SymbolKind::Namespace, - SymbolKind::Package, SymbolKind::Class, SymbolKind::Method, - SymbolKind::Property, SymbolKind::Field, SymbolKind::Constructor, - SymbolKind::Enum, SymbolKind::Interface, SymbolKind::Function, - SymbolKind::Variable, SymbolKind::Constant, SymbolKind::String, - SymbolKind::Number, SymbolKind::Boolean, SymbolKind::Array, - SymbolKind::Object, SymbolKind::Key, SymbolKind::Null, - SymbolKind::EnumMember, SymbolKind::Struct, SymbolKind::Event, - SymbolKind::Operator, SymbolKind::TypeParameter}); -} - Utils::optional<QList<SymbolKind> > SymbolCapabilities::SymbolKindCapabilities::valueSet() const { Utils::optional<QList<int>> array = optionalArray<int>(valueSetKey); @@ -55,13 +42,6 @@ void SymbolCapabilities::SymbolKindCapabilities::setValueSet(const QList<SymbolK insert(valueSetKey, enumArrayToJsonArray<SymbolKind>(valueSet)); } - -ClientCapabilities::ClientCapabilities() -{ - setTextDocument(TextDocumentClientCapabilities()); - setWorkspace(WorkspaceClientCapabilities()); -} - bool ClientCapabilities::isValid(QStringList *error) const { return checkOptional<WorkspaceClientCapabilities>(error, workspaceKey) @@ -85,14 +65,6 @@ bool WorkspaceClientCapabilities::isValid(QStringList *error) const && checkOptional<bool>(error,configurationKey); } -TextDocumentClientCapabilities::SynchronizationCapabilities::SynchronizationCapabilities() -{ - setDynamicRegistration(true); - setWillSave(true); - setWillSaveWaitUntil(false); - setDidSave(true); -} - bool TextDocumentClientCapabilities::SynchronizationCapabilities::isValid(QStringList *error) const { return DynamicRegistrationCapabilities::isValid(error) @@ -101,19 +73,6 @@ bool TextDocumentClientCapabilities::SynchronizationCapabilities::isValid(QStrin && checkOptional<bool>(error, didSaveKey); } -TextDocumentClientCapabilities::TextDocumentClientCapabilities() -{ - setSynchronization(SynchronizationCapabilities()); - setDocumentSymbol(SymbolCapabilities()); - setCompletion(CompletionCapabilities()); - CodeActionCapabilities cac; - CodeActionCapabilities::CodeActionLiteralSupport literalSupport; - literalSupport.setCodeActionKind( - CodeActionCapabilities::CodeActionLiteralSupport::CodeActionKind(QList<QString>{"*"})); - cac.setCodeActionLiteralSupport(literalSupport); - setCodeAction(cac); -} - bool TextDocumentClientCapabilities::isValid(QStringList *error) const { return checkOptional<SynchronizationCapabilities>(error, synchronizationKey) @@ -136,24 +95,12 @@ bool TextDocumentClientCapabilities::isValid(QStringList *error) const && checkOptional<DynamicRegistrationCapabilities>(error, renameKey); } -SymbolCapabilities::SymbolCapabilities() -{ - setSymbolKind(SymbolKindCapabilities()); -} - bool SymbolCapabilities::isValid(QStringList *error) const { return DynamicRegistrationCapabilities::isValid(error) && checkOptional<SymbolKindCapabilities>(error, symbolKindKey); } -TextDocumentClientCapabilities::CompletionCapabilities::CompletionCapabilities() -{ - setDynamicRegistration(true); - setCompletionItem(CompletionItemCapbilities()); - setCompletionItemKind(CompletionItemKindCapabilities()); -} - bool TextDocumentClientCapabilities::CompletionCapabilities::isValid(QStringList *error) const { return DynamicRegistrationCapabilities::isValid(error) diff --git a/src/libs/languageserverprotocol/clientcapabilities.h b/src/libs/languageserverprotocol/clientcapabilities.h index c10341b3f0..3664007dd1 100644 --- a/src/libs/languageserverprotocol/clientcapabilities.h +++ b/src/libs/languageserverprotocol/clientcapabilities.h @@ -46,13 +46,11 @@ public: class LANGUAGESERVERPROTOCOL_EXPORT SymbolCapabilities : public DynamicRegistrationCapabilities { public: - SymbolCapabilities(); using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities; - class SymbolKindCapabilities : public JsonObject + class LANGUAGESERVERPROTOCOL_EXPORT SymbolKindCapabilities : public JsonObject { public: - SymbolKindCapabilities(); using JsonObject::JsonObject; /* @@ -85,13 +83,11 @@ public: class LANGUAGESERVERPROTOCOL_EXPORT TextDocumentClientCapabilities : public JsonObject { public: - TextDocumentClientCapabilities(); using JsonObject::JsonObject; - class SynchronizationCapabilities : public DynamicRegistrationCapabilities + class LANGUAGESERVERPROTOCOL_EXPORT SynchronizationCapabilities : public DynamicRegistrationCapabilities { public: - SynchronizationCapabilities(); using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities; // The client supports sending will save notifications. @@ -124,16 +120,14 @@ public: { insert(synchronizationKey, synchronization); } void clearSynchronization() { remove(synchronizationKey); } - class CompletionCapabilities : public DynamicRegistrationCapabilities + class LANGUAGESERVERPROTOCOL_EXPORT CompletionCapabilities : public DynamicRegistrationCapabilities { public: - CompletionCapabilities(); using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities; - class CompletionItemCapbilities : public JsonObject + class LANGUAGESERVERPROTOCOL_EXPORT CompletionItemCapbilities : public JsonObject { public: - CompletionItemCapbilities(); using JsonObject::JsonObject; /* @@ -180,7 +174,7 @@ public: { insert(completionItemKey, completionItem); } void clearCompletionItem() { remove(completionItemKey); } - class CompletionItemKindCapabilities : public JsonObject + class LANGUAGESERVERPROTOCOL_EXPORT CompletionItemKindCapabilities : public JsonObject { public: CompletionItemKindCapabilities(); @@ -227,7 +221,7 @@ public: { insert(completionKey, completion); } void clearCompletion() { remove(completionKey); } - class HoverCapabilities : public DynamicRegistrationCapabilities + class LANGUAGESERVERPROTOCOL_EXPORT HoverCapabilities : public DynamicRegistrationCapabilities { public: using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities; @@ -246,12 +240,12 @@ public: void setHover(const HoverCapabilities &hover) { insert(hoverKey, hover); } void clearHover() { remove(hoverKey); } - class SignatureHelpCapabilities : public DynamicRegistrationCapabilities + class LANGUAGESERVERPROTOCOL_EXPORT SignatureHelpCapabilities : public DynamicRegistrationCapabilities { public: using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities; - class SignatureInformationCapabilities : public JsonObject + class LANGUAGESERVERPROTOCOL_EXPORT SignatureInformationCapabilities : public JsonObject { public: using JsonObject::JsonObject; @@ -355,17 +349,17 @@ public: { insert(implementationKey, implementation); } void clearImplementation() { remove(implementationKey); } - class CodeActionCapabilities : public DynamicRegistrationCapabilities + class LANGUAGESERVERPROTOCOL_EXPORT CodeActionCapabilities : public DynamicRegistrationCapabilities { public: using DynamicRegistrationCapabilities::DynamicRegistrationCapabilities; - class CodeActionLiteralSupport : public JsonObject + class LANGUAGESERVERPROTOCOL_EXPORT CodeActionLiteralSupport : public JsonObject { public: using JsonObject::JsonObject; - class CodeActionKind : public JsonObject + class LANGUAGESERVERPROTOCOL_EXPORT CodeActionKind : public JsonObject { public: using JsonObject::JsonObject; @@ -454,7 +448,7 @@ public: void setApplyEdit(bool applyEdit) { insert(applyEditKey, applyEdit); } void clearApplyEdit() { remove(applyEditKey); } - class WorkspaceEditCapabilities : public JsonObject + class LANGUAGESERVERPROTOCOL_EXPORT WorkspaceEditCapabilities : public JsonObject { public: using JsonObject::JsonObject; @@ -522,7 +516,6 @@ public: class LANGUAGESERVERPROTOCOL_EXPORT ClientCapabilities : public JsonObject { public: - ClientCapabilities(); using JsonObject::JsonObject; // Workspace specific client capabilities. diff --git a/src/libs/languageserverprotocol/icontent.h b/src/libs/languageserverprotocol/icontent.h index af14604739..1b57165b2e 100644 --- a/src/libs/languageserverprotocol/icontent.h +++ b/src/libs/languageserverprotocol/icontent.h @@ -92,7 +92,7 @@ using ResponseHandler = std::function<void(const QByteArray &, QTextCodec *)>; using ResponseHandlers = std::function<void(MessageId, const QByteArray &, QTextCodec *)>; using MethodHandler = std::function<void(const QString, MessageId, const IContent *)>; -inline LANGUAGESERVERPROTOCOL_EXPORT uint qHash(const LanguageServerProtocol::MessageId &id) +inline uint qHash(const LanguageServerProtocol::MessageId &id) { if (Utils::holds_alternative<int>(id)) return QT_PREPEND_NAMESPACE(qHash(Utils::get<int>(id))); @@ -102,8 +102,7 @@ inline LANGUAGESERVERPROTOCOL_EXPORT uint qHash(const LanguageServerProtocol::Me } template <typename Error> -inline LANGUAGESERVERPROTOCOL_EXPORT QDebug operator<<(QDebug stream, - const LanguageServerProtocol::MessageId &id) +inline QDebug operator<<(QDebug stream, const LanguageServerProtocol::MessageId &id) { if (Utils::holds_alternative<int>(id)) stream << Utils::get<int>(id); diff --git a/src/libs/languageserverprotocol/initializemessages.cpp b/src/libs/languageserverprotocol/initializemessages.cpp index 0464f8a13c..92e82d5107 100644 --- a/src/libs/languageserverprotocol/initializemessages.cpp +++ b/src/libs/languageserverprotocol/initializemessages.cpp @@ -54,27 +54,18 @@ QString Trace::toString() const } #undef RETURN_CASE -TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemCapbilities::CompletionItemCapbilities() -{ -} - Utils::optional<QList<MarkupKind>> TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemCapbilities:: documentationFormat() const { - Utils::optional<QList<int>> array = optionalArray<int>(documentationFormatKey); - if (!array) - return Utils::nullopt; - return Utils::make_optional(Utils::transform(array.value(), [] (int value) { - return static_cast<MarkupKind>(value); - })); + return optionalArray<MarkupKind>(documentationFormatKey); } void TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemCapbilities:: setDocumentationFormat(const QList<MarkupKind> &documentationFormat) { - insert(documentationFormatKey, enumArrayToJsonArray<MarkupKind>(documentationFormat)); + insertArray(documentationFormatKey, documentationFormat); } TextDocumentClientCapabilities::CompletionCapabilities::CompletionItemKindCapabilities::CompletionItemKindCapabilities() @@ -111,36 +102,26 @@ setValueSet(const QList<CompletionItemKind::Kind> &valueSet) Utils::optional<QList<MarkupKind> > TextDocumentClientCapabilities::HoverCapabilities::contentFormat() const { - Utils::optional<QList<int>> array = optionalArray<int>(contentFormatKey); - if (!array) - return Utils::nullopt; - return Utils::make_optional(Utils::transform(array.value(), [] (int value) { - return static_cast<MarkupKind>(value); - })); + return optionalArray<MarkupKind>(contentFormatKey); } void TextDocumentClientCapabilities::HoverCapabilities::setContentFormat(const QList<MarkupKind> &contentFormat) { - insert(contentFormatKey, enumArrayToJsonArray<MarkupKind>(contentFormat)); + insertArray(contentFormatKey, contentFormat); } Utils::optional<QList<MarkupKind>> TextDocumentClientCapabilities::SignatureHelpCapabilities::SignatureInformationCapabilities:: documentationFormat() const { - Utils::optional<QList<int>> array = optionalArray<int>(documentationFormatKey); - if (!array) - return Utils::nullopt; - return Utils::make_optional(Utils::transform(array.value(), [] (int value) { - return static_cast<MarkupKind>(value); - })); + return optionalArray<MarkupKind>(documentationFormatKey); } void TextDocumentClientCapabilities::SignatureHelpCapabilities::SignatureInformationCapabilities:: setDocumentationFormat(const QList<MarkupKind> &documentationFormat) { - insert(documentationFormatKey, enumArrayToJsonArray<MarkupKind>(documentationFormat)); + insertArray(documentationFormatKey, documentationFormat); } InitializeParams::InitializeParams() diff --git a/src/libs/languageserverprotocol/jsonkeys.h b/src/libs/languageserverprotocol/jsonkeys.h index 6dfc40c252..e3673085eb 100644 --- a/src/libs/languageserverprotocol/jsonkeys.h +++ b/src/libs/languageserverprotocol/jsonkeys.h @@ -69,6 +69,7 @@ constexpr char contentChangesKey[] = "contentChanges"; constexpr char contentCharsetName[] = "charset"; constexpr char contentFormatKey[] = "contentFormat"; constexpr char contentKey[] = "value"; +constexpr char contentsKey[] = "contents"; constexpr char contentLengthFieldName[] = "Content-Length"; constexpr char contentTypeFieldName[] = "Content-Type"; constexpr char contextKey[] = "context"; diff --git a/src/libs/languageserverprotocol/jsonobject.cpp b/src/libs/languageserverprotocol/jsonobject.cpp index 1f471db47b..0156276a67 100644 --- a/src/libs/languageserverprotocol/jsonobject.cpp +++ b/src/libs/languageserverprotocol/jsonobject.cpp @@ -61,11 +61,7 @@ JsonObject &JsonObject::operator=(const JsonObject &other) = default; JsonObject &JsonObject::operator=(JsonObject &&other) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) m_jsonObject.swap(other.m_jsonObject); -#else - m_jsonObject = other.m_jsonObject; // NOTE use QJsonObject::swap when minimum required Qt version >= 5.10 -#endif return *this; } diff --git a/src/libs/languageserverprotocol/jsonrpcmessages.h b/src/libs/languageserverprotocol/jsonrpcmessages.h index 66c28bea4b..473c9fe580 100644 --- a/src/libs/languageserverprotocol/jsonrpcmessages.h +++ b/src/libs/languageserverprotocol/jsonrpcmessages.h @@ -232,6 +232,7 @@ template <typename Result, typename ErrorDataType> class Response : public JsonRpcMessage { public: + explicit Response(const MessageId &id) { setId(id); } using JsonRpcMessage::JsonRpcMessage; MessageId id() const diff --git a/src/libs/languageserverprotocol/languagefeatures.cpp b/src/libs/languageserverprotocol/languagefeatures.cpp index 06793217f1..cfb4cc6fab 100644 --- a/src/libs/languageserverprotocol/languagefeatures.cpp +++ b/src/libs/languageserverprotocol/languagefeatures.cpp @@ -49,19 +49,19 @@ constexpr const char DocumentOnTypeFormattingRequest::methodName[]; constexpr const char RenameRequest::methodName[]; constexpr const char SignatureHelpRequest::methodName[]; -MarkedString LanguageServerProtocol::Hover::content() const +HoverContent LanguageServerProtocol::Hover::content() const { - return MarkedString(value(contentKey)); + return HoverContent(value(contentsKey)); } -void Hover::setContent(const MarkedString &content) +void Hover::setContent(const HoverContent &content) { - if (auto val = Utils::get_if<MarkedLanguageString>(&content)) - insert(contentKey, *val); + if (auto val = Utils::get_if<MarkedString>(&content)) + insert(contentsKey, *val); else if (auto val = Utils::get_if<MarkupContent>(&content)) - insert(contentKey, *val); - else if (auto val = Utils::get_if<QList<MarkedLanguageString>>(&content)) - insert(contentKey, LanguageClientArray<MarkedLanguageString>(*val).toJson()); + insert(contentsKey, *val); + else if (auto val = Utils::get_if<QList<MarkedString>>(&content)) + insert(contentsKey, LanguageClientArray<MarkedString>(*val).toJson()); else QTC_ASSERT_STRING("LanguageClient Using unknown type Hover::setContent"); } @@ -334,31 +334,52 @@ DocumentHighlightsResult::DocumentHighlightsResult(const QJsonValue &value) MarkedString::MarkedString(const QJsonValue &value) { + if (value.isObject()) { + MarkedLanguageString string(value.toObject()); + if (string.isValid(nullptr)) + emplace<MarkedLanguageString>(string); + } else if (value.isString()) { + emplace<QString>(value.toString()); + } +} + +LanguageServerProtocol::MarkedString::operator QJsonValue() const +{ + if (auto val = Utils::get_if<QString>(this)) + return *val; + if (auto val = Utils::get_if<MarkedLanguageString>(this)) + return QJsonValue(*val); + return {}; +} + +HoverContent::HoverContent(const QJsonValue &value) +{ if (value.isArray()) { - emplace<QList<MarkedLanguageString>>( - LanguageClientArray<MarkedLanguageString>(value).toList()); + emplace<QList<MarkedString>>(LanguageClientArray<MarkedString>(value).toList()); } else if (value.isObject()) { const QJsonObject &object = value.toObject(); MarkedLanguageString markedLanguageString(object); if (markedLanguageString.isValid(nullptr)) - emplace<MarkedLanguageString>(markedLanguageString); + emplace<MarkedString>(markedLanguageString); else emplace<MarkupContent>(MarkupContent(object)); + } else if (value.isString()) { + emplace<MarkedString>(MarkedString(value.toString())); } } -bool MarkedString::isValid(QStringList *errorHierarchy) const +bool HoverContent::isValid(QStringList *errorHierarchy) const { - if (Utils::holds_alternative<MarkedLanguageString>(*this) + if (Utils::holds_alternative<MarkedString>(*this) || Utils::holds_alternative<MarkupContent>(*this) - || Utils::holds_alternative<QList<MarkedLanguageString>>(*this)) { + || Utils::holds_alternative<QList<MarkedString>>(*this)) { return true; } if (errorHierarchy) { *errorHierarchy << QCoreApplication::translate( - "LanguageServerProtocol::MarkedString", - "MarkedString should be either MarkedLanguageString, " - "MarkupContent, or QList<MarkedLanguageString>."); + "LanguageServerProtocol::HoverContent", + "HoverContent should be either MarkedString, " + "MarkupContent, or QList<MarkedString>."); } return false; } diff --git a/src/libs/languageserverprotocol/languagefeatures.h b/src/libs/languageserverprotocol/languagefeatures.h index 30f3591e64..ddd732718a 100644 --- a/src/libs/languageserverprotocol/languagefeatures.h +++ b/src/libs/languageserverprotocol/languagefeatures.h @@ -58,14 +58,31 @@ public: { return check<QString>(error, languageKey) && check<QString>(error, valueKey); } }; -class MarkedString : public Utils::variant<MarkedLanguageString, QList<MarkedLanguageString>, MarkupContent> +class LANGUAGESERVERPROTOCOL_EXPORT MarkedString + : public Utils::variant<QString, MarkedLanguageString> { public: MarkedString() = default; - explicit MarkedString(const MarkedLanguageString &other) : variant(other) {} - explicit MarkedString(const QList<MarkedLanguageString> &other) : variant(other) {} - explicit MarkedString(const MarkupContent &other) : variant(other) {} + explicit MarkedString(const MarkedLanguageString &other) + : variant(other) + {} + explicit MarkedString(const QString &other) + : variant(other) + {} explicit MarkedString(const QJsonValue &value); + + operator QJsonValue() const; +}; + +class LANGUAGESERVERPROTOCOL_EXPORT HoverContent + : public Utils::variant<MarkedString, QList<MarkedString>, MarkupContent> +{ +public: + HoverContent() = default; + explicit HoverContent(const MarkedString &other) : variant(other) {} + explicit HoverContent(const QList<MarkedString> &other) : variant(other) {} + explicit HoverContent(const MarkupContent &other) : variant(other) {} + explicit HoverContent(const QJsonValue &value); bool isValid(QStringList *errorHierarchy) const; }; @@ -74,15 +91,15 @@ class LANGUAGESERVERPROTOCOL_EXPORT Hover : public JsonObject public: using JsonObject::JsonObject; - MarkedString content() const; - void setContent(const MarkedString &content); + HoverContent content() const; + void setContent(const HoverContent &content); Utils::optional<Range> range() const { return optionalValue<Range>(rangeKey); } void setRange(const Range &range) { insert(rangeKey, range); } void clearRange() { remove(rangeKey); } bool isValid(QStringList *error) const override - { return check<MarkedString>(error, contentKey) && checkOptional<Range>(error, rangeKey); } + { return check<HoverContent>(error, contentsKey) && checkOptional<Range>(error, rangeKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT HoverRequest @@ -332,9 +349,23 @@ public: using variant::variant; DocumentSymbolsResult() : variant(nullptr) {} DocumentSymbolsResult(const QJsonValue &value); + DocumentSymbolsResult(const DocumentSymbolsResult &other) : variant(other) {} + DocumentSymbolsResult(DocumentSymbolsResult &&other) : variant(std::move(other)) {} + using variant::operator=; + DocumentSymbolsResult &operator =(DocumentSymbolsResult &&other) + { + variant::operator=(std::move(other)); + return *this; + } + DocumentSymbolsResult &operator =(const DocumentSymbolsResult &other) + { + variant::operator=(other); + return *this; + } }; + class LANGUAGESERVERPROTOCOL_EXPORT DocumentSymbolsRequest : public Request<DocumentSymbolsResult, std::nullptr_t, DocumentSymbolParams> { diff --git a/src/libs/languageserverprotocol/lsptypes.cpp b/src/libs/languageserverprotocol/lsptypes.cpp index 991f7cc1f8..8aa1ecf81c 100644 --- a/src/libs/languageserverprotocol/lsptypes.cpp +++ b/src/libs/languageserverprotocol/lsptypes.cpp @@ -324,8 +324,10 @@ Position::Position(const QTextCursor &cursor) int Position::toPositionInDocument(QTextDocument *doc) const { const QTextBlock block = doc->findBlockByNumber(line()); - if (!block.isValid() || block.length() <= character()) + if (!block.isValid()) return -1; + if (block.length() <= character()) + return block.position() + block.length(); return block.position() + character(); } @@ -360,7 +362,7 @@ bool Range::overlaps(const Range &range) const return contains(range.start()) || contains(range.end()); } -bool DocumentFilter::applies(const Utils::FileName &fileName, const Utils::MimeType &mimeType) const +bool DocumentFilter::applies(const Utils::FilePath &fileName, const Utils::MimeType &mimeType) const { if (Utils::optional<QString> _scheme = scheme()) { if (_scheme.value() == fileName.toString()) @@ -404,14 +406,30 @@ DocumentUri::DocumentUri(const QString &other) : QUrl(QUrl::fromPercentEncoding(other.toLocal8Bit())) { } -DocumentUri::DocumentUri(const Utils::FileName &other) +DocumentUri::DocumentUri(const Utils::FilePath &other) : QUrl(QUrl::fromLocalFile(other.toString())) { } -Utils::FileName DocumentUri::toFileName() const +Utils::FilePath DocumentUri::toFileName() const { - return isLocalFile() ? Utils::FileName::fromUserInput(QUrl(*this).toLocalFile()) - : Utils::FileName(); + return isLocalFile() ? Utils::FilePath::fromUserInput(QUrl(*this).toLocalFile()) + : Utils::FilePath(); +} + +MarkupKind::MarkupKind(const QJsonValue &value) +{ + m_value = value.toString() == "markdown" ? markdown : plaintext; +} + +LanguageServerProtocol::MarkupKind::operator QJsonValue() const +{ + switch (m_value) { + case MarkupKind::markdown: + return "markdown"; + case MarkupKind::plaintext: + return "plaintext"; + } + return {}; } } // namespace LanguageServerProtocol diff --git a/src/libs/languageserverprotocol/lsptypes.h b/src/libs/languageserverprotocol/lsptypes.h index 9fe9a47a63..ade3ac7ccf 100644 --- a/src/libs/languageserverprotocol/lsptypes.h +++ b/src/libs/languageserverprotocol/lsptypes.h @@ -45,16 +45,16 @@ class LANGUAGESERVERPROTOCOL_EXPORT DocumentUri : public QUrl { public: DocumentUri() = default; - Utils::FileName toFileName() const; + Utils::FilePath toFileName() const; static DocumentUri fromProtocol(const QString &uri) { return DocumentUri(uri); } - static DocumentUri fromFileName(const Utils::FileName &file) { return DocumentUri(file); } + static DocumentUri fromFileName(const Utils::FilePath &file) { return DocumentUri(file); } operator QJsonValue() const { return QJsonValue(toString()); } private: DocumentUri(const QString &other); - DocumentUri(const Utils::FileName &other); + DocumentUri(const Utils::FilePath &other); friend class LanguageClientValue<QString>; }; @@ -372,16 +372,30 @@ public: void setPattern(const QString &pattern) { insert(patternKey, pattern); } void clearPattern() { remove(patternKey); } - bool applies(const Utils::FileName &fileName, + bool applies(const Utils::FilePath &fileName, const Utils::MimeType &mimeType = Utils::MimeType()) const; bool isValid(QStringList *error) const override; }; -enum class MarkupKind +class LANGUAGESERVERPROTOCOL_EXPORT MarkupKind { - plaintext, - markdown, +public: + enum Value { plaintext, markdown }; + MarkupKind() = default; + MarkupKind(const Value value) + : m_value(value) + {} + MarkupKind(const QJsonValue &value); + + operator QJsonValue() const; + Value value() const { return m_value; } + + bool operator==(const Value &value) const { return m_value == value; } + + bool isValid(void *) const { return true; } +private: + Value m_value = plaintext; }; class LANGUAGESERVERPROTOCOL_EXPORT MarkupContent : public JsonObject @@ -390,15 +404,15 @@ public: using JsonObject::JsonObject; // The type of the Markup - MarkupKind kind() const { return static_cast<MarkupKind>(typedValue<int>(kindKey)); } - void setKind(MarkupKind kind) { insert(kindKey, static_cast<int>(kind)); } + MarkupKind kind() const { return value(kindKey); } + void setKind(MarkupKind kind) { insert(kindKey, kind); } // The content itself QString content() const { return typedValue<QString>(contentKey); } void setContent(const QString &content) { insert(contentKey, content); } bool isValid(QStringList *error) const override - { return check<int>(error, kindKey) && check<QString>(error, contentKey); } + { return check<MarkupKind>(error, kindKey) && check<QString>(error, contentKey); } }; class LANGUAGESERVERPROTOCOL_EXPORT MarkupOrString : public Utils::variant<QString, MarkupContent> diff --git a/src/libs/languageserverprotocol/lsputils.h b/src/libs/languageserverprotocol/lsputils.h index ee98db37f4..4646f181e9 100644 --- a/src/libs/languageserverprotocol/lsputils.h +++ b/src/libs/languageserverprotocol/lsputils.h @@ -71,6 +71,8 @@ public: using Utils::variant<QList<T>, std::nullptr_t>::variant; using Utils::variant<QList<T>, std::nullptr_t>::operator=; + LanguageClientArray() {} + LanguageClientArray(const QList<T> &list) { *this = list; } diff --git a/src/libs/languageserverprotocol/servercapabilities.cpp b/src/libs/languageserverprotocol/servercapabilities.cpp index fcd1fadeac..6ebf4f431f 100644 --- a/src/libs/languageserverprotocol/servercapabilities.cpp +++ b/src/libs/languageserverprotocol/servercapabilities.cpp @@ -161,7 +161,7 @@ bool ServerCapabilities::WorkspaceServerCapabilities::WorkspaceFoldersCapabiliti && checkOptional<QString, bool>(error, changeNotificationsKey); } -bool TextDocumentRegistrationOptions::filterApplies(const Utils::FileName &fileName, +bool TextDocumentRegistrationOptions::filterApplies(const Utils::FilePath &fileName, const Utils::MimeType &mimeType) const { const LanguageClientArray<DocumentFilter> &selector = documentSelector(); diff --git a/src/libs/languageserverprotocol/servercapabilities.h b/src/libs/languageserverprotocol/servercapabilities.h index 0e31821b17..71d3e4a496 100644 --- a/src/libs/languageserverprotocol/servercapabilities.h +++ b/src/libs/languageserverprotocol/servercapabilities.h @@ -52,7 +52,7 @@ public: void setDocumentSelector(const LanguageClientArray<DocumentFilter> &documentSelector) { insert(documentSelectorKey, documentSelector.toJson()); } - bool filterApplies(const Utils::FileName &fileName, + bool filterApplies(const Utils::FilePath &fileName, const Utils::MimeType &mimeType = Utils::MimeType()) const; bool isValid(QStringList *error) const override @@ -268,7 +268,7 @@ public: void setDocumentSelector(const LanguageClientArray<DocumentFilter> &documentSelector) { insert(documentSelectorKey, documentSelector.toJson()); } - bool filterApplies(const Utils::FileName &fileName, + bool filterApplies(const Utils::FilePath &fileName, const Utils::MimeType &mimeType = Utils::MimeType()) const; // The id used to register the request. The id can be used to deregister diff --git a/src/libs/languageserverprotocol/textsynchronization.h b/src/libs/languageserverprotocol/textsynchronization.h index 2b659366cd..fa81cae51a 100644 --- a/src/libs/languageserverprotocol/textsynchronization.h +++ b/src/libs/languageserverprotocol/textsynchronization.h @@ -83,7 +83,7 @@ public: void setTextDocument(const VersionedTextDocumentIdentifier &textDocument) { insert(textDocumentKey, textDocument); } - class TextDocumentContentChangeEvent : public JsonObject + class LANGUAGESERVERPROTOCOL_EXPORT TextDocumentContentChangeEvent : public JsonObject { /* * An event describing a change to a text document. If range and rangeLength are omitted diff --git a/src/libs/languageserverprotocol/workspace.cpp b/src/libs/languageserverprotocol/workspace.cpp index 9f73af2ac0..e411878877 100644 --- a/src/libs/languageserverprotocol/workspace.cpp +++ b/src/libs/languageserverprotocol/workspace.cpp @@ -98,4 +98,14 @@ ExecuteCommandParams::ExecuteCommandParams(const Command &command) setArguments(command.arguments().value()); } +LanguageServerProtocol::WorkSpaceFolderResult::operator const QJsonValue() const +{ + if (!Utils::holds_alternative<QList<WorkSpaceFolder>>(*this)) + return QJsonValue::Null; + QJsonArray array; + for (auto folder : Utils::get<QList<WorkSpaceFolder>>(*this)) + array.append(QJsonValue(folder)); + return array; +} + } // namespace LanguageServerProtocol diff --git a/src/libs/languageserverprotocol/workspace.h b/src/libs/languageserverprotocol/workspace.h index 5f69d2c782..bf6a1b9096 100644 --- a/src/libs/languageserverprotocol/workspace.h +++ b/src/libs/languageserverprotocol/workspace.h @@ -29,8 +29,17 @@ namespace LanguageServerProtocol { +class LANGUAGESERVERPROTOCOL_EXPORT WorkSpaceFolderResult + : public Utils::variant<QList<WorkSpaceFolder>, std::nullptr_t> +{ +public: + using variant::variant; + using variant::operator=; + operator const QJsonValue() const; +}; + class LANGUAGESERVERPROTOCOL_EXPORT WorkSpaceFolderRequest : public Request< - Utils::variant<QList<WorkSpaceFolder>, Utils::nullopt_t>, std::nullptr_t, std::nullptr_t> + WorkSpaceFolderResult, std::nullptr_t, std::nullptr_t> { public: WorkSpaceFolderRequest(); diff --git a/src/libs/languageutils/CMakeLists.txt b/src/libs/languageutils/CMakeLists.txt new file mode 100644 index 0000000000..0cc47e7c60 --- /dev/null +++ b/src/libs/languageutils/CMakeLists.txt @@ -0,0 +1,7 @@ +add_qtc_library(LanguageUtils + PUBLIC_DEPENDS Qt5::Core + SOURCES + componentversion.cpp componentversion.h + fakemetaobject.cpp fakemetaobject.h + languageutils_global.h +) diff --git a/src/libs/libs.pro b/src/libs/libs.pro index 26495bbbf0..cbd788ced0 100644 --- a/src/libs/libs.pro +++ b/src/libs/libs.pro @@ -14,9 +14,9 @@ SUBDIRS += \ qmleditorwidgets \ glsl \ ssh \ - sqlite \ clangsupport \ - languageserverprotocol + languageserverprotocol \ + sqlite qtHaveModule(quick) { SUBDIRS += \ diff --git a/src/libs/modelinglib/CMakeLists.txt b/src/libs/modelinglib/CMakeLists.txt new file mode 100644 index 0000000000..7b09c932e4 --- /dev/null +++ b/src/libs/modelinglib/CMakeLists.txt @@ -0,0 +1,196 @@ +add_qtc_library(Modeling + DEFINES MODELING_LIBRARY + DEPENDS Qt5::Widgets Utils + PUBLIC_DEPENDS OptionalSvg + INCLUDES qtserialization/inc + PUBLIC_INCLUDES "${CMAKE_CURRENT_LIST_DIR}" + SOURCES + qmt/config/configcontroller.cpp qmt/config/configcontroller.h + qmt/config/sourcepos.cpp qmt/config/sourcepos.h + qmt/config/stereotypedefinitionparser.cpp qmt/config/stereotypedefinitionparser.h + qmt/config/stringtextsource.cpp qmt/config/stringtextsource.h + qmt/config/textscanner.cpp qmt/config/textscanner.h + qmt/config/textsource.h + qmt/config/token.cpp qmt/config/token.h + qmt/controller/container.h + qmt/controller/namecontroller.cpp qmt/controller/namecontroller.h + qmt/controller/references.h + qmt/controller/selection.cpp qmt/controller/selection.h + qmt/controller/undocommand.cpp qmt/controller/undocommand.h + qmt/controller/undocontroller.cpp qmt/controller/undocontroller.h + qmt/diagram_controller/dclonevisitor.cpp qmt/diagram_controller/dclonevisitor.h + qmt/diagram_controller/dcontainer.h + qmt/diagram_controller/dfactory.cpp qmt/diagram_controller/dfactory.h + qmt/diagram_controller/dflatassignmentvisitor.cpp qmt/diagram_controller/dflatassignmentvisitor.h + qmt/diagram_controller/diagramcontroller.cpp qmt/diagram_controller/diagramcontroller.h + qmt/diagram_controller/dreferences.h + qmt/diagram_controller/dselection.h + qmt/diagram_controller/dupdatevisitor.cpp qmt/diagram_controller/dupdatevisitor.h + qmt/diagram_controller/dvoidvisitor.cpp qmt/diagram_controller/dvoidvisitor.h + qmt/diagram/dannotation.cpp qmt/diagram/dannotation.h + qmt/diagram/dassociation.cpp qmt/diagram/dassociation.h + qmt/diagram/dboundary.cpp qmt/diagram/dboundary.h + qmt/diagram/dclass.cpp qmt/diagram/dclass.h + qmt/diagram/dcomponent.cpp qmt/diagram/dcomponent.h + qmt/diagram/dconnection.cpp qmt/diagram/dconnection.h + qmt/diagram/dconstvisitor.h + qmt/diagram/ddependency.cpp qmt/diagram/ddependency.h + qmt/diagram/ddiagram.cpp qmt/diagram/ddiagram.h + qmt/diagram/delement.cpp qmt/diagram/delement.h + qmt/diagram/dinheritance.cpp qmt/diagram/dinheritance.h + qmt/diagram/ditem.cpp qmt/diagram/ditem.h + qmt/diagram/dobject.cpp qmt/diagram/dobject.h + qmt/diagram/dpackage.cpp qmt/diagram/dpackage.h + qmt/diagram/drelation.cpp qmt/diagram/drelation.h + qmt/diagram/dswimlane.cpp qmt/diagram/dswimlane.h + qmt/diagram/dvisitor.h + qmt/diagram_scene/capabilities/alignable.h + qmt/diagram_scene/capabilities/editable.h + qmt/diagram_scene/capabilities/intersectionable.h + qmt/diagram_scene/capabilities/latchable.h + qmt/diagram_scene/capabilities/moveable.h + qmt/diagram_scene/capabilities/relationable.h + qmt/diagram_scene/capabilities/resizable.h + qmt/diagram_scene/capabilities/selectable.h + qmt/diagram_scene/capabilities/windable.h + qmt/diagram_scene/diagramgraphicsscene.cpp qmt/diagram_scene/diagramgraphicsscene.h + qmt/diagram_scene/diagramsceneconstants.h + qmt/diagram_scene/diagramscenemodel.cpp qmt/diagram_scene/diagramscenemodel.h + qmt/diagram_scene/diagramscenemodelitemvisitors.cpp qmt/diagram_scene/diagramscenemodelitemvisitors.h + qmt/diagram_scene/items/annotationitem.cpp qmt/diagram_scene/items/annotationitem.h + qmt/diagram_scene/items/associationitem.cpp qmt/diagram_scene/items/associationitem.h + qmt/diagram_scene/items/boundaryitem.cpp qmt/diagram_scene/items/boundaryitem.h + qmt/diagram_scene/items/classitem.cpp qmt/diagram_scene/items/classitem.h + qmt/diagram_scene/items/componentitem.cpp qmt/diagram_scene/items/componentitem.h + qmt/diagram_scene/items/connectionitem.cpp qmt/diagram_scene/items/connectionitem.h + qmt/diagram_scene/items/diagramitem.cpp qmt/diagram_scene/items/diagramitem.h + qmt/diagram_scene/items/itemitem.cpp qmt/diagram_scene/items/itemitem.h + qmt/diagram_scene/items/objectitem.cpp qmt/diagram_scene/items/objectitem.h + qmt/diagram_scene/items/packageitem.cpp qmt/diagram_scene/items/packageitem.h + qmt/diagram_scene/items/relationitem.cpp qmt/diagram_scene/items/relationitem.h + qmt/diagram_scene/items/stereotypedisplayvisitor.cpp qmt/diagram_scene/items/stereotypedisplayvisitor.h + qmt/diagram_scene/items/swimlaneitem.cpp qmt/diagram_scene/items/swimlaneitem.h + qmt/diagram_scene/latchcontroller.cpp qmt/diagram_scene/latchcontroller.h + qmt/diagram_scene/parts/alignbuttonsitem.cpp qmt/diagram_scene/parts/alignbuttonsitem.h + qmt/diagram_scene/parts/alignlineitem.cpp qmt/diagram_scene/parts/alignlineitem.h + qmt/diagram_scene/parts/arrowitem.cpp qmt/diagram_scene/parts/arrowitem.h + qmt/diagram_scene/parts/contextlabelitem.cpp qmt/diagram_scene/parts/contextlabelitem.h + qmt/diagram_scene/parts/customiconitem.cpp qmt/diagram_scene/parts/customiconitem.h + qmt/diagram_scene/parts/editabletextitem.cpp qmt/diagram_scene/parts/editabletextitem.h + qmt/diagram_scene/parts/pathselectionitem.cpp qmt/diagram_scene/parts/pathselectionitem.h + qmt/diagram_scene/parts/rectangularselectionitem.cpp qmt/diagram_scene/parts/rectangularselectionitem.h + qmt/diagram_scene/parts/relationstarter.cpp qmt/diagram_scene/parts/relationstarter.h + qmt/diagram_scene/parts/stereotypesitem.cpp qmt/diagram_scene/parts/stereotypesitem.h + qmt/diagram_scene/parts/templateparameterbox.cpp qmt/diagram_scene/parts/templateparameterbox.h + qmt/diagram_ui/diagram_mime_types.h + qmt/diagram_ui/diagramsmanager.cpp qmt/diagram_ui/diagramsmanager.h + qmt/diagram_ui/diagramsviewinterface.h + qmt/diagram_ui/sceneinspector.cpp qmt/diagram_ui/sceneinspector.h + qmt/diagram_widgets_ui/diagramsview.cpp qmt/diagram_widgets_ui/diagramsview.h + qmt/diagram_widgets_ui/diagramview.cpp qmt/diagram_widgets_ui/diagramview.h + qmt/diagram_widgets_ui/stackeddiagramsview.cpp qmt/diagram_widgets_ui/stackeddiagramsview.h + qmt/document_controller/documentcontroller.cpp qmt/document_controller/documentcontroller.h + qmt/infrastructure/contextmenuaction.cpp qmt/infrastructure/contextmenuaction.h + qmt/infrastructure/exceptions.cpp qmt/infrastructure/exceptions.h + qmt/infrastructure/geometryutilities.cpp qmt/infrastructure/geometryutilities.h + qmt/infrastructure/handle.h + qmt/infrastructure/handles.h + qmt/infrastructure/ioexceptions.cpp qmt/infrastructure/ioexceptions.h + qmt/infrastructure/qcompressedfile.cpp qmt/infrastructure/qcompressedfile.h + qmt/infrastructure/qmtassert.h + qmt/infrastructure/qmt_global.h + qmt/infrastructure/uid.h + qmt/model_controller/mchildrenvisitor.cpp qmt/model_controller/mchildrenvisitor.h + qmt/model_controller/mclonevisitor.cpp qmt/model_controller/mclonevisitor.h + qmt/model_controller/mcontainer.h + qmt/model_controller/mflatassignmentvisitor.cpp qmt/model_controller/mflatassignmentvisitor.h + qmt/model_controller/modelcontroller.cpp qmt/model_controller/modelcontroller.h + qmt/model_controller/mreferences.h + qmt/model_controller/mselection.h + qmt/model_controller/mvoidvisitor.cpp qmt/model_controller/mvoidvisitor.h + qmt/model/massociation.cpp qmt/model/massociation.h + qmt/model/mcanvasdiagram.cpp qmt/model/mcanvasdiagram.h + qmt/model/mclass.cpp qmt/model/mclass.h + qmt/model/mclassmember.cpp qmt/model/mclassmember.h + qmt/model/mcomponent.cpp qmt/model/mcomponent.h + qmt/model/mconnection.cpp qmt/model/mconnection.h + qmt/model/mconstvisitor.h + qmt/model/mdependency.cpp qmt/model/mdependency.h + qmt/model/mdiagram.cpp qmt/model/mdiagram.h + qmt/model/melement.cpp qmt/model/melement.h + qmt/model/minheritance.cpp qmt/model/minheritance.h + qmt/model/mitem.cpp qmt/model/mitem.h + qmt/model/mobject.cpp qmt/model/mobject.h + qmt/model/mpackage.cpp qmt/model/mpackage.h + qmt/model/mrelation.cpp qmt/model/mrelation.h + qmt/model/msourceexpansion.cpp qmt/model/msourceexpansion.h + qmt/model/mvisitor.h + qmt/model_ui/modeltreeviewinterface.h + qmt/model_ui/sortedtreemodel.cpp qmt/model_ui/sortedtreemodel.h + qmt/model_ui/stereotypescontroller.cpp qmt/model_ui/stereotypescontroller.h + qmt/model_ui/treemodel.cpp qmt/model_ui/treemodel.h + qmt/model_ui/treemodelmanager.cpp qmt/model_ui/treemodelmanager.h + qmt/model_widgets_ui/classmembersedit.cpp qmt/model_widgets_ui/classmembersedit.h + qmt/model_widgets_ui/modeltreeview.cpp qmt/model_widgets_ui/modeltreeview.h + qmt/model_widgets_ui/palettebox.cpp qmt/model_widgets_ui/palettebox.h + qmt/model_widgets_ui/propertiesview.cpp qmt/model_widgets_ui/propertiesview.h + qmt/model_widgets_ui/propertiesviewmview.cpp qmt/model_widgets_ui/propertiesviewmview.h + qmt/project_controller/projectcontroller.cpp qmt/project_controller/projectcontroller.h + qmt/project/project.cpp qmt/project/project.h + qmt/resources/resources.qrc + qmt/serializer/diagramserializer.cpp qmt/serializer/diagramserializer.h + qmt/serializer/infrastructureserializer.cpp qmt/serializer/infrastructureserializer.h + qmt/serializer/modelserializer.cpp qmt/serializer/modelserializer.h + qmt/serializer/projectserializer.cpp qmt/serializer/projectserializer.h + qmt/stereotype/customrelation.cpp qmt/stereotype/customrelation.h + qmt/stereotype/iconshape.cpp qmt/stereotype/iconshape.h + qmt/stereotype/shape.h + qmt/stereotype/shapepaintvisitor.cpp qmt/stereotype/shapepaintvisitor.h + qmt/stereotype/shapes.cpp qmt/stereotype/shapes.h + qmt/stereotype/shapevalue.cpp qmt/stereotype/shapevalue.h + qmt/stereotype/shapevisitor.h + qmt/stereotype/stereotypecontroller.cpp qmt/stereotype/stereotypecontroller.h + qmt/stereotype/stereotypeicon.cpp qmt/stereotype/stereotypeicon.h + qmt/stereotype/toolbar.cpp qmt/stereotype/toolbar.h + qmt/style/defaultstyle.cpp + qmt/style/defaultstyleengine.cpp qmt/style/defaultstyleengine.h + qmt/style/defaultstyle.h + qmt/style/objectvisuals.cpp qmt/style/objectvisuals.h + qmt/style/relationstarterstyle.cpp qmt/style/relationstarterstyle.h + qmt/style/stylecontroller.cpp qmt/style/stylecontroller.h + qmt/style/style.cpp + qmt/style/styledobject.cpp qmt/style/styledobject.h + qmt/style/styledrelation.cpp qmt/style/styledrelation.h + qmt/style/styleengine.h + qmt/style/style.h + qmt/tasks/alignonrastervisitor.cpp qmt/tasks/alignonrastervisitor.h + qmt/tasks/diagramscenecontroller.cpp qmt/tasks/diagramscenecontroller.h + qmt/tasks/finddiagramvisitor.cpp qmt/tasks/finddiagramvisitor.h + qmt/tasks/findrootdiagramvisitor.cpp qmt/tasks/findrootdiagramvisitor.h + qmt/tasks/ielementtasks.h + qmt/tasks/isceneinspector.h + qmt/tasks/voidelementtasks.cpp qmt/tasks/voidelementtasks.h + qstringparser/qstringparser.cpp qstringparser/qstringparser.h + qtserialization/inc/qark/access.h + qtserialization/inc/qark/archivebasics.h + qtserialization/inc/qark/attribute.h + qtserialization/inc/qark/baseclass.h + qtserialization/inc/qark/flag.h + qtserialization/inc/qark/friend_access.h + qtserialization/inc/qark/impl/loadingrefmap.h + qtserialization/inc/qark/impl/objectid.h + qtserialization/inc/qark/impl/savingrefmap.h + qtserialization/inc/qark/parameters.h + qtserialization/inc/qark/qxmlinarchive.h + qtserialization/inc/qark/qxmloutarchive.h + qtserialization/inc/qark/reference.h + qtserialization/inc/qark/serialize_basic.h + qtserialization/inc/qark/serialize_container.h + qtserialization/inc/qark/serialize_enum.h + qtserialization/inc/qark/serialize.h + qtserialization/inc/qark/serialize_pointer.h + qtserialization/inc/qark/tag.h + qtserialization/inc/qark/typeregistry.h + qtserialization/src/flag.cpp + qtserialization/src/savingrefmap.cpp +) diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.cpp b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.cpp index 37e74adeac..3bcc0727fb 100644 --- a/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.cpp +++ b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.cpp @@ -173,14 +173,13 @@ void ModelTreeView::dragMoveEvent(QDragMoveEvent *event) if (dynamic_cast<MObject*>(modelElement)) accept = true; if (m_autoDelayIndex == dropIndex) { - if (m_autoDelayStartTime.elapsed() > 1000) { + if (m_autoDelayStartTimer.elapsed() > 1000) { setExpanded(dropIndex, !isExpanded(dropIndex)); - m_autoDelayStartTime.start(); + m_autoDelayStartTimer.start(); } } else { m_autoDelayIndex = dropIndex; - m_autoDelayStartTime = QTime::currentTime(); - m_autoDelayStartTime.start(); + m_autoDelayStartTimer.start(); } } event->setAccepted(accept); diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.h b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.h index 724097a365..565d3671c2 100644 --- a/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.h +++ b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.h @@ -25,11 +25,11 @@ #pragma once -#include <QTreeView> #include "qmt/infrastructure/qmt_global.h" #include "qmt/model_ui/modeltreeviewinterface.h" -#include <QTime> +#include <QElapsedTimer> +#include <QTreeView> namespace qmt { @@ -70,7 +70,7 @@ private: SortedTreeModel *m_sortedTreeModel = nullptr; IElementTasks *m_elementTasks = nullptr; QModelIndex m_autoDelayIndex; - QTime m_autoDelayStartTime; + QElapsedTimer m_autoDelayStartTimer; }; } // namespace qmt diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp index 63d716d2d1..c8b11d44e1 100644 --- a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp +++ b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp @@ -352,7 +352,7 @@ void PropertiesView::MView::visitMElement(const MElement *element) m_stereotypeComboBox->addItems(m_propertiesView->stereotypeController()->knownStereotypes(m_stereotypeElement)); connect(m_stereotypeComboBox->lineEdit(), &QLineEdit::textEdited, this, &PropertiesView::MView::onStereotypesChanged); - connect(m_stereotypeComboBox, static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::activated), + connect(m_stereotypeComboBox, QOverload<const QString &>::of(&QComboBox::activated), this, &PropertiesView::MView::onStereotypesChanged); } if (!m_stereotypeComboBox->hasFocus()) { @@ -580,7 +580,7 @@ void PropertiesView::MView::visitMDependency(const MDependency *dependency) m_directionSelector = new QComboBox(m_topWidget); m_directionSelector->addItems(QStringList({ "->", "<-", "<->" })); addRow(tr("Direction:"), m_directionSelector, "direction"); - connect(m_directionSelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), + connect(m_directionSelector, QOverload<int>::of(&QComboBox::activated), this, &PropertiesView::MView::onDependencyDirectionChanged); } if (isSingleSelection) { @@ -664,7 +664,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association) m_endAKind = new QComboBox(m_topWidget); m_endAKind->addItems({ tr("Association"), tr("Aggregation"), tr("Composition") }); addRow(tr("Relationship:"), m_endAKind, "relationship a"); - connect(m_endAKind, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), + connect(m_endAKind, QOverload<int>::of(&QComboBox::activated), this, &PropertiesView::MView::onAssociationEndAKindChanged); } if (isSingleSelection) { @@ -729,7 +729,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association) m_endBKind = new QComboBox(m_topWidget); m_endBKind->addItems({ tr("Association"), tr("Aggregation"), tr("Composition") }); addRow(tr("Relationship:"), m_endBKind, "relationship b"); - connect(m_endBKind, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), + connect(m_endBKind, QOverload<int>::of(&QComboBox::activated), this, &PropertiesView::MView::onAssociationEndBKindChanged); } if (isSingleSelection) { @@ -930,7 +930,7 @@ void PropertiesView::MView::visitDObject(const DObject *object) m_visualSecondaryRoleSelector->addItems({ tr("Normal"), tr("Lighter"), tr("Darker"), tr("Soften"), tr("Outline"), tr("Flat") }); addRow(tr("Role:"), m_visualSecondaryRoleSelector, "role"); - connect(m_visualSecondaryRoleSelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), + connect(m_visualSecondaryRoleSelector, QOverload<int>::of(&QComboBox::activated), this, &PropertiesView::MView::onVisualSecondaryRoleChanged); } if (!m_visualSecondaryRoleSelector->hasFocus()) { @@ -958,7 +958,7 @@ void PropertiesView::MView::visitDObject(const DObject *object) m_stereotypeDisplaySelector->addItems({ tr("Smart"), tr("None"), tr("Label"), tr("Decoration"), tr("Icon") }); addRow(tr("Stereotype display:"), m_stereotypeDisplaySelector, "stereotype display"); - connect(m_stereotypeDisplaySelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), + connect(m_stereotypeDisplaySelector, QOverload<int>::of(&QComboBox::activated), this, &PropertiesView::MView::onStereotypeDisplayChanged); } if (!m_stereotypeDisplaySelector->hasFocus()) { @@ -995,7 +995,7 @@ void PropertiesView::MView::visitDClass(const DClass *klass) m_templateDisplaySelector = new QComboBox(m_topWidget); m_templateDisplaySelector->addItems({ tr("Smart"), tr("Box"), tr("Angle Brackets") }); addRow(tr("Template display:"), m_templateDisplaySelector, "template display"); - connect(m_templateDisplaySelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), + connect(m_templateDisplaySelector, QOverload<int>::of(&QComboBox::activated), this, &PropertiesView::MView::onTemplateDisplayChanged); } if (!m_templateDisplaySelector->hasFocus()) { @@ -1126,7 +1126,7 @@ void PropertiesView::MView::visitDAnnotation(const DAnnotation *annotation) tr("Subtitle"), tr("Emphasized"), tr("Soften"), tr("Footnote") })); addRow(tr("Role:"), m_annotationVisualRoleSelector, "visual role"); - connect(m_annotationVisualRoleSelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), + connect(m_annotationVisualRoleSelector, QOverload<int>::of(&QComboBox::activated), this, &PropertiesView::MView::onAnnotationVisualRoleChanged); } if (!m_annotationVisualRoleSelector->hasFocus()) { diff --git a/src/libs/qmldebug/CMakeLists.txt b/src/libs/qmldebug/CMakeLists.txt new file mode 100644 index 0000000000..cdc4c36fb4 --- /dev/null +++ b/src/libs/qmldebug/CMakeLists.txt @@ -0,0 +1,18 @@ +add_qtc_library(QmlDebug + DEPENDS Qt5::Network Utils + SOURCES + baseenginedebugclient.cpp baseenginedebugclient.h + basetoolsclient.cpp basetoolsclient.h + qdebugmessageclient.cpp qdebugmessageclient.h + qmldebug_global.h + qmldebugclient.cpp qmldebugclient.h + qmldebugcommandlinearguments.h + qmldebugconnection.cpp qmldebugconnection.h + qmldebugconnectionmanager.cpp qmldebugconnectionmanager.h + qmldebugconstants.h + qmlenginecontrolclient.cpp qmlenginecontrolclient.h + qmlenginedebugclient.h + qmloutputparser.cpp qmloutputparser.h + qmltoolsclient.cpp qmltoolsclient.h + qpacketprotocol.cpp qpacketprotocol.h +) diff --git a/src/libs/qmldebug/baseenginedebugclient.cpp b/src/libs/qmldebug/baseenginedebugclient.cpp index 86f54741fc..45cf7590c9 100644 --- a/src/libs/qmldebug/baseenginedebugclient.cpp +++ b/src/libs/qmldebug/baseenginedebugclient.cpp @@ -121,7 +121,7 @@ void BaseEngineDebugClient::decode(QDataStream &ds, { ObjectReference obj; obj.m_debugId = prop.m_value.toInt(); - prop.m_value = qVariantFromValue(obj); + prop.m_value = QVariant::fromValue(obj); break; } case QmlObjectProperty::Unknown: diff --git a/src/libs/qmldebug/qmldebugcommandlinearguments.h b/src/libs/qmldebug/qmldebugcommandlinearguments.h index 0e265c27cc..0c9979647a 100644 --- a/src/libs/qmldebug/qmldebugcommandlinearguments.h +++ b/src/libs/qmldebug/qmldebugcommandlinearguments.h @@ -39,7 +39,7 @@ enum QmlDebugServicesPreset { QmlPreviewServices }; -static inline QString qmlDebugServices(QmlDebugServicesPreset preset) +inline QString qmlDebugServices(QmlDebugServicesPreset preset) { switch (preset) { case NoQmlDebugServices: @@ -58,7 +58,7 @@ static inline QString qmlDebugServices(QmlDebugServicesPreset preset) } } -static inline QString qmlDebugCommandLineArguments(QmlDebugServicesPreset services, +inline QString qmlDebugCommandLineArguments(QmlDebugServicesPreset services, const QString &connectionMode, bool block) { if (services == NoQmlDebugServices) @@ -68,19 +68,19 @@ static inline QString qmlDebugCommandLineArguments(QmlDebugServicesPreset servic .arg(QLatin1String(block ? ",block" : "")).arg(qmlDebugServices(services)); } -static inline QString qmlDebugTcpArguments(QmlDebugServicesPreset services, - Utils::Port port, bool block = true) +inline QString qmlDebugTcpArguments(QmlDebugServicesPreset services, + Utils::Port port, bool block = true) { return qmlDebugCommandLineArguments(services, QString("port:%1").arg(port.number()), block); } -static inline QString qmlDebugNativeArguments(QmlDebugServicesPreset services, bool block = true) +inline QString qmlDebugNativeArguments(QmlDebugServicesPreset services, bool block = true) { return qmlDebugCommandLineArguments(services, QLatin1String("native"), block); } -static inline QString qmlDebugLocalArguments(QmlDebugServicesPreset services, const QString &socket, - bool block = true) +inline QString qmlDebugLocalArguments(QmlDebugServicesPreset services, const QString &socket, + bool block = true) { return qmlDebugCommandLineArguments(services, QLatin1String("file:") + socket, block); } diff --git a/src/libs/qmldebug/qmldebugconnection.cpp b/src/libs/qmldebug/qmldebugconnection.cpp index 6664df2b99..143277b379 100644 --- a/src/libs/qmldebug/qmldebugconnection.cpp +++ b/src/libs/qmldebug/qmldebugconnection.cpp @@ -45,17 +45,16 @@ const QString clientId = QLatin1String("QDeclarativeDebugClient"); class QmlDebugConnectionPrivate { public: - QmlDebugConnectionPrivate(); - QPacketProtocol *protocol; - QLocalServer *server; - QIODevice *device; // Currently a QTcpSocket or a QLocalSocket + QPacketProtocol *protocol = nullptr; + QLocalServer *server = nullptr; + QIODevice *device = nullptr; // Currently a QTcpSocket or a QLocalSocket - bool gotHello; + bool gotHello = false; QHash <QString, float> serverPlugins; QHash<QString, QmlDebugClient *> plugins; - int currentDataStreamVersion; - int maximumDataStreamVersion; + int currentDataStreamVersion = QmlDebugConnection::minimumDataStreamVersion(); + int maximumDataStreamVersion = QDataStream::Qt_DefaultCompiledVersion; void advertisePlugins(); void flush(); @@ -75,13 +74,6 @@ static QString socketErrorToString(QAbstractSocket::SocketError error) return QmlDebugConnection::tr("Error: %1").arg(errorString); } -QmlDebugConnectionPrivate::QmlDebugConnectionPrivate() : - protocol(0), server(0), device(0), gotHello(false), - currentDataStreamVersion(QmlDebugConnection::minimumDataStreamVersion()), - maximumDataStreamVersion(QDataStream::Qt_DefaultCompiledVersion) -{ -} - void QmlDebugConnectionPrivate::advertisePlugins() { if (!gotHello) @@ -118,7 +110,7 @@ void QmlDebugConnection::socketDisconnected() if (d->protocol) { d->protocol->disconnect(); d->protocol->deleteLater(); - d->protocol = 0; + d->protocol = nullptr; } if (d->device) { // Don't allow any "connected()" or "disconnected()" signals to be triggered anymore. @@ -126,7 +118,7 @@ void QmlDebugConnection::socketDisconnected() d->device->disconnect(); // Don't immediately delete it as it may do some cleanup on returning from a signal. d->device->deleteLater(); - d->device = 0; + d->device = nullptr; } } @@ -220,7 +212,7 @@ void QmlDebugConnection::protocolReadyRead() QHash<QString, QmlDebugClient *>::Iterator iter = d->plugins.begin(); for (; iter != d->plugins.end(); ++iter) { - const QString pluginName = iter.key(); + const QString &pluginName = iter.key(); QmlDebugClient::State newState = QmlDebugClient::Unavailable; if (d->serverPlugins.contains(pluginName)) newState = QmlDebugClient::Enabled; @@ -282,7 +274,7 @@ void QmlDebugConnection::close() QmlDebugClient *QmlDebugConnection::client(const QString &name) const { Q_D(const QmlDebugConnection); - return d->plugins.value(name, 0); + return d->plugins.value(name, nullptr); } bool QmlDebugConnection::addClient(const QString &name, QmlDebugClient *client) @@ -324,16 +316,11 @@ bool QmlDebugConnection::sendMessage(const QString &name, const QByteArray &mess return true; } -int QmlDebugConnection::minimumDataStreamVersion() -{ - return QDataStream::Qt_4_7; -} - void QmlDebugConnectionPrivate::flush() { - if (QAbstractSocket *socket = qobject_cast<QAbstractSocket *>(device)) + if (auto socket = qobject_cast<QAbstractSocket *>(device)) socket->flush(); - else if (QLocalSocket *socket = qobject_cast<QLocalSocket *>(device)) + else if (auto socket = qobject_cast<QLocalSocket *>(device)) socket->flush(); } @@ -341,7 +328,7 @@ void QmlDebugConnection::connectToHost(const QString &hostName, quint16 port) { Q_D(QmlDebugConnection); socketDisconnected(); - QTcpSocket *socket = new QTcpSocket(this); + auto socket = new QTcpSocket(this); socket->setProxy(QNetworkProxy::NoProxy); d->device = socket; d->protocol = new QPacketProtocol(socket, this); @@ -352,8 +339,8 @@ void QmlDebugConnection::connectToHost(const QString &hostName, quint16 port) emit logStateChange(socketStateToString(state)); }); - connect(socket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)> - (&QAbstractSocket::error), this, [this](QAbstractSocket::SocketError error) { + connect(socket, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error), + this, [this](QAbstractSocket::SocketError error) { emit logError(socketErrorToString(error)); socketDisconnected(); }); @@ -391,8 +378,8 @@ void QmlDebugConnection::newConnection() connect(socket, &QLocalSocket::disconnected, this, &QmlDebugConnection::socketDisconnected); - connect(socket, static_cast<void (QLocalSocket::*)(QLocalSocket::LocalSocketError)> - (&QLocalSocket::error), this, [this](QLocalSocket::LocalSocketError error) { + connect(socket, QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error), + this, [this](QLocalSocket::LocalSocketError error) { emit logError(socketErrorToString(static_cast<QAbstractSocket::SocketError>(error))); socketDisconnected(); }); @@ -420,12 +407,11 @@ void QmlDebugConnection::setMaximumDataStreamVersion(int maximumVersion) QAbstractSocket::SocketState QmlDebugConnection::socketState() const { Q_D(const QmlDebugConnection); - if (QAbstractSocket *socket = qobject_cast<QAbstractSocket *>(d->device)) + if (auto socket = qobject_cast<QAbstractSocket *>(d->device)) return socket->state(); - else if (QLocalSocket *socket = qobject_cast<QLocalSocket *>(d->device)) + if (auto socket = qobject_cast<QLocalSocket *>(d->device)) return static_cast<QAbstractSocket::SocketState>(socket->state()); - else - return QAbstractSocket::UnconnectedState; + return QAbstractSocket::UnconnectedState; } } // namespace QmlDebug diff --git a/src/libs/qmldebug/qmldebugconnection.h b/src/libs/qmldebug/qmldebugconnection.h index 6fe2e35a16..6ca73a1f3c 100644 --- a/src/libs/qmldebug/qmldebugconnection.h +++ b/src/libs/qmldebug/qmldebugconnection.h @@ -30,6 +30,7 @@ #include <QObject> #include <QUrl> #include <QAbstractSocket> +#include <QDataStream> namespace QmlDebug { @@ -38,10 +39,9 @@ class QmlDebugConnectionPrivate; class QMLDEBUG_EXPORT QmlDebugConnection : public QObject { Q_OBJECT - Q_DISABLE_COPY(QmlDebugConnection) Q_DECLARE_PRIVATE(QmlDebugConnection) public: - QmlDebugConnection(QObject * = 0); + QmlDebugConnection(QObject *parent = nullptr); ~QmlDebugConnection() override; void connectToHost(const QString &hostName, quint16 port); @@ -62,7 +62,10 @@ public: float serviceVersion(const QString &serviceName) const; bool sendMessage(const QString &name, const QByteArray &message); - static int minimumDataStreamVersion(); + static constexpr int minimumDataStreamVersion() + { + return QDataStream::Qt_4_7; + } signals: void connected(); diff --git a/src/libs/qmleditorwidgets/CMakeLists.txt b/src/libs/qmleditorwidgets/CMakeLists.txt new file mode 100644 index 0000000000..b235601754 --- /dev/null +++ b/src/libs/qmleditorwidgets/CMakeLists.txt @@ -0,0 +1,22 @@ +add_qtc_library(QmlEditorWidgets + DEPENDS qmljs Utils Qt5::Widgets + SOURCES + colorbox.cpp colorbox.h + colorbutton.cpp colorbutton.h + contextpanetext.ui + contextpanetextwidget.cpp contextpanetextwidget.h + contextpanewidget.cpp contextpanewidget.h + contextpanewidgetborderimage.ui + contextpanewidgetimage.cpp contextpanewidgetimage.h contextpanewidgetimage.ui + contextpanewidgetrectangle.cpp contextpanewidgetrectangle.h contextpanewidgetrectangle.ui + customcolordialog.cpp customcolordialog.h + easingpane/easingcontextpane.cpp easingpane/easingcontextpane.h easingpane/easingcontextpane.ui + easingpane/easinggraph.cpp easingpane/easinggraph.h + easingpane/easingpane.qrc + filewidget.cpp filewidget.h + fontsizespinbox.cpp fontsizespinbox.h + gradientline.cpp gradientline.h + huecontrol.cpp huecontrol.h + qmleditorwidgets_global.h + resources.qrc +) diff --git a/src/libs/qmleditorwidgets/colorbox.cpp b/src/libs/qmleditorwidgets/colorbox.cpp index ad8109c27d..b0da2642e2 100644 --- a/src/libs/qmleditorwidgets/colorbox.cpp +++ b/src/libs/qmleditorwidgets/colorbox.cpp @@ -29,12 +29,10 @@ static inline QString properName(const QColor &color) { - QString s; if (color.alpha() == 255) - s.sprintf("#%02x%02x%02x", color.red(), color.green(), color.blue()); + return QString::asprintf("#%02x%02x%02x", color.red(), color.green(), color.blue()); else - s.sprintf("#%02x%02x%02x%02x", color.alpha(), color.red(), color.green(), color.blue()); - return s; + return QString::asprintf("#%02x%02x%02x%02x", color.alpha(), color.red(), color.green(), color.blue()); } static inline QColor properColor(const QString &str) diff --git a/src/libs/qmleditorwidgets/contextpanetextwidget.cpp b/src/libs/qmleditorwidgets/contextpanetextwidget.cpp index bba9bf4d95..70b6c700db 100644 --- a/src/libs/qmleditorwidgets/contextpanetextwidget.cpp +++ b/src/libs/qmleditorwidgets/contextpanetextwidget.cpp @@ -73,8 +73,7 @@ ContextPaneTextWidget::ContextPaneTextWidget(QWidget *parent) : connect(parentContextWidget->colorDialog(), &CustomColorDialog::rejected, this, &ContextPaneTextWidget::onColorDialogCancled); - connect(ui->fontSizeSpinBox, - static_cast<void (QmlEditorWidgets::FontSizeSpinBox::*)(int)>(&QmlEditorWidgets::FontSizeSpinBox::valueChanged), + connect(ui->fontSizeSpinBox, QOverload<int>::of(&QmlEditorWidgets::FontSizeSpinBox::valueChanged), this, &ContextPaneTextWidget::onFontSizeChanged); connect(ui->fontSizeSpinBox, &QmlEditorWidgets::FontSizeSpinBox::formatChanged, this, &ContextPaneTextWidget::onFontFormatChanged); @@ -104,7 +103,7 @@ ContextPaneTextWidget::ContextPaneTextWidget(QWidget *parent) : connect(ui->bottomAlignmentButton, &QToolButton::toggled, this, &ContextPaneTextWidget::onVerticalAlignmentChanged); - connect(ui->styleComboBox, static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentIndexChanged), + connect(ui->styleComboBox, QOverload<const QString &>::of(&QComboBox::currentIndexChanged), this, &ContextPaneTextWidget::onStyleComboBoxChanged); } diff --git a/src/libs/qmleditorwidgets/customcolordialog.cpp b/src/libs/qmleditorwidgets/customcolordialog.cpp index a99410467f..de603e0ea9 100644 --- a/src/libs/qmleditorwidgets/customcolordialog.cpp +++ b/src/libs/qmleditorwidgets/customcolordialog.cpp @@ -113,17 +113,13 @@ CustomColorDialog::CustomColorDialog(QWidget *parent) : QFrame(parent ) resize(sizeHint()); connect(m_colorBox, &ColorBox::colorChanged, this, &CustomColorDialog::onColorBoxChanged); - connect(m_alphaSpinBox, - static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), + connect(m_alphaSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &CustomColorDialog::spinBoxChanged); - connect(m_rSpinBox, - static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), + connect(m_rSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &CustomColorDialog::spinBoxChanged); - connect(m_gSpinBox, - static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), + connect(m_gSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &CustomColorDialog::spinBoxChanged); - connect(m_bSpinBox, - static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), + connect(m_bSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &CustomColorDialog::spinBoxChanged); connect(m_hueControl, &HueControl::hueChanged, this, &CustomColorDialog::onHueChanged); diff --git a/src/libs/qmljs/CMakeLists.txt b/src/libs/qmljs/CMakeLists.txt new file mode 100644 index 0000000000..6a4ef362bc --- /dev/null +++ b/src/libs/qmljs/CMakeLists.txt @@ -0,0 +1,53 @@ +add_qtc_library(qmljs + DEPENDS ExtensionSystem Utils + PUBLIC_DEPENDS CPlusPlus Qt5::Widgets Qt5::Xml LanguageUtils + SOURCES + jsoncheck.cpp jsoncheck.h + parser/qmldirparser.cpp parser/qmldirparser_p.h + parser/qmlerror.cpp parser/qmlerror.h + parser/qmljsast.cpp parser/qmljsast_p.h + parser/qmljsastfwd_p.h + parser/qmljsastvisitor.cpp parser/qmljsastvisitor_p.h + parser/qmljsengine_p.cpp parser/qmljsengine_p.h + parser/qmljsglobal_p.h + parser/qmljsgrammar.cpp parser/qmljsgrammar_p.h + parser/qmljskeywords_p.h + parser/qmljslexer.cpp parser/qmljslexer_p.h + parser/qmljsmemorypool_p.h + parser/qmljsparser.cpp parser/qmljsparser_p.h + persistenttrie.cpp persistenttrie.h + qmljs_global.h + qmljsbind.cpp qmljsbind.h + qmljsbundle.cpp qmljsbundle.h + qmljscheck.cpp qmljscheck.h + qmljscodeformatter.cpp qmljscodeformatter.h + qmljscompletioncontextfinder.cpp qmljscompletioncontextfinder.h + qmljsconstants.h + qmljscontext.cpp qmljscontext.h + qmljsdialect.cpp qmljsdialect.h + qmljsdocument.cpp qmljsdocument.h + qmljsevaluate.cpp qmljsevaluate.h + qmljsfindexportedcpptypes.cpp qmljsfindexportedcpptypes.h + qmljsicons.cpp qmljsicons.h + qmljsicontextpane.h + qmljsimportdependencies.cpp qmljsimportdependencies.h + qmljsindenter.cpp qmljsindenter.h + qmljsinterpreter.cpp qmljsinterpreter.h + qmljslineinfo.cpp qmljslineinfo.h + qmljslink.cpp qmljslink.h + qmljsmodelmanagerinterface.cpp qmljsmodelmanagerinterface.h + qmljsplugindumper.cpp qmljsplugindumper.h + qmljspropertyreader.cpp qmljspropertyreader.h + qmljsreformatter.cpp qmljsreformatter.h + qmljsrewriter.cpp qmljsrewriter.h + qmljsscanner.cpp qmljsscanner.h + qmljsscopeastpath.cpp qmljsscopeastpath.h + qmljsscopebuilder.cpp qmljsscopebuilder.h + qmljsscopechain.cpp qmljsscopechain.h + qmljssimplereader.cpp qmljssimplereader.h + qmljsstaticanalysismessage.cpp qmljsstaticanalysismessage.h + qmljstypedescriptionreader.cpp qmljstypedescriptionreader.h + qmljsutils.cpp qmljsutils.h + qmljsvalueowner.cpp qmljsvalueowner.h + qmljsviewercontext.cpp qmljsviewercontext.h +) diff --git a/src/libs/qmljs/parser/qmljslexer.cpp b/src/libs/qmljs/parser/qmljslexer.cpp index 19d367be1b..ab7a33917e 100644 --- a/src/libs/qmljs/parser/qmljslexer.cpp +++ b/src/libs/qmljs/parser/qmljslexer.cpp @@ -116,6 +116,7 @@ void Lexer::setCode(const QString &code, int lineno, bool qmlMode) _tokenText.reserve(1024); _errorMessage.clear(); _tokenSpell = QStringRef(); + _rawString = QStringRef(); _codePtr = code.unicode(); _endPtr = _codePtr + code.length(); @@ -149,13 +150,20 @@ void Lexer::setCode(const QString &code, int lineno, bool qmlMode) void Lexer::scanChar() { - unsigned sequenceLength = isLineTerminatorSequence(); + if (_skipLinefeed) { + Q_ASSERT(*_codePtr == QLatin1Char('\n')); + ++_codePtr; + _skipLinefeed = false; + } _char = *_codePtr++; - if (sequenceLength == 2) - _char = *_codePtr++; - ++_currentColumnNumber; + if (isLineTerminator()) { + if (_char == QLatin1Char('\r')) { + if (_codePtr < _endPtr && *_codePtr == QLatin1Char('\n')) + _skipLinefeed = true; + _char = QLatin1Char('\n'); + } ++_currentLineNumber; _currentColumnNumber = 0; } @@ -232,6 +240,7 @@ int Lexer::lex() again: _tokenSpell = QStringRef(); + _rawString = QStringRef(); _tokenKind = scanToken(); _tokenLength = _codePtr - _tokenStartPtr - 1; @@ -807,12 +816,15 @@ int Lexer::scanString(ScanStringMode mode) QChar quote = (mode == TemplateContinuation) ? QChar(TemplateHead) : QChar(mode); bool multilineStringLiteral = false; - const QChar *startCode = _codePtr; + const QChar *startCode = _codePtr - 1; + // in case we just parsed a \r, we need to reset this flag to get things working + // correctly in the loop below and afterwards + _skipLinefeed = false; if (_engine) { while (_codePtr <= _endPtr) { - if (isLineTerminator() && quote != QLatin1Char('`')) { - if (qmlMode()) + if (isLineTerminator()) { + if ((quote == QLatin1Char('`') || qmlMode())) break; _errorCode = IllegalCharacter; _errorMessage = QCoreApplication::translate("QmlParser", "Stray newline in string literal"); @@ -822,7 +834,8 @@ int Lexer::scanString(ScanStringMode mode) } else if (_char == '$' && quote == QLatin1Char('`')) { break; } else if (_char == quote) { - _tokenSpell = _engine->midRef(startCode - _code.unicode() - 1, _codePtr - startCode); + _tokenSpell = _engine->midRef(startCode - _code.unicode(), _codePtr - startCode - 1); + _rawString = _tokenSpell; scanChar(); if (quote == QLatin1Char('`')) @@ -835,28 +848,36 @@ int Lexer::scanString(ScanStringMode mode) else return T_STRING_LITERAL; } - scanChar(); + // don't use scanChar() here, that would transform \r sequences and the midRef() call would create the wrong result + _char = *_codePtr++; + ++_currentColumnNumber; } } + // rewind by one char, so things gets scanned correctly + --_codePtr; + _validTokenText = true; - _tokenText.resize(0); - startCode--; - while (startCode != _codePtr - 1) - _tokenText += *startCode++; + _tokenText = QString(startCode, _codePtr - startCode); + + auto setRawString = [&](const QChar *end) { + QString raw(startCode, end - startCode - 1); + raw.replace(QLatin1String("\r\n"), QLatin1String("\n")); + raw.replace(QLatin1Char('\r'), QLatin1Char('\n')); + _rawString = _engine->newStringRef(raw); + }; + + scanChar(); while (_codePtr <= _endPtr) { - if (unsigned sequenceLength = isLineTerminatorSequence()) { - multilineStringLiteral = true; - _tokenText += _char; - if (sequenceLength == 2) - _tokenText += *_codePtr; - scanChar(); - } else if (_char == mode) { + if (_char == quote) { scanChar(); - if (_engine) + if (_engine) { _tokenSpell = _engine->newStringRef(_tokenText); + if (quote == QLatin1Char('`')) + setRawString(_codePtr - 1); + } if (quote == QLatin1Char('`')) _bracesCount = _outerTemplateBraceCount.pop(); @@ -871,8 +892,10 @@ int Lexer::scanString(ScanStringMode mode) scanChar(); scanChar(); _bracesCount = 1; - if (_engine) + if (_engine) { _tokenSpell = _engine->newStringRef(_tokenText); + setRawString(_codePtr - 2); + } return (mode == TemplateHead ? T_TEMPLATE_HEAD : T_TEMPLATE_MIDDLE); } else if (_char == QLatin1Char('\\')) { diff --git a/src/libs/qmljs/parser/qmljslexer_p.h b/src/libs/qmljs/parser/qmljslexer_p.h index 39128b4409..5773606c39 100644 --- a/src/libs/qmljs/parser/qmljslexer_p.h +++ b/src/libs/qmljs/parser/qmljslexer_p.h @@ -146,6 +146,7 @@ public: int tokenStartColumn() const { return _tokenColumn; } inline QStringRef tokenSpell() const { return _tokenSpell; } + inline QStringRef rawString() const { return _rawString; } double tokenValue() const { return _tokenValue; } QString tokenText() const; @@ -198,6 +199,7 @@ private: QString _tokenText; QString _errorMessage; QStringRef _tokenSpell; + QStringRef _rawString; const QChar *_codePtr; const QChar *_endPtr; @@ -233,6 +235,7 @@ private: bool _followsClosingBrace; bool _delimited; bool _qmlMode; + bool _skipLinefeed = false; int _generatorLevel = 0; bool _staticIsKeyword = false; }; diff --git a/src/libs/qmljs/persistenttrie.cpp b/src/libs/qmljs/persistenttrie.cpp index f3be5a48ca..08c17dd164 100644 --- a/src/libs/qmljs/persistenttrie.cpp +++ b/src/libs/qmljs/persistenttrie.cpp @@ -545,7 +545,6 @@ QDebug &operator<<(QDebug &dbg, const Trie &trie) } Trie::Trie() {} Trie::Trie(const TrieNode::Ptr &trie) : trie(trie) {} -Trie::Trie(const Trie &o) : trie(o.trie){} QStringList Trie::complete(const QString &root, const QString &base, LookupFlags flags) const diff --git a/src/libs/qmljs/persistenttrie.h b/src/libs/qmljs/persistenttrie.h index 35ab652967..184525b13e 100644 --- a/src/libs/qmljs/persistenttrie.h +++ b/src/libs/qmljs/persistenttrie.h @@ -79,7 +79,6 @@ class QMLJS_EXPORT Trie public: Trie(); Trie(const TrieNode::Ptr &t); - Trie(const Trie &o); QStringList complete(const QString &root, const QString &base = QString(), LookupFlags flags = LookupFlags(CaseInsensitive|Partial)) const; diff --git a/src/libs/qmljs/qmljs-lib.pri b/src/libs/qmljs/qmljs-lib.pri index 2aa95a9f7a..47967446bf 100644 --- a/src/libs/qmljs/qmljs-lib.pri +++ b/src/libs/qmljs/qmljs-lib.pri @@ -36,7 +36,6 @@ HEADERS += \ $$PWD/jsoncheck.h \ $$PWD/qmljssimplereader.h \ $$PWD/persistenttrie.h \ - $$PWD/qmljsqrcparser.h \ $$PWD/qmljsconstants.h \ $$PWD/qmljsimportdependencies.h \ $$PWD/qmljsviewercontext.h \ @@ -70,7 +69,6 @@ SOURCES += \ $$PWD/jsoncheck.cpp \ $$PWD/qmljssimplereader.cpp \ $$PWD/persistenttrie.cpp \ - $$PWD/qmljsqrcparser.cpp \ $$PWD/qmljsimportdependencies.cpp \ $$PWD/qmljsviewercontext.cpp \ $$PWD/qmljsdialect.cpp diff --git a/src/libs/qmljs/qmljs.qbs b/src/libs/qmljs/qmljs.qbs index ddfb4c200e..a2580cab1e 100644 --- a/src/libs/qmljs/qmljs.qbs +++ b/src/libs/qmljs/qmljs.qbs @@ -42,7 +42,6 @@ Project { "qmljsmodelmanagerinterface.cpp", "qmljsmodelmanagerinterface.h", "qmljsplugindumper.cpp", "qmljsplugindumper.h", "qmljspropertyreader.cpp", "qmljspropertyreader.h", - "qmljsqrcparser.cpp", "qmljsqrcparser.h", "qmljsreformatter.cpp", "qmljsreformatter.h", "qmljsrewriter.cpp", "qmljsrewriter.h", "qmljsscanner.cpp", "qmljsscanner.h", diff --git a/src/libs/qmljs/qmljsbundle.cpp b/src/libs/qmljs/qmljsbundle.cpp index ec46379f2c..9789d37492 100644 --- a/src/libs/qmljs/qmljsbundle.cpp +++ b/src/libs/qmljs/qmljsbundle.cpp @@ -35,11 +35,6 @@ namespace QmlJS { typedef PersistentTrie::Trie Trie; -QmlBundle::QmlBundle(const QmlBundle &o) - : m_name(o.m_name), m_searchPaths(o.searchPaths()), m_installPaths(o.installPaths()), - m_supportedImports(o.m_supportedImports), m_implicitImports(o.m_implicitImports) -{ } - QmlBundle::QmlBundle() { } diff --git a/src/libs/qmljs/qmljsbundle.h b/src/libs/qmljs/qmljsbundle.h index 0bf00ab755..8057abc6d7 100644 --- a/src/libs/qmljs/qmljsbundle.h +++ b/src/libs/qmljs/qmljsbundle.h @@ -51,7 +51,6 @@ class QMLJS_EXPORT QmlBundle { typedef PersistentTrie::Trie Trie; public: - QmlBundle(const QmlBundle &o); QmlBundle(); QmlBundle(const QString &name, const Trie &searchPaths, diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp index ea43a4dec8..e5243830cd 100644 --- a/src/libs/qmljs/qmljscheck.cpp +++ b/src/libs/qmljs/qmljscheck.cpp @@ -384,6 +384,7 @@ protected: _possiblyUndeclaredUses.clear(); _seenNonDeclarationStatement = false; _formalParameterNames.clear(); + QTC_ASSERT(_block == 0, _block = 0); } void postVisit(Node *ast) @@ -399,8 +400,11 @@ protected: if (ast->name.isEmpty()) return false; const QString &name = ast->name.toString(); - if (!_declaredFunctions.contains(name) && !_declaredVariables.contains(name)) + if (!_declaredFunctions.contains(name) + && !(_declaredVariables.contains(name) + || _declaredBlockVariables.contains({name, _block}))) { _possiblyUndeclaredUses[name].append(ast->identifierToken); + } return false; } @@ -416,13 +420,26 @@ protected: if (ast->bindingIdentifier.isEmpty() || !ast->isVariableDeclaration()) return true; const QString &name = ast->bindingIdentifier.toString(); - - if (_formalParameterNames.contains(name)) + VariableScope scope = ast->scope; + if (_formalParameterNames.contains(name)) { addMessage(WarnAlreadyFormalParameter, ast->identifierToken, name); - else if (_declaredFunctions.contains(name)) + } else if (_declaredFunctions.contains(name)) { addMessage(WarnAlreadyFunction, ast->identifierToken, name); - else if (_declaredVariables.contains(name)) - addMessage(WarnDuplicateDeclaration, ast->identifierToken, name); + } else if (scope == VariableScope::Let || scope == VariableScope::Const) { + if (_declaredBlockVariables.contains({name, _block})) + addMessage(WarnDuplicateDeclaration, ast->identifierToken, name); + } else if (scope == VariableScope::Var) { + if (_declaredVariables.contains(name)) { + addMessage(WarnDuplicateDeclaration, ast->identifierToken, name); + } else { + for (auto k : _declaredBlockVariables.keys()) { + if (k.first == name) { + addMessage(WarnDuplicateDeclaration, ast->identifierToken, name); + break; + } + } + } + } if (_possiblyUndeclaredUses.contains(name)) { foreach (const SourceLocation &loc, _possiblyUndeclaredUses.value(name)) { @@ -430,7 +447,10 @@ protected: } _possiblyUndeclaredUses.remove(name); } - _declaredVariables[name] = ast; + if (scope == VariableScope::Let || scope == VariableScope::Const) + _declaredBlockVariables[{name, _block}] = ast; + else + _declaredVariables[name] = ast; return true; } @@ -451,7 +471,7 @@ protected: if (_formalParameterNames.contains(name)) addMessage(WarnAlreadyFormalParameter, ast->identifierToken, name); - else if (_declaredVariables.contains(name)) + else if (_declaredVariables.contains(name) || _declaredBlockVariables.contains({name, _block})) addMessage(WarnAlreadyVar, ast->identifierToken, name); else if (_declaredFunctions.contains(name)) addMessage(WarnDuplicateDeclaration, ast->identifierToken, name); @@ -469,6 +489,25 @@ protected: return false; } + bool visit(Block *) override + { + ++_block; + return true; + } + + void endVisit(Block *) override + { + auto it = _declaredBlockVariables.begin(); + auto end = _declaredBlockVariables.end(); + while (it != end) { + if (it.key().second == _block) + it = _declaredBlockVariables.erase(it); + else + ++it; + } + --_block; + } + private: void addMessage(Type type, const SourceLocation &loc, const QString &arg1 = QString()) { @@ -478,9 +517,11 @@ private: QList<Message> _messages; QStringList _formalParameterNames; QHash<QString, PatternElement *> _declaredVariables; + QHash<QPair<QString, uint>, PatternElement *> _declaredBlockVariables; QHash<QString, FunctionDeclaration *> _declaredFunctions; QHash<QString, QList<SourceLocation> > _possiblyUndeclaredUses; bool _seenNonDeclarationStatement; + uint _block = 0; }; class IdsThatShouldNotBeUsedInDesigner : public QStringList @@ -1635,7 +1676,7 @@ bool Check::visit(CallExpression *ast) if (!whiteListedFunction && !isMathFunction && !isDateFunction && !isDirectInConnectionsScope) addMessage(ErrFunctionsNotSupportedInQmlUi, location); - static const QStringList globalFunctions = {"String", "Boolean", "Date", "Number", "Object", "QT_TR_NOOP", "QT_TRANSLATE_NOOP", "QT_TRID_NOOP"}; + static const QStringList globalFunctions = {"String", "Boolean", "Date", "Number", "Object", "Array", "QT_TR_NOOP", "QT_TRANSLATE_NOOP", "QT_TRID_NOOP"}; if (!name.isEmpty() && name.at(0).isUpper() && !globalFunctions.contains(name)) { addMessage(WarnExpectedNewWithUppercaseFunction, location); diff --git a/src/libs/qmljs/qmljsdialect.cpp b/src/libs/qmljs/qmljsdialect.cpp index 0cb463b2e5..cfe71b2265 100644 --- a/src/libs/qmljs/qmljsdialect.cpp +++ b/src/libs/qmljs/qmljsdialect.cpp @@ -30,7 +30,6 @@ namespace QmlJS { - bool Dialect::isQmlLikeLanguage() const { switch (m_dialect) { @@ -233,7 +232,7 @@ QDebug operator << (QDebug &dbg, const Dialect &dialect) return dbg; } -PathAndLanguage::PathAndLanguage(const Utils::FileName &path, Dialect language) +PathAndLanguage::PathAndLanguage(const Utils::FilePath &path, Dialect language) : m_path(path), m_language(language) { } @@ -294,11 +293,11 @@ void PathsAndLanguages::compact() return; int oldCompactionPlace = 0; - Utils::FileName oldPath = m_list.first().path(); + Utils::FilePath oldPath = m_list.first().path(); QList<PathAndLanguage> compactedList; bool restrictFailed = false; for (int i = 1; i < m_list.length(); ++i) { - Utils::FileName newPath = m_list.at(i).path(); + Utils::FilePath newPath = m_list.at(i).path(); if (newPath == oldPath) { int newCompactionPlace = i - 1; compactedList << m_list.mid(oldCompactionPlace, newCompactionPlace - oldCompactionPlace); diff --git a/src/libs/qmljs/qmljsdialect.h b/src/libs/qmljs/qmljsdialect.h index 8d1ca30deb..230642e145 100644 --- a/src/libs/qmljs/qmljsdialect.h +++ b/src/libs/qmljs/qmljsdialect.h @@ -78,11 +78,8 @@ QMLJS_EXPORT QDebug operator << (QDebug &dbg, const Dialect &dialect); class QMLJS_EXPORT PathAndLanguage { public: - PathAndLanguage(const Utils::FileName &path = Utils::FileName(), Dialect language = Dialect::AnyLanguage); - PathAndLanguage(const PathAndLanguage &o) - : m_path(o.path()), m_language(o.language()) - { } - Utils::FileName path() const { + PathAndLanguage(const Utils::FilePath &path = Utils::FilePath(), Dialect language = Dialect::AnyLanguage); + Utils::FilePath path() const { return m_path; } Dialect language() const { @@ -91,7 +88,7 @@ public: bool operator ==(const PathAndLanguage &other) const; bool operator < (const PathAndLanguage &other) const; private: - Utils::FileName m_path; + Utils::FilePath m_path; Dialect m_language; }; @@ -130,11 +127,8 @@ public: explicit PathsAndLanguages(const QList<PathAndLanguage> &list) : m_list(list) { } - PathsAndLanguages(const PathsAndLanguages &o) - : m_list(o.m_list) - { } - bool maybeInsert(const Utils::FileName &path, Dialect language = Dialect::AnyLanguage) { + bool maybeInsert(const Utils::FilePath &path, Dialect language = Dialect::AnyLanguage) { return maybeInsert(PathAndLanguage(path, language)); } diff --git a/src/libs/qmljs/qmljsdocument.cpp b/src/libs/qmljs/qmljsdocument.cpp index a4551b1c1c..6ebe5b0b2f 100644 --- a/src/libs/qmljs/qmljsdocument.cpp +++ b/src/libs/qmljs/qmljsdocument.cpp @@ -458,14 +458,6 @@ Snapshot::~Snapshot() { } -Snapshot::Snapshot(const Snapshot &o) - : _documents(o._documents), - _documentsByPath(o._documentsByPath), - _libraries(o._libraries), - _dependencies(o._dependencies) -{ -} - void Snapshot::insert(const Document::Ptr &document, bool allowInvalid) { if (document && (allowInvalid || document->qmlProgram() || document->jsProgram())) { diff --git a/src/libs/qmljs/qmljsdocument.h b/src/libs/qmljs/qmljsdocument.h index 4029373992..82df720776 100644 --- a/src/libs/qmljs/qmljsdocument.h +++ b/src/libs/qmljs/qmljsdocument.h @@ -230,7 +230,6 @@ class QMLJS_EXPORT Snapshot public: Snapshot(); - Snapshot(const Snapshot &o); ~Snapshot(); typedef Base::iterator iterator; diff --git a/src/libs/qmljs/qmljsimportdependencies.cpp b/src/libs/qmljs/qmljsimportdependencies.cpp index adc9c9ff57..afa8d58b3a 100644 --- a/src/libs/qmljs/qmljsimportdependencies.cpp +++ b/src/libs/qmljs/qmljsimportdependencies.cpp @@ -25,9 +25,9 @@ #include "qmljsimportdependencies.h" #include "qmljsinterpreter.h" -#include "qmljsqrcparser.h" #include "qmljsviewercontext.h" +#include <utils/qrcparser.h> #include <utils/qtcassert.h> #include <QCryptographicHash> @@ -139,10 +139,10 @@ ImportKey::ImportKey(ImportType::Enum type, const QString &path, int majorVersio break; case ImportType::File: case ImportType::QrcFile: - splitPath = QrcParser::normalizedQrcFilePath(path).split(QLatin1Char('/')); + splitPath = Utils::QrcParser::normalizedQrcFilePath(path).split(QLatin1Char('/')); break; case ImportType::QrcDirectory: - splitPath = QrcParser::normalizedQrcDirectoryPath(path).split(QLatin1Char('/')); + splitPath = Utils::QrcParser::normalizedQrcDirectoryPath(path).split(QLatin1Char('/')); if (splitPath.length() > 1 && splitPath.last().isEmpty()) splitPath.removeLast(); break; diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp index 03083501b6..91f195f8fc 100644 --- a/src/libs/qmljs/qmljsinterpreter.cpp +++ b/src/libs/qmljs/qmljsinterpreter.cpp @@ -2340,6 +2340,16 @@ Import::Import(const Import &other) valid(other.valid), used(false) { } +Import &Import::operator=(const Import &other) +{ + object = other.object; + info = other.info; + libraryPath = other.libraryPath; + valid = other.valid; + used = false; + return *this; +} + TypeScope::TypeScope(const Imports *imports, ValueOwner *valueOwner) : ObjectValue(valueOwner) , m_imports(imports) diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h index 9da1aa8635..f2e953180c 100644 --- a/src/libs/qmljs/qmljsinterpreter.h +++ b/src/libs/qmljs/qmljsinterpreter.h @@ -1038,6 +1038,7 @@ class QMLJS_EXPORT Import { public: Import(); Import(const Import &other); + Import &operator=(const Import &other); // const! ObjectValue *object; diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp index 737ec6cc46..1acdb68ed9 100644 --- a/src/libs/qmljs/qmljslink.cpp +++ b/src/libs/qmljs/qmljslink.cpp @@ -30,9 +30,10 @@ #include "qmljsbind.h" #include "qmljsutils.h" #include "qmljsmodelmanagerinterface.h" -#include "qmljsqrcparser.h" #include "qmljsconstants.h" +#include <utils/qrcparser.h> + #include <QDir> using namespace LanguageUtils; @@ -557,7 +558,7 @@ void LinkPrivate::loadImplicitDirectoryImports(Imports *imports, Document::Ptr d foreach (const QString &path, ModelManagerInterface::instance()->qrcPathsForFile(doc->fileName())) { processImport(ImportInfo::qrcDirectoryImport( - QrcParser::qrcDirectoryPathForQrcFilePath(path))); + Utils::QrcParser::qrcDirectoryPathForQrcFilePath(path))); } } diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp index 82d4da3f4a..6bb1bc8ff9 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp @@ -52,6 +52,8 @@ #include <stdio.h> +using namespace Utils; + namespace QmlJS { QMLJS_EXPORT Q_LOGGING_CATEGORY(qmljsLog, "qtc.qmljs.common", QtWarningMsg) @@ -1098,14 +1100,14 @@ void ModelManagerInterface::updateImportPaths() PathAndLanguage pAndL = iPaths.at(i); const QString canonicalPath = pAndL.path().toFileInfo().canonicalFilePath(); if (!canonicalPath.isEmpty()) - allImportPaths.maybeInsert(Utils::FileName::fromString(canonicalPath), + allImportPaths.maybeInsert(Utils::FilePath::fromString(canonicalPath), pAndL.language()); } } while (vCtxsIter.hasNext()) { vCtxsIter.next(); foreach (const QString &path, vCtxsIter.value().paths) - allImportPaths.maybeInsert(Utils::FileName::fromString(path), vCtxsIter.value().language); + allImportPaths.maybeInsert(Utils::FilePath::fromString(path), vCtxsIter.value().language); } pInfoIter.toFront(); while (pInfoIter.hasNext()) { @@ -1116,7 +1118,7 @@ void ModelManagerInterface::updateImportPaths() .searchPaths().stringList()) { const QString canonicalPath = QFileInfo(path).canonicalFilePath(); if (!canonicalPath.isEmpty()) - allImportPaths.maybeInsert(Utils::FileName::fromString(canonicalPath), l); + allImportPaths.maybeInsert(Utils::FilePath::fromString(canonicalPath), l); } } } @@ -1125,16 +1127,16 @@ void ModelManagerInterface::updateImportPaths() pInfoIter.next(); QString pathAtt = pInfoIter.value().qtQmlPath; if (!pathAtt.isEmpty()) - allImportPaths.maybeInsert(Utils::FileName::fromString(pathAtt), Dialect::QmlQtQuick2); + allImportPaths.maybeInsert(Utils::FilePath::fromString(pathAtt), Dialect::QmlQtQuick2); } { QString pathAtt = defaultProjectInfo().qtQmlPath; if (!pathAtt.isEmpty()) - allImportPaths.maybeInsert(Utils::FileName::fromString(pathAtt), Dialect::QmlQtQuick2); + allImportPaths.maybeInsert(Utils::FilePath::fromString(pathAtt), Dialect::QmlQtQuick2); } foreach (const QString &path, m_defaultImportPaths) - allImportPaths.maybeInsert(Utils::FileName::fromString(path), Dialect::Qml); + allImportPaths.maybeInsert(Utils::FilePath::fromString(path), Dialect::Qml); allImportPaths.compact(); { diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.h b/src/libs/qmljs/qmljsmodelmanagerinterface.h index 5de25eead3..cd36cbca2f 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.h +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.h @@ -28,11 +28,11 @@ #include "qmljs_global.h" #include "qmljsbundle.h" #include "qmljsdocument.h" -#include "qmljsqrcparser.h" #include "qmljsdialect.h" #include <cplusplus/CppDocument.h> #include <utils/environment.h> +#include <utils/qrcparser.h> #include <QFuture> #include <QHash> @@ -255,7 +255,7 @@ private: void cleanupFutures(); void iterateQrcFiles(ProjectExplorer::Project *project, QrcResourceSelector resources, - std::function<void(QrcParser::ConstPtr)> callback); + std::function<void(Utils::QrcParser::ConstPtr)> callback); mutable QMutex m_mutex; QmlJS::Snapshot m_validSnapshot; @@ -272,7 +272,7 @@ private: QTimer *m_asyncResetTimer = nullptr; QHash<QString, QPair<CPlusPlus::Document::Ptr, bool> > m_queuedCppDocuments; QFuture<void> m_cppQmlTypesUpdater; - QrcCache m_qrcCache; + Utils::QrcCache m_qrcCache; QHash<QString, QString> m_qrcContents; CppDataHash m_cppDataHash; diff --git a/src/libs/qmljs/qmljsreformatter.cpp b/src/libs/qmljs/qmljsreformatter.cpp index e95ff2f339..d60d6179f3 100644 --- a/src/libs/qmljs/qmljsreformatter.cpp +++ b/src/libs/qmljs/qmljsreformatter.cpp @@ -96,6 +96,7 @@ class Rewriter : protected Visitor int _lastNewlineOffset = -1; bool _hadEmptyLine = false; int _binaryExpDepth = 0; + bool _hasOpenComment = false; public: Rewriter(Document::Ptr doc) @@ -201,6 +202,9 @@ protected: void out(const QString &str, const SourceLocation &lastLoc = SourceLocation()) { + if (_hasOpenComment) { + newLine(); + } if (lastLoc.isValid()) { QList<SourceLocation> comments = _doc->engine()->comments(); for (; _nextComment < comments.size(); ++_nextComment) { @@ -371,6 +375,7 @@ protected: { // if preceded by a newline, it's an empty line! _hadEmptyLine = _line.trimmed().isEmpty(); + _hasOpenComment = false; // if the preceding line wasn't empty, reindent etc. if (!_hadEmptyLine) { @@ -524,6 +529,7 @@ protected: out(" "); out(toString(nextCommentLoc)); + _hasOpenComment = true; } } } @@ -531,6 +537,39 @@ protected: bool visit(UiPragma *ast) override { out("pragma ", ast->pragmaToken); + out(ast->name.toString()); + newLine(); + return false; + } + + bool visit(UiEnumDeclaration *ast) override + { + out(ast->enumToken); + out(" "); + out(ast->name.toString()); + out(" "); + out("{"); // TODO: out(ast->lbraceToken); + newLine(); + + accept(ast->members); + + out(ast->rbraceToken); + return false; + } + + bool visit(UiEnumMemberList *list) override + { + for (UiEnumMemberList *it = list; it; it = it->next) { + out(it->memberToken); + if (it->valueToken.isValid()) { + out(" = "); + out(it->valueToken); + } + if (it->next) { + out(","); + } + newLine(); + } return false; } @@ -563,9 +602,10 @@ protected: bool visit(UiObjectInitializer *ast) override { out(ast->lbraceToken); - if (ast->members) + if (ast->members) { lnAcceptIndented(ast->members); - newLine(); + newLine(); + } out(ast->rbraceToken); return false; } @@ -593,10 +633,10 @@ protected: if (!ast->typeModifier.isNull()) { out(ast->typeModifierToken); out("<"); - out(ast->typeToken); + accept(ast->memberType); out(">"); } else { - out(ast->typeToken); + accept(ast->memberType); } out(" "); if (ast->statement) { @@ -677,8 +717,10 @@ protected: bool visit(ObjectPattern *ast) override { out(ast->lbraceToken); - lnAcceptIndented(ast->properties); - newLine(); + if (ast->properties) { + lnAcceptIndented(ast->properties); + newLine(); + } out(ast->rbraceToken); return false; } @@ -914,14 +956,23 @@ protected: bool visit(VariableStatement *ast) override { - out("var ", ast->declarationKindToken); + out(ast->declarationKindToken); + out(" "); accept(ast->declarations); return false; } bool visit(PatternElement *ast) override { - + if (ast->isForDeclaration) { + if (ast->scope == VariableScope::Var) { + out("var "); + } else if (ast->scope == VariableScope::Let) { + out("let "); + } else if (ast->scope == VariableScope::Const) { + out("const "); + } + } out(ast->identifierToken); if (ast->initializer) { if (ast->isVariableDeclaration()) @@ -985,7 +1036,12 @@ protected: out(ast->forToken); out(" "); out(ast->lparenToken); - accept(ast->initialiser); + if (ast->initialiser) { + accept(ast->initialiser); + } else if (ast->declarations) { + out("var "); + accept(ast->declarations); + } out("; ", ast->firstSemicolonToken); accept(ast->condition); out("; ", ast->secondSemicolonToken); @@ -1273,6 +1329,8 @@ protected: { for (FormalParameterList *it = ast; it; it = it->next) { out(it->element->bindingIdentifier.toString()); // TODO + if (it->next) + out(", "); } return false; } diff --git a/src/libs/qt-breakpad/qtcrashhandler/dumpsender.cpp b/src/libs/qt-breakpad/qtcrashhandler/dumpsender.cpp index c8f03ea8d9..8e1deea715 100644 --- a/src/libs/qt-breakpad/qtcrashhandler/dumpsender.cpp +++ b/src/libs/qt-breakpad/qtcrashhandler/dumpsender.cpp @@ -145,8 +145,7 @@ void DumpSender::sendDumpAndQuit() connect(reply, &QNetworkReply::uploadProgress, this, &DumpSender::uploadProgress); connect(reply, &QNetworkReply::finished, QCoreApplication::instance(), &QCoreApplication::quit); - connect(reply, - static_cast<void (QNetworkReply::*)(QNetworkReply::NetworkError)>(&QNetworkReply::error), + connect(reply, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error), QCoreApplication::instance(), &QCoreApplication::quit); } diff --git a/src/libs/qtcreatorcdbext/CMakeLists.txt b/src/libs/qtcreatorcdbext/CMakeLists.txt new file mode 100644 index 0000000000..15ab799083 --- /dev/null +++ b/src/libs/qtcreatorcdbext/CMakeLists.txt @@ -0,0 +1,46 @@ +#todo +# - handle if there is no debug python lib python35_d +# - needs to be tested + +if (MINGW) + message(STATUS "MinGW detected. Removing qtcreatorcdbext from build.") + return() +endif() + +include(CheckIncludeFile) +check_include_file(wdbgexts.h HAVE_WDBGEXTS_H) +if (NOT HAVE_WDBGEXTS_H) + message(WARNING "wdbgexts.h not found. Removing qtcreatorcdbext from build.") + return() +endif() + +find_package(PythonLibs 3.5) +if (NOT ${PYTHONLIBS_FOUND}) + message(WARNING "PythonLibs 3.5 not found. Removing qtcreatorcdbext from build.") + return() +endif() + +add_qtc_library(qtcreatorcdbext + DEPENDS ${PYTHON_LIBRARIES} + INCLUDES ${PYTHON_INCLUDE_DIR} + DEFINES WITH_PYTHON=1 + SOURCES + common.cpp common.h + containers.cpp containers.h + eventcallback.cpp eventcallback.h + extensioncontext.cpp extensioncontext.h + gdbmihelpers.cpp gdbmihelpers.h + iinterfacepointer.h + knowntype.h + outputcallback.cpp outputcallback.h + pycdbextmodule.cpp pycdbextmodule.h + pyfield.cpp pyfield.h + pystdoutredirect.cpp pystdoutredirect.h + pytype.cpp pytype.h + pyvalue.cpp pyvalue.h + qtcreatorcdbextension.cpp + stringutils.cpp stringutils.h + symbolgroup.cpp symbolgroup.h + symbolgroupnode.cpp symbolgroupnode.h + symbolgroupvalue.cpp symbolgroupvalue.h +) diff --git a/src/libs/qtcreatorcdbext/common.h b/src/libs/qtcreatorcdbext/common.h index b538313b3f..fd76c1be7e 100644 --- a/src/libs/qtcreatorcdbext/common.h +++ b/src/libs/qtcreatorcdbext/common.h @@ -34,9 +34,16 @@ #include <windows.h> #define KDEXT_64BIT -#pragma warning( disable : 4838 ) -#include <wdbgexts.h> -#pragma warning( default : 4838 ) +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wc++11-narrowing" +# include <wdbgexts.h> +# pragma clang diagnostic pop +#else +# pragma warning( disable : 4838 ) +# include <wdbgexts.h> +# pragma warning( default : 4838 ) +#endif // __clang__ #include <dbgeng.h> typedef IDebugControl3 CIDebugControl; diff --git a/src/libs/qtcreatorcdbext/qtcreatorcdbext.pro b/src/libs/qtcreatorcdbext/qtcreatorcdbext.pro index 545656dc24..774e889b2a 100644 --- a/src/libs/qtcreatorcdbext/qtcreatorcdbext.pro +++ b/src/libs/qtcreatorcdbext/qtcreatorcdbext.pro @@ -100,7 +100,7 @@ HEADERS += extensioncontext.h \ symbolgroupnode.h isEmpty(PYTHON_INSTALL_DIR):PYTHON_INSTALL_DIR=$$(PYTHON_INSTALL_DIR) -exists($$PYTHON_INSTALL_DIR) { +!isEmpty(PYTHON_INSTALL_DIR):exists($$PYTHON_INSTALL_DIR) { DEFINES += WITH_PYTHON=1 INCLUDEPATH += $$PYTHON_INSTALL_DIR/include diff --git a/src/libs/sqlite/CMakeLists.txt b/src/libs/sqlite/CMakeLists.txt new file mode 100644 index 0000000000..22ba4bac34 --- /dev/null +++ b/src/libs/sqlite/CMakeLists.txt @@ -0,0 +1,27 @@ +add_qtc_library(Sqlite + DEFINES + SQLITE_THREADSAFE=2 SQLITE_ENABLE_FTS4 SQLITE_ENABLE_FTS3_PARENTHESIS + SQLITE_ENABLE_UNLOCK_NOTIFY SQLITE_ENABLE_COLUMN_METADATA + BUILD_SQLITE_LIBRARY + DEPENDS Qt5::Core + PUBLIC_INCLUDES "${CMAKE_CURRENT_LIST_DIR}" "${CMAKE_CURRENT_LIST_DIR}/../3rdparty/sqlite" + SOURCES + ../3rdparty/sqlite/sqlite3.c + createtablesqlstatementbuilder.cpp createtablesqlstatementbuilder.h + sqlitebasestatement.cpp sqlitebasestatement.h + sqlitecolumn.h + sqlitedatabase.cpp sqlitedatabase.h + sqlitedatabasebackend.cpp sqlitedatabasebackend.h + sqliteexception.cpp sqliteexception.h + sqliteglobal.cpp sqliteglobal.h + sqliteindex.h + sqlitereadstatement.cpp sqlitereadstatement.h + sqlitereadwritestatement.cpp sqlitereadwritestatement.h + sqlitetable.h + sqlitetransaction.h + sqlitewritestatement.cpp sqlitewritestatement.h + sqlstatementbuilder.cpp sqlstatementbuilder.h + sqlstatementbuilderexception.h + utf8string.cpp utf8string.h + utf8stringvector.cpp utf8stringvector.h +) diff --git a/src/libs/sqlite/README.md b/src/libs/sqlite/README.md new file mode 100644 index 0000000000..88944dcd42 --- /dev/null +++ b/src/libs/sqlite/README.md @@ -0,0 +1,13 @@ +# SQLite + +Minimum version is the same as the sqlite version in the source tree. + +We compile SQLite with the flowing settings: +* SQLITE_THREADSAFE=2 +* SQLITE_ENABLE_FTS4 +* SQLITE_ENABLE_FTS3_PARENTHESIS +* SQLITE_ENABLE_UNLOCK_NOTIFY +* SQLITE_ENABLE_COLUMN_METADATA +* SQLITE_ENABLE_JSON1 + +Be prepared that we demand more functionality from SQLite in the future. diff --git a/src/libs/sqlite/sqlite-lib.pri b/src/libs/sqlite/sqlite-lib.pri index fb46370052..4d7f906a19 100644 --- a/src/libs/sqlite/sqlite-lib.pri +++ b/src/libs/sqlite/sqlite-lib.pri @@ -19,16 +19,14 @@ SOURCES += \ $$PWD/sqlitereadwritestatement.cpp \ $$PWD/sqlitewritestatement.cpp \ $$PWD/sqlstatementbuilder.cpp \ - $$PWD/sqlstatementbuilderexception.cpp \ $$PWD/utf8string.cpp \ $$PWD/utf8stringvector.cpp \ $$PWD/sqlitedatabase.cpp \ - $$PWD/sqlitetable.cpp \ - $$PWD/sqlitecolumn.cpp \ $$PWD/sqlitebasestatement.cpp HEADERS += \ $$PWD/createtablesqlstatementbuilder.h \ $$PWD/sqlitedatabasebackend.h \ + $$PWD/sqlitedatabaseinterface.h \ $$PWD/sqliteexception.h \ $$PWD/sqliteglobal.h \ $$PWD/sqlitereadstatement.h \ @@ -48,4 +46,6 @@ HEADERS += \ DEFINES += SQLITE_THREADSAFE=2 SQLITE_ENABLE_FTS4 SQLITE_ENABLE_FTS3_PARENTHESIS \ SQLITE_ENABLE_UNLOCK_NOTIFY SQLITE_ENABLE_COLUMN_METADATA SQLITE_ENABLE_JSON1 +OTHER_FILES += README.md + contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols diff --git a/src/libs/sqlite/sqlite-source.pri b/src/libs/sqlite/sqlite-source.pri index b297e31da2..5729293901 100644 --- a/src/libs/sqlite/sqlite-source.pri +++ b/src/libs/sqlite/sqlite-source.pri @@ -17,12 +17,9 @@ SOURCES += \ sqliteworkerthread.cpp \ sqlitewritestatement.cpp \ sqlstatementbuilder.cpp \ - sqlstatementbuilderexception.cpp \ utf8string.cpp \ utf8stringvector.cpp \ sqlitedatabase.cpp \ - sqlitetable.cpp \ - sqlitecolumn.cpp \ tablewriteworker.cpp \ tablewriteworkerproxy.cpp HEADERS += \ diff --git a/src/libs/sqlite/sqlitecolumn.cpp b/src/libs/sqlite/sqlitecolumn.cpp deleted file mode 100644 index 201f1fbcb9..0000000000 --- a/src/libs/sqlite/sqlitecolumn.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "sqlitecolumn.h" - -namespace Sqlite { - - -} // namespace Sqlite diff --git a/src/libs/sqlite/sqlitedatabase.h b/src/libs/sqlite/sqlitedatabase.h index d0eae28f79..2c35a293c2 100644 --- a/src/libs/sqlite/sqlitedatabase.h +++ b/src/libs/sqlite/sqlitedatabase.h @@ -26,6 +26,7 @@ #pragma once #include "sqlitedatabasebackend.h" +#include "sqlitedatabaseinterface.h" #include "sqliteglobal.h" #include "sqlitetable.h" #include "sqlitetransaction.h" @@ -43,7 +44,7 @@ using namespace std::chrono_literals; class ReadStatement; class WriteStatement; -class SQLITE_EXPORT Database final : public TransactionInterface +class SQLITE_EXPORT Database final : public TransactionInterface, public DatabaseInterface { template <typename Database> friend class Statement; @@ -105,19 +106,18 @@ public: return m_databaseBackend.changesCount(); } - int totalChangesCount() - { - return m_databaseBackend.totalChangesCount(); - } + int totalChangesCount() { return m_databaseBackend.totalChangesCount(); } + + void walCheckpointFull() override { m_databaseBackend.walCheckpointFull(); } private: - void deferredBegin(); - void immediateBegin(); - void exclusiveBegin(); - void commit(); - void rollback(); - void lock(); - void unlock(); + void deferredBegin() override; + void immediateBegin() override; + void exclusiveBegin() override; + void commit() override; + void rollback() override; + void lock() override; + void unlock() override; void initializeTables(); void registerTransactionStatements(); diff --git a/src/libs/sqlite/sqlitedatabasebackend.cpp b/src/libs/sqlite/sqlitedatabasebackend.cpp index a42564aca5..bf9dfab6fc 100644 --- a/src/libs/sqlite/sqlitedatabasebackend.cpp +++ b/src/libs/sqlite/sqlitedatabasebackend.cpp @@ -406,6 +406,27 @@ void DatabaseBackend::setBusyTimeout(std::chrono::milliseconds timeout) sqlite3_busy_timeout(m_databaseHandle, int(timeout.count())); } +void DatabaseBackend::walCheckpointFull() +{ + int resultCode = sqlite3_wal_checkpoint_v2(m_databaseHandle, + nullptr, + SQLITE_CHECKPOINT_TRUNCATE, + nullptr, + nullptr); + + switch (resultCode) { + case SQLITE_OK: + break; + case SQLITE_BUSY: + throw DatabaseIsBusy("DatabaseBackend::walCheckpointFull: Operation could not concluded " + "because database is busy!"); + case SQLITE_ERROR: + throwException("DatabaseBackend::walCheckpointFull: Error occurred!"); + case SQLITE_MISUSE: + throwExceptionStatic("DatabaseBackend::walCheckpointFull: Misuse of database!"); + } +} + void DatabaseBackend::throwExceptionStatic(const char *whatHasHappens) { throw Exception(whatHasHappens); diff --git a/src/libs/sqlite/sqlitedatabasebackend.h b/src/libs/sqlite/sqlitedatabasebackend.h index 2de55672aa..7f3973f878 100644 --- a/src/libs/sqlite/sqlitedatabasebackend.h +++ b/src/libs/sqlite/sqlitedatabasebackend.h @@ -85,6 +85,8 @@ public: void setBusyTimeout(std::chrono::milliseconds timeout); + void walCheckpointFull(); + protected: bool databaseIsOpen() const; diff --git a/src/libs/sqlite/sqlstatementbuilderexception.cpp b/src/libs/sqlite/sqlitedatabaseinterface.h index 82f5b4f792..61ea3ac928 100644 --- a/src/libs/sqlite/sqlstatementbuilderexception.cpp +++ b/src/libs/sqlite/sqlitedatabaseinterface.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -23,12 +23,15 @@ ** ****************************************************************************/ -#include "sqlstatementbuilderexception.h" +#pragma once namespace Sqlite { +class DatabaseInterface +{ +public: + virtual void walCheckpointFull() = 0; - - - - +protected: + ~DatabaseInterface() = default; +}; } // namespace Sqlite diff --git a/src/libs/ssh/CMakeLists.txt b/src/libs/ssh/CMakeLists.txt new file mode 100644 index 0000000000..6f5d1cb764 --- /dev/null +++ b/src/libs/ssh/CMakeLists.txt @@ -0,0 +1,22 @@ +add_qtc_library(QtcSsh + DEPENDS Qt5::Core Qt5::Network Qt5::Widgets Utils + SOURCES + sftpdefs.cpp sftpdefs.h + sftpfilesystemmodel.cpp sftpfilesystemmodel.h + sftpsession.cpp sftpsession.h + sftptransfer.cpp sftptransfer.h + ssh.qrc + ssh_global.h + sshconnection.cpp sshconnection.h + sshconnectionmanager.cpp sshconnectionmanager.h + sshkeycreationdialog.cpp sshkeycreationdialog.h sshkeycreationdialog.ui + sshlogging.cpp sshlogging_p.h + sshprocess.cpp sshprocess.h + sshconnection.cpp sshconnection.h + sshconnectionmanager.cpp sshconnectionmanager.h + sshkeycreationdialog.cpp sshkeycreationdialog.h sshkeycreationdialog.ui + sshlogging.cpp sshlogging_p.h + sshremoteprocess.cpp sshremoteprocess.h + sshremoteprocessrunner.cpp sshremoteprocessrunner.h + sshsettings.cpp sshsettings.h +) diff --git a/src/libs/ssh/sftpfilesystemmodel.cpp b/src/libs/ssh/sftpfilesystemmodel.cpp index 555796b812..0e9eb48e5e 100644 --- a/src/libs/ssh/sftpfilesystemmodel.cpp +++ b/src/libs/ssh/sftpfilesystemmodel.cpp @@ -30,6 +30,7 @@ #include "sshconnectionmanager.h" #include <utils/qtcassert.h> +#include <utils/utilsicons.h> #include <QFileInfo> #include <QHash> @@ -167,9 +168,9 @@ QVariant SftpFileSystemModel::data(const QModelIndex &index, int role) const switch (node->fileInfo.type) { case FileTypeRegular: case FileTypeOther: - return QIcon(":/ssh/images/unknownfile.png"); + return Utils::Icons::UNKNOWN_FILE.icon(); case FileTypeDirectory: - return QIcon(":/ssh/images/dir.png"); + return Utils::Icons::DIR.icon(); case FileTypeUnknown: return QIcon(":/ssh/images/help.png"); // Shows a question mark. } diff --git a/src/libs/ssh/sftpsession.cpp b/src/libs/ssh/sftpsession.cpp index 0119bea266..528475ed2b 100644 --- a/src/libs/ssh/sftpsession.cpp +++ b/src/libs/ssh/sftpsession.cpp @@ -83,6 +83,8 @@ struct SftpSession::SftpSessionPrivate SftpJobId queueCommand(CommandType command, const QStringList &paths) { + qCDebug(sshLog) << "queueing command" << int(command) << paths; + const SftpJobId jobId = nextJobId++; pendingCommands.enqueue(Command(command, paths, jobId)); runNextCommand(); @@ -111,6 +113,7 @@ SftpSession::SftpSession(const QStringList &connectionArgs) : d(new SftpSessionP { d->connectionArgs = connectionArgs; connect(&d->sftpProc, &QProcess::started, [this] { + qCDebug(sshLog) << "sftp process started"; d->sftpProc.write("\n"); // Force initial prompt. }); connect(&d->sftpProc, &QProcess::errorOccurred, [this](QProcess::ProcessError error) { @@ -120,6 +123,8 @@ SftpSession::SftpSession(const QStringList &connectionArgs) : d(new SftpSessionP } }); connect(&d->sftpProc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [this] { + qCDebug(sshLog) << "sftp process finished"; + d->state = State::Inactive; if (d->sftpProc.exitStatus() != QProcess::NormalExit) { emit done(tr("sftp crashed.")); @@ -138,7 +143,7 @@ void SftpSession::doStart() { if (d->state != State::Starting) return; - const FileName sftpBinary = SshSettings::sftpFilePath(); + const FilePath sftpBinary = SshSettings::sftpFilePath(); if (!sftpBinary.exists()) { d->state = State::Inactive; emit done(tr("Cannot establish SFTP session: sftp binary \"%1\" does not exist.") @@ -269,6 +274,8 @@ void SftpSession::start() void SftpSession::quit() { + qCDebug(sshLog) << "quitting sftp session, current state is" << int(state()); + switch (state()) { case State::Starting: case State::Closing: diff --git a/src/libs/ssh/sftptransfer.cpp b/src/libs/ssh/sftptransfer.cpp index 887d8f36fa..52b821bc39 100644 --- a/src/libs/ssh/sftptransfer.cpp +++ b/src/libs/ssh/sftptransfer.cpp @@ -132,7 +132,7 @@ SftpTransfer::SftpTransfer(const FilesToTransfer &files, Internal::FileTransferT void SftpTransfer::doStart() { - const FileName sftpBinary = SshSettings::sftpFilePath(); + const FilePath sftpBinary = SshSettings::sftpFilePath(); if (!sftpBinary.exists()) { emitError(tr("sftp binary \"%1\" does not exist.").arg(sftpBinary.toUserOutput())); return; diff --git a/src/libs/ssh/ssh.qrc b/src/libs/ssh/ssh.qrc index 4b0c6a8c51..9801217093 100644 --- a/src/libs/ssh/ssh.qrc +++ b/src/libs/ssh/ssh.qrc @@ -1,7 +1,5 @@ <RCC> <qresource prefix="/ssh"> - <file>images/dir.png</file> <file>images/help.png</file> - <file>images/unknownfile.png</file> </qresource> </RCC> diff --git a/src/libs/ssh/sshconnection.cpp b/src/libs/ssh/sshconnection.cpp index 91d8446db9..b368ccc8ef 100644 --- a/src/libs/ssh/sshconnection.cpp +++ b/src/libs/ssh/sshconnection.cpp @@ -231,7 +231,7 @@ void SshConnection::disconnectFromHost() case Connecting: case Connected: if (!d->sharingEnabled) { - emitDisconnected(); + QTimer::singleShot(0, this, &SshConnection::emitDisconnected); return; } d->state = Disconnecting; @@ -309,7 +309,7 @@ SshConnection::~SshConnection() delete d; } -SshRemoteProcessPtr SshConnection::createRemoteProcess(const QByteArray &command) +SshRemoteProcessPtr SshConnection::createRemoteProcess(const QString &command) { QTC_ASSERT(state() == Connected, return SshRemoteProcessPtr()); return SshRemoteProcessPtr(new SshRemoteProcess(command, d->connectionArgs())); @@ -317,7 +317,7 @@ SshRemoteProcessPtr SshConnection::createRemoteProcess(const QByteArray &command SshRemoteProcessPtr SshConnection::createRemoteShell() { - return createRemoteProcess(QByteArray()); + return createRemoteProcess({}); } SftpTransferPtr SshConnection::createUpload(const FilesToTransfer &files, @@ -342,7 +342,7 @@ void SshConnection::doConnectToHost() { if (d->state != Connecting) return; - const FileName sshBinary = SshSettings::sshFilePath(); + const FilePath sshBinary = SshSettings::sshFilePath(); if (!sshBinary.exists()) { emitError(tr("Cannot establish SSH connection: ssh binary \"%1\" does not exist.") .arg(sshBinary.toUserOutput())); diff --git a/src/libs/ssh/sshconnection.h b/src/libs/ssh/sshconnection.h index 1b5775682e..89af4d71d9 100644 --- a/src/libs/ssh/sshconnection.h +++ b/src/libs/ssh/sshconnection.h @@ -111,7 +111,7 @@ public: bool sharingEnabled() const; ~SshConnection(); - SshRemoteProcessPtr createRemoteProcess(const QByteArray &command); + SshRemoteProcessPtr createRemoteProcess(const QString &command); SshRemoteProcessPtr createRemoteShell(); SftpTransferPtr createUpload(const FilesToTransfer &files, FileTransferErrorHandling errorHandlingMode); diff --git a/src/libs/ssh/sshremoteprocess.cpp b/src/libs/ssh/sshremoteprocess.cpp index 4bd09b37e1..635f23e150 100644 --- a/src/libs/ssh/sshremoteprocess.cpp +++ b/src/libs/ssh/sshremoteprocess.cpp @@ -54,21 +54,19 @@ using namespace Internal; struct SshRemoteProcess::SshRemoteProcessPrivate { - QByteArray remoteCommand; + QString remoteCommand; QStringList connectionArgs; QString displayName; bool useTerminal = false; }; -SshRemoteProcess::SshRemoteProcess(const QByteArray &command, const QStringList &connectionArgs) +SshRemoteProcess::SshRemoteProcess(const QString &command, const QStringList &connectionArgs) : d(new SshRemoteProcessPrivate) { d->remoteCommand = command; d->connectionArgs = connectionArgs; - connect(this, - static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), - [this] { + connect(this, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this] { QString error; if (exitStatus() == QProcess::CrashExit) error = tr("The ssh process crashed: %1").arg(errorString()); @@ -129,7 +127,7 @@ QStringList SshRemoteProcess::fullLocalCommandLine() const if (!d->displayName.isEmpty()) args.prepend("-X"); if (!d->remoteCommand.isEmpty()) - args << QLatin1String(d->remoteCommand); + args << d->remoteCommand; args.prepend(SshSettings::sshFilePath().toString()); return args; } diff --git a/src/libs/ssh/sshremoteprocess.h b/src/libs/ssh/sshremoteprocess.h index 82dd1b9dcb..02ab3546fd 100644 --- a/src/libs/ssh/sshremoteprocess.h +++ b/src/libs/ssh/sshremoteprocess.h @@ -30,10 +30,6 @@ #include <QStringList> -QT_BEGIN_NAMESPACE -class QByteArray; -QT_END_NAMESPACE - namespace QSsh { class SshConnection; @@ -56,7 +52,7 @@ signals: void done(const QString &error); private: - SshRemoteProcess(const QByteArray &command, const QStringList &connectionArgs); + SshRemoteProcess(const QString &command, const QStringList &connectionArgs); void doStart(); struct SshRemoteProcessPrivate; diff --git a/src/libs/ssh/sshremoteprocessrunner.cpp b/src/libs/ssh/sshremoteprocessrunner.cpp index 11b75f6a25..7a062e6ab8 100644 --- a/src/libs/ssh/sshremoteprocessrunner.cpp +++ b/src/libs/ssh/sshremoteprocessrunner.cpp @@ -50,7 +50,7 @@ public: SshRemoteProcessPtr m_process; SshConnection *m_connection; bool m_runInTerminal; - QByteArray m_command; + QString m_command; QString m_lastConnectionErrorString; QProcess::ExitStatus m_exitStatus; QByteArray m_stdout; @@ -76,8 +76,7 @@ SshRemoteProcessRunner::~SshRemoteProcessRunner() delete d; } -void SshRemoteProcessRunner::run(const QByteArray &command, - const SshConnectionParameters &sshParams) +void SshRemoteProcessRunner::run(const QString &command, const SshConnectionParameters &sshParams) { QTC_ASSERT(d->m_state == Inactive, return); @@ -85,14 +84,14 @@ void SshRemoteProcessRunner::run(const QByteArray &command, runInternal(command, sshParams); } -void SshRemoteProcessRunner::runInTerminal(const QByteArray &command, +void SshRemoteProcessRunner::runInTerminal(const QString &command, const SshConnectionParameters &sshParams) { d->m_runInTerminal = true; runInternal(command, sshParams); } -void SshRemoteProcessRunner::runInternal(const QByteArray &command, +void SshRemoteProcessRunner::runInternal(const QString &command, const SshConnectionParameters &sshParams) { setState(Connecting); @@ -197,7 +196,7 @@ void SshRemoteProcessRunner::setState(int newState) } } -QByteArray SshRemoteProcessRunner::command() const { return d->m_command; } +QString SshRemoteProcessRunner::command() const { return d->m_command; } QString SshRemoteProcessRunner::lastConnectionErrorString() const { return d->m_lastConnectionErrorString; } diff --git a/src/libs/ssh/sshremoteprocessrunner.h b/src/libs/ssh/sshremoteprocessrunner.h index 029fb6bb3d..082f30ed57 100644 --- a/src/libs/ssh/sshremoteprocessrunner.h +++ b/src/libs/ssh/sshremoteprocessrunner.h @@ -39,9 +39,9 @@ public: SshRemoteProcessRunner(QObject *parent = 0); ~SshRemoteProcessRunner(); - void run(const QByteArray &command, const SshConnectionParameters &sshParams); - void runInTerminal(const QByteArray &command, const SshConnectionParameters &sshParams); - QByteArray command() const; + void run(const QString &command, const SshConnectionParameters &sshParams); + void runInTerminal(const QString &command, const SshConnectionParameters &sshParams); + QString command() const; QString lastConnectionErrorString() const; @@ -69,7 +69,7 @@ private: void handleProcessFinished(const QString &error); void handleStdout(); void handleStderr(); - void runInternal(const QByteArray &command, const QSsh::SshConnectionParameters &sshParams); + void runInternal(const QString &command, const QSsh::SshConnectionParameters &sshParams); void setState(int newState); Internal::SshRemoteProcessRunnerPrivate * const d; diff --git a/src/libs/ssh/sshsettings.cpp b/src/libs/ssh/sshsettings.cpp index 12f17bbade..0086d05376 100644 --- a/src/libs/ssh/sshsettings.cpp +++ b/src/libs/ssh/sshsettings.cpp @@ -39,11 +39,11 @@ struct SshSettings { bool useConnectionSharing = !HostOsInfo::isWindowsHost(); int connectionSharingTimeOutInMinutes = 10; - FileName sshFilePath; - FileName sftpFilePath; - FileName askpassFilePath; - FileName keygenFilePath; - QSsh::SshSettings::SearchPathRetriever searchPathRetriever = [] { return FileNameList(); }; + FilePath sshFilePath; + FilePath sftpFilePath; + FilePath askpassFilePath; + FilePath keygenFilePath; + QSsh::SshSettings::SearchPathRetriever searchPathRetriever = [] { return FilePathList(); }; }; } // namespace Internal @@ -79,11 +79,11 @@ void SshSettings::loadSettings(QSettings *settings) value = settings->value(connectionSharingTimeoutKey()); if (value.isValid()) sshSettings->connectionSharingTimeOutInMinutes = value.toInt(); - sshSettings->sshFilePath = FileName::fromString(settings->value(sshFilePathKey()).toString()); - sshSettings->sftpFilePath = FileName::fromString(settings->value(sftpFilePathKey()).toString()); - sshSettings->askpassFilePath = FileName::fromString( + sshSettings->sshFilePath = FilePath::fromString(settings->value(sshFilePathKey()).toString()); + sshSettings->sftpFilePath = FilePath::fromString(settings->value(sftpFilePathKey()).toString()); + sshSettings->askpassFilePath = FilePath::fromString( settings->value(askPassFilePathKey()).toString()); - sshSettings->keygenFilePath = FileName::fromString( + sshSettings->keygenFilePath = FilePath::fromString( settings->value(keygenFilePathKey()).toString()); } @@ -114,51 +114,51 @@ int SshSettings::connectionSharingTimeout() return sshSettings->connectionSharingTimeOutInMinutes; } -static FileName filePathValue(const FileName &value, const QStringList &candidateFileNames) +static FilePath filePathValue(const FilePath &value, const QStringList &candidateFileNames) { if (!value.isEmpty()) return value; - const QList<FileName> additionalSearchPaths = sshSettings->searchPathRetriever(); + const QList<FilePath> additionalSearchPaths = sshSettings->searchPathRetriever(); for (const QString &candidate : candidateFileNames) { - const FileName filePath = Environment::systemEnvironment() + const FilePath filePath = Environment::systemEnvironment() .searchInPath(candidate, additionalSearchPaths); if (!filePath.isEmpty()) return filePath; } - return FileName(); + return FilePath(); } -static FileName filePathValue(const FileName &value, const QString &candidateFileName) +static FilePath filePathValue(const FilePath &value, const QString &candidateFileName) { return filePathValue(value, QStringList(candidateFileName)); } -void SshSettings::setSshFilePath(const FileName &ssh) { sshSettings->sshFilePath = ssh; } -FileName SshSettings::sshFilePath() { return filePathValue(sshSettings->sshFilePath, "ssh"); } +void SshSettings::setSshFilePath(const FilePath &ssh) { sshSettings->sshFilePath = ssh; } +FilePath SshSettings::sshFilePath() { return filePathValue(sshSettings->sshFilePath, "ssh"); } -void SshSettings::setSftpFilePath(const FileName &sftp) { sshSettings->sftpFilePath = sftp; } -FileName SshSettings::sftpFilePath() { return filePathValue(sshSettings->sftpFilePath, "sftp"); } +void SshSettings::setSftpFilePath(const FilePath &sftp) { sshSettings->sftpFilePath = sftp; } +FilePath SshSettings::sftpFilePath() { return filePathValue(sshSettings->sftpFilePath, "sftp"); } -void SshSettings::setAskpassFilePath(const FileName &askPass) +void SshSettings::setAskpassFilePath(const FilePath &askPass) { sshSettings->askpassFilePath = askPass; } -FileName SshSettings::askpassFilePath() +FilePath SshSettings::askpassFilePath() { - FileName candidate; + FilePath candidate; candidate = sshSettings->askpassFilePath; if (candidate.isEmpty()) - candidate = FileName::fromString(Environment::systemEnvironment().value("SSH_ASKPASS")); + candidate = FilePath::fromString(Environment::systemEnvironment().value("SSH_ASKPASS")); return filePathValue(candidate, QStringList{"qtc-askpass", "ssh-askpass"}); } -void SshSettings::setKeygenFilePath(const FileName &keygen) +void SshSettings::setKeygenFilePath(const FilePath &keygen) { sshSettings->keygenFilePath = keygen; } -FileName SshSettings::keygenFilePath() +FilePath SshSettings::keygenFilePath() { return filePathValue(sshSettings->keygenFilePath, "ssh-keygen"); } diff --git a/src/libs/ssh/sshsettings.h b/src/libs/ssh/sshsettings.h index dc29ead606..08692b6e8c 100644 --- a/src/libs/ssh/sshsettings.h +++ b/src/libs/ssh/sshsettings.h @@ -49,19 +49,19 @@ public: static void setConnectionSharingTimeout(int timeInMinutes); static int connectionSharingTimeout(); - static void setSshFilePath(const Utils::FileName &ssh); - static Utils::FileName sshFilePath(); + static void setSshFilePath(const Utils::FilePath &ssh); + static Utils::FilePath sshFilePath(); - static void setSftpFilePath(const Utils::FileName &sftp); - static Utils::FileName sftpFilePath(); + static void setSftpFilePath(const Utils::FilePath &sftp); + static Utils::FilePath sftpFilePath(); - static void setAskpassFilePath(const Utils::FileName &askPass); - static Utils::FileName askpassFilePath(); + static void setAskpassFilePath(const Utils::FilePath &askPass); + static Utils::FilePath askpassFilePath(); - static void setKeygenFilePath(const Utils::FileName &keygen); - static Utils::FileName keygenFilePath(); + static void setKeygenFilePath(const Utils::FilePath &keygen); + static Utils::FilePath keygenFilePath(); - using SearchPathRetriever = std::function<Utils::FileNameList()>; + using SearchPathRetriever = std::function<Utils::FilePathList()>; static void setExtraSearchPathRetriever(const SearchPathRetriever &pathRetriever); }; diff --git a/src/libs/tracing/CMakeLists.txt b/src/libs/tracing/CMakeLists.txt new file mode 100644 index 0000000000..153756323e --- /dev/null +++ b/src/libs/tracing/CMakeLists.txt @@ -0,0 +1,35 @@ +if (WITH_TESTS) + set(TEST_SOURCES + runscenegraphtest.cpp runscenegraphtest.h + ) +endif() + +add_qtc_library(Tracing + DEPENDS Utils Qt5::Qml Qt5::Quick + PUBLIC_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}" + SOURCES ${TEST_SOURCES} + flamegraph.cpp flamegraph.h + flamegraphattached.h + safecastable.h + qml/tracing.qrc + timelineabstractrenderer.cpp timelineabstractrenderer.h timelineabstractrenderer_p.h + timelineformattime.cpp timelineformattime.h + timelineitemsrenderpass.cpp timelineitemsrenderpass.h + timelinemodel.cpp timelinemodel.h timelinemodel_p.h + timelinemodelaggregator.cpp timelinemodelaggregator.h + timelinenotesmodel.cpp timelinenotesmodel.h timelinenotesmodel_p.h + timelinenotesrenderpass.cpp timelinenotesrenderpass.h + timelineoverviewrenderer.cpp timelineoverviewrenderer.h timelineoverviewrenderer_p.h + timelinerenderer.cpp timelinerenderer.h timelinerenderer_p.h + timelinerenderpass.cpp timelinerenderpass.h + timelinerenderstate.cpp timelinerenderstate.h timelinerenderstate_p.h + timelineselectionrenderpass.cpp timelineselectionrenderpass.h + timelinetheme.cpp timelinetheme.h + timelinetracefile.cpp timelinetracefile.h + timelinetracemanager.cpp timelinetracemanager.h + timelinezoomcontrol.cpp timelinezoomcontrol.h + traceevent.h + traceeventtype.h + tracestashfile.h + tracing_global.h +) diff --git a/src/libs/tracing/timelineabstractrenderer.h b/src/libs/tracing/timelineabstractrenderer.h index f28fd07672..64475ef3ae 100644 --- a/src/libs/tracing/timelineabstractrenderer.h +++ b/src/libs/tracing/timelineabstractrenderer.h @@ -35,7 +35,6 @@ namespace Timeline { - class TRACING_EXPORT TimelineAbstractRenderer : public QQuickItem { Q_OBJECT diff --git a/src/libs/tracing/timelinemodel_p.h b/src/libs/tracing/timelinemodel_p.h index 53136571be..bc2ac76850 100644 --- a/src/libs/tracing/timelinemodel_p.h +++ b/src/libs/tracing/timelinemodel_p.h @@ -90,7 +90,7 @@ public: ranges.prepend(start); return 0; } - const Range &range = ranges[--i]; + const Range &range = ranges.at(--i); if (range.start < start.start || (range.start == start.start && range.duration >= start.duration)) { ranges.insert(++i, start); @@ -106,7 +106,7 @@ public: endTimes.prepend(end); return 0; } - if (endTimes[--i].end <= end.end) { + if (endTimes.at(--i).end <= end.end) { endTimes.insert(++i, end); return i; } diff --git a/src/libs/tracing/timelinerenderer.h b/src/libs/tracing/timelinerenderer.h index b963ec7871..16a766d695 100644 --- a/src/libs/tracing/timelinerenderer.h +++ b/src/libs/tracing/timelinerenderer.h @@ -35,7 +35,6 @@ namespace Timeline { - class TRACING_EXPORT TimelineRenderer : public TimelineAbstractRenderer { Q_OBJECT diff --git a/src/libs/tracing/tracestashfile.h b/src/libs/tracing/tracestashfile.h index c3443e1300..0ab6105047 100644 --- a/src/libs/tracing/tracestashfile.h +++ b/src/libs/tracing/tracestashfile.h @@ -153,7 +153,7 @@ public: void clear() { file.remove(); - stream.unsetDevice(); + stream.setDevice(nullptr); } bool flush() diff --git a/src/libs/utils/CMakeLists.txt b/src/libs/utils/CMakeLists.txt new file mode 100644 index 0000000000..00307728a6 --- /dev/null +++ b/src/libs/utils/CMakeLists.txt @@ -0,0 +1,204 @@ +if (IDE_LIBEXEC_PATH AND IDE_BIN_PATH) + file(RELATIVE_PATH RELATIVE_TOOLS_PATH + "${CMAKE_INSTALL_PREFIX}/${IDE_BIN_PATH}" "${CMAKE_INSTALL_PREFIX}/${IDE_LIBEXEC_PATH}") +else() + message(WARNING "IDE_LIBEXEC_PATH or IDE_BIN_PATH undefined when calculating tools path") + set(RELATIVE_TOOLS_PATH "") +endif() + +add_qtc_library(Utils + DEPENDS Qt5::Xml + PUBLIC_DEPENDS Qt5::Concurrent Qt5::Core Qt5::Network Qt5::Qml Qt5::Gui Qt5::Widgets + DEFINES + "QTC_REL_TOOLS_PATH=\"${RELATIVE_TOOLS_PATH}\"" + SOURCES + ../3rdparty/optional/optional.hpp + ../3rdparty/variant/variant.hpp + QtConcurrentTools + algorithm.h + ansiescapecodehandler.cpp ansiescapecodehandler.h + appmainwindow.cpp appmainwindow.h + basetreeview.cpp basetreeview.h + benchmarker.cpp benchmarker.h + buildablehelperlibrary.cpp buildablehelperlibrary.h + categorysortfiltermodel.cpp categorysortfiltermodel.h + changeset.cpp changeset.h + checkablemessagebox.cpp checkablemessagebox.h + classnamevalidatinglineedit.cpp classnamevalidatinglineedit.h + codegeneration.cpp codegeneration.h + completinglineedit.cpp completinglineedit.h + completingtextedit.cpp completingtextedit.h + consoleprocess.cpp consoleprocess.h consoleprocess_p.h + cpplanguage_details.h + crumblepath.cpp crumblepath.h + delegates.cpp delegates.h + declarationmacros.h + detailsbutton.cpp detailsbutton.h + detailswidget.cpp detailswidget.h + differ.cpp differ.h + dropsupport.cpp dropsupport.h + elfreader.cpp elfreader.h + elidinglabel.cpp elidinglabel.h + environment.cpp environment.h + environmentdialog.cpp environmentdialog.h + environmentmodel.cpp environmentmodel.h + execmenu.cpp execmenu.h + executeondestruction.h + fadingindicator.cpp fadingindicator.h + faketooltip.cpp faketooltip.h + fancylineedit.cpp fancylineedit.h + fancymainwindow.cpp fancymainwindow.h + filecrumblabel.cpp filecrumblabel.h + fileinprojectfinder.cpp fileinprojectfinder.h + filenamevalidatinglineedit.cpp filenamevalidatinglineedit.h + filesearch.cpp filesearch.h + filesystemwatcher.cpp filesystemwatcher.h + fileutils.cpp fileutils.h + filewizardpage.cpp filewizardpage.h + fixedsizeclicklabel.cpp fixedsizeclicklabel.h + flowlayout.cpp flowlayout.h + functiontraits.h + fuzzymatcher.cpp fuzzymatcher.h + genericconstants.h + globalfilechangeblocker.cpp globalfilechangeblocker.h + guard.cpp guard.h + headerviewstretcher.cpp headerviewstretcher.h + highlightingitemdelegate.cpp highlightingitemdelegate.h + historycompleter.cpp historycompleter.h + hostosinfo.cpp hostosinfo.h + htmldocextractor.cpp htmldocextractor.h + icon.cpp icon.h + itemviews.cpp itemviews.h + json.cpp json.h + jsontreeitem.cpp jsontreeitem.h + linecolumn.h + link.h + listmodel.h + listutils.h + macroexpander.cpp macroexpander.h + mapreduce.h + mimetypes/mimedatabase.cpp mimetypes/mimedatabase.h mimetypes/mimedatabase_p.h + mimetypes/mimeglobpattern.cpp mimetypes/mimeglobpattern_p.h + mimetypes/mimemagicrule.cpp mimetypes/mimemagicrule_p.h + mimetypes/mimemagicrulematcher.cpp mimetypes/mimemagicrulematcher_p.h + mimetypes/mimeprovider.cpp mimetypes/mimeprovider_p.h + mimetypes/mimetype.cpp mimetypes/mimetype.h mimetypes/mimetype_p.h + mimetypes/mimetypeparser.cpp mimetypes/mimetypeparser_p.h + navigationtreeview.cpp navigationtreeview.h + networkaccessmanager.cpp networkaccessmanager.h + newclasswidget.cpp newclasswidget.h newclasswidget.ui + optional.h + osspecificaspects.h + outputformat.h + outputformatter.cpp outputformatter.h + overridecursor.cpp overridecursor.h + parameteraction.cpp parameteraction.h + pathchooser.cpp pathchooser.h + pathlisteditor.cpp pathlisteditor.h + persistentsettings.cpp persistentsettings.h + pointeralgorithm.h + port.cpp port.h + portlist.cpp portlist.h + predicates.h + processhandle.cpp processhandle.h + progressindicator.cpp progressindicator.h + projectintropage.cpp projectintropage.h projectintropage.ui + proxyaction.cpp proxyaction.h + proxycredentialsdialog.cpp proxycredentialsdialog.h proxycredentialsdialog.ui + qrcparser.cpp qrcparser.h + qtcassert.cpp qtcassert.h + qtcolorbutton.cpp qtcolorbutton.h + qtcprocess.cpp qtcprocess.h + reloadpromptutils.cpp reloadpromptutils.h + removefiledialog.cpp removefiledialog.h removefiledialog.ui + runextensions.cpp runextensions.h + savedaction.cpp savedaction.h + savefile.cpp savefile.h + scopedswap.h + settingsaccessor.cpp settingsaccessor.h + settingsselector.cpp settingsselector.h + settingsutils.h + shellcommand.cpp shellcommand.h + shellcommandpage.cpp shellcommandpage.h + sizedarray.h + smallstring.h + smallstringfwd.h + smallstringio.h + smallstringiterator.h + smallstringlayout.h + smallstringliteral.h + smallstringmemory.h + smallstringvector.h + smallstringview.h + statuslabel.cpp statuslabel.h + stringutils.cpp stringutils.h + styledbar.cpp styledbar.h + stylehelper.cpp stylehelper.h + synchronousprocess.cpp synchronousprocess.h + templateengine.cpp templateengine.h + temporarydirectory.cpp temporarydirectory.h + temporaryfile.cpp temporaryfile.h + textfieldcheckbox.cpp textfieldcheckbox.h + textfieldcombobox.cpp textfieldcombobox.h + textfileformat.cpp textfileformat.h + textutils.cpp textutils.h + theme/theme.cpp theme/theme.h theme/theme_p.h + tooltip/effects.h + tooltip/reuse.h + tooltip/tips.cpp tooltip/tips.h + tooltip/tooltip.cpp tooltip/tooltip.h + touchbar/touchbar.h + treemodel.cpp treemodel.h + treeviewcombobox.cpp treeviewcombobox.h + uncommentselection.cpp uncommentselection.h + unixutils.cpp unixutils.h + url.cpp url.h + utils.qrc + utils_global.h + utilsicons.cpp utilsicons.h + variant.h + winutils.cpp winutils.h + wizard.cpp wizard.h + wizardpage.cpp wizardpage.h +) + +extend_qtc_target(Utils CONDITION WIN32 + SOURCES + consoleprocess_win.cpp + process_ctrlc_stub.cpp + touchbar/touchbar.cpp + DEPENDS + user32 iphlpapi ws2_32 shell32 + DEFINES + _UNICODE UNICODE + PUBLIC_DEFINES + _CRT_SECURE_NO_WARNINGS _SCL_SECURE_NO_WARNINGS +) + +extend_qtc_target(Utils CONDITION APPLE + SOURCES + consoleprocess_unix.cpp + fileutils_mac.mm fileutils_mac.h + processhandle_mac.mm + theme/theme_mac.mm theme/theme_mac.h + touchbar/touchbar_appdelegate_mac.mm touchbar/touchbar_appdelegate_mac_p.h + touchbar/touchbar_mac.mm touchbar/touchbar_mac_p.h + DEPENDS + ${FWFoundation} ${FWAppKit} +) + +extend_qtc_target(Utils CONDITION UNIX AND NOT APPLE + SOURCES + consoleprocess_unix.cpp + touchbar/touchbar.cpp +) + +if (WIN32) + add_qtc_executable(qtcreator_process_stub + SOURCES process_stub_win.c + DEPENDS shell32 + DEFINES _UNICODE UNICODE _CRT_SECURE_NO_WARNINGS + ) +else() + add_qtc_executable(qtcreator_process_stub SOURCES process_stub_unix.c) +endif() diff --git a/src/libs/utils/algorithm.h b/src/libs/utils/algorithm.h index bae78aacda..9e80755a3a 100644 --- a/src/libs/utils/algorithm.h +++ b/src/libs/utils/algorithm.h @@ -48,6 +48,323 @@ namespace Utils { +///////////////////////// +// anyOf +///////////////////////// +template<typename T, typename F> +bool anyOf(const T &container, F predicate); +template<typename T, typename R, typename S> +bool anyOf(const T &container, R (S::*predicate)() const); +template<typename T, typename R, typename S> +bool anyOf(const T &container, R S::*member); + +///////////////////////// +// count +///////////////////////// +template<typename T, typename F> +int count(const T &container, F predicate); + +///////////////////////// +// allOf +///////////////////////// +template<typename T, typename F> +bool allOf(const T &container, F predicate); + +///////////////////////// +// erase +///////////////////////// +template<typename T, typename F> +void erase(T &container, F predicate); + +///////////////////////// +// contains +///////////////////////// +template<typename T, typename F> +bool contains(const T &container, F function); +template<typename T, typename R, typename S> +bool contains(const T &container, R (S::*function)() const); +template<typename C, typename R, typename S> +bool contains(const C &container, R S::*member); + +///////////////////////// +// findOr +///////////////////////// +template<typename C, typename F> +Q_REQUIRED_RESULT typename C::value_type findOr(const C &container, + typename C::value_type other, + F function); +template<typename T, typename R, typename S> +Q_REQUIRED_RESULT typename T::value_type findOr(const T &container, + typename T::value_type other, + R (S::*function)() const); +template<typename T, typename R, typename S> +Q_REQUIRED_RESULT typename T::value_type findOr(const T &container, + typename T::value_type other, + R S::*member); + +///////////////////////// +// findOrDefault +///////////////////////// +template<typename C, typename F> +Q_REQUIRED_RESULT typename std::enable_if_t<std::is_copy_assignable<typename C::value_type>::value, + typename C::value_type> +findOrDefault(const C &container, F function); +template<typename C, typename R, typename S> +Q_REQUIRED_RESULT typename std::enable_if_t<std::is_copy_assignable<typename C::value_type>::value, + typename C::value_type> +findOrDefault(const C &container, R (S::*function)() const); +template<typename C, typename R, typename S> +Q_REQUIRED_RESULT typename std::enable_if_t<std::is_copy_assignable<typename C::value_type>::value, + typename C::value_type> +findOrDefault(const C &container, R S::*member); + +///////////////////////// +// indexOf +///////////////////////// +template<typename C, typename F> +Q_REQUIRED_RESULT int indexOf(const C &container, F function); + +///////////////////////// +// maxElementOr +///////////////////////// +template<typename T> +typename T::value_type maxElementOr(const T &container, typename T::value_type other); + +///////////////////////// +// filtered +///////////////////////// +template<typename C, typename F> +Q_REQUIRED_RESULT C filtered(const C &container, F predicate); +template<typename C, typename R, typename S> +Q_REQUIRED_RESULT C filtered(const C &container, R (S::*predicate)() const); + +///////////////////////// +// partition +///////////////////////// +// Recommended usage: +// C hit; +// C miss; +// std::tie(hit, miss) = Utils::partition(container, predicate); +template<typename C, typename F> +Q_REQUIRED_RESULT std::tuple<C, C> partition(const C &container, F predicate); +template<typename C, typename R, typename S> +Q_REQUIRED_RESULT std::tuple<C, C> partition(const C &container, R (S::*predicate)() const); + +///////////////////////// +// filteredUnique +///////////////////////// +template<typename C> +Q_REQUIRED_RESULT C filteredUnique(const C &container); + +///////////////////////// +// qobject_container_cast +///////////////////////// +template<class T, template<typename> class Container, typename Base> +Container<T> qobject_container_cast(const Container<Base> &container); + +///////////////////////// +// static_container_cast +///////////////////////// +template<class T, template<typename> class Container, typename Base> +Container<T> static_container_cast(const Container<Base> &container); + +///////////////////////// +// sort +///////////////////////// +template<typename Container> +inline void sort(Container &container); +template<typename Container, typename Predicate> +inline void sort(Container &container, Predicate p); +template<typename Container, typename R, typename S> +inline void sort(Container &container, R S::*member); +template<typename Container, typename R, typename S> +inline void sort(Container &container, R (S::*function)() const); + +///////////////////////// +// reverseForeach +///////////////////////// +template<typename Container, typename Op> +inline void reverseForeach(const Container &c, const Op &operation); + +///////////////////////// +// toReferences +///////////////////////// +template<template<typename...> class ResultContainer, typename SourceContainer> +auto toReferences(SourceContainer &sources); +template<typename SourceContainer> +auto toReferences(SourceContainer &sources); + +///////////////////////// +// toConstReferences +///////////////////////// +template<template<typename...> class ResultContainer, typename SourceContainer> +auto toConstReferences(const SourceContainer &sources); +template<typename SourceContainer> +auto toConstReferences(const SourceContainer &sources); + +///////////////////////// +// take +///////////////////////// +template<class C, typename P> +Q_REQUIRED_RESULT optional<typename C::value_type> take(C &container, P predicate); +template<typename C, typename R, typename S> +Q_REQUIRED_RESULT decltype(auto) take(C &container, R S::*member); +template<typename C, typename R, typename S> +Q_REQUIRED_RESULT decltype(auto) take(C &container, R (S::*function)() const); + +///////////////////////// +// setUnionMerge +///////////////////////// +// Works like std::set_union but provides a merge function for items that match +// !(a > b) && !(b > a) which normally means that there is an "equal" match. +// It uses iterators to support move_iterators. +template<class InputIt1, class InputIt2, class OutputIt, class Merge, class Compare> +OutputIt setUnionMerge(InputIt1 first1, + InputIt1 last1, + InputIt2 first2, + InputIt2 last2, + OutputIt d_first, + Merge merge, + Compare comp); +template<class InputIt1, class InputIt2, class OutputIt, class Merge> +OutputIt setUnionMerge( + InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first, Merge merge); +template<class OutputContainer, class InputContainer1, class InputContainer2, class Merge, class Compare> +OutputContainer setUnionMerge(InputContainer1 &&input1, + InputContainer2 &&input2, + Merge merge, + Compare comp); +template<class OutputContainer, class InputContainer1, class InputContainer2, class Merge> +OutputContainer setUnionMerge(InputContainer1 &&input1, InputContainer2 &&input2, Merge merge); + +///////////////////////// +// usize / ssize +///////////////////////// +template<typename Container> +std::make_unsigned_t<typename Container::size_type> usize(Container container); +template<typename Container> +std::make_signed_t<typename Container::size_type> ssize(Container container); + +///////////////////////// +// setUnion +///////////////////////// +template<typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare> +OutputIterator set_union(InputIterator1 first1, + InputIterator1 last1, + InputIterator2 first2, + InputIterator2 last2, + OutputIterator result, + Compare comp); +template<typename InputIterator1, typename InputIterator2, typename OutputIterator> +OutputIterator set_union(InputIterator1 first1, + InputIterator1 last1, + InputIterator2 first2, + InputIterator2 last2, + OutputIterator result); + +///////////////////////// +// transform +///////////////////////// +// function without result type deduction: +template<typename ResultContainer, // complete result container type + typename SC, // input container type + typename F> // function type +Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function); + +// function with result type deduction: +template<template<typename> class C, // result container type + typename SC, // input container type + typename F, // function type + typename Value = typename std::decay_t<SC>::value_type, + typename Result = std::decay_t<std::result_of_t<F(Value &)>>, + typename ResultContainer = C<Result>> +Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function); +template<template<typename, typename> class C, // result container type + typename SC, // input container type + typename F, // function type + typename Value = typename std::decay_t<SC>::value_type, + typename Result = std::decay_t<std::result_of_t<F(Value &)>>, + typename ResultContainer = C<Result, std::allocator<Result>>> +Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function); + +// member function without result type deduction: +template<template<typename...> class C, // result container type + typename SC, // input container type + typename R, + typename S> +Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R (S::*p)() const); + +// member function with result type deduction: +template<typename ResultContainer, // complete result container type + typename SC, // input container type + typename R, + typename S> +Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R (S::*p)() const); + +// member without result type deduction: +template<typename ResultContainer, // complete result container type + typename SC, // input container + typename R, + typename S> +Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R S::*p); + +// member with result type deduction: +template<template<typename...> class C, // result container + typename SC, // input container + typename R, + typename S> +Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R S::*p); + +// same container types for input and output, const input +// function: +template<template<typename...> class C, // container type + typename F, // function type + typename... CArgs> // Arguments to SC +Q_REQUIRED_RESULT decltype(auto) transform(const C<CArgs...> &container, F function); + +// same container types for input and output, const input +// member function: +template<template<typename...> class C, // container type + typename R, + typename S, + typename... CArgs> // Arguments to SC +Q_REQUIRED_RESULT decltype(auto) transform(const C<CArgs...> &container, R (S::*p)() const); + +// same container types for input and output, const input +// members: +template<template<typename...> class C, // container + typename R, + typename S, + typename... CArgs> // Arguments to SC +Q_REQUIRED_RESULT decltype(auto) transform(const C<CArgs...> &container, R S::*p); + +// same container types for input and output, non-const input +// function: +template<template<typename...> class C, // container type + typename F, // function type + typename... CArgs> // Arguments to SC +Q_REQUIRED_RESULT decltype(auto) transform(C<CArgs...> &container, F function); + +// same container types for input and output, non-const input +// member function: +template<template<typename...> class C, // container type + typename R, + typename S, + typename... CArgs> // Arguments to SC +Q_REQUIRED_RESULT decltype(auto) transform(C<CArgs...> &container, R (S::*p)() const); + +// same container types for input and output, non-const input +// members: +template<template<typename...> class C, // container + typename R, + typename S, + typename... CArgs> // Arguments to SC +Q_REQUIRED_RESULT decltype(auto) transform(C<CArgs...> &container, R S::*p); + +///////////////////////////////////////////////////////////////////////////// +//////// Implementations ////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + ////////////////// // anyOf ///////////////// @@ -367,25 +684,23 @@ decltype(auto) transform(SC &&container, F function) // function with result type deduction: template<template<typename> class C, // result container type - typename SC, // input container type - typename F, // function type - typename Value = typename std::decay_t<SC>::value_type, - typename Result = std::decay_t<std::result_of_t<F(Value&)>>, - typename ResultContainer = C<Result>> -Q_REQUIRED_RESULT -decltype(auto) transform(SC &&container, F function) + typename SC, // input container type + typename F, // function type + typename Value, + typename Result, + typename ResultContainer> +Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function) { return transform<ResultContainer>(std::forward<SC>(container), function); } template<template<typename, typename> class C, // result container type - typename SC, // input container type - typename F, // function type - typename Value = typename std::decay_t<SC>::value_type, - typename Result = std::decay_t<std::result_of_t<F(Value&)>>, - typename ResultContainer = C<Result, std::allocator<Result>>> -Q_REQUIRED_RESULT -decltype(auto) transform(SC &&container, F function) + typename SC, // input container type + typename F, // function type + typename Value, + typename Result, + typename ResultContainer> +Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function) { return transform<ResultContainer>(std::forward<SC>(container), function); } @@ -862,4 +1177,70 @@ std::make_signed_t<typename Container::size_type> ssize(Container container) { return static_cast<std::make_signed_t<typename Container::size_type>>(container.size()); } + +template<typename Compare> +struct CompareIter +{ + Compare compare; + + explicit constexpr CompareIter(Compare compare) + : compare(std::move(compare)) + {} + + template<typename Iterator1, typename Iterator2> + constexpr bool operator()(Iterator1 it1, Iterator2 it2) + { + return bool(compare(*it1, *it2)); + } +}; + +template<typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare> +OutputIterator set_union_impl(InputIterator1 first1, + InputIterator1 last1, + InputIterator2 first2, + InputIterator2 last2, + OutputIterator result, + Compare comp) +{ + auto compare = CompareIter<Compare>(comp); + + while (first1 != last1 && first2 != last2) { + if (compare(first1, first2)) { + *result = *first1; + ++first1; + } else if (compare(first2, first1)) { + *result = *first2; + ++first2; + } else { + *result = *first1; + ++first1; + ++first2; + } + ++result; + } + + return std::copy(first2, last2, std::copy(first1, last1, result)); +} + +template<typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare> +OutputIterator set_union(InputIterator1 first1, + InputIterator1 last1, + InputIterator2 first2, + InputIterator2 last2, + OutputIterator result, + Compare comp) +{ + return Utils::set_union_impl(first1, last1, first2, last2, result, comp); +} + +template<typename InputIterator1, typename InputIterator2, typename OutputIterator> +OutputIterator set_union(InputIterator1 first1, + InputIterator1 last1, + InputIterator2 first2, + InputIterator2 last2, + OutputIterator result) +{ + return Utils::set_union_impl( + first1, last1, first2, last2, result, std::less<typename InputIterator1::value_type>{}); +} } // namespace Utils diff --git a/src/libs/utils/basetreeview.cpp b/src/libs/utils/basetreeview.cpp index d77b8d4d55..352b17bb4b 100644 --- a/src/libs/utils/basetreeview.cpp +++ b/src/libs/utils/basetreeview.cpp @@ -183,7 +183,7 @@ public: QAbstractItemModel *m = q->model(); for (int i = 0; i < 100 && a.isValid(); ++i) { const QString s = m->data(a).toString(); - int w = fm.width(s) + 10; + int w = fm.horizontalAdvance(s) + 10; if (column == 0) { for (QModelIndex b = a.parent(); b.isValid(); b = b.parent()) w += ind; @@ -204,7 +204,8 @@ public: QTC_ASSERT(m, return -1); QFontMetrics fm = q->fontMetrics(); - int minimum = fm.width(m->headerData(column, Qt::Horizontal).toString()) + 2 * fm.width(QLatin1Char('m')); + int minimum = fm.horizontalAdvance(m->headerData(column, Qt::Horizontal).toString()) + + 2 * fm.horizontalAdvance(QLatin1Char('m')); considerItems(column, q->indexAt(QPoint(1, 1)), &minimum, false); QVariant extraIndices = m->data(QModelIndex(), BaseTreeView::ExtraIndicesForColumnWidth); @@ -254,8 +255,8 @@ public: // when we have that size already, in that case minimize. if (currentSize == suggestedSize) { QFontMetrics fm = q->fontMetrics(); - int headerSize = fm.width(q->model()->headerData(logicalIndex, Qt::Horizontal).toString()); - int minSize = 10 * fm.width(QLatin1Char('x')); + int headerSize = fm.horizontalAdvance(q->model()->headerData(logicalIndex, Qt::Horizontal).toString()); + int minSize = 10 * fm.horizontalAdvance(QLatin1Char('x')); targetSize = qMax(minSize, headerSize); } diff --git a/src/libs/utils/buildablehelperlibrary.cpp b/src/libs/utils/buildablehelperlibrary.cpp index 3c53e09b2a..33ba624dc4 100644 --- a/src/libs/utils/buildablehelperlibrary.cpp +++ b/src/libs/utils/buildablehelperlibrary.cpp @@ -27,11 +27,13 @@ #include "hostosinfo.h" #include "synchronousprocess.h" -#include <QDir> #include <QDateTime> #include <QDebug> +#include <QDir> #include <QRegExp> +#include <set> + namespace Utils { bool BuildableHelperLibrary::isQtChooser(const QFileInfo &info) @@ -71,32 +73,54 @@ static bool isQmake(const QString &path) return !BuildableHelperLibrary::qtVersionForQMake(fi.absoluteFilePath()).isEmpty(); } -FileName BuildableHelperLibrary::findSystemQt(const Environment &env) +static FilePath findQmakeInDir(const FilePath &path) { - const QString qmake = QLatin1String("qmake"); - FileNameList paths = env.path(); - foreach (const FileName &path, paths) { - if (path.isEmpty()) - continue; - - QDir dir(path.toString()); + if (path.isEmpty()) + return FilePath(); + + const QString qmake = "qmake"; + QDir dir(path.toString()); + if (dir.exists(qmake)) { + const QString qmakePath = dir.absoluteFilePath(qmake); + if (isQmake(qmakePath)) + return FilePath::fromString(qmakePath); + } - if (dir.exists(qmake)) { - const QString qmakePath = dir.absoluteFilePath(qmake); - if (isQmake(qmakePath)) - return FileName::fromString(qmakePath); - } + // Prefer qmake-qt5 to qmake-qt4 by sorting the filenames in reverse order. + const QFileInfoList candidates = dir.entryInfoList( + BuildableHelperLibrary::possibleQMakeCommands(), + QDir::Files, QDir::Name | QDir::Reversed); + for (const QFileInfo &fi : candidates) { + if (fi.fileName() == qmake) + continue; + if (isQmake(fi.absoluteFilePath())) + return FilePath::fromFileInfo(fi); + } + return FilePath(); +} - // Prefer qmake-qt5 to qmake-qt4 by sorting the filenames in reverse order. - foreach (const QFileInfo &fi, dir.entryInfoList(possibleQMakeCommands(), QDir::Files, QDir::Name | QDir::Reversed)) { - if (fi.fileName() == qmake) - continue; +FilePath BuildableHelperLibrary::findSystemQt(const Environment &env) +{ + const FilePathList list = findQtsInEnvironment(env, 1); + return list.size() == 1 ? list.first() : FilePath(); +} - if (isQmake(fi.absoluteFilePath())) - return FileName(fi); - } +FilePathList BuildableHelperLibrary::findQtsInEnvironment(const Environment &env, int maxCount) +{ + FilePathList qmakeList; + std::set<QString> canonicalEnvPaths; + const FilePathList paths = env.path(); + for (const FilePath &path : paths) { + if (!canonicalEnvPaths.insert(path.toFileInfo().canonicalFilePath()).second) + continue; + const FilePath qmake = findQmakeInDir(path); + if (qmake.isEmpty()) + continue; + qmakeList << qmake; + if (maxCount != -1 && qmakeList.size() == maxCount) + break; } - return FileName(); + return qmakeList; } QString BuildableHelperLibrary::qtVersionForQMake(const QString &qmakePath) @@ -165,7 +189,7 @@ bool BuildableHelperLibrary::copyFiles(const QString &sourcePath, QString *errorMessage) { // try remove the directory - if (!FileUtils::removeRecursively(FileName::fromString(targetDirectory), errorMessage)) + if (!FileUtils::removeRecursively(FilePath::fromString(targetDirectory), errorMessage)) return false; if (!QDir().mkpath(targetDirectory)) { *errorMessage = QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "The target directory %1 could not be created.").arg(targetDirectory); @@ -196,7 +220,7 @@ bool BuildableHelperLibrary::copyFiles(const QString &sourcePath, // Helper: Run a build process with merged stdout/stderr static inline bool runBuildProcessI(QProcess &proc, - const FileName &binary, + const FilePath &binary, const QStringList &args, int timeoutS, bool ignoreNonNullExitCode, @@ -237,7 +261,7 @@ static inline bool runBuildProcessI(QProcess &proc, // Run a build process with merged stdout/stderr and qWarn about errors. static bool runBuildProcess(QProcess &proc, - const FileName &binary, + const FilePath &binary, const QStringList &args, int timeoutS, bool ignoreNonNullExitCode, @@ -276,7 +300,7 @@ bool BuildableHelperLibrary::buildHelper(const BuildHelperArguments &arguments, arguments.directory)); log->append(newline); - const FileName makeFullPath = arguments.environment.searchInPath(arguments.makeCommand); + const FilePath makeFullPath = arguments.environment.searchInPath(arguments.makeCommand); if (QFileInfo::exists(arguments.directory + QLatin1String("/Makefile"))) { if (makeFullPath.isEmpty()) { *errorMessage = QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", diff --git a/src/libs/utils/buildablehelperlibrary.h b/src/libs/utils/buildablehelperlibrary.h index c818749f2b..45d37d65c4 100644 --- a/src/libs/utils/buildablehelperlibrary.h +++ b/src/libs/utils/buildablehelperlibrary.h @@ -37,7 +37,8 @@ class QTCREATOR_UTILS_EXPORT BuildableHelperLibrary public: // returns the full path to the first qmake, qmake-qt4, qmake4 that has // at least version 2.0.0 and thus is a qt4 qmake - static FileName findSystemQt(const Environment &env); + static FilePath findSystemQt(const Environment &env); + static FilePathList findQtsInEnvironment(const Environment &env, int maxCount = -1); static bool isQtChooser(const QFileInfo &info); static QString qtChooserToQmakePath(const QString &path); // return true if the qmake at qmakePath is a Qt (used by QtVersion) @@ -60,9 +61,9 @@ public: QString directory; Environment environment; - FileName qmakeCommand; + FilePath qmakeCommand; QString targetMode; - FileName mkspec; + FilePath mkspec; QString proFilename; QStringList qmakeArguments; diff --git a/src/libs/utils/checkablemessagebox.cpp b/src/libs/utils/checkablemessagebox.cpp index 857711fd8a..3ec411cfb3 100644 --- a/src/libs/utils/checkablemessagebox.cpp +++ b/src/libs/utils/checkablemessagebox.cpp @@ -32,6 +32,7 @@ #include <QLabel> #include <QPushButton> #include <QSettings> +#include <QStyle> /*! \class Utils::CheckableMessageBox @@ -107,6 +108,7 @@ public: QCheckBox *checkBox = nullptr; QDialogButtonBox *buttonBox = nullptr; QAbstractButton *clickedButton = nullptr; + QMessageBox::Icon icon = QMessageBox::NoIcon; }; CheckableMessageBox::CheckableMessageBox(QWidget *parent) : @@ -148,17 +150,53 @@ void CheckableMessageBox::setText(const QString &t) d->messageLabel->setText(t); } -QPixmap CheckableMessageBox::iconPixmap() const -{ - if (const QPixmap *p = d->pixmapLabel->pixmap()) - return QPixmap(*p); +QMessageBox::Icon CheckableMessageBox::icon() const +{ + return d->icon; +} + +// See QMessageBoxPrivate::standardIcon +static QPixmap pixmapForIcon(QMessageBox::Icon icon, QWidget *w) +{ + const QStyle *style = w ? w->style() : QApplication::style(); + const int iconSize = style->pixelMetric(QStyle::PM_MessageBoxIconSize, nullptr, w); + QIcon tmpIcon; + switch (icon) { + case QMessageBox::Information: + tmpIcon = style->standardIcon(QStyle::SP_MessageBoxInformation, nullptr, w); + break; + case QMessageBox::Warning: + tmpIcon = style->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, w); + break; + case QMessageBox::Critical: + tmpIcon = style->standardIcon(QStyle::SP_MessageBoxCritical, nullptr, w); + break; + case QMessageBox::Question: + tmpIcon = style->standardIcon(QStyle::SP_MessageBoxQuestion, nullptr, w); + break; + default: + break; + } + if (!tmpIcon.isNull()) { + QWindow *window = nullptr; + if (w) { + window = w->windowHandle(); + if (!window) { + if (const QWidget *nativeParent = w->nativeParentWidget()) + window = nativeParent->windowHandle(); + } + } + return tmpIcon.pixmap(window, QSize(iconSize, iconSize)); + } return QPixmap(); } -void CheckableMessageBox::setIconPixmap(const QPixmap &p) +void CheckableMessageBox::setIcon(QMessageBox::Icon icon) { - d->pixmapLabel->setPixmap(p); - d->pixmapLabel->setVisible(!p.isNull()); + d->icon = icon; + const QPixmap pixmap = pixmapForIcon(icon, this); + d->pixmapLabel->setPixmap(pixmap); + d->pixmapLabel->setVisible(!pixmap.isNull()); } bool CheckableMessageBox::isChecked() const @@ -239,7 +277,7 @@ CheckableMessageBox::question(QWidget *parent, { CheckableMessageBox mb(parent); mb.setWindowTitle(title); - mb.setIconPixmap(QMessageBox::standardIcon(QMessageBox::Question)); + mb.setIcon(QMessageBox::Question); mb.setText(question); mb.setCheckBoxText(checkBoxText); mb.setChecked(*checkBoxSetting); @@ -261,7 +299,7 @@ CheckableMessageBox::information(QWidget *parent, { CheckableMessageBox mb(parent); mb.setWindowTitle(title); - mb.setIconPixmap(QMessageBox::standardIcon(QMessageBox::Information)); + mb.setIcon(QMessageBox::Information); mb.setText(text); mb.setCheckBoxText(checkBoxText); mb.setChecked(*checkBoxSetting); @@ -297,9 +335,7 @@ void initDoNotAskAgainMessageBox(CheckableMessageBox &messageBox, const QString DoNotAskAgainType type) { messageBox.setWindowTitle(title); - messageBox.setIconPixmap(QMessageBox::standardIcon(type == Information - ? QMessageBox::Information - : QMessageBox::Question)); + messageBox.setIcon(type == Information ? QMessageBox::Information : QMessageBox::Question); messageBox.setText(text); messageBox.setCheckBoxVisible(true); messageBox.setCheckBoxText(type == Information ? CheckableMessageBox::msgDoNotShowAgain() diff --git a/src/libs/utils/checkablemessagebox.h b/src/libs/utils/checkablemessagebox.h index c6359f72cd..042e88aa96 100644 --- a/src/libs/utils/checkablemessagebox.h +++ b/src/libs/utils/checkablemessagebox.h @@ -42,7 +42,7 @@ class QTCREATOR_UTILS_EXPORT CheckableMessageBox : public QDialog { Q_OBJECT Q_PROPERTY(QString text READ text WRITE setText) - Q_PROPERTY(QPixmap iconPixmap READ iconPixmap WRITE setIconPixmap) + Q_PROPERTY(QMessageBox::Icon icon READ icon WRITE setIcon) Q_PROPERTY(bool isChecked READ isChecked WRITE setChecked) Q_PROPERTY(QString checkBoxText READ checkBoxText WRITE setCheckBoxText) Q_PROPERTY(QDialogButtonBox::StandardButtons buttons READ standardButtons WRITE setStandardButtons) @@ -109,9 +109,8 @@ public: QDialogButtonBox::StandardButton defaultButton() const; void setDefaultButton(QDialogButtonBox::StandardButton s); - // See static QMessageBox::standardPixmap() - QPixmap iconPixmap() const; - void setIconPixmap (const QPixmap &p); + QMessageBox::Icon icon() const; + void setIcon(QMessageBox::Icon icon); // Query the result QAbstractButton *clickedButton() const; diff --git a/src/libs/utils/completingtextedit.cpp b/src/libs/utils/completingtextedit.cpp index f4d7b0441c..3a34973c00 100644 --- a/src/libs/utils/completingtextedit.cpp +++ b/src/libs/utils/completingtextedit.cpp @@ -114,7 +114,7 @@ void CompletingTextEdit::setCompleter(QCompleter *c) completer()->setWidget(this); completer()->setCompletionMode(QCompleter::PopupCompletion); - connect(completer(), static_cast<void (QCompleter::*)(const QString &)>(&QCompleter::activated), + connect(completer(), QOverload<const QString &>::of(&QCompleter::activated), this, [this](const QString &str) { d->insertCompletion(str); }); } diff --git a/src/libs/utils/consoleprocess.h b/src/libs/utils/consoleprocess.h index 28be67f0bf..3dec9838c3 100644 --- a/src/libs/utils/consoleprocess.h +++ b/src/libs/utils/consoleprocess.h @@ -70,7 +70,9 @@ public: QProcess::ProcessError error() const; QString errorString() const; - bool start(const QString &program, const QString &args); + enum class MetaCharMode { Abort, Ignore }; + bool start(const QString &program, const QString &args, + MetaCharMode metaCharMode = MetaCharMode::Abort); public slots: void stop(); diff --git a/src/libs/utils/consoleprocess_unix.cpp b/src/libs/utils/consoleprocess_unix.cpp index 92b69952f6..43afffa0a2 100644 --- a/src/libs/utils/consoleprocess_unix.cpp +++ b/src/libs/utils/consoleprocess_unix.cpp @@ -65,7 +65,7 @@ void ConsoleProcess::setSettings(QSettings *settings) d->m_settings = settings; } -bool ConsoleProcess::start(const QString &program, const QString &args) +bool ConsoleProcess::start(const QString &program, const QString &args, MetaCharMode metaCharMode) { if (isRunning()) return false; @@ -75,7 +75,8 @@ bool ConsoleProcess::start(const QString &program, const QString &args) QtcProcess::SplitError perr; QtcProcess::Arguments pargs = QtcProcess::prepareArgs(args, &perr, HostOsInfo::hostOs(), - &d->m_environment, &d->m_workingDir); + &d->m_environment, &d->m_workingDir, + metaCharMode == MetaCharMode::Abort); QString pcmd; if (perr == QtcProcess::SplitOk) { pcmd = program; @@ -436,12 +437,6 @@ bool ConsoleProcess::startTerminalEmulator(QSettings *settings, const QString &w const Utils::Environment &env) { const TerminalCommand term = terminalEmulator(settings); -#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) - // for 5.9 and below we cannot set the environment - Q_UNUSED(env); - return QProcess::startDetached(term.command, QtcProcess::splitArgs(term.openArgs), - workingDir); -#else QProcess process; process.setProgram(term.command); process.setArguments(QtcProcess::splitArgs(term.openArgs)); @@ -449,7 +444,6 @@ bool ConsoleProcess::startTerminalEmulator(QSettings *settings, const QString &w process.setWorkingDirectory(workingDir); return process.startDetached(); -#endif } } // namespace Utils diff --git a/src/libs/utils/consoleprocess_win.cpp b/src/libs/utils/consoleprocess_win.cpp index 2a68ddaba8..be65c42cc8 100644 --- a/src/libs/utils/consoleprocess_win.cpp +++ b/src/libs/utils/consoleprocess_win.cpp @@ -51,8 +51,10 @@ qint64 ConsoleProcess::applicationMainThreadID() const return d->m_appMainThreadId; } -bool ConsoleProcess::start(const QString &program, const QString &args) +bool ConsoleProcess::start(const QString &program, const QString &args, MetaCharMode metaCharMode) { + Q_UNUSED(metaCharMode); + if (isRunning()) return false; diff --git a/src/libs/utils/cpplanguage_details.h b/src/libs/utils/cpplanguage_details.h index 43474d03cb..e9c9a5aa40 100644 --- a/src/libs/utils/cpplanguage_details.h +++ b/src/libs/utils/cpplanguage_details.h @@ -29,9 +29,10 @@ namespace Utils { -enum class Language : unsigned char { C, Cxx }; +enum class Language : unsigned char { None, C, Cxx }; enum class LanguageVersion : unsigned char { + None, C89, C99, C11, diff --git a/src/libs/utils/delegates.cpp b/src/libs/utils/delegates.cpp index a677c8c992..2240e8a6a4 100644 --- a/src/libs/utils/delegates.cpp +++ b/src/libs/utils/delegates.cpp @@ -84,7 +84,7 @@ void AnnotatedItemDelegate::paint(QPainter *painter, painter->save(); painter->setPen(disabled.color(QPalette::WindowText)); - static int extra = opt.fontMetrics.width(m_delimiter) + 10; + static int extra = opt.fontMetrics.horizontalAdvance(m_delimiter) + 10; const QPixmap &pixmap = opt.icon.pixmap(opt.decorationSize); const QRect &iconRect = style->itemPixmapRect(opt.rect, opt.decorationAlignment, pixmap); const QRect &displayRect = style->itemTextRect(opt.fontMetrics, opt.rect, diff --git a/src/libs/utils/detailsbutton.cpp b/src/libs/utils/detailsbutton.cpp index 5f2c88eca3..329975afdb 100644 --- a/src/libs/utils/detailsbutton.cpp +++ b/src/libs/utils/detailsbutton.cpp @@ -79,7 +79,7 @@ DetailsButton::DetailsButton(QWidget *parent) : QAbstractButton(parent), m_fader QSize DetailsButton::sizeHint() const { // TODO: Adjust this when icons become available! - const int w = fontMetrics().width(text()) + 32; + const int w = fontMetrics().horizontalAdvance(text()) + 32; if (HostOsInfo::isMacHost()) return QSize(w, 34); return QSize(w, 22); diff --git a/src/libs/utils/elidinglabel.cpp b/src/libs/utils/elidinglabel.cpp index e584bd8bb6..1d90665af5 100644 --- a/src/libs/utils/elidinglabel.cpp +++ b/src/libs/utils/elidinglabel.cpp @@ -66,7 +66,7 @@ void ElidingLabel::paintEvent(QPaintEvent *) QRect contents = contentsRect().adjusted(m, m, -m, -m); QFontMetrics fm = fontMetrics(); QString txt = text(); - if (txt.length() > 4 && fm.width(txt) > contents.width()) { + if (txt.length() > 4 && fm.horizontalAdvance(txt) > contents.width()) { setToolTip(txt); txt = fm.elidedText(txt, m_elideMode, contents.width()); } else { diff --git a/src/libs/utils/environment.cpp b/src/libs/utils/environment.cpp index a82d6c27f0..d61a75ebf7 100644 --- a/src/libs/utils/environment.cpp +++ b/src/libs/utils/environment.cpp @@ -392,14 +392,14 @@ void Environment::clear() m_values.clear(); } -FileName Environment::searchInDirectory(const QStringList &execs, const FileName &directory, - QSet<FileName> &alreadyChecked) const +FilePath Environment::searchInDirectory(const QStringList &execs, const FilePath &directory, + QSet<FilePath> &alreadyChecked) const { const int checkedCount = alreadyChecked.count(); alreadyChecked.insert(directory); if (directory.isEmpty() || alreadyChecked.count() == checkedCount) - return FileName(); + return FilePath(); const QString dir = directory.toString(); @@ -407,9 +407,9 @@ FileName Environment::searchInDirectory(const QStringList &execs, const FileName for (const QString &exec : execs) { fi.setFile(dir, exec); if (fi.isFile() && fi.isExecutable()) - return FileName::fromString(fi.absoluteFilePath()); + return FilePath::fromString(fi.absoluteFilePath()); } - return FileName(); + return FilePath(); } QStringList Environment::appendExeExtensions(const QString &executable) const @@ -435,23 +435,25 @@ bool Environment::isSameExecutable(const QString &exe1, const QString &exe2) con const QStringList exe2List = appendExeExtensions(exe2); for (const QString &i1 : exe1List) { for (const QString &i2 : exe2List) { - const FileName f1 = FileName::fromString(i1); - const FileName f2 = FileName::fromString(i2); + const FilePath f1 = FilePath::fromString(i1); + const FilePath f2 = FilePath::fromString(i2); if (f1 == f2) return true; if (FileUtils::resolveSymlinks(f1) == FileUtils::resolveSymlinks(f2)) return true; + if (FileUtils::fileId(f1) == FileUtils::fileId(f2)) + return true; } } return false; } -FileName Environment::searchInPath(const QString &executable, - const FileNameList &additionalDirs, +FilePath Environment::searchInPath(const QString &executable, + const FilePathList &additionalDirs, const PathFilter &func) const { if (executable.isEmpty()) - return FileName(); + return FilePath(); const QString exec = QDir::cleanPath(expandVariables(executable)); const QFileInfo fi(exec); @@ -462,34 +464,34 @@ FileName Environment::searchInPath(const QString &executable, for (const QString &path : execs) { QFileInfo pfi = QFileInfo(path); if (pfi.isFile() && pfi.isExecutable()) - return FileName::fromString(path); + return FilePath::fromString(path); } - return FileName::fromString(exec); + return FilePath::fromString(exec); } - QSet<FileName> alreadyChecked; - for (const FileName &dir : additionalDirs) { - FileName tmp = searchInDirectory(execs, dir, alreadyChecked); + QSet<FilePath> alreadyChecked; + for (const FilePath &dir : additionalDirs) { + FilePath tmp = searchInDirectory(execs, dir, alreadyChecked); if (!tmp.isEmpty() && (!func || func(tmp))) return tmp; } if (executable.contains('/')) - return FileName(); + return FilePath(); - for (const FileName &p : path()) { - FileName tmp = searchInDirectory(execs, p, alreadyChecked); + for (const FilePath &p : path()) { + FilePath tmp = searchInDirectory(execs, p, alreadyChecked); if (!tmp.isEmpty() && (!func || func(tmp))) return tmp; } - return FileName(); + return FilePath(); } -FileNameList Environment::path() const +FilePathList Environment::path() const { const QStringList pathComponents = value("PATH") .split(OsSpecificAspects::pathListSeparator(m_osType), QString::SkipEmptyParts); - return Utils::transform(pathComponents, &FileName::fromUserInput); + return Utils::transform(pathComponents, &FilePath::fromUserInput); } QString Environment::value(const QString &key) const @@ -688,6 +690,11 @@ QString Environment::expandVariables(const QString &input) const return result; } +FilePath Environment::expandVariables(const FilePath &variables) const +{ + return FilePath::fromString(expandVariables(variables.toString())); +} + QStringList Environment::expandVariables(const QStringList &variables) const { return Utils::transform(variables, [this](const QString &i) { return expandVariables(i); }); diff --git a/src/libs/utils/environment.h b/src/libs/utils/environment.h index cab78a082b..f1e957ab6d 100644 --- a/src/libs/utils/environment.h +++ b/src/libs/utils/environment.h @@ -124,17 +124,18 @@ public: Environment::const_iterator constEnd() const; Environment::const_iterator constFind(const QString &name) const; - using PathFilter = std::function<bool(const FileName &)>; - FileName searchInPath(const QString &executable, - const FileNameList &additionalDirs = FileNameList(), + using PathFilter = std::function<bool(const FilePath &)>; + FilePath searchInPath(const QString &executable, + const FilePathList &additionalDirs = FilePathList(), const PathFilter &func = PathFilter()) const; - FileNameList path() const; + FilePathList path() const; QStringList appendExeExtensions(const QString &executable) const; bool isSameExecutable(const QString &exe1, const QString &exe2) const; QString expandVariables(const QString &input) const; + FilePath expandVariables(const FilePath &input) const; QStringList expandVariables(const QStringList &input) const; bool operator!=(const Environment &other) const; @@ -143,8 +144,8 @@ public: static void modifySystemEnvironment(const QList<EnvironmentItem> &list); // use with care!!! private: - FileName searchInDirectory(const QStringList &execs, const FileName &directory, - QSet<FileName> &alreadyChecked) const; + FilePath searchInDirectory(const QStringList &execs, const FilePath &directory, + QSet<FilePath> &alreadyChecked) const; QMap<QString, QString> m_values; OsType m_osType; }; diff --git a/src/libs/utils/filecrumblabel.cpp b/src/libs/utils/filecrumblabel.cpp index a4bbe37c44..cf03af553c 100644 --- a/src/libs/utils/filecrumblabel.cpp +++ b/src/libs/utils/filecrumblabel.cpp @@ -38,22 +38,22 @@ FileCrumbLabel::FileCrumbLabel(QWidget *parent) setTextFormat(Qt::RichText); setWordWrap(true); connect(this, &QLabel::linkActivated, this, [this](const QString &url) { - emit pathClicked(FileName::fromString(QUrl(url).toLocalFile())); + emit pathClicked(FilePath::fromString(QUrl(url).toLocalFile())); }); - setPath(FileName()); + setPath(FilePath()); } -static QString linkForPath(const FileName &path, const QString &display) +static QString linkForPath(const FilePath &path, const QString &display) { return "<a href=\"" + QUrl::fromLocalFile(path.toString()).toString(QUrl::FullyEncoded) + "\">" + display + "</a>"; } -void FileCrumbLabel::setPath(const FileName &path) +void FileCrumbLabel::setPath(const FilePath &path) { QStringList links; - FileName current = path; + FilePath current = path; while (!current.isEmpty()) { const QString fileName = current.fileName(); if (!fileName.isEmpty()) { diff --git a/src/libs/utils/filecrumblabel.h b/src/libs/utils/filecrumblabel.h index 6320b115c0..05dd050812 100644 --- a/src/libs/utils/filecrumblabel.h +++ b/src/libs/utils/filecrumblabel.h @@ -38,10 +38,10 @@ class QTCREATOR_UTILS_EXPORT FileCrumbLabel : public QLabel public: FileCrumbLabel(QWidget *parent = nullptr); - void setPath(const FileName &path); + void setPath(const FilePath &path); signals: - void pathClicked(const FileName &path); + void pathClicked(const FilePath &path); }; } // Utils diff --git a/src/libs/utils/fileinprojectfinder.cpp b/src/libs/utils/fileinprojectfinder.cpp index 2be64260e8..3dbde17792 100644 --- a/src/libs/utils/fileinprojectfinder.cpp +++ b/src/libs/utils/fileinprojectfinder.cpp @@ -24,15 +24,20 @@ ****************************************************************************/ #include "fileinprojectfinder.h" + +#include "algorithm.h" #include "fileutils.h" #include "hostosinfo.h" +#include "qrcparser.h" #include "qtcassert.h" +#include <QCursor> #include <QDebug> +#include <QDir> #include <QFileInfo> #include <QLoggingCategory> +#include <QMenu> #include <QUrl> -#include <QDir> #include <algorithm> @@ -77,7 +82,7 @@ static bool checkPath(const QString &candidate, int matchLength, FileInProjectFinder::FileInProjectFinder() = default; FileInProjectFinder::~FileInProjectFinder() = default; -void FileInProjectFinder::setProjectDirectory(const FileName &absoluteProjectPath) +void FileInProjectFinder::setProjectDirectory(const FilePath &absoluteProjectPath) { if (absoluteProjectPath == m_projectDir) return; @@ -90,21 +95,22 @@ void FileInProjectFinder::setProjectDirectory(const FileName &absoluteProjectPat m_cache.clear(); } -FileName FileInProjectFinder::projectDirectory() const +FilePath FileInProjectFinder::projectDirectory() const { return m_projectDir; } -void FileInProjectFinder::setProjectFiles(const FileNameList &projectFiles) +void FileInProjectFinder::setProjectFiles(const FilePathList &projectFiles) { if (m_projectFiles == projectFiles) return; m_projectFiles = projectFiles; m_cache.clear(); + m_qrcUrlFinder.setProjectFiles(projectFiles); } -void FileInProjectFinder::setSysroot(const FileName &sysroot) +void FileInProjectFinder::setSysroot(const FilePath &sysroot) { if (m_sysroot == sysroot) return; @@ -113,7 +119,7 @@ void FileInProjectFinder::setSysroot(const FileName &sysroot) m_cache.clear(); } -void FileInProjectFinder::addMappedPath(const FileName &localFilePath, const QString &remoteFilePath) +void FileInProjectFinder::addMappedPath(const FilePath &localFilePath, const QString &remoteFilePath) { const QStringList segments = remoteFilePath.split('/', QString::SkipEmptyParts); @@ -136,18 +142,29 @@ void FileInProjectFinder::addMappedPath(const FileName &localFilePath, const QSt folder specified. Third, we walk the list of project files, and search for a file name match there. If all fails, it returns the original path from the file URL. */ -QString FileInProjectFinder::findFile(const QUrl &fileUrl, bool *success) const +FilePathList FileInProjectFinder::findFile(const QUrl &fileUrl, bool *success) const { qCDebug(finderLog) << "FileInProjectFinder: trying to find file" << fileUrl.toString() << "..."; + if (fileUrl.scheme() == "qrc" || fileUrl.toString().startsWith(':')) { + const FilePathList result = m_qrcUrlFinder.find(fileUrl); + if (!result.isEmpty()) { + if (success) + *success = true; + return result; + } + } + QString originalPath = fileUrl.toLocalFile(); if (originalPath.isEmpty()) // e.g. qrc:// originalPath = fileUrl.path(); - QString result = originalPath; + FilePathList result; bool found = findFileOrDirectory(originalPath, [&](const QString &fileName, int) { - result = fileName; + result << FilePath::fromString(fileName); }); + if (!found) + result << FilePath::fromString(originalPath); if (success) *success = found; @@ -155,12 +172,12 @@ QString FileInProjectFinder::findFile(const QUrl &fileUrl, bool *success) const return result; } -bool FileInProjectFinder::handleSuccess(const QString &originalPath, const QString &found, +bool FileInProjectFinder::handleSuccess(const QString &originalPath, const QStringList &found, int matchLength, const char *where) const { qCDebug(finderLog) << "FileInProjectFinder: found" << found << where; CacheEntry entry; - entry.path = found; + entry.paths = found; entry.matchLength = matchLength; m_cache.insert(originalPath, entry); return true; @@ -189,8 +206,10 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH if (node) { if (!node->localPath.isEmpty()) { const QString localPath = node->localPath.toString(); - if (checkPath(localPath, origLength, fileHandler, directoryHandler)) - return handleSuccess(originalPath, localPath, origLength, "in mapped paths"); + if (checkPath(localPath, origLength, fileHandler, directoryHandler)) { + return handleSuccess(originalPath, QStringList(localPath), origLength, + "in mapped paths"); + } } else if (directoryHandler) { directoryHandler(node->children.keys(), origLength); qCDebug(finderLog) << "FileInProjectFinder: found virtual directory" << originalPath @@ -203,13 +222,18 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH if (it != m_cache.end()) { qCDebug(finderLog) << "FileInProjectFinder: checking cache ..."; // check if cached path is still there - const CacheEntry &candidate = it.value(); - if (checkPath(candidate.path, candidate.matchLength, fileHandler, directoryHandler)) { - qCDebug(finderLog) << "FileInProjectFinder: found" << candidate.path << "in the cache"; - return true; - } else { - m_cache.erase(it); + CacheEntry &candidate = it.value(); + for (auto pathIt = candidate.paths.begin(); pathIt != candidate.paths.end();) { + if (checkPath(*pathIt, candidate.matchLength, fileHandler, directoryHandler)) { + qCDebug(finderLog) << "FileInProjectFinder: found" << *pathIt << "in the cache"; + ++pathIt; + } else { + pathIt = candidate.paths.erase(pathIt); + } } + if (!candidate.paths.empty()) + return true; + m_cache.erase(it); } if (!m_projectDir.isEmpty()) { @@ -231,7 +255,7 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH if (prefixToIgnore == -1 && checkPath(originalPath, origLength, fileHandler, directoryHandler)) { - return handleSuccess(originalPath, originalPath, origLength, + return handleSuccess(originalPath, QStringList(originalPath), origLength, "in project directory"); } } @@ -254,8 +278,11 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH candidate.remove(0, prefixToIgnore); candidate.prepend(m_projectDir.toString()); const int matchLength = origLength - prefixToIgnore; - if (checkPath(candidate, matchLength, fileHandler, directoryHandler)) - return handleSuccess(originalPath, candidate, matchLength, "in project directory"); + // FIXME: This might be a worse match than what we find later. + if (checkPath(candidate, matchLength, fileHandler, directoryHandler)) { + return handleSuccess(originalPath, QStringList(candidate), matchLength, + "in project directory"); + } prefixToIgnore = originalPath.indexOf(separator, prefixToIgnore + 1); } } @@ -264,31 +291,38 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH qCDebug(finderLog) << "FileInProjectFinder: checking project files ..."; QStringList matches; - const QString lastSegment = FileName::fromString(originalPath).fileName(); + const QString lastSegment = FilePath::fromString(originalPath).fileName(); if (fileHandler) matches.append(filesWithSameFileName(lastSegment)); if (directoryHandler) matches.append(pathSegmentsWithSameName(lastSegment)); - const QString matchedFilePath = bestMatch(matches, originalPath); - const int matchLength = commonPostFixLength(matchedFilePath, originalPath); - if (!matchedFilePath.isEmpty() - && checkPath(matchedFilePath, matchLength, fileHandler, directoryHandler)) { - return handleSuccess(originalPath, matchedFilePath, matchLength, - "when matching project files"); + const QStringList matchedFilePaths = bestMatches(matches, originalPath); + if (!matchedFilePaths.empty()) { + const int matchLength = commonPostFixLength(matchedFilePaths.first(), originalPath); + QStringList hits; + for (const QString &matchedFilePath : matchedFilePaths) { + if (checkPath(matchedFilePath, matchLength, fileHandler, directoryHandler)) + hits << matchedFilePath; + } + if (!hits.empty()) + return handleSuccess(originalPath, hits, matchLength, "when matching project files"); } CacheEntry foundPath = findInSearchPaths(originalPath, fileHandler, directoryHandler); - if (!foundPath.path.isEmpty()) - return handleSuccess(originalPath, foundPath.path, foundPath.matchLength, "in search path"); + if (!foundPath.paths.isEmpty()) { + return handleSuccess(originalPath, foundPath.paths, foundPath.matchLength, + "in search path"); + } qCDebug(finderLog) << "FileInProjectFinder: checking absolute path in sysroot ..."; // check if absolute path is found in sysroot if (!m_sysroot.isEmpty()) { - FileName sysrootPath = m_sysroot; - sysrootPath.appendPath(originalPath); - if (checkPath(sysrootPath.toString(), origLength, fileHandler, directoryHandler)) - return handleSuccess(originalPath, sysrootPath.toString(), origLength, "in sysroot"); + const FilePath sysrootPath = m_sysroot.pathAppended(originalPath); + if (checkPath(sysrootPath.toString(), origLength, fileHandler, directoryHandler)) { + return handleSuccess(originalPath, QStringList(sysrootPath.toString()), origLength, + "in sysroot"); + } } qCDebug(finderLog) << "FileInProjectFinder: couldn't find file!"; @@ -299,10 +333,10 @@ bool FileInProjectFinder::findFileOrDirectory(const QString &originalPath, FileH FileInProjectFinder::CacheEntry FileInProjectFinder::findInSearchPaths( const QString &filePath, FileHandler fileHandler, DirectoryHandler directoryHandler) const { - for (const FileName &dirPath : m_searchDirectories) { + for (const FilePath &dirPath : m_searchDirectories) { const CacheEntry found = findInSearchPath(dirPath.toString(), filePath, fileHandler, directoryHandler); - if (!found.path.isEmpty()) + if (!found.paths.isEmpty()) return found; } @@ -327,17 +361,17 @@ FileInProjectFinder::CacheEntry FileInProjectFinder::findInSearchPath( QString s = filePath; while (!s.isEmpty()) { CacheEntry result; - result.path = searchPath + QLatin1Char('/') + s; + result.paths << searchPath + '/' + s; result.matchLength = s.length() + 1; - qCDebug(finderLog) << "FileInProjectFinder: trying" << result.path; + qCDebug(finderLog) << "FileInProjectFinder: trying" << result.paths.first(); - if (checkPath(result.path, result.matchLength, fileHandler, directoryHandler)) + if (checkPath(result.paths.first(), result.matchLength, fileHandler, directoryHandler)) return result; QString next = chopFirstDir(s); if (next.isEmpty()) { if (directoryHandler && QFileInfo(searchPath).fileName() == s) { - result.path = searchPath; + result.paths = QStringList{searchPath}; directoryHandler(QDir(searchPath).entryList(), result.matchLength); return result; } @@ -352,7 +386,7 @@ FileInProjectFinder::CacheEntry FileInProjectFinder::findInSearchPath( QStringList FileInProjectFinder::filesWithSameFileName(const QString &fileName) const { QStringList result; - foreach (const FileName &f, m_projectFiles) { + foreach (const FilePath &f, m_projectFiles) { if (f.fileName() == fileName) result << f.toString(); } @@ -362,8 +396,8 @@ QStringList FileInProjectFinder::filesWithSameFileName(const QString &fileName) QStringList FileInProjectFinder::pathSegmentsWithSameName(const QString &pathSegment) const { QStringList result; - for (const FileName &f : m_projectFiles) { - FileName currentPath = f.parentDir(); + for (const FilePath &f : m_projectFiles) { + FilePath currentPath = f.parentDir(); do { if (currentPath.fileName() == pathSegment) { if (result.isEmpty() || result.last() != currentPath.toString()) @@ -386,32 +420,38 @@ int FileInProjectFinder::commonPostFixLength(const QString &candidatePath, return rank; } -QString FileInProjectFinder::bestMatch(const QStringList &filePaths, const QString &filePathToFind) +QStringList FileInProjectFinder::bestMatches(const QStringList &filePaths, + const QString &filePathToFind) { if (filePaths.isEmpty()) - return QString(); + return {}; if (filePaths.length() == 1) { qCDebug(finderLog) << "FileInProjectFinder: found" << filePaths.first() << "in project files"; - return filePaths.first(); + return filePaths; } - auto it = std::max_element(filePaths.constBegin(), filePaths.constEnd(), - [&filePathToFind] (const QString &a, const QString &b) -> bool { - return commonPostFixLength(a, filePathToFind) < commonPostFixLength(b, filePathToFind); - }); - if (it != filePaths.cend()) { - qCDebug(finderLog) << "FileInProjectFinder: found best match" << *it << "in project files"; - return *it; + int bestRank = -1; + QStringList bestFilePaths; + for (const QString &fp : filePaths) { + const int currentRank = commonPostFixLength(fp, filePathToFind); + if (currentRank < bestRank) + continue; + if (currentRank > bestRank) { + bestRank = currentRank; + bestFilePaths.clear(); + } + bestFilePaths << fp; } - return QString(); + QTC_CHECK(!bestFilePaths.empty()); + return bestFilePaths; } -FileNameList FileInProjectFinder::searchDirectories() const +FilePathList FileInProjectFinder::searchDirectories() const { return m_searchDirectories; } -void FileInProjectFinder::setAdditionalSearchDirectories(const FileNameList &searchDirectories) +void FileInProjectFinder::setAdditionalSearchDirectories(const FilePathList &searchDirectories) { m_searchDirectories = searchDirectories; } @@ -421,4 +461,43 @@ FileInProjectFinder::PathMappingNode::~PathMappingNode() qDeleteAll(children); } +FilePathList FileInProjectFinder::QrcUrlFinder::find(const QUrl &fileUrl) const +{ + const auto fileIt = m_fileCache.constFind(fileUrl); + if (fileIt != m_fileCache.cend()) + return fileIt.value(); + QStringList hits; + for (const FilePath &f : m_allQrcFiles) { + QrcParser::Ptr &qrcParser = m_parserCache[f]; + if (!qrcParser) + qrcParser = QrcParser::parseQrcFile(f.toString(), QString()); + if (!qrcParser->isValid()) + continue; + qrcParser->collectFilesAtPath(QrcParser::normalizedQrcFilePath(fileUrl.toString()), &hits); + } + hits.removeDuplicates(); + const FilePathList result = transform(hits, &FilePath::fromString); + m_fileCache.insert(fileUrl, result); + return result; +} + +void FileInProjectFinder::QrcUrlFinder::setProjectFiles(const FilePathList &projectFiles) +{ + m_allQrcFiles = filtered(projectFiles, [](const FilePath &f) { return f.endsWith(".qrc"); }); + m_fileCache.clear(); + m_parserCache.clear(); +} + +FilePath chooseFileFromList(const FilePathList &candidates) +{ + if (candidates.length() == 1) + return candidates.first(); + QMenu filesMenu; + for (const FilePath &candidate : candidates) + filesMenu.addAction(candidate.toUserOutput()); + if (const QAction * const action = filesMenu.exec(QCursor::pos())) + return FilePath::fromUserInput(action->text()); + return FilePath(); +} + } // namespace Utils diff --git a/src/libs/utils/fileinprojectfinder.h b/src/libs/utils/fileinprojectfinder.h index 43a954ff93..66b5317235 100644 --- a/src/libs/utils/fileinprojectfinder.h +++ b/src/libs/utils/fileinprojectfinder.h @@ -29,11 +29,13 @@ #include <utils/fileutils.h> #include <QHash> +#include <QSharedPointer> #include <QStringList> QT_FORWARD_DECLARE_CLASS(QUrl) namespace Utils { +class QrcParser; class QTCREATOR_UTILS_EXPORT FileInProjectFinder { @@ -45,34 +47,44 @@ public: FileInProjectFinder(); ~FileInProjectFinder(); - void setProjectDirectory(const FileName &absoluteProjectPath); - FileName projectDirectory() const; + void setProjectDirectory(const FilePath &absoluteProjectPath); + FilePath projectDirectory() const; - void setProjectFiles(const FileNameList &projectFiles); - void setSysroot(const FileName &sysroot); + void setProjectFiles(const FilePathList &projectFiles); + void setSysroot(const FilePath &sysroot); - void addMappedPath(const FileName &localFilePath, const QString &remoteFilePath); + void addMappedPath(const FilePath &localFilePath, const QString &remoteFilePath); - QString findFile(const QUrl &fileUrl, bool *success = nullptr) const; + FilePathList findFile(const QUrl &fileUrl, bool *success = nullptr) const; bool findFileOrDirectory(const QString &originalPath, FileHandler fileHandler = nullptr, DirectoryHandler directoryHandler = nullptr) const; - FileNameList searchDirectories() const; - void setAdditionalSearchDirectories(const FileNameList &searchDirectories); + FilePathList searchDirectories() const; + void setAdditionalSearchDirectories(const FilePathList &searchDirectories); private: struct PathMappingNode { ~PathMappingNode(); - FileName localPath; + FilePath localPath; QHash<QString, PathMappingNode *> children; }; struct CacheEntry { - QString path; + QStringList paths; int matchLength = 0; }; + class QrcUrlFinder { + public: + FilePathList find(const QUrl &fileUrl) const; + void setProjectFiles(const FilePathList &projectFiles); + private: + FilePathList m_allQrcFiles; + mutable QHash<QUrl, FilePathList> m_fileCache; + mutable QHash<FilePath, QSharedPointer<QrcParser>> m_parserCache; + }; + CacheEntry findInSearchPaths(const QString &filePath, FileHandler fileHandler, DirectoryHandler directoryHandler) const; static CacheEntry findInSearchPath(const QString &searchPath, const QString &filePath, @@ -80,19 +92,22 @@ private: QStringList filesWithSameFileName(const QString &fileName) const; QStringList pathSegmentsWithSameName(const QString &path) const; - bool handleSuccess(const QString &originalPath, const QString &found, int confidence, + bool handleSuccess(const QString &originalPath, const QStringList &found, int confidence, const char *where) const; static int commonPostFixLength(const QString &candidatePath, const QString &filePathToFind); - static QString bestMatch(const QStringList &filePaths, const QString &filePathToFind); + static QStringList bestMatches(const QStringList &filePaths, const QString &filePathToFind); - FileName m_projectDir; - FileName m_sysroot; - FileNameList m_projectFiles; - FileNameList m_searchDirectories; + FilePath m_projectDir; + FilePath m_sysroot; + FilePathList m_projectFiles; + FilePathList m_searchDirectories; PathMappingNode m_pathMapRoot; mutable QHash<QString, CacheEntry> m_cache; + QrcUrlFinder m_qrcUrlFinder; }; +QTCREATOR_UTILS_EXPORT FilePath chooseFileFromList(const FilePathList &candidates); + } // namespace Utils diff --git a/src/libs/utils/filesearch.cpp b/src/libs/utils/filesearch.cpp index c34532a1de..0bdf3991c5 100644 --- a/src/libs/utils/filesearch.cpp +++ b/src/libs/utils/filesearch.cpp @@ -482,7 +482,7 @@ static bool matches(const QList<QRegExp> &exprList, const QString &filePath) { return Utils::anyOf(exprList, [&filePath](QRegExp reg) { return (reg.exactMatch(filePath) - || reg.exactMatch(FileName::fromString(filePath).fileName())); + || reg.exactMatch(FilePath::fromString(filePath).fileName())); }); } diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp index a476cd8d89..acf9c6190d 100644 --- a/src/libs/utils/fileutils.cpp +++ b/src/libs/utils/fileutils.cpp @@ -28,20 +28,27 @@ #include "algorithm.h" #include "qtcassert.h" +#include "qtcprocess.h" #include <QDataStream> #include <QDir> #include <QDebug> #include <QDateTime> +#include <QOperatingSystemVersion> #include <QRegExp> #include <QTimer> #include <QUrl> +#include <qplatformdefs.h> #ifdef QT_GUI_LIB #include <QMessageBox> #endif #ifdef Q_OS_WIN +// We need defines for Windows 8 +#undef _WIN32_WINNT +#define _WIN32_WINNT _WIN32_WINNT_WIN8 + #include <qt_windows.h> #include <shlobj.h> #endif @@ -51,7 +58,7 @@ #endif QT_BEGIN_NAMESPACE -QDebug operator<<(QDebug dbg, const Utils::FileName &c) +QDebug operator<<(QDebug dbg, const Utils::FilePath &c) { return dbg << c.toString(); } @@ -60,6 +67,34 @@ QT_END_NAMESPACE namespace Utils { +/*! \class Utils::CommandLine + + \brief The CommandLine class represents a command line of a QProcess + or similar utility. + +*/ + +void CommandLine::addArg(const QString &arg, OsType osType) +{ + QtcProcess::addArg(&m_arguments, arg, osType); +} + +void CommandLine::addArgs(const QStringList &inArgs, OsType osType) +{ + for (const QString &arg : inArgs) + addArg(arg, osType); +} + +void CommandLine::addArgs(const QString &inArgs) +{ + QtcProcess::addArgs(&m_arguments, inArgs); +} + +QString CommandLine::toUserOutput() const +{ + return m_executable.toUserOutput() + ' ' + m_arguments; +} + /*! \class Utils::FileUtils \brief The FileUtils class contains file and directory related convenience @@ -74,7 +109,7 @@ namespace Utils { Returns whether the operation succeeded. */ -bool FileUtils::removeRecursively(const FileName &filePath, QString *error) +bool FileUtils::removeRecursively(const FilePath &filePath, QString *error) { QFileInfo fileInfo = filePath.toFileInfo(); if (!fileInfo.exists() && !fileInfo.isSymLink()) @@ -101,7 +136,7 @@ bool FileUtils::removeRecursively(const FileName &filePath, QString *error) QStringList fileNames = dir.entryList(QDir::Files | QDir::Hidden | QDir::System | QDir::Dirs | QDir::NoDotAndDotDot); foreach (const QString &fileName, fileNames) { - if (!removeRecursively(FileName(filePath).appendPath(fileName), error)) + if (!removeRecursively(filePath.pathAppended(fileName), error)) return false; } if (!QDir::root().rmdir(dir.path())) { @@ -140,7 +175,7 @@ bool FileUtils::removeRecursively(const FileName &filePath, QString *error) Returns whether the operation succeeded. */ -bool FileUtils::copyRecursively(const FileName &srcFilePath, const FileName &tgtFilePath, +bool FileUtils::copyRecursively(const FilePath &srcFilePath, const FilePath &tgtFilePath, QString *error, const std::function<bool (QFileInfo, QFileInfo, QString *)> ©Helper) { QFileInfo srcFileInfo = srcFilePath.toFileInfo(); @@ -160,10 +195,8 @@ bool FileUtils::copyRecursively(const FileName &srcFilePath, const FileName &tgt QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System); foreach (const QString &fileName, fileNames) { - FileName newSrcFilePath = srcFilePath; - newSrcFilePath.appendPath(fileName); - FileName newTgtFilePath = tgtFilePath; - newTgtFilePath.appendPath(fileName); + const FilePath newSrcFilePath = srcFilePath.pathAppended(fileName); + const FilePath newTgtFilePath = tgtFilePath.pathAppended(fileName); if (!copyRecursively(newSrcFilePath, newTgtFilePath, error, copyHelper)) return false; } @@ -185,23 +218,23 @@ bool FileUtils::copyRecursively(const FileName &srcFilePath, const FileName &tgt } /*! - If \a filePath is a directory, the function will recursively check all files and return - true if one of them is newer than \a timeStamp. If \a filePath is a single file, true will + If this is a directory, the function will recursively check all files and return + true if one of them is newer than \a timeStamp. If this is a single file, true will be returned if the file is newer than \a timeStamp. Returns whether at least one file in \a filePath has a newer date than \a timeStamp. */ -bool FileUtils::isFileNewerThan(const FileName &filePath, const QDateTime &timeStamp) +bool FilePath::isNewerThan(const QDateTime &timeStamp) const { - QFileInfo fileInfo = filePath.toFileInfo(); + const QFileInfo fileInfo = toFileInfo(); if (!fileInfo.exists() || fileInfo.lastModified() >= timeStamp) return true; if (fileInfo.isDir()) { - const QStringList dirContents = QDir(filePath.toString()) + const QStringList dirContents = QDir(toString()) .entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); - foreach (const QString &curFileName, dirContents) { - if (isFileNewerThan(FileName(filePath).appendPath(curFileName), timeStamp)) + for (const QString &curFileName : dirContents) { + if (pathAppended(curFileName).isNewerThan(timeStamp)) return true; } } @@ -218,30 +251,30 @@ bool FileUtils::isFileNewerThan(const FileName &filePath, const QDateTime &timeS Returns the symlink target file path. */ -FileName FileUtils::resolveSymlinks(const FileName &path) +FilePath FileUtils::resolveSymlinks(const FilePath &path) { QFileInfo f = path.toFileInfo(); int links = 16; while (links-- && f.isSymLink()) f.setFile(f.dir(), f.symLinkTarget()); if (links <= 0) - return FileName(); - return FileName::fromString(f.filePath()); + return FilePath(); + return FilePath::fromString(f.filePath()); } /*! - Recursively resolves possibly present symlinks in \a filePath. + Recursively resolves possibly present symlinks in this file name. Unlike QFileInfo::canonicalFilePath(), this function will not return an empty string if path doesn't exist. Returns the canonical path. */ -FileName FileUtils::canonicalPath(const FileName &path) +FilePath FilePath::canonicalPath() const { - const QString result = path.toFileInfo().canonicalFilePath(); + const QString result = toFileInfo().canonicalFilePath(); if (result.isEmpty()) - return path; - return FileName::fromString(result); + return *this; + return FilePath::fromString(result); } /*! @@ -250,16 +283,16 @@ FileName FileUtils::canonicalPath(const FileName &path) Returns the possibly shortened path with native separators. */ -QString FileUtils::shortNativePath(const FileName &path) +QString FilePath::shortNativePath() const { if (HostOsInfo::isAnyUnixHost()) { - const FileName home = FileName::fromString(QDir::cleanPath(QDir::homePath())); - if (path.isChildOf(home)) { + const FilePath home = FilePath::fromString(QDir::cleanPath(QDir::homePath())); + if (isChildOf(home)) { return QLatin1Char('~') + QDir::separator() - + QDir::toNativeSeparators(path.relativeChildPath(home).toString()); + + QDir::toNativeSeparators(relativeChildPath(home).toString()); } } - return path.toUserOutput(); + return toUserOutput(); } QString FileUtils::fileSystemFriendlyName(const QString &name) @@ -293,10 +326,10 @@ QString FileUtils::qmakeFriendlyName(const QString &name) return fileSystemFriendlyName(result); } -bool FileUtils::makeWritable(const FileName &path) +bool FileUtils::makeWritable(const FilePath &path) { - const QString fileName = path.toString(); - return QFile::setPermissions(fileName, QFile::permissions(fileName) | QFile::WriteUser); + const QString filePath = path.toString(); + return QFile::setPermissions(filePath, QFile::permissions(filePath) | QFile::WriteUser); } // makes sure that capitalization of directories is canonical on Windows and OS X. @@ -347,12 +380,80 @@ QString FileUtils::resolvePath(const QString &baseDir, const QString &fileName) return QDir::cleanPath(baseDir + QLatin1Char('/') + fileName); } -FileName FileUtils::commonPath(const FileName &oldCommonPath, const FileName &fileName) +FilePath FileUtils::commonPath(const FilePath &oldCommonPath, const FilePath &filePath) { - FileName newCommonPath = oldCommonPath; - while (!newCommonPath.isEmpty() && !fileName.isChildOf(newCommonPath)) + FilePath newCommonPath = oldCommonPath; + while (!newCommonPath.isEmpty() && !filePath.isChildOf(newCommonPath)) newCommonPath = newCommonPath.parentDir(); - return canonicalPath(newCommonPath); + return newCommonPath.canonicalPath(); +} + +// Copied from qfilesystemengine_win.cpp +#ifdef Q_OS_WIN + +// File ID for Windows up to version 7. +static inline QByteArray fileIdWin7(HANDLE handle) +{ + BY_HANDLE_FILE_INFORMATION info; + if (GetFileInformationByHandle(handle, &info)) { + char buffer[sizeof "01234567:0123456701234567\0"]; + qsnprintf(buffer, sizeof(buffer), "%lx:%08lx%08lx", + info.dwVolumeSerialNumber, + info.nFileIndexHigh, + info.nFileIndexLow); + return QByteArray(buffer); + } + return QByteArray(); +} + +// File ID for Windows starting from version 8. +static QByteArray fileIdWin8(HANDLE handle) +{ + QByteArray result; + FILE_ID_INFO infoEx; + if (GetFileInformationByHandleEx(handle, + static_cast<FILE_INFO_BY_HANDLE_CLASS>(18), // FileIdInfo in Windows 8 + &infoEx, sizeof(FILE_ID_INFO))) { + result = QByteArray::number(infoEx.VolumeSerialNumber, 16); + result += ':'; + // Note: MinGW-64's definition of FILE_ID_128 differs from the MSVC one. + result += QByteArray(reinterpret_cast<const char *>(&infoEx.FileId), int(sizeof(infoEx.FileId))).toHex(); + } + return result; +} + +static QByteArray fileIdWin(HANDLE fHandle) +{ + return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8 ? + fileIdWin8(HANDLE(fHandle)) : fileIdWin7(HANDLE(fHandle)); +} +#endif + +QByteArray FileUtils::fileId(const FilePath &fileName) +{ + QByteArray result; + +#ifdef Q_OS_WIN + const HANDLE handle = + CreateFile((wchar_t*)fileName.toUserOutput().utf16(), 0, + FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (handle != INVALID_HANDLE_VALUE) { + result = fileIdWin(handle); + CloseHandle(handle); + } +#else // Copied from qfilesystemengine_unix.cpp + if (Q_UNLIKELY(fileName.isEmpty())) + return result; + + QT_STATBUF statResult; + if (QT_STAT(fileName.toString().toLocal8Bit().constData(), &statResult)) + return result; + result = QByteArray::number(quint64(statResult.st_dev), 16); + result += ':'; + result += QByteArray::number(quint64(statResult.st_ino)); +#endif + return result; } QByteArray FileReader::fetchQrc(const QString &fileName) @@ -553,114 +654,131 @@ TempFileSaver::~TempFileSaver() QFile::remove(m_fileName); } -/*! \class Utils::FileName +/*! \class Utils::FilePath - \brief The FileName class is a light-weight convenience class for filenames. + \brief The FilePath class is a light-weight convenience class for filenames. On windows filenames are compared case insensitively. */ -FileName::FileName() - : QString() +FilePath::FilePath() { - } -/// Constructs a FileName from \a info -FileName::FileName(const QFileInfo &info) - : QString(info.absoluteFilePath()) +/// Constructs a FilePath from \a info +FilePath FilePath::fromFileInfo(const QFileInfo &info) { + return FilePath::fromString(info.absoluteFilePath()); } /// \returns a QFileInfo -QFileInfo FileName::toFileInfo() const +QFileInfo FilePath::toFileInfo() const { - return QFileInfo(*this); + return QFileInfo(m_data); +} + +FilePath FilePath::fromUrl(const QUrl &url) +{ + FilePath fn; + fn.m_url = url; + fn.m_data = url.path(); + return fn; } /// \returns a QString for passing on to QString based APIs -const QString &FileName::toString() const +const QString &FilePath::toString() const +{ + return m_data; +} + +QUrl FilePath::toUrl() const { - return *this; + return m_url; } /// \returns a QString to display to the user /// Converts the separators to the native format -QString FileName::toUserOutput() const +QString FilePath::toUserOutput() const { - return QDir::toNativeSeparators(toString()); + if (m_url.isEmpty()) + return QDir::toNativeSeparators(toString()); + return m_url.toString(); } -QString FileName::fileName(int pathComponents) const +QString FilePath::fileName(int pathComponents) const { if (pathComponents < 0) - return *this; + return m_data; const QChar slash = QLatin1Char('/'); - int i = lastIndexOf(slash); + int i = m_data.lastIndexOf(slash); if (pathComponents == 0 || i == -1) - return mid(i + 1); + return m_data.mid(i + 1); int component = i + 1; // skip adjacent slashes - while (i > 0 && at(--i) == slash); + while (i > 0 && m_data.at(--i) == slash) + ; while (i >= 0 && --pathComponents >= 0) { - i = lastIndexOf(slash, i); + i = m_data.lastIndexOf(slash, i); component = i + 1; - while (i > 0 && at(--i) == slash); + while (i > 0 && m_data.at(--i) == slash) + ; } // If there are no more slashes before the found one, return the entire string - if (i > 0 && lastIndexOf(slash, i) != -1) - return mid(component); - return *this; + if (i > 0 && m_data.lastIndexOf(slash, i) != -1) + return m_data.mid(component); + return m_data; } /// \returns a bool indicating whether a file with this -/// FileName exists. -bool FileName::exists() const +/// FilePath exists. +bool FilePath::exists() const { - return !isEmpty() && QFileInfo::exists(*this); + return !isEmpty() && QFileInfo::exists(m_data); } /// Find the parent directory of a given directory. -/// Returns an empty FileName if the current directory is already +/// Returns an empty FilePath if the current directory is already /// a root level directory. -/// \returns \a FileName with the last segment removed. -FileName FileName::parentDir() const +/// \returns \a FilePath with the last segment removed. +FilePath FilePath::parentDir() const { const QString basePath = toString(); if (basePath.isEmpty()) - return FileName(); + return FilePath(); const QDir base(basePath); if (base.isRoot()) - return FileName(); + return FilePath(); const QString path = basePath + QLatin1String("/.."); const QString parent = QDir::cleanPath(path); - QTC_ASSERT(parent != path, return FileName()); + QTC_ASSERT(parent != path, return FilePath()); - return FileName::fromString(parent); + return FilePath::fromString(parent); } -/// Constructs a FileName from \a filename +/// Constructs a FilePath from \a filename /// \a filename is not checked for validity. -FileName FileName::fromString(const QString &filename) +FilePath FilePath::fromString(const QString &filename) { - return FileName(filename); + FilePath fn; + fn.m_data = filename; + return fn; } -/// Constructs a FileName from \a fileName. The \a defaultExtension is appended +/// Constructs a FilePath from \a filePath. The \a defaultExtension is appended /// to \a filename if that does not have an extension already. -/// \a fileName is not checked for validity. -FileName FileName::fromString(const QString &filename, const QString &defaultExtension) +/// \a filePath is not checked for validity. +FilePath FilePath::fromStringWithExtension(const QString &filepath, const QString &defaultExtension) { - if (filename.isEmpty() || defaultExtension.isEmpty()) - return filename; + if (filepath.isEmpty() || defaultExtension.isEmpty()) + return FilePath::fromString(filepath); - QString rc = filename; - QFileInfo fi(filename); + QString rc = filepath; + QFileInfo fi(filepath); // Add extension unless user specified something else const QChar dot = QLatin1Char('.'); if (!fi.fileName().contains(dot)) { @@ -668,138 +786,148 @@ FileName FileName::fromString(const QString &filename, const QString &defaultExt rc += dot; rc += defaultExtension; } - return rc; -} - -/// Constructs a FileName from \a fileName -/// \a fileName is not checked for validity. -FileName FileName::fromLatin1(const QByteArray &filename) -{ - return FileName(QString::fromLatin1(filename)); + return FilePath::fromString(rc); } -/// Constructs a FileName from \a fileName -/// \a fileName is only passed through QDir::cleanPath -FileName FileName::fromUserInput(const QString &filename) +/// Constructs a FilePath from \a filePath +/// \a filePath is only passed through QDir::cleanPath +FilePath FilePath::fromUserInput(const QString &filePath) { - QString clean = QDir::cleanPath(filename); + QString clean = QDir::cleanPath(filePath); if (clean.startsWith(QLatin1String("~/"))) clean = QDir::homePath() + clean.mid(1); - return FileName(clean); + return FilePath::fromString(clean); } -/// Constructs a FileName from \a fileName, which is encoded as UTF-8. -/// \a fileName is not checked for validity. -FileName FileName::fromUtf8(const char *filename, int filenameSize) +/// Constructs a FilePath from \a filePath, which is encoded as UTF-8. +/// \a filePath is not checked for validity. +FilePath FilePath::fromUtf8(const char *filename, int filenameSize) { - return FileName(QString::fromUtf8(filename, filenameSize)); + return FilePath::fromString(QString::fromUtf8(filename, filenameSize)); } -FileName::FileName(const QString &string) - : QString(string) +FilePath FilePath::fromVariant(const QVariant &variant) { + if (variant.type() == QVariant::Url) + return FilePath::fromUrl(variant.toUrl()); + return FilePath::fromString(variant.toString()); +} +QVariant FilePath::toVariant() const +{ + if (!m_url.isEmpty()) + return m_url; + return m_data; } -bool FileName::operator==(const FileName &other) const +bool FilePath::operator==(const FilePath &other) const { - return QString::compare(*this, other, HostOsInfo::fileNameCaseSensitivity()) == 0; + if (!m_url.isEmpty()) + return m_url == other.m_url; + return QString::compare(m_data, other.m_data, HostOsInfo::fileNameCaseSensitivity()) == 0; } -bool FileName::operator!=(const FileName &other) const +bool FilePath::operator!=(const FilePath &other) const { return !(*this == other); } -bool FileName::operator<(const FileName &other) const +bool FilePath::operator<(const FilePath &other) const { - return QString::compare(*this, other, HostOsInfo::fileNameCaseSensitivity()) < 0; + if (!m_url.isEmpty()) + return m_url < other.m_url; + return QString::compare(m_data, other.m_data, HostOsInfo::fileNameCaseSensitivity()) < 0; } -bool FileName::operator<=(const FileName &other) const +bool FilePath::operator<=(const FilePath &other) const { - return QString::compare(*this, other, HostOsInfo::fileNameCaseSensitivity()) <= 0; + return !(other < *this); } -bool FileName::operator>(const FileName &other) const +bool FilePath::operator>(const FilePath &other) const { return other < *this; } -bool FileName::operator>=(const FileName &other) const +bool FilePath::operator>=(const FilePath &other) const { - return other <= *this; + return !(*this < other); } -FileName FileName::operator+(const QString &s) const +FilePath FilePath::operator+(const QString &s) const { - FileName result(*this); - result.appendString(s); - return result; + return FilePath::fromString(m_data + s); } -/// \returns whether FileName is a child of \a s -bool FileName::isChildOf(const FileName &s) const +/// \returns whether FilePath is a child of \a s +bool FilePath::isChildOf(const FilePath &s) const { if (s.isEmpty()) return false; - if (!QString::startsWith(s, HostOsInfo::fileNameCaseSensitivity())) + if (!m_data.startsWith(s.m_data, HostOsInfo::fileNameCaseSensitivity())) return false; - if (size() <= s.size()) + if (m_data.size() <= s.m_data.size()) return false; // s is root, '/' was already tested in startsWith - if (s.QString::endsWith(QLatin1Char('/'))) + if (s.m_data.endsWith(QLatin1Char('/'))) return true; // s is a directory, next character should be '/' (/tmpdir is NOT a child of /tmp) - return at(s.size()) == QLatin1Char('/'); + return m_data.at(s.m_data.size()) == QLatin1Char('/'); } /// \overload -bool FileName::isChildOf(const QDir &dir) const +bool FilePath::isChildOf(const QDir &dir) const { - return isChildOf(FileName::fromString(dir.absolutePath())); + return isChildOf(FilePath::fromString(dir.absolutePath())); } -/// \returns whether FileName endsWith \a s -bool FileName::endsWith(const QString &s) const +/// \returns whether FilePath endsWith \a s +bool FilePath::endsWith(const QString &s) const { - return QString::endsWith(s, HostOsInfo::fileNameCaseSensitivity()); + return m_data.endsWith(s, HostOsInfo::fileNameCaseSensitivity()); } -/// \returns the relativeChildPath of FileName to parent if FileName is a child of parent -/// \note returns a empty FileName if FileName is not a child of parent +bool FilePath::isLocal() const +{ + return m_url.isEmpty() || m_url.isLocalFile(); +} + +/// \returns the relativeChildPath of FilePath to parent if FilePath is a child of parent +/// \note returns a empty FilePath if FilePath is not a child of parent /// That is, this never returns a path starting with "../" -FileName FileName::relativeChildPath(const FileName &parent) const +FilePath FilePath::relativeChildPath(const FilePath &parent) const { if (!isChildOf(parent)) - return FileName(); - return FileName(QString::mid(parent.size() + 1, -1)); + return FilePath(); + return FilePath::fromString(m_data.mid(parent.m_data.size() + 1, -1)); } -/// Appends \a s, ensuring a / between the parts -FileName &FileName::appendPath(const QString &s) +FilePath FilePath::pathAppended(const QString &str) const { - if (s.isEmpty()) - return *this; - if (!isEmpty() && !QString::endsWith(QLatin1Char('/'))) - appendString(QLatin1Char('/')); - appendString(s); - return *this; + FilePath fn = *this; + if (str.isEmpty()) + return fn; + if (!isEmpty() && !m_data.endsWith(QLatin1Char('/'))) + fn.m_data.append('/'); + fn.m_data.append(str); + return fn; } -FileName &FileName::appendString(const QString &str) +FilePath FilePath::stringAppended(const QString &str) const { - QString::append(str); - return *this; + FilePath fn = *this; + fn.m_data.append(str); + return fn; } -FileName &FileName::appendString(QChar str) +uint FilePath::hash(uint seed) const { - QString::append(str); - return *this; + if (Utils::HostOsInfo::fileNameCaseSensitivity() == Qt::CaseInsensitive) + return qHash(m_data.toUpper(), seed); + return qHash(m_data, seed); } -QTextStream &operator<<(QTextStream &s, const FileName &fn) +QTextStream &operator<<(QTextStream &s, const FilePath &fn) { return s << fn.toString(); } @@ -813,14 +941,4 @@ void withNtfsPermissions(const std::function<void()> &task) qt_ntfs_permission_lookup--; } #endif - } // namespace Utils - -QT_BEGIN_NAMESPACE -uint qHash(const Utils::FileName &a) -{ - if (Utils::HostOsInfo::fileNameCaseSensitivity() == Qt::CaseInsensitive) - return qHash(a.toString().toUpper()); - return qHash(a.toString()); -} -QT_END_NAMESPACE diff --git a/src/libs/utils/fileutils.h b/src/libs/utils/fileutils.h index aa6310c760..ec018b9c3b 100644 --- a/src/libs/utils/fileutils.h +++ b/src/libs/utils/fileutils.h @@ -33,11 +33,12 @@ #include <QXmlStreamWriter> // Mac. #include <QMetaType> #include <QStringList> +#include <QUrl> #include <functional> #include <memory> -namespace Utils {class FileName; } +namespace Utils { class FilePath; } QT_BEGIN_NAMESPACE class QDataStream; @@ -49,7 +50,7 @@ class QTemporaryFile; class QTextStream; class QWidget; -QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug dbg, const Utils::FileName &c); +QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug dbg, const Utils::FilePath &c); // for withNtfsPermissions #ifdef Q_OS_WIN @@ -60,76 +61,114 @@ QT_END_NAMESPACE namespace Utils { -class QTCREATOR_UTILS_EXPORT FileName : private QString +class QTCREATOR_UTILS_EXPORT FilePath { public: - FileName(); - explicit FileName(const QFileInfo &info); - QFileInfo toFileInfo() const; - static FileName fromString(const QString &filename); - static FileName fromString(const QString &filename, const QString &defaultExtension); - static FileName fromLatin1(const QByteArray &filename); - static FileName fromUserInput(const QString &filename); - static FileName fromUtf8(const char *filename, int filenameSize = -1); + FilePath(); + + static FilePath fromString(const QString &filepath); + static FilePath fromFileInfo(const QFileInfo &info); + static FilePath fromStringWithExtension(const QString &filepath, const QString &defaultExtension); + static FilePath fromUserInput(const QString &filepath); + static FilePath fromUtf8(const char *filepath, int filepathSize = -1); + static FilePath fromVariant(const QVariant &variant); + const QString &toString() const; + QFileInfo toFileInfo() const; + QVariant toVariant() const; + QString toUserOutput() const; + QString shortNativePath() const; + QString fileName(int pathComponents = 0) const; bool exists() const; - FileName parentDir() const; + FilePath parentDir() const; - bool operator==(const FileName &other) const; - bool operator!=(const FileName &other) const; - bool operator<(const FileName &other) const; - bool operator<=(const FileName &other) const; - bool operator>(const FileName &other) const; - bool operator>=(const FileName &other) const; - FileName operator+(const QString &s) const; + bool operator==(const FilePath &other) const; + bool operator!=(const FilePath &other) const; + bool operator<(const FilePath &other) const; + bool operator<=(const FilePath &other) const; + bool operator>(const FilePath &other) const; + bool operator>=(const FilePath &other) const; + FilePath operator+(const QString &s) const; - bool isChildOf(const FileName &s) const; + bool isChildOf(const FilePath &s) const; bool isChildOf(const QDir &dir) const; bool endsWith(const QString &s) const; + bool isLocal() const; + + bool isNewerThan(const QDateTime &timeStamp) const; + + FilePath relativeChildPath(const FilePath &parent) const; + FilePath pathAppended(const QString &str) const; + FilePath stringAppended(const QString &str) const; + + FilePath canonicalPath() const; + + void clear() { m_data.clear(); } + bool isEmpty() const { return m_data.isEmpty(); } + + uint hash(uint seed) const; + + // NOTE: FileName operations on FilePath created from URL currenly + // do not work except for .toVariant() and .toUrl(). + static FilePath fromUrl(const QUrl &url); + QUrl toUrl() const; - FileName relativeChildPath(const FileName &parent) const; - FileName &appendPath(const QString &s); - FileName &appendString(const QString &str); - FileName &appendString(QChar str); - - using QString::chop; - using QString::clear; - using QString::count; - using QString::isEmpty; - using QString::isNull; - using QString::length; - using QString::size; private: - FileName(const QString &string); + QString m_data; + QUrl m_url; }; -QTCREATOR_UTILS_EXPORT QTextStream &operator<<(QTextStream &s, const FileName &fn); +QTCREATOR_UTILS_EXPORT QTextStream &operator<<(QTextStream &s, const FilePath &fn); + +using FilePathList = QList<FilePath>; + +using FileName = FilePath; +using FileNameList = FilePathList; -using FileNameList = QList<FileName>; +class QTCREATOR_UTILS_EXPORT CommandLine +{ +public: + CommandLine() {} + + CommandLine(const FilePath &executable, const QString &arguments) + : m_executable(executable), m_arguments(arguments) + {} + + void addArg(const QString &arg, OsType osType = HostOsInfo::hostOs()); + void addArgs(const QStringList &inArgs, OsType osType = HostOsInfo::hostOs()); + void addArgs(const QString &inArgs); + + QString toUserOutput() const; + + FilePath executable() const { return m_executable; } + QString arguments() const { return m_arguments; } + +private: + FilePath m_executable; + QString m_arguments; +}; class QTCREATOR_UTILS_EXPORT FileUtils { public: - static bool removeRecursively(const FileName &filePath, QString *error = nullptr); + static bool removeRecursively(const FilePath &filePath, QString *error = nullptr); static bool copyRecursively( - const FileName &srcFilePath, const FileName &tgtFilePath, QString *error = nullptr, + const FilePath &srcFilePath, const FilePath &tgtFilePath, QString *error = nullptr, const std::function<bool (QFileInfo, QFileInfo, QString *)> ©Helper = nullptr); - static bool isFileNewerThan(const FileName &filePath, const QDateTime &timeStamp); - static FileName resolveSymlinks(const FileName &path); - static FileName canonicalPath(const FileName &path); - static QString shortNativePath(const FileName &path); + static FilePath resolveSymlinks(const FilePath &path); static QString fileSystemFriendlyName(const QString &name); static int indexOfQmakeUnfriendly(const QString &name, int startpos = 0); static QString qmakeFriendlyName(const QString &name); - static bool makeWritable(const FileName &path); + static bool makeWritable(const FilePath &path); static QString normalizePathName(const QString &name); static bool isRelativePath(const QString &fileName); static bool isAbsolutePath(const QString &fileName) { return !isRelativePath(fileName); } static QString resolvePath(const QString &baseDir, const QString &fileName); - static FileName commonPath(const FileName &oldCommonPath, const FileName &fileName); + static FilePath commonPath(const FilePath &oldCommonPath, const FilePath &fileName); + static QByteArray fileId(const FilePath &fileName); }; // for actually finding out if e.g. directories are writable on Windows @@ -240,16 +279,14 @@ private: bool m_autoRemove = true; }; -} // namespace Utils +inline uint qHash(const Utils::FilePath &a, uint seed = 0) { return a.hash(seed); } -QT_BEGIN_NAMESPACE -QTCREATOR_UTILS_EXPORT uint qHash(const Utils::FileName &a); -QT_END_NAMESPACE +} // namespace Utils namespace std { -template<> struct hash<Utils::FileName> +template<> struct hash<Utils::FilePath> { - using argument_type = Utils::FileName; + using argument_type = Utils::FilePath; using result_type = size_t; result_type operator()(const argument_type &fn) const { @@ -260,4 +297,4 @@ template<> struct hash<Utils::FileName> }; } // namespace std -Q_DECLARE_METATYPE(Utils::FileName) +Q_DECLARE_METATYPE(Utils::FilePath) diff --git a/src/libs/sqlite/sqlitetable.cpp b/src/libs/utils/genericconstants.h index 99b0e95938..a380fc15ba 100644 --- a/src/libs/sqlite/sqlitetable.cpp +++ b/src/libs/utils/genericconstants.h @@ -23,10 +23,15 @@ ** ****************************************************************************/ -#include "sqlitetable.h" +#pragma once -namespace Sqlite { +namespace Utils { +namespace Constants { +const char BEAUTIFIER_SETTINGS_GROUP[] = "Beautifier"; +const char BEAUTIFIER_GENERAL_GROUP[] = "General"; +const char BEAUTIFIER_AUTO_FORMAT_ON_SAVE[] = "autoFormatOnSave"; -} // namespace Sqlite +} // namespace Constants +} // namespace Utils diff --git a/src/libs/utils/highlightingitemdelegate.cpp b/src/libs/utils/highlightingitemdelegate.cpp index e253689843..4874200e86 100644 --- a/src/libs/utils/highlightingitemdelegate.cpp +++ b/src/libs/utils/highlightingitemdelegate.cpp @@ -114,7 +114,8 @@ int HighlightingItemDelegate::drawLineNumber(QPainter *painter, const QStyleOpti const bool isSelected = option.state & QStyle::State_Selected; const QString lineText = QString::number(lineNumber); const int minimumLineNumberDigits = qMax(kMinimumLineNumberDigits, lineText.count()); - const int fontWidth = painter->fontMetrics().width(QString(minimumLineNumberDigits, '0')); + const int fontWidth = + painter->fontMetrics().horizontalAdvance(QString(minimumLineNumberDigits, '0')); const int lineNumberAreaWidth = lineNumberAreaHorizontalPadding + fontWidth + lineNumberAreaHorizontalPadding; QRect lineNumberAreaRect(rect); diff --git a/src/libs/ssh/images/dir.png b/src/libs/utils/images/dir.png Binary files differindex 57cec6bcd3..57cec6bcd3 100644 --- a/src/libs/ssh/images/dir.png +++ b/src/libs/utils/images/dir.png diff --git a/src/libs/utils/images/pinned.png b/src/libs/utils/images/pinned.png Binary files differnew file mode 100644 index 0000000000..dc96231ca4 --- /dev/null +++ b/src/libs/utils/images/pinned.png diff --git a/src/libs/utils/images/pinned@2x.png b/src/libs/utils/images/pinned@2x.png Binary files differnew file mode 100644 index 0000000000..d7c59e83ce --- /dev/null +++ b/src/libs/utils/images/pinned@2x.png diff --git a/src/libs/utils/images/settings.png b/src/libs/utils/images/settings.png Binary files differnew file mode 100644 index 0000000000..2621923499 --- /dev/null +++ b/src/libs/utils/images/settings.png diff --git a/src/libs/utils/images/settings@2x.png b/src/libs/utils/images/settings@2x.png Binary files differnew file mode 100644 index 0000000000..456f0cc56b --- /dev/null +++ b/src/libs/utils/images/settings@2x.png diff --git a/src/libs/utils/images/sort_alphabetically.png b/src/libs/utils/images/sort_alphabetically.png Binary files differnew file mode 100644 index 0000000000..c15eb56d50 --- /dev/null +++ b/src/libs/utils/images/sort_alphabetically.png diff --git a/src/libs/utils/images/sort_alphabetically@2x.png b/src/libs/utils/images/sort_alphabetically@2x.png Binary files differnew file mode 100644 index 0000000000..1a2e5d9520 --- /dev/null +++ b/src/libs/utils/images/sort_alphabetically@2x.png diff --git a/src/libs/utils/images/toggleprogressdetails.png b/src/libs/utils/images/toggleprogressdetails.png Binary files differnew file mode 100644 index 0000000000..b2353cd9d0 --- /dev/null +++ b/src/libs/utils/images/toggleprogressdetails.png diff --git a/src/libs/utils/images/toggleprogressdetails@2x.png b/src/libs/utils/images/toggleprogressdetails@2x.png Binary files differnew file mode 100644 index 0000000000..28a212491e --- /dev/null +++ b/src/libs/utils/images/toggleprogressdetails@2x.png diff --git a/src/libs/ssh/images/unknownfile.png b/src/libs/utils/images/unknownfile.png Binary files differindex 88f77592d1..88f77592d1 100644 --- a/src/libs/ssh/images/unknownfile.png +++ b/src/libs/utils/images/unknownfile.png diff --git a/src/libs/utils/listmodel.h b/src/libs/utils/listmodel.h new file mode 100644 index 0000000000..5f4de811e6 --- /dev/null +++ b/src/libs/utils/listmodel.h @@ -0,0 +1,183 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "utils_global.h" +#include "treemodel.h" + +namespace Utils { + +template <class ChildType> +class BaseListModel : public TreeModel<TypedTreeItem<ChildType>, ChildType> +{ +public: + using BaseModel = TreeModel<TypedTreeItem<ChildType>, ChildType>; + using BaseModel::rootItem; + + explicit BaseListModel(QObject *parent = nullptr) : BaseModel(parent) {} + + int itemCount() const { return rootItem()->childCount(); } + ChildType *itemAt(int row) const { return rootItem()->childAt(row); } + + void appendItem(ChildType *item) { rootItem()->appendChild(item); } + + template <class Predicate> + void forItems(const Predicate &pred) const + { + rootItem()->forFirstLevelChildren(pred); + } + + template <class Predicate> + ChildType *findItem(const Predicate &pred) const + { + return rootItem()->findFirstLevelChild(pred); + } + + void sortItems(const std::function<bool(const ChildType *, const ChildType *)> &lessThan) + { + return rootItem()->sortChildren([lessThan](const TreeItem *a, const TreeItem *b) { + return lessThan(static_cast<const ChildType *>(a), static_cast<const ChildType *>(b)); + }); + } + + int indexOf(const ChildType *item) const { return rootItem()->indexOf(item); } + + void clear() { rootItem()->removeChildren(); } + + using const_iterator = typename QVector<TreeItem *>::const_iterator; + const_iterator begin() const { return rootItem()->begin(); } + const_iterator end() const { return rootItem()->end(); } + +}; + +template <class ItemData> +class ListItem : public TreeItem +{ +public: + ItemData itemData; +}; + +template <class ItemData> +class ListModel : public BaseListModel<ListItem<ItemData>> +{ +public: + using ChildType = ListItem<ItemData>; + using BaseModel = BaseListModel<ChildType>; + + explicit ListModel(QObject *parent = nullptr) : BaseModel(parent) {} + + const ItemData &dataAt(int row) const + { + static const ItemData dummyData = {}; + auto item = BaseModel::itemAt(row); + return item ? item->itemData : dummyData; + } + + ChildType *findItemByData(const std::function<bool(const ItemData &)> &pred) const + { + return BaseModel::rootItem()->findFirstLevelChild([pred](ChildType *child) { + return pred(child->itemData); + }); + } + + void destroyItems(const std::function<bool(const ItemData &)> &pred) + { + QList<ChildType *> toDestroy; + BaseModel::rootItem()->forFirstLevelChildren([pred, &toDestroy](ChildType *item) { + if (pred(item->itemData)) + toDestroy.append(item); + }); + for (ChildType *item : toDestroy) + this->destroyItem(item); + } + + ItemData *findData(const std::function<bool(const ItemData &)> &pred) const + { + ChildType *item = findItemByData(pred); + return item ? &item->itemData : nullptr; + } + + void forItems(const std::function<void(ItemData &)> &func) const + { + BaseModel::rootItem()->forFirstLevelChildren([func](ChildType *child) { + func(child->itemData); + }); + } + + ChildType *appendItem(const ItemData &data) + { + auto item = new ChildType; + item->itemData = data; + BaseModel::rootItem()->appendChild(item); + return item; + } + + QVariant data(const QModelIndex &idx, int role) const override + { + TreeItem *item = BaseModel::itemForIndex(idx); + if (item && item->parent() == BaseModel::rootItem()) + return itemData(static_cast<ChildType *>(item)->itemData, idx.column(), role); + return {}; + } + + Qt::ItemFlags flags(const QModelIndex &idx) const override + { + TreeItem *item = BaseModel::itemForIndex(idx); + if (item && item->parent() == BaseModel::rootItem()) + return itemFlags(static_cast<ChildType *>(item)->itemData, idx.column()); + return {}; + } + + virtual QVariant itemData(const ItemData &idata, int column, int role) const + { + if (m_dataAccessor) + return m_dataAccessor(idata, column, role); + return {}; + } + + virtual Qt::ItemFlags itemFlags(const ItemData &idata, int column) const + { + if (m_flagsAccessor) + return m_flagsAccessor(idata, column); + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + } + + void setDataAccessor(const std::function<QVariant(const ItemData &, int, int)> &accessor) + { + m_dataAccessor = accessor; + } + + void setFlagsAccessor(const std::function<Qt::ItemFlags(const ItemData &, int)> &accessor) + { + m_flagsAccessor = accessor; + } + +private: + std::function<QVariant(const ItemData &, int, int)> m_dataAccessor; + std::function<Qt::ItemFlags(const ItemData &, int)> m_flagsAccessor; +}; + +} // namespace Utils diff --git a/src/libs/utils/macroexpander.cpp b/src/libs/utils/macroexpander.cpp index eb3f05e175..a41fbde31d 100644 --- a/src/libs/utils/macroexpander.cpp +++ b/src/libs/utils/macroexpander.cpp @@ -290,11 +290,39 @@ QString MacroExpander::expand(const QString &stringWithVariables) const return res; } +FilePath MacroExpander::expand(const FilePath &fileNameWithVariables) const +{ + return FilePath::fromString(expand(fileNameWithVariables.toString())); +} + QByteArray MacroExpander::expand(const QByteArray &stringWithVariables) const { return expand(QString::fromLatin1(stringWithVariables)).toLatin1(); } +QVariant MacroExpander::expandVariant(const QVariant &v) const +{ + const auto type = QMetaType::Type(v.type()); + if (type == QMetaType::QString) { + return expand(v.toString()); + } else if (type == QMetaType::QStringList) { + return Utils::transform(v.toStringList(), + [this](const QString &s) -> QVariant { return expand(s); }); + } else if (type == QMetaType::QVariantList) { + return Utils::transform(v.toList(), [this](const QVariant &v) { return expandVariant(v); }); + } else if (type == QMetaType::QVariantMap) { + const auto map = v.toMap(); + QVariantMap result; + QMapIterator<QString, QVariant> it(map); + while (it.hasNext()) { + it.next(); + result.insert(it.key(), expandVariant(it.value())); + } + return result; + } + return v; +} + QString MacroExpander::expandProcessArgs(const QString &argsWithVariables) const { return QtcProcess::expandMacros(argsWithVariables, d); @@ -394,7 +422,7 @@ void MacroExpander::registerFileVariables(const QByteArray &prefix, registerVariable(prefix + kFileNamePostfix, tr("%1: File name without path.").arg(heading), - [base]() -> QString { QString tmp = base(); return tmp.isEmpty() ? QString() : FileName::fromString(tmp).fileName(); }, + [base]() -> QString { QString tmp = base(); return tmp.isEmpty() ? QString() : FilePath::fromString(tmp).fileName(); }, visibleInChooser); registerVariable(prefix + kFileBaseNamePostfix, diff --git a/src/libs/utils/macroexpander.h b/src/libs/utils/macroexpander.h index f17ae86b8c..70448069c5 100644 --- a/src/libs/utils/macroexpander.h +++ b/src/libs/utils/macroexpander.h @@ -37,6 +37,7 @@ namespace Utils { namespace Internal { class MacroExpanderPrivate; } +class FilePath; class MacroExpander; using MacroExpanderProvider = std::function<MacroExpander *()>; using MacroExpanderProviders = QVector<MacroExpanderProvider>; @@ -55,7 +56,9 @@ public: QString value(const QByteArray &variable, bool *found = nullptr) const; QString expand(const QString &stringWithVariables) const; + FilePath expand(const FilePath &fileNameWithVariables) const; QByteArray expand(const QByteArray &stringWithVariables) const; + QVariant expandVariant(const QVariant &v) const; QString expandProcessArgs(const QString &argsWithVariables) const; diff --git a/src/libs/utils/mimetypes/mimeprovider.cpp b/src/libs/utils/mimetypes/mimeprovider.cpp index d444aa899c..46d3eb71bd 100644 --- a/src/libs/utils/mimetypes/mimeprovider.cpp +++ b/src/libs/utils/mimetypes/mimeprovider.cpp @@ -803,11 +803,7 @@ void MimeXMLProvider::ensureLoaded() // if (!fdoXmlFound) { // // We could instead install the file as part of installing Qt? -#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) const char freedesktopOrgXml[] = ":/qt-project.org/qmime/packages/freedesktop.org.xml"; -#else - const char freedesktopOrgXml[] = ":/qt-project.org/qmime/freedesktop.org.xml"; -#endif allFiles.prepend(QLatin1String(freedesktopOrgXml)); // } diff --git a/src/libs/utils/newclasswidget.cpp b/src/libs/utils/newclasswidget.cpp index 8700b8204c..9205d435dc 100644 --- a/src/libs/utils/newclasswidget.cpp +++ b/src/libs/utils/newclasswidget.cpp @@ -88,7 +88,7 @@ NewClassWidget::NewClassWidget(QWidget *parent) : connect(d->m_ui.classLineEdit, &QLineEdit::textEdited, this, &NewClassWidget::classNameEdited); connect(d->m_ui.baseClassComboBox, - static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), + QOverload<int>::of(&QComboBox::currentIndexChanged), this, &NewClassWidget::suggestClassNameFromBase); connect(d->m_ui.baseClassComboBox, &QComboBox::editTextChanged, this, &NewClassWidget::slotValidChanged); diff --git a/src/libs/utils/outputformatter.cpp b/src/libs/utils/outputformatter.cpp index ec85a748a6..7926422da6 100644 --- a/src/libs/utils/outputformatter.cpp +++ b/src/libs/utils/outputformatter.cpp @@ -78,7 +78,8 @@ void OutputFormatter::appendMessage(const QString &text, OutputFormat format) void OutputFormatter::appendMessage(const QString &text, const QTextCharFormat &format) { - foreach (const FormattedText &output, parseAnsi(text, format)) + const QList<FormattedText> formattedTextList = parseAnsi(text, format); + for (const FormattedText &output : formattedTextList) append(output.text, output.format); } diff --git a/src/libs/utils/outputformatter.h b/src/libs/utils/outputformatter.h index c516ca14e2..1db42453d5 100644 --- a/src/libs/utils/outputformatter.h +++ b/src/libs/utils/outputformatter.h @@ -62,6 +62,9 @@ public: virtual void clear() {} void setBoldFontEnabled(bool enabled); +signals: + void contentChanged(); + protected: void initFormats(); virtual void clearLastLine(); diff --git a/src/libs/utils/pathchooser.cpp b/src/libs/utils/pathchooser.cpp index e29b0c7663..f08391d6a6 100644 --- a/src/libs/utils/pathchooser.cpp +++ b/src/libs/utils/pathchooser.cpp @@ -193,14 +193,14 @@ QString PathChooserPrivate::expandedPath(const QString &input) const if (m_macroExpander) expandedInput = m_macroExpander->expand(expandedInput); - const QString path = FileName::fromUserInput(expandedInput).toString(); + const QString path = FilePath::fromUserInput(expandedInput).toString(); if (path.isEmpty()) return path; switch (m_acceptingKind) { case PathChooser::Command: case PathChooser::ExistingCommand: { - const FileName expanded = m_environment.searchInPath(path, {FileName::fromString(m_baseDirectory)}); + const FilePath expanded = m_environment.searchInPath(path, {FilePath::fromString(m_baseDirectory)}); return expanded.isEmpty() ? path : expanded.toString(); } case PathChooser::Any: @@ -293,12 +293,12 @@ void PathChooser::setBaseDirectory(const QString &directory) triggerChanged(); } -FileName PathChooser::baseFileName() const +FilePath PathChooser::baseFileName() const { - return FileName::fromString(d->m_baseDirectory); + return FilePath::fromString(d->m_baseDirectory); } -void PathChooser::setBaseFileName(const FileName &base) +void PathChooser::setBaseFileName(const FilePath &base) { setBaseDirectory(base.toString()); } @@ -323,14 +323,14 @@ QString PathChooser::path() const return fileName().toString(); } -FileName PathChooser::rawFileName() const +FilePath PathChooser::rawFileName() const { - return FileName::fromString(QDir::fromNativeSeparators(d->m_lineEdit->text())); + return FilePath::fromString(QDir::fromNativeSeparators(d->m_lineEdit->text())); } -FileName PathChooser::fileName() const +FilePath PathChooser::fileName() const { - return FileName::fromUserInput(d->expandedPath(rawFileName().toString())); + return FilePath::fromUserInput(d->expandedPath(rawFileName().toString())); } // FIXME: try to remove again @@ -352,7 +352,7 @@ void PathChooser::setPath(const QString &path) d->m_lineEdit->setTextKeepingActiveCursor(QDir::toNativeSeparators(path)); } -void PathChooser::setFileName(const FileName &fn) +void PathChooser::setFileName(const FilePath &fn) { d->m_lineEdit->setTextKeepingActiveCursor(fn.toUserOutput()); } diff --git a/src/libs/utils/pathchooser.h b/src/libs/utils/pathchooser.h index 73939e1bf4..09d98e71c8 100644 --- a/src/libs/utils/pathchooser.h +++ b/src/libs/utils/pathchooser.h @@ -55,8 +55,8 @@ class QTCREATOR_UTILS_EXPORT PathChooser : public QWidget Q_PROPERTY(QStringList commandVersionArguments READ commandVersionArguments WRITE setCommandVersionArguments) Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly DESIGNABLE true) // Designer does not know this type, so force designable to false: - Q_PROPERTY(Utils::FileName fileName READ fileName WRITE setFileName DESIGNABLE false) - Q_PROPERTY(Utils::FileName baseFileName READ baseFileName WRITE setBaseFileName DESIGNABLE false) + Q_PROPERTY(Utils::FilePath fileName READ fileName WRITE setFileName DESIGNABLE false) + Q_PROPERTY(Utils::FilePath baseFileName READ baseFileName WRITE setBaseFileName DESIGNABLE false) Q_PROPERTY(QColor errorColor READ errorColor WRITE setErrorColor DESIGNABLE true) Q_PROPERTY(QColor okColor READ okColor WRITE setOkColor DESIGNABLE true) @@ -93,8 +93,8 @@ public: QString path() const; QString rawPath() const; // The raw unexpanded input. - FileName rawFileName() const; // The raw unexpanded input. - FileName fileName() const; + FilePath rawFileName() const; // The raw unexpanded input. + FilePath fileName() const; static QString expandedDirectory(const QString &input, const Environment &env, const QString &baseDir); @@ -102,8 +102,8 @@ public: QString baseDirectory() const; void setBaseDirectory(const QString &directory); - FileName baseFileName() const; - void setBaseFileName(const FileName &base); + FilePath baseFileName() const; + void setBaseFileName(const FilePath &base); void setEnvironment(const Environment &env); @@ -172,7 +172,7 @@ signals: public slots: void setPath(const QString &); - void setFileName(const FileName &); + void setFileName(const FilePath &); void setErrorColor(const QColor &errorColor); void setOkColor(const QColor &okColor); diff --git a/src/libs/utils/persistentsettings.cpp b/src/libs/utils/persistentsettings.cpp index db0f8d0db5..92d32109ea 100644 --- a/src/libs/utils/persistentsettings.cpp +++ b/src/libs/utils/persistentsettings.cpp @@ -341,7 +341,7 @@ QVariantMap PersistentSettingsReader::restoreValues() const return m_valueMap; } -bool PersistentSettingsReader::load(const FileName &fileName) +bool PersistentSettingsReader::load(const FilePath &fileName) { m_valueMap.clear(); @@ -409,7 +409,7 @@ static void writeVariantValue(QXmlStreamWriter &w, const Context &ctx, } } -PersistentSettingsWriter::PersistentSettingsWriter(const FileName &fileName, const QString &docType) : +PersistentSettingsWriter::PersistentSettingsWriter(const FilePath &fileName, const QString &docType) : m_fileName(fileName), m_docType(docType) { } @@ -438,7 +438,7 @@ bool PersistentSettingsWriter::save(const QVariantMap &data, QWidget *parent) co } #endif // QT_GUI_LIB -FileName PersistentSettingsWriter::fileName() const +FilePath PersistentSettingsWriter::fileName() const { return m_fileName; } //** * @brief Set contents of file (e.g. from data read from it). */ diff --git a/src/libs/utils/persistentsettings.h b/src/libs/utils/persistentsettings.h index a7255dcb8a..92dbf0d8c9 100644 --- a/src/libs/utils/persistentsettings.h +++ b/src/libs/utils/persistentsettings.h @@ -42,7 +42,7 @@ public: PersistentSettingsReader(); QVariant restoreValue(const QString &variable, const QVariant &defaultValue = QVariant()) const; QVariantMap restoreValues() const; - bool load(const FileName &fileName); + bool load(const FilePath &fileName); private: QMap<QString, QVariant> m_valueMap; @@ -51,7 +51,7 @@ private: class QTCREATOR_UTILS_EXPORT PersistentSettingsWriter { public: - PersistentSettingsWriter(const FileName &fileName, const QString &docType); + PersistentSettingsWriter(const FilePath &fileName, const QString &docType); ~PersistentSettingsWriter(); bool save(const QVariantMap &data, QString *errorString) const; @@ -59,14 +59,14 @@ public: bool save(const QVariantMap &data, QWidget *parent) const; #endif - FileName fileName() const; + FilePath fileName() const; void setContents(const QVariantMap &data); private: bool write(const QVariantMap &data, QString *errorString) const; - const FileName m_fileName; + const FilePath m_fileName; const QString m_docType; mutable QMap<QString, QVariant> m_savedData; }; diff --git a/src/libs/utils/projectintropage.cpp b/src/libs/utils/projectintropage.cpp index a449fe1285..56127ac479 100644 --- a/src/libs/utils/projectintropage.cpp +++ b/src/libs/utils/projectintropage.cpp @@ -101,7 +101,7 @@ ProjectIntroPage::ProjectIntroPage(QWidget *parent) : connect(d->m_ui.nameLineEdit, &FancyLineEdit::validReturnPressed, this, &ProjectIntroPage::slotActivated); connect(d->m_ui.projectComboBox, - static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), + QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ProjectIntroPage::slotChanged); setProperty(SHORT_TITLE_PROPERTY, tr("Location")); diff --git a/src/libs/qmljs/qmljsqrcparser.cpp b/src/libs/utils/qrcparser.cpp index 0a68ebe2fb..21904d3716 100644 --- a/src/libs/qmljs/qmljsqrcparser.cpp +++ b/src/libs/utils/qrcparser.cpp @@ -23,22 +23,26 @@ ** ****************************************************************************/ -#include "qmljsqrcparser.h" -#include "qmljsconstants.h" -#include <QFile> +#include "qrcparser.h" + +#include <utils/qtcassert.h> + +#include <QCoreApplication> #include <QDir> -#include <QFileInfo> -#include <QStringList> #include <QDomDocument> +#include <QFile> +#include <QFileInfo> #include <QLocale> +#include <QLoggingCategory> +#include <QMultiHash> #include <QMutex> -#include <QSet> #include <QMutexLocker> -#include <QMultiHash> -#include <QCoreApplication> -#include <utils/qtcassert.h> +#include <QSet> +#include <QStringList> + +Q_LOGGING_CATEGORY(qrcParserLog, "qtc.qrcParser", QtWarningMsg) -namespace QmlJS { +namespace Utils { namespace Internal { /*! @@ -81,7 +85,7 @@ public: QStringList languages() const; private: static QString fixPrefix(const QString &prefix); - QStringList allUiLanguages(const QLocale *locale) const; + const QStringList allUiLanguages(const QLocale *locale) const; SMap m_resources; SMap m_files; @@ -339,8 +343,7 @@ bool QrcParserPrivate::parseFile(const QString &path, const QString &contents) QString QrcParserPrivate::firstFileAtPath(const QString &path, const QLocale &locale) const { QTC_CHECK(path.startsWith(QLatin1Char('/'))); - QStringList langs = allUiLanguages(&locale); - foreach (const QString &language, langs) { + for (const QString &language : allUiLanguages(&locale)) { if (m_languages.contains(language)) { SMap::const_iterator res = m_resources.find(language + path); if (res != m_resources.end()) @@ -354,8 +357,7 @@ void QrcParserPrivate::collectFilesAtPath(const QString &path, QStringList *file const QLocale *locale) const { QTC_CHECK(path.startsWith(QLatin1Char('/'))); - QStringList langs = allUiLanguages(locale); - foreach (const QString &language, langs) { + for (const QString &language : allUiLanguages(locale)) { if (m_languages.contains(language)) { SMap::const_iterator res = m_resources.find(language + path); if (res != m_resources.end()) @@ -369,8 +371,7 @@ bool QrcParserPrivate::hasDirAtPath(const QString &path, const QLocale *locale) { QTC_CHECK(path.startsWith(QLatin1Char('/'))); QTC_CHECK(path.endsWith(QLatin1Char('/'))); - QStringList langs = allUiLanguages(locale); - foreach (const QString &language, langs) { + for (const QString &language : allUiLanguages(locale)) { if (m_languages.contains(language)) { QString key = language + path; SMap::const_iterator res = m_resources.lowerBound(key); @@ -387,8 +388,7 @@ void QrcParserPrivate::collectFilesInPath(const QString &path, QMap<QString,QStr QTC_CHECK(path.startsWith(QLatin1Char('/'))); QTC_CHECK(path.endsWith(QLatin1Char('/'))); SMap::const_iterator end = m_resources.end(); - QStringList langs = allUiLanguages(locale); - foreach (const QString &language, langs) { + for (const QString &language : allUiLanguages(locale)) { QString key = language + path; SMap::const_iterator res = m_resources.lowerBound(key); while (res != end && res.key().startsWith(key)) { @@ -397,7 +397,7 @@ void QrcParserPrivate::collectFilesInPath(const QString &path, QMap<QString,QStr if (endDir == -1) { QString fileName = res.key().right(res.key().size()-key.size()); QStringList &els = (*contents)[fileName]; - foreach (const QString &val, res.value()) + for (const QString &val : res.value()) if (!els.contains(val)) els << val; ++res; @@ -420,12 +420,12 @@ void QrcParserPrivate::collectResourceFilesForSourceFile(const QString &sourceFi { // TODO: use FileName from fileutils for file paths - QStringList langs = allUiLanguages(locale); + const QStringList langs = allUiLanguages(locale); SMap::const_iterator file = m_files.find(sourceFile); if (file == m_files.end()) return; - foreach (const QString &resource, file.value()) { - foreach (const QString &language, langs) { + for (const QString &resource : file.value()) { + for (const QString &language : langs) { if (resource.startsWith(language) && !results->contains(resource)) results->append(resource); } @@ -459,7 +459,7 @@ QString QrcParserPrivate::fixPrefix(const QString &prefix) return result; } -QStringList QrcParserPrivate::allUiLanguages(const QLocale *locale) const +const QStringList QrcParserPrivate::allUiLanguages(const QLocale *locale) const { if (!locale) return languages(); @@ -496,7 +496,7 @@ QrcParser::Ptr QrcCachePrivate::addPath(const QString &path, const QString &cont } QrcParser::Ptr newParser = QrcParser::parseQrcFile(path, contents); if (!newParser->isValid()) - qCWarning(qmljsLog) << "adding invalid qrc " << path << " to the cache:" << newParser->errorMessages(); + qCWarning(qrcParserLog) << "adding invalid qrc " << path << " to the cache:" << newParser->errorMessages(); { QMutexLocker l(&m_mutex); QPair<QrcParser::Ptr,int> currentValue = m_cache.value(path, {QrcParser::Ptr(0), 0}); diff --git a/src/libs/qmljs/qmljsqrcparser.h b/src/libs/utils/qrcparser.h index 6973fa6d39..b5a7be761b 100644 --- a/src/libs/qmljs/qmljsqrcparser.h +++ b/src/libs/utils/qrcparser.h @@ -24,7 +24,7 @@ ****************************************************************************/ #pragma once -#include "qmljs_global.h" +#include "utils_global.h" #include <QMap> #include <QSharedPointer> @@ -33,14 +33,14 @@ QT_FORWARD_DECLARE_CLASS(QLocale) -namespace QmlJS { +namespace Utils { namespace Internal { class QrcParserPrivate; class QrcCachePrivate; } -class QMLJS_EXPORT QrcParser +class QTCREATOR_UTILS_EXPORT QrcParser { public: typedef QSharedPointer<QrcParser> Ptr; @@ -69,7 +69,7 @@ private: Internal::QrcParserPrivate *d; }; -class QMLJS_EXPORT QrcCache +class QTCREATOR_UTILS_EXPORT QrcCache { public: QrcCache(); diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp index dd4fe16f49..992e1817c0 100644 --- a/src/libs/utils/qtcprocess.cpp +++ b/src/libs/utils/qtcprocess.cpp @@ -595,12 +595,12 @@ static QString quoteArgWin(const QString &arg) } QtcProcess::Arguments QtcProcess::prepareArgs(const QString &cmd, SplitError *err, OsType osType, - const Environment *env, const QString *pwd) + const Environment *env, const QString *pwd, bool abortOnMeta) { if (osType == OsTypeWindows) return prepareArgsWin(cmd, err, env, pwd); else - return Arguments::createUnixArgs(splitArgs(cmd, osType, true, err, env, pwd)); + return Arguments::createUnixArgs(splitArgs(cmd, osType, abortOnMeta, err, env, pwd)); } @@ -694,7 +694,8 @@ void QtcProcess::start() const OsType osType = HostOsInfo::hostOs(); if (m_haveEnv) { if (m_environment.size() == 0) - qWarning("QtcProcess::start: Empty environment set when running '%s'.", qPrintable(m_command)); + qWarning("QtcProcess::start: Empty environment set when running '%s'.", + qPrintable(m_commandLine.executable().toString())); env = m_environment; QProcess::setEnvironment(env.toStringList()); @@ -705,7 +706,9 @@ void QtcProcess::start() const QString &workDir = workingDirectory(); QString command; QtcProcess::Arguments arguments; - bool success = prepareCommand(m_command, m_arguments, &command, &arguments, osType, &env, &workDir); + bool success = prepareCommand(m_commandLine.executable().toString(), + m_commandLine.arguments(), + &command, &arguments, osType, &env, &workDir); if (osType == OsTypeWindows) { QString args; if (m_useCtrlCStub) { diff --git a/src/libs/utils/qtcprocess.h b/src/libs/utils/qtcprocess.h index 44c5786661..5eeacf666e 100644 --- a/src/libs/utils/qtcprocess.h +++ b/src/libs/utils/qtcprocess.h @@ -38,10 +38,9 @@ class QTCREATOR_UTILS_EXPORT QtcProcess : public QProcess public: QtcProcess(QObject *parent = nullptr); - void setEnvironment(const Environment &env) - { m_environment = env; m_haveEnv = true; } - void setCommand(const QString &command, const QString &arguments) - { m_command = command; m_arguments = arguments; } + + void setEnvironment(const Environment &env) { m_environment = env; m_haveEnv = true; } + void setCommand(const CommandLine &cmdLine) { m_commandLine = cmdLine; } void setUseCtrlCStub(bool enabled); void start(); void terminate(); @@ -80,7 +79,8 @@ public: //! Prepare argument of a shell command for feeding into QProcess static Arguments prepareArgs(const QString &cmd, SplitError *err, OsType osType = HostOsInfo::hostOs(), - const Environment *env = nullptr, const QString *pwd = nullptr); + const Environment *env = nullptr, const QString *pwd = nullptr, + bool abortOnMeta = true); //! Prepare a shell command for feeding into QProcess static bool prepareCommand(const QString &command, const QString &arguments, QString *outCmd, Arguments *outArgs, OsType osType = HostOsInfo::hostOs(), @@ -141,8 +141,7 @@ public: }; private: - QString m_command; - QString m_arguments; + CommandLine m_commandLine; Environment m_environment; bool m_haveEnv = false; bool m_useCtrlCStub = false; diff --git a/src/libs/utils/reloadpromptutils.cpp b/src/libs/utils/reloadpromptutils.cpp index 2270053be0..09a9855784 100644 --- a/src/libs/utils/reloadpromptutils.cpp +++ b/src/libs/utils/reloadpromptutils.cpp @@ -33,7 +33,7 @@ namespace Utils { -QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FileName &fileName, +QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FilePath &fileName, bool modified, bool enableDiffOption, QWidget *parent) @@ -50,7 +50,10 @@ QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FileName &fileName, msg = QCoreApplication::translate("Utils::reloadPrompt", "The file <i>%1</i> has been changed on disk. Do you want to reload it?"); } - msg = msg.arg(fileName.fileName()); + msg = "<p>" + msg.arg(fileName.fileName()) + "</p><p>" + + QCoreApplication::translate("Utils::reloadPrompt", + "The default behavior can be set in Tools > Options > Environment > System.") + + "</p>"; return reloadPrompt(title, msg, fileName.toUserOutput(), enableDiffOption, parent); } diff --git a/src/libs/utils/reloadpromptutils.h b/src/libs/utils/reloadpromptutils.h index 8991d52b59..82aa409cf5 100644 --- a/src/libs/utils/reloadpromptutils.h +++ b/src/libs/utils/reloadpromptutils.h @@ -33,7 +33,7 @@ class QWidget; QT_END_NAMESPACE namespace Utils { -class FileName; +class FilePath; enum ReloadPromptAnswer { ReloadCurrent, @@ -44,7 +44,7 @@ enum ReloadPromptAnswer { CloseCurrent }; -QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FileName &fileName, +QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FilePath &fileName, bool modified, bool enableDiffOption, QWidget *parent); diff --git a/src/libs/utils/runextensions.h b/src/libs/utils/runextensions.h index 6925504693..eacbd8dc4c 100644 --- a/src/libs/utils/runextensions.h +++ b/src/libs/utils/runextensions.h @@ -600,4 +600,59 @@ const QFuture<T> &onResultReady(const QFuture<T> &future, Function f) return future; } -} // Utils +/*! + Adds a handler for when the future is finished. + This creates a new QFutureWatcher. Do not use if you intend to react on multiple conditions + or create a QFutureWatcher already for other reasons. +*/ +template<typename R, typename T> +const QFuture<T> &onFinished(const QFuture<T> &future, + R *receiver, + void (R::*member)(const QFuture<T> &)) +{ + auto watcher = new QFutureWatcher<T>(); + QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater); + QObject::connect(watcher, + &QFutureWatcherBase::finished, + receiver, + [receiver, member, watcher]() { (receiver->*member)(watcher->future()); }); + watcher->setFuture(future); + return future; +} + +/*! + Adds a handler for when the future is finished. The guard object determines the lifetime of + the connection. + This creates a new QFutureWatcher. Do not use if you intend to react on multiple conditions + or create a QFutureWatcher already for other reasons. +*/ +template<typename T, typename Function> +const QFuture<T> &onFinished(const QFuture<T> &future, QObject *guard, Function f) +{ + auto watcher = new QFutureWatcher<T>(); + QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater); + QObject::connect(watcher, &QFutureWatcherBase::finished, guard, [f, watcher]() { + f(watcher->future()); + }); + watcher->setFuture(future); + return future; +} + +/*! + Adds a handler for when the future is finished. + This creates a new QFutureWatcher. Do not use if you intend to react on multiple conditions + or create a QFutureWatcher already for other reasons. +*/ +template<typename T, typename Function> +const QFuture<T> &onFinished(const QFuture<T> &future, Function f) +{ + auto watcher = new QFutureWatcher<T>(); + QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater); + QObject::connect(watcher, &QFutureWatcherBase::finished, [f, watcher]() { + f(watcher->future()); + }); + watcher->setFuture(future); + return future; +} + +} // namespace Utils diff --git a/src/libs/utils/savedaction.cpp b/src/libs/utils/savedaction.cpp index 0000e54d31..87a785f6db 100644 --- a/src/libs/utils/savedaction.cpp +++ b/src/libs/utils/savedaction.cpp @@ -235,7 +235,7 @@ void SavedAction::connectWidget(QWidget *widget, ApplyMode applyMode) } else if (auto spinBox = qobject_cast<QSpinBox *>(widget)) { spinBox->setValue(m_value.toInt()); if (applyMode == ImmediateApply) { - connect(spinBox, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), + connect(spinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, [this, spinBox]() { setValue(spinBox->value()); }); } } else if (auto lineEdit = qobject_cast<QLineEdit *>(widget)) { diff --git a/src/libs/utils/savefile.cpp b/src/libs/utils/savefile.cpp index cac25546db..b25432a280 100644 --- a/src/libs/utils/savefile.cpp +++ b/src/libs/utils/savefile.cpp @@ -119,7 +119,7 @@ bool SaveFile::commit() } QString finalFileName - = FileUtils::resolveSymlinks(FileName::fromString(m_finalFileName)).toString(); + = FileUtils::resolveSymlinks(FilePath::fromString(m_finalFileName)).toString(); #ifdef Q_OS_WIN // Release the file lock diff --git a/src/libs/utils/settingsaccessor.cpp b/src/libs/utils/settingsaccessor.cpp index 662ad4bd43..f6d90df7e0 100644 --- a/src/libs/utils/settingsaccessor.cpp +++ b/src/libs/utils/settingsaccessor.cpp @@ -98,7 +98,7 @@ bool SettingsAccessor::saveSettings(const QVariantMap &data, QWidget *parent) co /*! * Read data from \a path. Do all the necessary postprocessing of the data. */ -SettingsAccessor::RestoreData SettingsAccessor::readData(const FileName &path, QWidget *parent) const +SettingsAccessor::RestoreData SettingsAccessor::readData(const FilePath &path, QWidget *parent) const { Q_UNUSED(parent); RestoreData result = readFile(path); @@ -111,13 +111,13 @@ SettingsAccessor::RestoreData SettingsAccessor::readData(const FileName &path, Q * Store the \a data in \a path on disk. Do all the necessary preprocessing of the data. */ optional<SettingsAccessor::Issue> -SettingsAccessor::writeData(const FileName &path, const QVariantMap &data, QWidget *parent) const +SettingsAccessor::writeData(const FilePath &path, const QVariantMap &data, QWidget *parent) const { Q_UNUSED(parent); return writeFile(path, prepareToWriteSettings(data)); } -QVariantMap SettingsAccessor::restoreSettings(const FileName &settingsPath, QWidget *parent) const +QVariantMap SettingsAccessor::restoreSettings(const FilePath &settingsPath, QWidget *parent) const { const RestoreData result = readData(settingsPath, parent); @@ -131,7 +131,7 @@ QVariantMap SettingsAccessor::restoreSettings(const FileName &settingsPath, QWid * * This method does not do *any* processing of the file contents. */ -SettingsAccessor::RestoreData SettingsAccessor::readFile(const FileName &path) const +SettingsAccessor::RestoreData SettingsAccessor::readFile(const FilePath &path) const { PersistentSettingsReader reader; if (!reader.load(path)) { @@ -156,7 +156,7 @@ SettingsAccessor::RestoreData SettingsAccessor::readFile(const FileName &path) c * This method does not do *any* processing of the file contents. */ optional<SettingsAccessor::Issue> -SettingsAccessor::writeFile(const FileName &path, const QVariantMap &data) const +SettingsAccessor::writeFile(const FilePath &path, const QVariantMap &data) const { if (data.isEmpty()) { return Issue(QCoreApplication::translate("Utils::SettingsAccessor", "Failed to Write File"), @@ -176,7 +176,7 @@ SettingsAccessor::writeFile(const FileName &path, const QVariantMap &data) const } SettingsAccessor::ProceedInfo -SettingsAccessor::reportIssues(const SettingsAccessor::Issue &issue, const FileName &path, +SettingsAccessor::reportIssues(const SettingsAccessor::Issue &issue, const FilePath &path, QWidget *parent) const { if (!path.exists()) @@ -217,14 +217,14 @@ QVariantMap SettingsAccessor::prepareToWriteSettings(const QVariantMap &data) co // BackingUpSettingsAccessor: // -------------------------------------------------------------------- -FileNameList BackUpStrategy::readFileCandidates(const FileName &baseFileName) const +FilePathList BackUpStrategy::readFileCandidates(const FilePath &baseFileName) const { const QFileInfo pfi = baseFileName.toFileInfo(); const QStringList filter(pfi.fileName() + '*'); const QFileInfoList list = QDir(pfi.dir()).entryInfoList(filter, QDir::Files | QDir::Hidden | QDir::System); - return Utils::transform(list, [](const QFileInfo &fi) { return FileName::fromString(fi.absoluteFilePath()); }); + return Utils::transform(list, [](const QFileInfo &fi) { return FilePath::fromString(fi.absoluteFilePath()); }); } int BackUpStrategy::compare(const SettingsAccessor::RestoreData &data1, @@ -239,14 +239,12 @@ int BackUpStrategy::compare(const SettingsAccessor::RestoreData &data1, return 0; } -optional<FileName> -BackUpStrategy::backupName(const QVariantMap &oldData, const FileName &path, const QVariantMap &data) const +optional<FilePath> +BackUpStrategy::backupName(const QVariantMap &oldData, const FilePath &path, const QVariantMap &data) const { if (oldData == data) return nullopt; - FileName backup = path; - backup.appendString(".bak"); - return backup; + return path.stringAppended(".bak"); } BackingUpSettingsAccessor::BackingUpSettingsAccessor(const QString &docType, @@ -264,9 +262,9 @@ BackingUpSettingsAccessor::BackingUpSettingsAccessor(std::unique_ptr<BackUpStrat { } SettingsAccessor::RestoreData -BackingUpSettingsAccessor::readData(const FileName &path, QWidget *parent) const +BackingUpSettingsAccessor::readData(const FilePath &path, QWidget *parent) const { - const FileNameList fileList = readFileCandidates(path); + const FilePathList fileList = readFileCandidates(path); if (fileList.isEmpty()) // No settings found at all. return RestoreData(path, QVariantMap()); @@ -289,7 +287,7 @@ BackingUpSettingsAccessor::readData(const FileName &path, QWidget *parent) const } optional<SettingsAccessor::Issue> -BackingUpSettingsAccessor::writeData(const FileName &path, const QVariantMap &data, +BackingUpSettingsAccessor::writeData(const FilePath &path, const QVariantMap &data, QWidget *parent) const { if (data.isEmpty()) @@ -300,9 +298,9 @@ BackingUpSettingsAccessor::writeData(const FileName &path, const QVariantMap &da return SettingsAccessor::writeData(path, data, parent); } -FileNameList BackingUpSettingsAccessor::readFileCandidates(const FileName &path) const +FilePathList BackingUpSettingsAccessor::readFileCandidates(const FilePath &path) const { - FileNameList result = Utils::filteredUnique(m_strategy->readFileCandidates(path)); + FilePathList result = Utils::filteredUnique(m_strategy->readFileCandidates(path)); if (result.removeOne(baseFilePath())) result.prepend(baseFilePath()); @@ -310,10 +308,10 @@ FileNameList BackingUpSettingsAccessor::readFileCandidates(const FileName &path) } SettingsAccessor::RestoreData -BackingUpSettingsAccessor::bestReadFileData(const FileNameList &candidates, QWidget *parent) const +BackingUpSettingsAccessor::bestReadFileData(const FilePathList &candidates, QWidget *parent) const { SettingsAccessor::RestoreData bestMatch; - for (const FileName &c : candidates) { + for (const FilePath &c : candidates) { RestoreData cData = SettingsAccessor::readData(c, parent); if (m_strategy->compare(bestMatch, cData) > 0) bestMatch = cData; @@ -321,7 +319,7 @@ BackingUpSettingsAccessor::bestReadFileData(const FileNameList &candidates, QWid return bestMatch; } -void BackingUpSettingsAccessor::backupFile(const FileName &path, const QVariantMap &data, +void BackingUpSettingsAccessor::backupFile(const FilePath &path, const QVariantMap &data, QWidget *parent) const { RestoreData oldSettings = SettingsAccessor::readData(path, parent); @@ -330,7 +328,7 @@ void BackingUpSettingsAccessor::backupFile(const FileName &path, const QVariantM // Do we need to do a backup? const QString origName = path.toString(); - optional<FileName> backupFileName = m_strategy->backupName(oldSettings.data, path, data); + optional<FilePath> backupFileName = m_strategy->backupName(oldSettings.data, path, data); if (backupFileName) QFile::copy(origName, backupFileName.value().toString()); } @@ -361,22 +359,23 @@ int VersionedBackUpStrategy::compare(const SettingsAccessor::RestoreData &data1, return -1; } -optional<FileName> -VersionedBackUpStrategy::backupName(const QVariantMap &oldData, const FileName &path, const QVariantMap &data) const +optional<FilePath> +VersionedBackUpStrategy::backupName(const QVariantMap &oldData, const FilePath &path, const QVariantMap &data) const { Q_UNUSED(data); - FileName backupName = path; + FilePath backupName = path; const QByteArray oldEnvironmentId = settingsIdFromMap(oldData); const int oldVersion = versionFromMap(oldData); if (!oldEnvironmentId.isEmpty() && oldEnvironmentId != m_accessor->settingsId()) - backupName.appendString('.' + QString::fromLatin1(oldEnvironmentId).mid(1, 7)); + backupName = backupName.stringAppended + ('.' + QString::fromLatin1(oldEnvironmentId).mid(1, 7)); if (oldVersion != m_accessor->currentVersion()) { VersionUpgrader *upgrader = m_accessor->upgrader(oldVersion); if (upgrader) - backupName.appendString('.' + upgrader->backupExtension()); + backupName = backupName.stringAppended('.' + upgrader->backupExtension()); else - backupName.appendString('.' + QString::number(oldVersion)); + backupName = backupName.stringAppended('.' + QString::number(oldVersion)); } if (backupName == path) return nullopt; @@ -464,7 +463,7 @@ bool UpgradingSettingsAccessor::isValidVersionAndId(const int version, const QBy && (id.isEmpty() || id == m_id || m_id.isEmpty()); } -SettingsAccessor::RestoreData UpgradingSettingsAccessor::readData(const FileName &path, +SettingsAccessor::RestoreData UpgradingSettingsAccessor::readData(const FilePath &path, QWidget *parent) const { return upgradeSettings(BackingUpSettingsAccessor::readData(path, parent), currentVersion()); @@ -606,7 +605,7 @@ MergingSettingsAccessor::MergingSettingsAccessor(std::unique_ptr<BackUpStrategy> UpgradingSettingsAccessor(std::move(strategy), docType, displayName, applicationDisplayName) { } -SettingsAccessor::RestoreData MergingSettingsAccessor::readData(const FileName &path, +SettingsAccessor::RestoreData MergingSettingsAccessor::readData(const FilePath &path, QWidget *parent) const { RestoreData mainData = UpgradingSettingsAccessor::readData(path, parent); // FULLY upgraded! diff --git a/src/libs/utils/settingsaccessor.h b/src/libs/utils/settingsaccessor.h index 10675cbf4c..fd5cf87ef7 100644 --- a/src/libs/utils/settingsaccessor.h +++ b/src/libs/utils/settingsaccessor.h @@ -99,7 +99,7 @@ public: class RestoreData { public: RestoreData() = default; - RestoreData(const FileName &path, const QVariantMap &data) : path{path}, data{data} { } + RestoreData(const FilePath &path, const QVariantMap &data) : path{path}, data{data} { } RestoreData(const QString &title, const QString &message, const Issue::Type type) : RestoreData(Issue(title, message, type)) { } @@ -109,7 +109,7 @@ public: bool hasError() const { return hasIssue() && issue.value().type == Issue::Type::ERROR; } bool hasWarning() const { return hasIssue() && issue.value().type == Issue::Type::WARNING; } - FileName path; + FilePath path; QVariantMap data; optional<Issue> issue; }; @@ -121,26 +121,26 @@ public: const QString displayName; const QString applicationDisplayName; - void setBaseFilePath(const FileName &baseFilePath) { m_baseFilePath = baseFilePath; } + void setBaseFilePath(const FilePath &baseFilePath) { m_baseFilePath = baseFilePath; } void setReadOnly() { m_readOnly = true; } - FileName baseFilePath() const { return m_baseFilePath; } + FilePath baseFilePath() const { return m_baseFilePath; } - virtual RestoreData readData(const FileName &path, QWidget *parent) const; - virtual optional<Issue> writeData(const FileName &path, const QVariantMap &data, QWidget *parent) const; + virtual RestoreData readData(const FilePath &path, QWidget *parent) const; + virtual optional<Issue> writeData(const FilePath &path, const QVariantMap &data, QWidget *parent) const; protected: // Report errors: - QVariantMap restoreSettings(const FileName &settingsPath, QWidget *parent) const; - ProceedInfo reportIssues(const Issue &issue, const FileName &path, QWidget *parent) const; + QVariantMap restoreSettings(const FilePath &settingsPath, QWidget *parent) const; + ProceedInfo reportIssues(const Issue &issue, const FilePath &path, QWidget *parent) const; virtual QVariantMap preprocessReadSettings(const QVariantMap &data) const; virtual QVariantMap prepareToWriteSettings(const QVariantMap &data) const; - virtual RestoreData readFile(const FileName &path) const; - virtual optional<Issue> writeFile(const FileName &path, const QVariantMap &data) const; + virtual RestoreData readFile(const FilePath &path) const; + virtual optional<Issue> writeFile(const FilePath &path, const QVariantMap &data) const; private: - FileName m_baseFilePath; + FilePath m_baseFilePath; mutable std::unique_ptr<PersistentSettingsWriter> m_writer; bool m_readOnly = false; }; @@ -154,14 +154,14 @@ class QTCREATOR_UTILS_EXPORT BackUpStrategy public: virtual ~BackUpStrategy() = default; - virtual FileNameList readFileCandidates(const FileName &baseFileName) const; + virtual FilePathList readFileCandidates(const FilePath &baseFileName) const; // Return -1 if data1 is better that data2, 0 if both are equally worthwhile // and 1 if data2 is better than data1 virtual int compare(const SettingsAccessor::RestoreData &data1, const SettingsAccessor::RestoreData &data2) const; - virtual optional<FileName> - backupName(const QVariantMap &oldData, const FileName &path, const QVariantMap &data) const; + virtual optional<FilePath> + backupName(const QVariantMap &oldData, const FilePath &path, const QVariantMap &data) const; }; class QTCREATOR_UTILS_EXPORT BackingUpSettingsAccessor : public SettingsAccessor @@ -172,16 +172,16 @@ public: BackingUpSettingsAccessor(std::unique_ptr<BackUpStrategy> &&strategy, const QString &docType, const QString &displayName, const QString &applicationDisplayName); - RestoreData readData(const FileName &path, QWidget *parent) const override; - optional<Issue> writeData(const FileName &path, const QVariantMap &data, + RestoreData readData(const FilePath &path, QWidget *parent) const override; + optional<Issue> writeData(const FilePath &path, const QVariantMap &data, QWidget *parent) const override; BackUpStrategy *strategy() const { return m_strategy.get(); } private: - FileNameList readFileCandidates(const FileName &path) const; - RestoreData bestReadFileData(const FileNameList &candidates, QWidget *parent) const; - void backupFile(const FileName &path, const QVariantMap &data, QWidget *parent) const; + FilePathList readFileCandidates(const FilePath &path) const; + RestoreData bestReadFileData(const FilePathList &candidates, QWidget *parent) const; + void backupFile(const FilePath &path, const QVariantMap &data, QWidget *parent) const; std::unique_ptr<BackUpStrategy> m_strategy; }; @@ -202,8 +202,8 @@ public: int compare(const SettingsAccessor::RestoreData &data1, const SettingsAccessor::RestoreData &data2) const override; - optional<FileName> - backupName(const QVariantMap &oldData, const FileName &path, const QVariantMap &data) const override; + optional<FilePath> + backupName(const QVariantMap &oldData, const FilePath &path, const QVariantMap &data) const override; const UpgradingSettingsAccessor *accessor() const { return m_accessor; } @@ -251,7 +251,7 @@ public: bool isValidVersionAndId(const int version, const QByteArray &id) const; VersionUpgrader *upgrader(const int version) const; - RestoreData readData(const FileName &path, QWidget *parent) const override; + RestoreData readData(const FilePath &path, QWidget *parent) const override; protected: QVariantMap prepareToWriteSettings(const QVariantMap &data) const override; @@ -284,7 +284,7 @@ public: const QString &docType, const QString &displayName, const QString &applicationDisplayName); - RestoreData readData(const FileName &path, QWidget *parent) const final; + RestoreData readData(const FilePath &path, QWidget *parent) const final; void setSecondaryAccessor(std::unique_ptr<SettingsAccessor> &&secondary); diff --git a/src/libs/utils/settingsselector.cpp b/src/libs/utils/settingsselector.cpp index ddfa7a137c..6ae5bff43c 100644 --- a/src/libs/utils/settingsselector.cpp +++ b/src/libs/utils/settingsselector.cpp @@ -73,7 +73,7 @@ SettingsSelector::SettingsSelector(QWidget *parent) : connect(m_renameButton, &QAbstractButton::clicked, this, &SettingsSelector::renameButtonClicked); connect(m_configurationCombo, - static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), + QOverload<int>::of(&QComboBox::currentIndexChanged), this, &SettingsSelector::currentChanged); } diff --git a/src/libs/utils/shellcommand.cpp b/src/libs/utils/shellcommand.cpp index 14f52d2539..5a84c92f15 100644 --- a/src/libs/utils/shellcommand.cpp +++ b/src/libs/utils/shellcommand.cpp @@ -68,11 +68,11 @@ class ShellCommandPrivate { public: struct Job { - explicit Job(const QString &wd, const FileName &b, const QStringList &a, int t, + explicit Job(const QString &wd, const FilePath &b, const QStringList &a, int t, const ExitCodeInterpreter &interpreter); QString workingDirectory; - FileName binary; + FilePath binary; QStringList arguments; ExitCodeInterpreter exitCodeInterpreter; int timeoutS; @@ -113,7 +113,7 @@ ShellCommandPrivate::~ShellCommandPrivate() delete m_progressParser; } -ShellCommandPrivate::Job::Job(const QString &wd, const FileName &b, const QStringList &a, +ShellCommandPrivate::Job::Job(const QString &wd, const FilePath &b, const QStringList &a, int t, const ExitCodeInterpreter &interpreter) : workingDirectory(wd), binary(b), @@ -195,13 +195,13 @@ void ShellCommand::addFlags(unsigned f) d->m_flags |= f; } -void ShellCommand::addJob(const FileName &binary, const QStringList &arguments, +void ShellCommand::addJob(const FilePath &binary, const QStringList &arguments, const QString &workingDirectory, const ExitCodeInterpreter &interpreter) { addJob(binary, arguments, defaultTimeoutS(), workingDirectory, interpreter); } -void ShellCommand::addJob(const FileName &binary, const QStringList &arguments, int timeoutS, +void ShellCommand::addJob(const FilePath &binary, const QStringList &arguments, int timeoutS, const QString &workingDirectory, const ExitCodeInterpreter &interpreter) { d->m_jobs.push_back(Internal::ShellCommandPrivate::Job(workDirectory(workingDirectory), binary, @@ -319,7 +319,7 @@ void ShellCommand::run(QFutureInterface<void> &future) this->deleteLater(); } -SynchronousProcessResponse ShellCommand::runCommand(const FileName &binary, +SynchronousProcessResponse ShellCommand::runCommand(const FilePath &binary, const QStringList &arguments, int timeoutS, const QString &workingDirectory, const ExitCodeInterpreter &interpreter) @@ -359,7 +359,7 @@ SynchronousProcessResponse ShellCommand::runCommand(const FileName &binary, return response; } -SynchronousProcessResponse ShellCommand::runFullySynchronous(const FileName &binary, +SynchronousProcessResponse ShellCommand::runFullySynchronous(const FilePath &binary, const QStringList &arguments, QSharedPointer<OutputProxy> proxy, int timeoutS, @@ -399,7 +399,7 @@ SynchronousProcessResponse ShellCommand::runFullySynchronous(const FileName &bin return resp; } -SynchronousProcessResponse ShellCommand::runSynchronous(const FileName &binary, +SynchronousProcessResponse ShellCommand::runSynchronous(const FilePath &binary, const QStringList &arguments, QSharedPointer<OutputProxy> proxy, int timeoutS, diff --git a/src/libs/utils/shellcommand.h b/src/libs/utils/shellcommand.h index 22ff4a8df2..f0c427ef53 100644 --- a/src/libs/utils/shellcommand.h +++ b/src/libs/utils/shellcommand.h @@ -46,7 +46,7 @@ QT_END_NAMESPACE namespace Utils { -class FileName; +class FilePath; namespace Internal { class ShellCommandPrivate; } class QTCREATOR_UTILS_EXPORT ProgressParser @@ -79,7 +79,7 @@ signals: void append(const QString &text); void appendSilently(const QString &text); void appendError(const QString &text); - void appendCommand(const QString &workingDirectory, const Utils::FileName &binary, + void appendCommand(const QString &workingDirectory, const Utils::FilePath &binary, const QStringList &args); void appendMessage(const QString &text); }; @@ -112,9 +112,9 @@ public: QString displayName() const; void setDisplayName(const QString &name); - void addJob(const FileName &binary, const QStringList &arguments, + void addJob(const FilePath &binary, const QStringList &arguments, const QString &workingDirectory = QString(), const ExitCodeInterpreter &interpreter = defaultExitCodeInterpreter); - void addJob(const FileName &binary, const QStringList &arguments, int timeoutS, + void addJob(const FilePath &binary, const QStringList &arguments, int timeoutS, const QString &workingDirectory = QString(), const ExitCodeInterpreter &interpreter = defaultExitCodeInterpreter); void execute(); // Execute tasks asynchronously! void abort(); @@ -145,7 +145,7 @@ public: // This is called once per job in a thread. // When called from the UI thread it will execute fully synchronously, so no signals will // be triggered! - virtual SynchronousProcessResponse runCommand(const FileName &binary, const QStringList &arguments, + virtual SynchronousProcessResponse runCommand(const FilePath &binary, const QStringList &arguments, int timeoutS, const QString &workingDirectory = QString(), const ExitCodeInterpreter &interpreter = defaultExitCodeInterpreter); @@ -171,12 +171,12 @@ private: void run(QFutureInterface<void> &future); // Run without a event loop in fully blocking mode. No signals will be delivered. - SynchronousProcessResponse runFullySynchronous(const FileName &binary, const QStringList &arguments, + SynchronousProcessResponse runFullySynchronous(const FilePath &binary, const QStringList &arguments, QSharedPointer<OutputProxy> proxy, int timeoutS, const QString &workingDirectory, const ExitCodeInterpreter &interpreter = defaultExitCodeInterpreter); // Run with an event loop. Signals will be delivered. - SynchronousProcessResponse runSynchronous(const FileName &binary, const QStringList &arguments, + SynchronousProcessResponse runSynchronous(const FilePath &binary, const QStringList &arguments, QSharedPointer<OutputProxy> proxy, int timeoutS, const QString &workingDirectory, const ExitCodeInterpreter &interpreter = defaultExitCodeInterpreter); diff --git a/src/libs/utils/smallstringlayout.h b/src/libs/utils/smallstringlayout.h index dc6867af5d..c381fbd44b 100644 --- a/src/libs/utils/smallstringlayout.h +++ b/src/libs/utils/smallstringlayout.h @@ -198,13 +198,6 @@ struct StringDataLayout { shortString.string[0] = '\0'; } - StringDataLayout &operator=(const StringDataLayout &other) - { - this->shortString = other.shortString; - - return *this; - } - union { AllocatedLayout<MaximumShortStringDataAreaSize> allocated; ReferenceLayout<MaximumShortStringDataAreaSize> reference; diff --git a/src/libs/utils/stringutils.cpp b/src/libs/utils/stringutils.cpp index b39af367d5..161cf44e74 100644 --- a/src/libs/utils/stringutils.cpp +++ b/src/libs/utils/stringutils.cpp @@ -143,7 +143,7 @@ bool AbstractMacroExpander::expandNestedMacros(const QString &str, int *pos, QSt varName.reserve(strLen - i); for (; i < strLen; prev = c) { c = str.at(i++); - if (c == '\\' && i < strLen && validateVarName(varName)) { + if (c == '\\' && i < strLen) { c = str.at(i++); // For the replacement, do not skip the escape sequence when followed by a digit. // This is needed for enabling convenient capture group replacement, diff --git a/src/libs/utils/stylehelper.cpp b/src/libs/utils/stylehelper.cpp index e44037f5a1..388da7eeba 100644 --- a/src/libs/utils/stylehelper.cpp +++ b/src/libs/utils/stylehelper.cpp @@ -209,9 +209,9 @@ static void verticalGradientHelper(QPainter *p, const QRect &spanRect, const QRe void StyleHelper::verticalGradient(QPainter *painter, const QRect &spanRect, const QRect &clipRect, bool lightColored) { if (StyleHelper::usePixmapCache()) { - QString key; + QColor keyColor = baseColor(lightColored); - key.sprintf("mh_vertical %d %d %d %d %d", + const QString key = QString::asprintf("mh_vertical %d %d %d %d %d", spanRect.width(), spanRect.height(), clipRect.width(), clipRect.height(), keyColor.rgb()); @@ -267,9 +267,9 @@ QRect &rect, bool lightColored) void StyleHelper::horizontalGradient(QPainter *painter, const QRect &spanRect, const QRect &clipRect, bool lightColored) { if (StyleHelper::usePixmapCache()) { - QString key; + QColor keyColor = baseColor(lightColored); - key.sprintf("mh_horizontal %d %d %d %d %d %d", + const QString key = QString::asprintf("mh_horizontal %d %d %d %d %d %d", spanRect.width(), spanRect.height(), clipRect.width(), clipRect.height(), keyColor.rgb(), spanRect.x()); @@ -309,8 +309,7 @@ void StyleHelper::drawArrow(QStyle::PrimitiveElement element, QPainter *painter, QRect r = option->rect; int size = qMin(r.height(), r.width()); QPixmap pixmap; - QString pixmapName; - pixmapName.sprintf("StyleHelper::drawArrow-%d-%d-%d-%f", + const QString pixmapName = QString::asprintf("StyleHelper::drawArrow-%d-%d-%d-%f", element, size, enabled, devicePixelRatio); if (!QPixmapCache::find(pixmapName, &pixmap)) { QImage image(size * devicePixelRatio, size * devicePixelRatio, QImage::Format_ARGB32_Premultiplied); @@ -351,8 +350,7 @@ void StyleHelper::drawArrow(QStyle::PrimitiveElement element, QPainter *painter, void StyleHelper::menuGradient(QPainter *painter, const QRect &spanRect, const QRect &clipRect) { if (StyleHelper::usePixmapCache()) { - QString key; - key.sprintf("mh_menu %d %d %d %d %d", + const QString key = QString::asprintf("mh_menu %d %d %d %d %d", spanRect.width(), spanRect.height(), clipRect.width(), clipRect.height(), StyleHelper::baseColor().rgb()); diff --git a/src/libs/utils/synchronousprocess.cpp b/src/libs/utils/synchronousprocess.cpp index a153e6ac91..bfb9d0d296 100644 --- a/src/libs/utils/synchronousprocess.cpp +++ b/src/libs/utils/synchronousprocess.cpp @@ -297,8 +297,7 @@ SynchronousProcess::SynchronousProcess() : { d->m_timer.setInterval(1000); connect(&d->m_timer, &QTimer::timeout, this, &SynchronousProcess::slotTimeout); - connect(&d->m_process, - static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), + connect(&d->m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &SynchronousProcess::finished); connect(&d->m_process, &QProcess::errorOccurred, this, &SynchronousProcess::error); connect(&d->m_process, &QProcess::readyReadStandardOutput, diff --git a/src/libs/utils/textfieldcombobox.cpp b/src/libs/utils/textfieldcombobox.cpp index db940ad53a..aad64d2e7d 100644 --- a/src/libs/utils/textfieldcombobox.cpp +++ b/src/libs/utils/textfieldcombobox.cpp @@ -43,7 +43,7 @@ TextFieldComboBox::TextFieldComboBox(QWidget *parent) : QComboBox(parent) { setEditable(false); - connect(this, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), + connect(this, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &TextFieldComboBox::slotCurrentIndexChanged); } diff --git a/src/libs/utils/touchbar/touchbar.pri b/src/libs/utils/touchbar/touchbar.pri index 8d60ee423b..5f18595785 100644 --- a/src/libs/utils/touchbar/touchbar.pri +++ b/src/libs/utils/touchbar/touchbar.pri @@ -9,7 +9,6 @@ macos { $$PWD/touchbar_mac.mm \ $$PWD/touchbar_appdelegate_mac.mm - QT += macextras LIBS += -framework Foundation -framework AppKit } else { SOURCES += $$PWD/touchbar.cpp diff --git a/src/libs/utils/touchbar/touchbar_mac.mm b/src/libs/utils/touchbar/touchbar_mac.mm index 67c83aec0c..ee5a45bf72 100644 --- a/src/libs/utils/touchbar/touchbar_mac.mm +++ b/src/libs/utils/touchbar/touchbar_mac.mm @@ -29,8 +29,6 @@ #include <utils/utilsicons.h> -#include <QtMac> - #import <AppKit/NSButton.h> #import <AppKit/NSCustomTouchBarItem.h> #import <AppKit/NSImage.h> @@ -145,8 +143,12 @@ static NSImage *iconToTemplateNSImage(const QIcon &icon) { // touch bar icons are max 18-22 pts big. our are always 22 pts big. const QPixmap pixmap = icon.pixmap(22); - NSImage *image = QtMac::toNSImage(pixmap); - // toNSImage ignores devicePixelRatio, so fixup after the fact + + CGImageRef cgImage = pixmap.toImage().toCGImage(); + NSImage *image = [[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize]; + CFRelease(cgImage); + + // The above code ignores devicePixelRatio, so fixup after the fact const CGFloat userWidth = pixmap.width() / pixmap.devicePixelRatio(); const CGFloat userHeight = pixmap.height() / pixmap.devicePixelRatio(); image.size = CGSizeMake(userWidth, userHeight); // scales the image diff --git a/src/libs/utils/unixutils.cpp b/src/libs/utils/unixutils.cpp index 7db05c22ea..77daae645c 100644 --- a/src/libs/utils/unixutils.cpp +++ b/src/libs/utils/unixutils.cpp @@ -77,7 +77,7 @@ QString UnixUtils::substituteFileBrowserParameters(const QString &pre, const QSt } else if (c == QLatin1Char('f')) { s = QLatin1Char('"') + file + QLatin1Char('"'); } else if (c == QLatin1Char('n')) { - s = QLatin1Char('"') + FileName::fromString(file).fileName() + QLatin1Char('"'); + s = QLatin1Char('"') + FilePath::fromString(file).fileName() + QLatin1Char('"'); } else if (c == QLatin1Char('%')) { s = c; } else { diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri index 5a2712cc3f..c7fef47c97 100644 --- a/src/libs/utils/utils-lib.pri +++ b/src/libs/utils/utils-lib.pri @@ -13,7 +13,7 @@ shared { } } -QT += widgets gui network qml +QT += widgets gui network qml xml CONFIG += exceptions # used by portlist.cpp, textfileformat.cpp, and ssh/* @@ -27,6 +27,7 @@ SOURCES += \ $$PWD/environment.cpp \ $$PWD/environmentmodel.cpp \ $$PWD/environmentdialog.cpp \ + $$PWD/qrcparser.cpp \ $$PWD/qtcprocess.cpp \ $$PWD/reloadpromptutils.cpp \ $$PWD/settingsaccessor.cpp \ @@ -131,12 +132,14 @@ win32:SOURCES += $$PWD/consoleprocess_win.cpp else:SOURCES += $$PWD/consoleprocess_unix.cpp HEADERS += \ + $$PWD/genericconstants.h \ $$PWD/globalfilechangeblocker.h \ $$PWD/benchmarker.h \ $$PWD/environment.h \ $$PWD/environmentmodel.h \ $$PWD/environmentdialog.h \ $$PWD/pointeralgorithm.h \ + $$PWD/qrcparser.h \ $$PWD/qtcprocess.h \ $$PWD/utils_global.h \ $$PWD/reloadpromptutils.h \ @@ -266,7 +269,8 @@ HEADERS += \ $$PWD/removefiledialog.h \ $$PWD/differ.h \ $$PWD/cpplanguage_details.h \ - $$PWD/jsontreeitem.h + $$PWD/jsontreeitem.h \ + $$PWD/listmodel.h FORMS += $$PWD/filewizardpage.ui \ $$PWD/newclasswidget.ui \ diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs index d50f7f41f6..694045e290 100644 --- a/src/libs/utils/utils.qbs +++ b/src/libs/utils/utils.qbs @@ -33,7 +33,7 @@ Project { cpp.frameworks: ["Foundation", "AppKit"] } - Depends { name: "Qt"; submodules: ["concurrent", "network", "qml", "widgets"] } + Depends { name: "Qt"; submodules: ["concurrent", "network", "qml", "widgets", "xml"] } Depends { name: "Qt.macextras"; condition: qbs.targetOS.contains("macos") } Depends { name: "app_version_header" } @@ -146,6 +146,7 @@ Project { "jsontreeitem.h", "linecolumn.h", "link.h", + "listmodel.h", "listutils.h", "macroexpander.cpp", "macroexpander.h", @@ -191,6 +192,8 @@ Project { "proxycredentialsdialog.cpp", "proxycredentialsdialog.h", "proxycredentialsdialog.ui", + "qrcparser.cpp", + "qrcparser.h", "qtcassert.cpp", "qtcassert.h", "qtcolorbutton.cpp", diff --git a/src/libs/utils/utils.qrc b/src/libs/utils/utils.qrc index 6ad7dd3196..a8731b6b20 100644 --- a/src/libs/utils/utils.qrc +++ b/src/libs/utils/utils.qrc @@ -34,6 +34,8 @@ <file>images/locked@2x.png</file> <file>images/unlocked.png</file> <file>images/unlocked@2x.png</file> + <file>images/pinned.png</file> + <file>images/pinned@2x.png</file> <file>images/broken.png</file> <file>images/broken@2x.png</file> <file>images/notloaded.png</file> @@ -213,6 +215,14 @@ <file>images/macos_touchbar_bookmark@2x.png</file> <file>images/macos_touchbar_clear.png</file> <file>images/macos_touchbar_clear@2x.png</file> + <file>images/settings.png</file> + <file>images/settings@2x.png</file> + <file>images/sort_alphabetically.png</file> + <file>images/sort_alphabetically@2x.png</file> + <file>images/toggleprogressdetails.png</file> + <file>images/toggleprogressdetails@2x.png</file> + <file>images/unknownfile.png</file> + <file>images/dir.png</file> </qresource> <qresource prefix="/codemodel"> <file>images/enum.png</file> diff --git a/src/libs/utils/utilsicons.cpp b/src/libs/utils/utilsicons.cpp index 9855165c3e..2227f530c6 100644 --- a/src/libs/utils/utilsicons.cpp +++ b/src/libs/utils/utilsicons.cpp @@ -28,7 +28,6 @@ namespace Utils { namespace Icons { - const Icon HOME({ {QLatin1String(":/utils/images/home.png"), Theme::PanelTextColorDark}}, Icon::Tint); const Icon HOME_TOOLBAR({ @@ -43,6 +42,8 @@ const Icon LOCKED({ {QLatin1String(":/utils/images/locked.png"), Theme::PanelTextColorDark}}, Icon::Tint); const Icon UNLOCKED_TOOLBAR({ {QLatin1String(":/utils/images/unlocked.png"), Theme::IconsBaseColor}}); +const Icon PINNED({ + {QLatin1String(":/utils/images/pinned.png"), Theme::PanelTextColorDark}}, Icon::Tint); const Icon NEXT({ {QLatin1String(":/utils/images/next.png"), Theme::IconsWarningColor}}, Icon::MenuTintedStyle); const Icon NEXT_TOOLBAR({ @@ -85,6 +86,8 @@ const Icon SNAPSHOT_TOOLBAR({ const Icon NEWSEARCH_TOOLBAR({ {QLatin1String(":/utils/images/zoom.png"), Theme::IconsBaseColor}, {QLatin1String(":/utils/images/iconoverlay_add_small.png"), Theme::IconsRunColor}}); +const Icon SETTINGS_TOOLBAR({ + {QLatin1String(":/utils/images/settings.png"), Theme::IconsBaseColor}}); const Icon NEWFILE({ {QLatin1String(":/utils/images/filenew.png"), Theme::PanelTextColorMid}}, Icon::Tint); @@ -102,6 +105,11 @@ const Icon EXPORTFILE_TOOLBAR({ const Icon MULTIEXPORTFILE_TOOLBAR({ {QLatin1String(":/utils/images/filemultiexport.png"), Theme::IconsBaseColor}}); +const Icon UNKNOWN_FILE({ + {QLatin1String(":/utils/images/unknownfile.png"), Theme::IconsBaseColor}}); +const Icon DIR({ + {QLatin1String(":/utils/images/dir.png"), Theme::IconsBaseColor}}); + const Icon UNDO({ {QLatin1String(":/utils/images/undo.png"), Theme::PanelTextColorMid}}, Icon::Tint); const Icon UNDO_TOOLBAR({ @@ -182,6 +190,11 @@ const Icon LINK({ {QLatin1String(":/utils/images/linkicon.png"), Theme::PanelTextColorMid}}, Icon::Tint); const Icon LINK_TOOLBAR({ {QLatin1String(":/utils/images/linkicon.png"), Theme::IconsBaseColor}}); +const Icon SORT_ALPHABETICALLY_TOOLBAR({ + {QLatin1String(":/utils/images/sort_alphabetically.png"), Theme::IconsBaseColor}}); +const Icon TOGGLE_PROGRESSDETAILS_TOOLBAR({ + {QLatin1String(":/utils/images/toggleprogressdetails.png"), Theme::IconsBaseColor}}); + const Icon WARNING({ {QLatin1String(":/utils/images/warningfill.png"), Theme::BackgroundColorNormal}, {QLatin1String(":/utils/images/warning.png"), Theme::IconsWarningColor}}, Icon::Tint); @@ -444,6 +457,10 @@ QIcon CodeModelIcon::iconForType(CodeModelIcon::Type type) }, Icon::Tint).icon()); return icon; } + case Unknown: { + const static QIcon icon(Icons::EMPTY16.icon()); + return icon; + } default: break; } diff --git a/src/libs/utils/utilsicons.h b/src/libs/utils/utilsicons.h index b229523911..ae6cd4d1dc 100644 --- a/src/libs/utils/utilsicons.h +++ b/src/libs/utils/utilsicons.h @@ -38,6 +38,7 @@ QTCREATOR_UTILS_EXPORT extern const Icon EDIT_CLEAR_TOOLBAR; QTCREATOR_UTILS_EXPORT extern const Icon LOCKED_TOOLBAR; QTCREATOR_UTILS_EXPORT extern const Icon LOCKED; QTCREATOR_UTILS_EXPORT extern const Icon UNLOCKED_TOOLBAR; +QTCREATOR_UTILS_EXPORT extern const Icon PINNED; QTCREATOR_UTILS_EXPORT extern const Icon NEXT; QTCREATOR_UTILS_EXPORT extern const Icon NEXT_TOOLBAR; QTCREATOR_UTILS_EXPORT extern const Icon PREV; @@ -56,6 +57,7 @@ QTCREATOR_UTILS_EXPORT extern const Icon BOOKMARK_TOOLBAR; QTCREATOR_UTILS_EXPORT extern const Icon BOOKMARK_TEXTEDITOR; QTCREATOR_UTILS_EXPORT extern const Icon SNAPSHOT_TOOLBAR; QTCREATOR_UTILS_EXPORT extern const Icon NEWSEARCH_TOOLBAR; +QTCREATOR_UTILS_EXPORT extern const Icon SETTINGS_TOOLBAR; QTCREATOR_UTILS_EXPORT extern const Icon NEWFILE; QTCREATOR_UTILS_EXPORT extern const Icon OPENFILE; @@ -66,6 +68,9 @@ QTCREATOR_UTILS_EXPORT extern const Icon SAVEFILE_TOOLBAR; QTCREATOR_UTILS_EXPORT extern const Icon EXPORTFILE_TOOLBAR; QTCREATOR_UTILS_EXPORT extern const Icon MULTIEXPORTFILE_TOOLBAR; +QTCREATOR_UTILS_EXPORT extern const Icon UNKNOWN_FILE; +QTCREATOR_UTILS_EXPORT extern const Icon DIR; + QTCREATOR_UTILS_EXPORT extern const Icon UNDO; QTCREATOR_UTILS_EXPORT extern const Icon UNDO_TOOLBAR; QTCREATOR_UTILS_EXPORT extern const Icon REDO; @@ -106,6 +111,8 @@ QTCREATOR_UTILS_EXPORT extern const Icon CLOSE_SPLIT_RIGHT; QTCREATOR_UTILS_EXPORT extern const Icon FILTER; QTCREATOR_UTILS_EXPORT extern const Icon LINK; QTCREATOR_UTILS_EXPORT extern const Icon LINK_TOOLBAR; +QTCREATOR_UTILS_EXPORT extern const Icon SORT_ALPHABETICALLY_TOOLBAR; +QTCREATOR_UTILS_EXPORT extern const Icon TOGGLE_PROGRESSDETAILS_TOOLBAR; QTCREATOR_UTILS_EXPORT extern const Icon INFO; QTCREATOR_UTILS_EXPORT extern const Icon INFO_TOOLBAR; diff --git a/src/libs/utils/variant.h b/src/libs/utils/variant.h index 00e9eaf252..371b9312d3 100644 --- a/src/libs/utils/variant.h +++ b/src/libs/utils/variant.h @@ -30,10 +30,25 @@ */ // TODO: replace by #include <(experimental/)variant> depending on compiler and C++ version -#include <3rdparty/variant/variant.hpp> +#if __cplusplus >= 201703L +#error Please delete variant.hpp and the #else section below, then remove this error +#include <variant> namespace Utils { +using std::get; +using std::get_if; +using std::holds_alternative; +using std::variant; +} // namespace Utils -using namespace mpark; +#else +#include <3rdparty/variant/variant.hpp> +namespace Utils { +using mpark::get; +using mpark::get_if; +using mpark::holds_alternative; +using mpark::variant; } // namespace Utils + +#endif diff --git a/src/libs/utils/wizardpage.h b/src/libs/utils/wizardpage.h index fa8c60b052..abeccfce13 100644 --- a/src/libs/utils/wizardpage.h +++ b/src/libs/utils/wizardpage.h @@ -29,6 +29,7 @@ #include <QSet> #include <QString> +#include <QVariant> #include <QWizardPage> #include <functional> @@ -41,30 +42,30 @@ namespace Internal { class QTCREATOR_UTILS_EXPORT ObjectToFieldWidgetConverter : public QWidget { Q_OBJECT - Q_PROPERTY(QString text READ text NOTIFY textChanged) + Q_PROPERTY(QVariant value READ value NOTIFY valueChanged) public: - template <class T, typename... Arguments> - static ObjectToFieldWidgetConverter *create(T *sender, void (T::*member)(Arguments...), const std::function<QString()> &toTextFunction) + template<class T, typename... Arguments> + static ObjectToFieldWidgetConverter *create(T *sender, + void (T::*member)(Arguments...), + const std::function<QVariant()> &toVariantFunction) { auto widget = new ObjectToFieldWidgetConverter(); - widget->toTextFunction = toTextFunction; + widget->toVariantFunction = toVariantFunction; connect(sender, &QObject::destroyed, widget, &QObject::deleteLater); - connect(sender, member, widget, [widget] () { - emit widget->textChanged(widget->text()); - }); + connect(sender, member, widget, [widget]() { emit widget->valueChanged(widget->value()); }); return widget; } signals: - void textChanged(const QString&); + void valueChanged(const QVariant &); private: ObjectToFieldWidgetConverter () = default; - // is used by the property text - QString text() {return toTextFunction();} - std::function<QString()> toTextFunction; + // is used by the property value + QVariant value() { return toVariantFunction(); } + std::function<QVariant()> toVariantFunction; }; } // Internal @@ -79,10 +80,17 @@ public: virtual void pageWasAdded(); // called when this page was added to a Utils::Wizard template<class T, typename... Arguments> - void registerObjectAsFieldWithName(const QString &name, T *sender, void (T::*changeSignal)(Arguments...), - const std::function<QString()> &senderToString) + void registerObjectAsFieldWithName(const QString &name, + T *sender, + void (T::*changeSignal)(Arguments...), + const std::function<QVariant()> &senderToVariant) { - registerFieldWithName(name, Internal::ObjectToFieldWidgetConverter::create(sender, changeSignal, senderToString), "text", SIGNAL(textChanged(QString))); + registerFieldWithName(name, + Internal::ObjectToFieldWidgetConverter::create(sender, + changeSignal, + senderToVariant), + "value", + SIGNAL(valueChanged(QValue))); } void registerFieldWithName(const QString &name, QWidget *widget, |