diff options
author | Eike Ziller <eike.ziller@qt.io> | 2017-07-25 11:54:44 +0200 |
---|---|---|
committer | Eike Ziller <eike.ziller@qt.io> | 2017-07-25 11:54:44 +0200 |
commit | efa5a7b6d76c85423e45b85e3db97186dc2d1923 (patch) | |
tree | 096f1a42d2b5943c742e1302489d548edfb026a4 | |
parent | c8962c34baae380f7db9840da419998007411226 (diff) | |
parent | 41127e0f4769bd32f3f5d88c2064ba61f222e195 (diff) | |
download | qt-creator-efa5a7b6d76c85423e45b85e3db97186dc2d1923.tar.gz |
Merge remote-tracking branch 'origin/4.4'
Conflicts:
qtcreator.pri
Change-Id: If5f4a9821a23ac0df81eb84b3980f9cf7ecd70ba
139 files changed, 2489 insertions, 1019 deletions
diff --git a/doc/images/qtcreator-refactoring-replace.png b/doc/images/qtcreator-refactoring-replace.png Binary files differindex 4c62c5f065..d0fa9dec47 100644 --- a/doc/images/qtcreator-refactoring-replace.png +++ b/doc/images/qtcreator-refactoring-replace.png diff --git a/doc/images/qtcreator-semanticerror-clang.png b/doc/images/qtcreator-semanticerror-clang.png Binary files differnew file mode 100644 index 0000000000..9980485832 --- /dev/null +++ b/doc/images/qtcreator-semanticerror-clang.png diff --git a/doc/images/qtcreator-syntaxerror-clang.png b/doc/images/qtcreator-syntaxerror-clang.png Binary files differnew file mode 100644 index 0000000000..8beee1832f --- /dev/null +++ b/doc/images/qtcreator-syntaxerror-clang.png diff --git a/doc/src/editors/creator-editors.qdoc b/doc/src/editors/creator-editors.qdoc index 9b55aad11a..1c040afe5a 100644 --- a/doc/src/editors/creator-editors.qdoc +++ b/doc/src/editors/creator-editors.qdoc @@ -187,11 +187,35 @@ \endlist - In addition, you can run static checks on the QML and JavaScript code in - your project to find common problems. + When using the Clang code model, errors and warnings are additionally marked + with icons and annotated. If a \l{http://clang.llvm.org/diagnostics.html} + {Clang fix-it} is available, you can execute it by clicking the + \inlineimage refactormarker.png + icon and pressing \key Enter. + + In the following figure, a semicolon is missing at the end of the + line. + + \image qtcreator-syntaxerror-clang.png + + In the following figure, the variable is not used. + + \image qtcreator-semanticerror-clang.png + + To specify the position where the annotations are displayed, select + \uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} > + \uicontrol Display > \uicontrol {Annotations next to lines}, and then + select whether to display the annotations directly next to the code, + aligned to the right of the code, or in the right margin. + + If you hide the annotations by deselecting the check box, you can move the + mouse pointer over an icon to view them. \section1 Checking JSON Data Structure + You can run static checks on the QML and JavaScript code in + your project to find common problems. + \QC validates instances of JSON entities against \l{http://tools.ietf.org/html/draft-zyp-json-schema-03} {A JSON Media Type for Describing the Structure and Meaning of JSON Documents}. @@ -1956,6 +1980,9 @@ \section1 Renaming Symbols + You can rename symbols in all files in a project. When you rename a class, + you can also change filenames that match the class name. + To rename a specific symbol in a Qt project: \list 1 @@ -1973,15 +2000,18 @@ \image qtcreator-refactoring-replace.png \li To replace all selected instances, enter the name of the new symbol - in the \uicontrol {Replace with} text box and click - \uicontrol Replace. + in the \uicontrol {Replace with} text box. To omit an instance, uncheck the check-box next to the instance. + \li If the symbol is a class, select the \uicontrol {Rename files} check + box to also change the filenames that match the class name. + + \li Select \uicontrol Replace. + \note This action replaces all selected instances of the symbol in all files listed in the \uicontrol {Search Results} pane. You cannot undo this action. - \endlist \note Renaming local symbols does not open the \uicontrol {Search Results} diff --git a/qbs/modules/qtc/qtc.qbs b/qbs/modules/qtc/qtc.qbs index 708e37c300..86effdd3b3 100644 --- a/qbs/modules/qtc/qtc.qbs +++ b/qbs/modules/qtc/qtc.qbs @@ -17,6 +17,8 @@ Module { property string qtcreator_compat_version: ide_compat_version_major + '.' + ide_compat_version_minor + '.' + ide_compat_version_release + property string qtcreator_copyright_year: '2017' + property string libDirName: "lib" property string ide_app_path: qbs.targetOS.contains("macos") ? "" : "bin" property string ide_app_target: qbs.targetOS.contains("macos") ? "Qt Creator" : "qtcreator" diff --git a/qtcreator.pri b/qtcreator.pri index cf11309acc..4dddddce4a 100644 --- a/qtcreator.pri +++ b/qtcreator.pri @@ -5,6 +5,7 @@ QTCREATOR_VERSION = 4.4.82 QTCREATOR_COMPAT_VERSION = 4.4.82 VERSION = $$QTCREATOR_VERSION QTCREATOR_DISPLAY_VERSION = 4.5.0-beta1 +QTCREATOR_COPYRIGHT_YEAR = 2017 BINARY_ARTIFACTS_BRANCH = master CONFIG += c++14 diff --git a/scripts/clangCompleteAt.sh b/scripts/clangCompleteAt.sh index e80fbd623a..18f225a920 100755 --- a/scripts/clangCompleteAt.sh +++ b/scripts/clangCompleteAt.sh @@ -94,7 +94,7 @@ runCodeCompletion() if [ -n "${CINDEXTEST_EXEC}" ]; then command="${CINDEXTEST_EXEC} -code-completion-at=${FILE}:${LINE}:${COLUMN} ${FILE}" else - command="${CLANG_EXEC} -cc1 -code-completion-at ${FILE}:${LINE}:${COLUMN} ${FILE}" + command="${CLANG_EXEC} -fsyntax-only -Xclang -code-completion-at -Xclang ${FILE}:${LINE}:${COLUMN} ${FILE}" fi echo "Command: $command" eval $command diff --git a/share/qtcreator/templates/wizards/classes/cpp/wizard.json b/share/qtcreator/templates/wizards/classes/cpp/wizard.json index 7c690b54c6..18b84d8d56 100644 --- a/share/qtcreator/templates/wizards/classes/cpp/wizard.json +++ b/share/qtcreator/templates/wizards/classes/cpp/wizard.json @@ -6,6 +6,7 @@ "trDescription": "Creates a C++ header and a source file for a new class that you can add to a C++ project.", "trDisplayName": "C++ Class", "trDisplayCategory": "C++", + "iconText": "h/cpp", "enabled": "%{JS: [ %{Plugins} ].indexOf('CppEditor') >= 0}", "options": diff --git a/share/qtcreator/templates/wizards/classes/python/wizard.json b/share/qtcreator/templates/wizards/classes/python/wizard.json index d3613085b0..7031d0ba99 100644 --- a/share/qtcreator/templates/wizards/classes/python/wizard.json +++ b/share/qtcreator/templates/wizards/classes/python/wizard.json @@ -6,6 +6,7 @@ "trDescription": "Creates new Python class file.", "trDisplayName": "Python Class", "trDisplayCategory": "Python", + "iconText": "py", "enabled": "%{JS: [ %{Plugins} ].indexOf('PythonEditor') >= 0}", "options": diff --git a/share/qtcreator/templates/wizards/classes/qtquickui/wizard.json b/share/qtcreator/templates/wizards/classes/qtquickui/wizard.json index 3786457ee1..a1d4338994 100644 --- a/share/qtcreator/templates/wizards/classes/qtquickui/wizard.json +++ b/share/qtcreator/templates/wizards/classes/qtquickui/wizard.json @@ -6,6 +6,7 @@ "trDescription": "Creates a Qt Quick Designer UI form along with a matching QML file for implementation purposes. You can add the form and file to an existing Qt Quick Project.", "trDisplayName": "QtQuick UI File", "trDisplayCategory": "Qt", + "iconText": "ui.qml", "featuresRequired": [ "QtSupport.Wizards.FeatureQtQuick.UiFiles" ], "enabled": "%{JS: [ %{Plugins} ].indexOf('QmlJSEditor') >= 0}", diff --git a/share/qtcreator/templates/wizards/files/cppheader/wizard.json b/share/qtcreator/templates/wizards/files/cppheader/wizard.json index 6ea6fe5b09..bda6770d09 100644 --- a/share/qtcreator/templates/wizards/files/cppheader/wizard.json +++ b/share/qtcreator/templates/wizards/files/cppheader/wizard.json @@ -6,6 +6,7 @@ "trDescription": "Creates a C++ header file that you can add to a C++ project.", "trDisplayName": "C++ Header File", "trDisplayCategory": "C++", + "iconText": "h", "enabled": "%{JS: [ %{Plugins} ].indexOf('CppEditor') >= 0}", "options": { "key": "FileName", "value": "%{JS: Cpp.fileName('%{TargetPath}', '%{JS: Util.preferredSuffix('text/x-c++hdr')}')}" }, diff --git a/share/qtcreator/templates/wizards/files/cppsource/wizard.json b/share/qtcreator/templates/wizards/files/cppsource/wizard.json index 504de97238..7eebc282b5 100644 --- a/share/qtcreator/templates/wizards/files/cppsource/wizard.json +++ b/share/qtcreator/templates/wizards/files/cppsource/wizard.json @@ -6,6 +6,7 @@ "trDescription": "Creates a C++ source file that you can add to a C++ project.", "trDisplayName": "C++ Source File", "trDisplayCategory": "C++", + "iconText": "cpp", "enabled": "%{JS: [ %{Plugins} ].indexOf('CppEditor') >= 0}", "options": { "key": "FileName", "value": "%{JS: Cpp.fileName('%{TargetPath}', '%{JS: Util.preferredSuffix('text/x-c++src')}')}" }, diff --git a/share/qtcreator/templates/wizards/files/form/wizard.json b/share/qtcreator/templates/wizards/files/form/wizard.json index 2e3a42671d..26d15d2b59 100644 --- a/share/qtcreator/templates/wizards/files/form/wizard.json +++ b/share/qtcreator/templates/wizards/files/form/wizard.json @@ -6,6 +6,7 @@ "trDescription": "Creates a Qt Designer form that you can add to a Qt Widget Project. This is useful if you already have an existing class for the UI business logic.", "trDisplayName": "Qt Designer Form", "trDisplayCategory": "Qt", + "iconText": "ui", "enabled": "%{JS: [ %{Plugins} ].indexOf('Designer') >= 0}", "options": [ diff --git a/share/qtcreator/templates/wizards/files/glsl/gl/fragment/wizard.json b/share/qtcreator/templates/wizards/files/glsl/gl/fragment/wizard.json index e3229e274c..eb5e994782 100644 --- a/share/qtcreator/templates/wizards/files/glsl/gl/fragment/wizard.json +++ b/share/qtcreator/templates/wizards/files/glsl/gl/fragment/wizard.json @@ -6,6 +6,7 @@ "trDescription": "Creates a fragment shader in the Desktop OpenGL Shading Language (GLSL). Fragment shaders generate the final pixel colors for triangles, points and lines rendered with OpenGL.", "trDisplayName": "Fragment Shader (Desktop OpenGL)", "trDisplayCategory": "GLSL", + "iconText": "frag", "platformIndependent": true, "enabled": "%{JS: [ %{Plugins} ].indexOf('GLSLEditor') >= 0}", diff --git a/share/qtcreator/templates/wizards/files/glsl/gl/vertex/wizard.json b/share/qtcreator/templates/wizards/files/glsl/gl/vertex/wizard.json index a1c5904e4c..bd76a76d6b 100644 --- a/share/qtcreator/templates/wizards/files/glsl/gl/vertex/wizard.json +++ b/share/qtcreator/templates/wizards/files/glsl/gl/vertex/wizard.json @@ -6,6 +6,7 @@ "trDescription": "Creates a vertex shader in the Desktop OpenGL Shading Language (GLSL). Vertex shaders transform the positions, normals and texture coordinates of triangles, points and lines rendered with OpenGL.", "trDisplayName": "Vertex Shader (Desktop OpenGL)", "trDisplayCategory": "GLSL", + "iconText": "vert", "platformIndependent": true, "enabled": "%{JS: [ %{Plugins} ].indexOf('GLSLEditor') >= 0}", diff --git a/share/qtcreator/templates/wizards/files/glsl/gles/fragment/wizard.json b/share/qtcreator/templates/wizards/files/glsl/gles/fragment/wizard.json index c83c58e8bb..c95b336aea 100644 --- a/share/qtcreator/templates/wizards/files/glsl/gles/fragment/wizard.json +++ b/share/qtcreator/templates/wizards/files/glsl/gles/fragment/wizard.json @@ -6,6 +6,7 @@ "trDescription": "Creates a fragment shader in the OpenGL/ES 2.0 Shading Language (GLSL/ES). Fragment shaders generate the final pixel colors for triangles, points and lines rendered with OpenGL.", "trDisplayName": "Fragment Shader (OpenGL/ES 2.0)", "trDisplayCategory": "GLSL", + "iconText": "fsh", "platformIndependent": true, "enabled": "%{JS: [ %{Plugins} ].indexOf('GLSLEditor') >= 0}", diff --git a/share/qtcreator/templates/wizards/files/glsl/gles/vertex/wizard.json b/share/qtcreator/templates/wizards/files/glsl/gles/vertex/wizard.json index edddc2dc15..68d430d29d 100644 --- a/share/qtcreator/templates/wizards/files/glsl/gles/vertex/wizard.json +++ b/share/qtcreator/templates/wizards/files/glsl/gles/vertex/wizard.json @@ -6,6 +6,7 @@ "trDescription": "Creates a vertex shader in the OpenGL/ES 2.0 Shading Language (GLSL/ES). Vertex shaders transform the positions, normals and texture coordinates of triangles, points and lines rendered with OpenGL.", "trDisplayName": "Vertex Shader (OpenGL/ES 2.0)", "trDisplayCategory": "GLSL", + "iconText": "vsh", "platformIndependent": true, "enabled": "%{JS: [ %{Plugins} ].indexOf('GLSLEditor') >= 0}", diff --git a/share/qtcreator/templates/wizards/files/java/wizard.json b/share/qtcreator/templates/wizards/files/java/wizard.json index 8986fb961b..427dc84e16 100644 --- a/share/qtcreator/templates/wizards/files/java/wizard.json +++ b/share/qtcreator/templates/wizards/files/java/wizard.json @@ -6,6 +6,7 @@ "trDescription": "Creates a Java file with boilerplate code.", "trDisplayName": "Java File", "trDisplayCategory": "Java", + "iconText": "java", "enabled": "%{JS: [ %{Plugins} ].indexOf('Android') >= 0}", "options": [ { "key": "ClassName", "value": "%{JS: '%{FileName}'.charAt(0).toUpperCase() + '%{FileName}'.substr(1)}" } ], diff --git a/share/qtcreator/templates/wizards/files/js/wizard.json b/share/qtcreator/templates/wizards/files/js/wizard.json index 57886e007b..62d3211cda 100644 --- a/share/qtcreator/templates/wizards/files/js/wizard.json +++ b/share/qtcreator/templates/wizards/files/js/wizard.json @@ -6,6 +6,7 @@ "trDescription": "Creates a JavaScript file.", "trDisplayName": "JS File", "trDisplayCategory": "Qt", + "iconText": "js", "enabled": "%{JS: [ %{Plugins} ].indexOf('QmlJSEditor') >= 0}", "pages" : diff --git a/share/qtcreator/templates/wizards/files/modeling/wizard.json b/share/qtcreator/templates/wizards/files/modeling/wizard.json index 75b0958524..2f8cff689a 100644 --- a/share/qtcreator/templates/wizards/files/modeling/wizard.json +++ b/share/qtcreator/templates/wizards/files/modeling/wizard.json @@ -6,6 +6,7 @@ "trDescription": "Creates a new empty model with an empty diagram.", "trDisplayName": "Model", "trDisplayCategory": "Modeling", + "iconText": "qmodel", "platformIndependent": true, "enabled": "%{JS: [ %{Plugins} ].indexOf('ModelEditor') >= 0}", diff --git a/share/qtcreator/templates/wizards/files/python/wizard.json b/share/qtcreator/templates/wizards/files/python/wizard.json index d9bf845631..32b720f3d4 100644 --- a/share/qtcreator/templates/wizards/files/python/wizard.json +++ b/share/qtcreator/templates/wizards/files/python/wizard.json @@ -6,6 +6,7 @@ "trDescription": "Creates an empty Python script file using UTF-8 charset.", "trDisplayName": "Python File", "trDisplayCategory": "Python", + "iconText": "py", "enabled": "%{JS: [ %{Plugins} ].indexOf('PythonEditor') >= 0}", "pages" : diff --git a/share/qtcreator/templates/wizards/files/qrc/wizard.json b/share/qtcreator/templates/wizards/files/qrc/wizard.json index 0badcf7acc..bbbd8e98f9 100644 --- a/share/qtcreator/templates/wizards/files/qrc/wizard.json +++ b/share/qtcreator/templates/wizards/files/qrc/wizard.json @@ -6,6 +6,7 @@ "trDescription": "Creates a Qt Resource file (.qrc).", "trDisplayName": "Qt Resource File", "trDisplayCategory": "Qt", + "iconText": "qrc", "enabled": "%{JS: [ %{Plugins} ].indexOf('ResourceEditor') >= 0}", "pages" : diff --git a/share/qtcreator/templates/wizards/files/qtquick2/wizard.json b/share/qtcreator/templates/wizards/files/qtquick2/wizard.json index 5a4c8bbf6f..544368b173 100644 --- a/share/qtcreator/templates/wizards/files/qtquick2/wizard.json +++ b/share/qtcreator/templates/wizards/files/qtquick2/wizard.json @@ -6,6 +6,7 @@ "trDescription": "Creates a QML file with boilerplate code, starting with \"import QtQuick 2.0\".", "trDisplayName": "QML File (Qt Quick 2)", "trDisplayCategory": "Qt", + "iconText": "qml", "enabled": "%{JS: [ %{Plugins} ].indexOf('QmlJSEditor') >= 0}", "pages" : diff --git a/share/qtcreator/templates/wizards/files/scxml/wizard.json b/share/qtcreator/templates/wizards/files/scxml/wizard.json index f9d7246925..893662337d 100644 --- a/share/qtcreator/templates/wizards/files/scxml/wizard.json +++ b/share/qtcreator/templates/wizards/files/scxml/wizard.json @@ -6,6 +6,7 @@ "trDescription": "Creates a new empty state chart.", "trDisplayName": "State Chart", "trDisplayCategory": "Modeling", + "iconText": "scxml", "platformIndependent": true, "enabled": "%{JS: [ %{Plugins} ].indexOf('QtSupport') >= 0}", diff --git a/share/qtcreator/templates/wizards/files/text/wizard.json b/share/qtcreator/templates/wizards/files/text/wizard.json index 2e20706c55..11e0577a2d 100644 --- a/share/qtcreator/templates/wizards/files/text/wizard.json +++ b/share/qtcreator/templates/wizards/files/text/wizard.json @@ -6,6 +6,7 @@ "trDescription": "Creates an empty file.", "trDisplayName": "Empty File", "trDisplayCategory": "General", + "iconText": "txt", "platformIndependent": true, "enabled": "%{JS: [ %{Plugins} ].indexOf('TextEditor') >= 0}", diff --git a/src/app/app.pro b/src/app/app.pro index 58dca7ba05..1414e7d7fc 100644 --- a/src/app/app.pro +++ b/src/app/app.pro @@ -20,6 +20,12 @@ QT_BREAKPAD_ROOT_PATH = $$(QT_BREAKPAD_ROOT_PATH) include($$QT_BREAKPAD_ROOT_PATH/qtbreakpad.pri) } win32 { + # We need the version in two separate formats for the .rc file + # RC_VERSION=4,3,82,0 (quadruple) + # RC_VERSION_STRING="4.4.0-beta1" (free text) + DEFINES += RC_VERSION=$$replace(QTCREATOR_VERSION, "\\.", ","),0 \ + RC_VERSION_STRING=\\\"$${QTCREATOR_DISPLAY_VERSION}\\\" \ + RC_COPYRIGHT='"\\\"2008-$${QTCREATOR_COPYRIGHT_YEAR} The Qt Company Ltd\\\""' RC_FILE = qtcreator.rc } else:macx { LIBS += -framework CoreFoundation diff --git a/src/app/app.qbs b/src/app/app.qbs index 0af41ca20d..b3023fcbe7 100644 --- a/src/app/app.qbs +++ b/src/app/app.qbs @@ -41,7 +41,6 @@ QtcProduct { "Info.plist", "main.cpp", "qtcreator.xcassets", - "qtcreator.rc", "../shared/qtsingleapplication/qtsingleapplication.h", "../shared/qtsingleapplication/qtsingleapplication.cpp", "../shared/qtsingleapplication/qtlocalpeer.h", @@ -52,6 +51,16 @@ QtcProduct { ] Group { + // We need the version in two separate formats for the .rc file + // RC_VERSION=4,3,82,0 (quadruple) + // RC_VERSION_STRING="4.4.0-beta1" (free text) + cpp.defines: outer.concat(["RC_VERSION=" + qtc.qtcreator_version.replace(/\./g, ",") + ",0", + "RC_VERSION_STRING=\"" + qtc.qtcreator_display_version + "\"", + "RC_COPYRIGHT=\"2008-" + qtc.qtcreator_copyright_year + " The Qt Company Ltd\""]) + files: "qtcreator.rc" + } + + Group { name: "qtcreator.sh" condition: qbs.targetOS.contains("unix") && !qbs.targetOS.contains("macos") files: "../../bin/qtcreator.sh" diff --git a/src/app/app_version.h.in b/src/app/app_version.h.in index 19bff44d49..97fd0735a4 100644 --- a/src/app/app_version.h.in +++ b/src/app/app_version.h.in @@ -42,7 +42,7 @@ namespace Constants { const char * const IDE_VERSION_LONG = IDE_VERSION_STR; const char * const IDE_VERSION_DISPLAY = STRINGIFY(IDE_VERSION_DISPLAY_DEF); const char * const IDE_AUTHOR = \"The Qt Company Ltd\"; -const char * const IDE_YEAR = \"2017\"; +const char * const IDE_YEAR = \"$${QTCREATOR_COPYRIGHT_YEAR}\"; #ifdef IDE_REVISION const char * const IDE_REVISION_STR = STRINGIFY(IDE_REVISION); diff --git a/src/app/app_version_header.qbs b/src/app/app_version_header.qbs index 5730be7542..e6903d6cc5 100644 --- a/src/app/app_version_header.qbs +++ b/src/app/app_version_header.qbs @@ -42,6 +42,8 @@ Product { + product.moduleProperty("qtc", "ide_version_minor") + "\n"); content = content.replace(/(\n#define IDE_VERSION_RELEASE) .+\n/, "$1 " + product.moduleProperty("qtc", "ide_version_release") + "\n"); + content = content.replace(/(\n#define IDE_COPYRIGHT_YEAR) .+\n/, "$1 " + + product.moduleProperty("qtc", "qtcreator_copyright_year") + "\n"); file = new TextFile(output.filePath, TextFile.WriteOnly); file.truncate(); file.write(content); diff --git a/src/app/qtcreator.rc b/src/app/qtcreator.rc index b23a85f322..89f03c4708 100644 --- a/src/app/qtcreator.rc +++ b/src/app/qtcreator.rc @@ -1,3 +1,5 @@ +#include <windows.h> + IDI_ICON1 ICON DISCARDABLE "qtcreator.ico" IDI_ICON2 ICON DISCARDABLE "winicons/c.ico" IDI_ICON3 ICON DISCARDABLE "winicons/cpp.ico" @@ -6,3 +8,25 @@ IDI_ICON5 ICON DISCARDABLE "winicons/ui.ico" IDI_ICON6 ICON DISCARDABLE "winicons/pro.ico" IDI_ICON7 ICON DISCARDABLE "winicons/pri.ico" IDI_ICON8 ICON DISCARDABLE "winicons/qml.ico" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RC_VERSION + PRODUCTVERSION RC_VERSION +{ + BLOCK "StringFileInfo" + { + // U.S. English - Windows, Multilingual + BLOCK "040904E4" + { + VALUE "FileDescription", "Qt Creator" + VALUE "FileVersion", RC_VERSION_STRING + VALUE "ProductName", "Qt Creator" + VALUE "ProductVersion", RC_VERSION_STRING + VALUE "LegalCopyright", RC_COPYRIGHT + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 // 1252 = 0x04E4 + } +} diff --git a/src/libs/clangbackendipc/clangbackendipc-lib.pri b/src/libs/clangbackendipc/clangbackendipc-lib.pri index e930763843..3f3758772d 100644 --- a/src/libs/clangbackendipc/clangbackendipc-lib.pri +++ b/src/libs/clangbackendipc/clangbackendipc-lib.pri @@ -8,163 +8,164 @@ QT += network INCLUDEPATH += $$PWD -SOURCES += $$PWD/clangcodemodelserverinterface.cpp \ - $$PWD/clangcodemodelserverproxy.cpp \ +SOURCES += \ + $$PWD/cancelmessage.cpp \ + $$PWD/clangbackendipcdebugutils.cpp \ $$PWD/clangcodemodelclientinterface.cpp \ - $$PWD/cmbendmessage.cpp \ - $$PWD/cmbalivemessage.cpp \ $$PWD/clangcodemodelclientproxy.cpp \ - $$PWD/writemessageblock.cpp \ - $$PWD/readmessageblock.cpp \ - $$PWD/ipcinterface.cpp \ - $$PWD/connectionserver.cpp \ - $$PWD/connectionclient.cpp \ - $$PWD/cmbechomessage.cpp \ - $$PWD/cmbregistertranslationunitsforeditormessage.cpp \ - $$PWD/filecontainer.cpp \ - $$PWD/cmbunregistertranslationunitsforeditormessage.cpp \ - $$PWD/cmbcompletecodemessage.cpp \ + $$PWD/clangcodemodelconnectionclient.cpp \ + $$PWD/clangcodemodelserverinterface.cpp \ + $$PWD/clangcodemodelserverproxy.cpp \ + $$PWD/cmbalivemessage.cpp \ $$PWD/cmbcodecompletedmessage.cpp \ - $$PWD/codecompletion.cpp \ + $$PWD/cmbcompletecodemessage.cpp \ + $$PWD/cmbechomessage.cpp \ + $$PWD/cmbendmessage.cpp \ $$PWD/cmbregisterprojectsforeditormessage.cpp \ + $$PWD/cmbregistertranslationunitsforeditormessage.cpp \ $$PWD/cmbunregisterprojectsforeditormessage.cpp \ - $$PWD/translationunitdoesnotexistmessage.cpp \ + $$PWD/cmbunregistertranslationunitsforeditormessage.cpp \ $$PWD/codecompletionchunk.cpp \ - $$PWD/projectpartcontainer.cpp \ - $$PWD/projectpartsdonotexistmessage.cpp \ - $$PWD/lineprefixer.cpp \ - $$PWD/clangbackendipcdebugutils.cpp \ + $$PWD/codecompletion.cpp \ + $$PWD/connectionclient.cpp \ + $$PWD/connectionserver.cpp \ $$PWD/diagnosticcontainer.cpp \ - $$PWD/sourcerangecontainer.cpp \ - $$PWD/sourcelocationcontainer.cpp \ + $$PWD/documentannotationschangedmessage.cpp \ + $$PWD/dynamicastmatcherdiagnosticcontainer.cpp \ + $$PWD/dynamicastmatcherdiagnosticcontextcontainer.cpp \ + $$PWD/dynamicastmatcherdiagnosticmessagecontainer.cpp \ + $$PWD/filecontainer.cpp \ + $$PWD/filecontainerv2.cpp \ + $$PWD/filepath.cpp \ $$PWD/fixitcontainer.cpp \ - $$PWD/requestdocumentannotations.cpp \ - $$PWD/requestreferencesmessage.cpp \ - $$PWD/registerunsavedfilesforeditormessage.cpp \ - $$PWD/unregisterunsavedfilesforeditormessage.cpp \ - $$PWD/updatetranslationunitsforeditormessage.cpp \ - $$PWD/updatevisibletranslationunitsmessage.cpp \ $$PWD/highlightingmarkcontainer.cpp \ - $$PWD/refactoringclientinterface.cpp \ + $$PWD/ipcclientinterface.cpp \ + $$PWD/ipcinterface.cpp \ + $$PWD/ipcserverinterface.cpp \ + $$PWD/lineprefixer.cpp \ $$PWD/messageenvelop.cpp \ + $$PWD/pchmanagerclientinterface.cpp \ + $$PWD/pchmanagerclientproxy.cpp \ + $$PWD/pchmanagerserverinterface.cpp \ + $$PWD/pchmanagerserverproxy.cpp \ + $$PWD/precompiledheadersupdatedmessage.cpp \ + $$PWD/projectpartcontainer.cpp \ + $$PWD/projectpartcontainerv2.cpp \ + $$PWD/projectpartpch.cpp \ + $$PWD/projectpartsdonotexistmessage.cpp \ + $$PWD/readmessageblock.cpp \ + $$PWD/refactoringclientinterface.cpp \ + $$PWD/refactoringclientproxy.cpp \ $$PWD/refactoringserverinterface.cpp \ $$PWD/refactoringserverproxy.cpp \ - $$PWD/ipcclientinterface.cpp \ - $$PWD/ipcserverinterface.cpp \ - $$PWD/clangcodemodelconnectionclient.cpp \ - $$PWD/documentannotationschangedmessage.cpp \ $$PWD/referencesmessage.cpp \ - $$PWD/refactoringclientproxy.cpp \ - $$PWD/sourcelocationscontainer.cpp \ - $$PWD/sourcelocationcontainerv2.cpp \ - $$PWD/sourcelocationsforrenamingmessage.cpp \ + $$PWD/registerunsavedfilesforeditormessage.cpp \ + $$PWD/removepchprojectpartsmessage.cpp \ + $$PWD/requestdocumentannotations.cpp \ + $$PWD/requestreferencesmessage.cpp \ $$PWD/requestsourcelocationforrenamingmessage.cpp \ - $$PWD/filepath.cpp \ - $$PWD/sourcerangescontainer.cpp \ + $$PWD/requestsourcerangesanddiagnosticsforquerymessage.cpp \ + $$PWD/requestsourcerangesforquerymessage.cpp \ $$PWD/sourcefilepathcontainerbase.cpp \ + $$PWD/sourcelocationcontainer.cpp \ + $$PWD/sourcelocationcontainerv2.cpp \ + $$PWD/sourcelocationscontainer.cpp \ + $$PWD/sourcelocationsforrenamingmessage.cpp \ + $$PWD/sourcerangecontainer.cpp \ $$PWD/sourcerangecontainerv2.cpp \ - $$PWD/dynamicastmatcherdiagnosticcontainer.cpp \ - $$PWD/dynamicastmatcherdiagnosticcontextcontainer.cpp \ - $$PWD/dynamicastmatcherdiagnosticmessagecontainer.cpp \ - $$PWD/requestsourcerangesanddiagnosticsforquerymessage.cpp \ $$PWD/sourcerangesanddiagnosticsforquerymessage.cpp \ + $$PWD/sourcerangescontainer.cpp \ + $$PWD/sourcerangesforquerymessage.cpp \ $$PWD/sourcerangewithtextcontainer.cpp \ - $$PWD/filecontainerv2.cpp \ - $$PWD/cancelmessage.cpp \ - $$PWD/pchmanagerclientinterface.cpp \ - $$PWD/pchmanagerserverinterface.cpp \ - $$PWD/projectpartcontainerv2.cpp \ + $$PWD/translationunitdoesnotexistmessage.cpp \ + $$PWD/unregisterunsavedfilesforeditormessage.cpp \ $$PWD/updatepchprojectpartsmessage.cpp \ - $$PWD/pchmanagerserverproxy.cpp \ - $$PWD/pchmanagerclientproxy.cpp \ - $$PWD/projectpartpch.cpp \ - $$PWD/precompiledheadersupdatedmessage.cpp \ - $$PWD/removepchprojectpartsmessage.cpp \ - $$PWD/sourcerangesforquerymessage.cpp \ - $$PWD/requestsourcerangesforquerymessage.cpp + $$PWD/updatetranslationunitsforeditormessage.cpp \ + $$PWD/updatevisibletranslationunitsmessage.cpp \ + $$PWD/writemessageblock.cpp \ HEADERS += \ + $$PWD/cancelmessage.h \ + $$PWD/clangbackendipcdebugutils.h \ + $$PWD/clangbackendipc_global.h \ + $$PWD/clangcodemodelclientinterface.h \ + $$PWD/clangcodemodelclientmessages.h \ + $$PWD/clangcodemodelclientproxy.h \ + $$PWD/clangcodemodelconnectionclient.h \ $$PWD/clangcodemodelserverinterface.h \ + $$PWD/clangcodemodelservermessages.h \ $$PWD/clangcodemodelserverproxy.h \ - $$PWD/clangcodemodelclientinterface.h \ - $$PWD/cmbendmessage.h \ + $$PWD/clangrefactoringclientmessages.h \ + $$PWD/clangrefactoringmessages.h \ + $$PWD/clangrefactoringservermessages.h \ $$PWD/cmbalivemessage.h \ - $$PWD/clangcodemodelclientproxy.h \ - $$PWD/writemessageblock.h \ - $$PWD/readmessageblock.h \ - $$PWD/ipcinterface.h \ - $$PWD/connectionserver.h \ - $$PWD/connectionclient.h \ - $$PWD/cmbechomessage.h \ - $$PWD/cmbregistertranslationunitsforeditormessage.h \ - $$PWD/filecontainer.h \ - $$PWD/cmbunregistertranslationunitsforeditormessage.h \ - $$PWD/cmbcompletecodemessage.h \ $$PWD/cmbcodecompletedmessage.h \ - $$PWD/codecompletion.h \ + $$PWD/cmbcompletecodemessage.h \ + $$PWD/cmbechomessage.h \ + $$PWD/cmbendmessage.h \ $$PWD/cmbregisterprojectsforeditormessage.h \ + $$PWD/cmbregistertranslationunitsforeditormessage.h \ $$PWD/cmbunregisterprojectsforeditormessage.h \ - $$PWD/translationunitdoesnotexistmessage.h \ + $$PWD/cmbunregistertranslationunitsforeditormessage.h \ $$PWD/codecompletionchunk.h \ - $$PWD/projectpartcontainer.h \ - $$PWD/projectpartsdonotexistmessage.h \ - $$PWD/clangbackendipc_global.h \ - $$PWD/lineprefixer.h \ - $$PWD/clangbackendipcdebugutils.h \ + $$PWD/codecompletion.h \ + $$PWD/connectionclient.h \ + $$PWD/connectionserver.h \ $$PWD/diagnosticcontainer.h \ - $$PWD/sourcerangecontainer.h \ - $$PWD/sourcelocationcontainer.h \ + $$PWD/documentannotationschangedmessage.h \ + $$PWD/dynamicastmatcherdiagnosticcontainer.h \ + $$PWD/dynamicastmatcherdiagnosticcontextcontainer.h \ + $$PWD/dynamicastmatcherdiagnosticmessagecontainer.h \ + $$PWD/dynamicmatcherdiagnostics.h \ + $$PWD/filecontainer.h \ + $$PWD/filecontainerv2.h \ + $$PWD/filepath.h \ $$PWD/fixitcontainer.h \ - $$PWD/requestdocumentannotations.h \ - $$PWD/referencesmessage.h \ - $$PWD/requestreferencesmessage.h \ - $$PWD/registerunsavedfilesforeditormessage.h \ - $$PWD/unregisterunsavedfilesforeditormessage.h \ - $$PWD/updatetranslationunitsforeditormessage.h \ - $$PWD/updatevisibletranslationunitsmessage.h \ $$PWD/highlightingmarkcontainer.h \ - $$PWD/messageenvelop.h \ $$PWD/ipcclientinterface.h \ + $$PWD/ipcinterface.h \ $$PWD/ipcserverinterface.h \ - $$PWD/clangcodemodelconnectionclient.h \ - $$PWD/documentannotationschangedmessage.h \ + $$PWD/lineprefixer.h \ + $$PWD/messageenvelop.h \ + $$PWD/pchmanagerclientinterface.h \ + $$PWD/pchmanagerclientproxy.h \ + $$PWD/pchmanagerserverinterface.h \ + $$PWD/pchmanagerserverproxy.h \ + $$PWD/precompiledheadersupdatedmessage.h \ + $$PWD/projectpartcontainer.h \ + $$PWD/projectpartcontainerv2.h \ + $$PWD/projectpartpch.h \ + $$PWD/projectpartsdonotexistmessage.h \ + $$PWD/readmessageblock.h \ $$PWD/refactoringclientinterface.h \ + $$PWD/refactoringclientproxy.h \ $$PWD/refactoringserverinterface.h \ $$PWD/refactoringserverproxy.h \ - $$PWD/refactoringclientproxy.h \ - $$PWD/sourcelocationscontainer.h \ - $$PWD/sourcelocationcontainerv2.h \ - $$PWD/sourcelocationsforrenamingmessage.h \ + $$PWD/referencesmessage.h \ + $$PWD/registerunsavedfilesforeditormessage.h \ + $$PWD/removepchprojectpartsmessage.h \ + $$PWD/requestdocumentannotations.h \ + $$PWD/requestreferencesmessage.h \ $$PWD/requestsourcelocationforrenamingmessage.h \ - $$PWD/filepath.h \ - $$PWD/sourcerangescontainer.h \ + $$PWD/requestsourcerangesanddiagnosticsforquerymessage.h \ + $$PWD/requestsourcerangesforquerymessage.h \ $$PWD/sourcefilepathcontainerbase.h \ + $$PWD/sourcelocationcontainer.h \ + $$PWD/sourcelocationcontainerv2.h \ + $$PWD/sourcelocationscontainer.h \ + $$PWD/sourcelocationsforrenamingmessage.h \ + $$PWD/sourcerangecontainer.h \ $$PWD/sourcerangecontainerv2.h \ - $$PWD/dynamicmatcherdiagnostics.h \ - $$PWD/dynamicastmatcherdiagnosticcontainer.h \ - $$PWD/dynamicastmatcherdiagnosticcontextcontainer.h \ - $$PWD/dynamicastmatcherdiagnosticmessagecontainer.h \ - $$PWD/requestsourcerangesanddiagnosticsforquerymessage.h \ $$PWD/sourcerangesanddiagnosticsforquerymessage.h \ + $$PWD/sourcerangescontainer.h \ + $$PWD/sourcerangesforquerymessage.h \ $$PWD/sourcerangewithtextcontainer.h \ - $$PWD/filecontainerv2.h \ - $$PWD/cancelmessage.h \ - $$PWD/pchmanagerclientinterface.h \ - $$PWD/pchmanagerserverinterface.h \ - $$PWD/projectpartcontainerv2.h \ - $$PWD/updatepchprojectpartsmessage.h \ - $$PWD/pchmanagerserverproxy.h \ - $$PWD/pchmanagerclientproxy.h \ - $$PWD/projectpartpch.h \ - $$PWD/precompiledheadersupdatedmessage.h \ $$PWD/stringcache.h \ - $$PWD/removepchprojectpartsmessage.h \ - $$PWD/clangcodemodelclientmessages.h \ - $$PWD/clangcodemodelservermessages.h \ - $$PWD/sourcerangesforquerymessage.h \ - $$PWD/clangrefactoringmessages.h \ - $$PWD/clangrefactoringclientmessages.h \ - $$PWD/clangrefactoringservermessages.h \ - $$PWD/requestsourcerangesforquerymessage.h + $$PWD/translationunitdoesnotexistmessage.h \ + $$PWD/unregisterunsavedfilesforeditormessage.h \ + $$PWD/updatepchprojectpartsmessage.h \ + $$PWD/updatetranslationunitsforeditormessage.h \ + $$PWD/updatevisibletranslationunitsmessage.h \ + $$PWD/writemessageblock.h \ contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols diff --git a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticcontextcontainer.h b/src/libs/clangbackendipc/dynamicastmatcherdiagnosticcontextcontainer.h index 61d7e2fff5..c220aa2377 100644 --- a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticcontextcontainer.h +++ b/src/libs/clangbackendipc/dynamicastmatcherdiagnosticcontextcontainer.h @@ -55,7 +55,7 @@ public: return m_contextType; } - Utils::SmallString contextTypeText() const; + CMBIPC_EXPORT Utils::SmallString contextTypeText() const; const Utils::SmallStringVector &arguments() const { diff --git a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.cpp b/src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.cpp index af4de3e058..e17ecd4da9 100644 --- a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.cpp +++ b/src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.cpp @@ -33,8 +33,8 @@ namespace ClangBackEnd { QDebug operator<<(QDebug debug, const DynamicASTMatcherDiagnosticMessageContainer &container) { debug.nospace() << "DynamicASTMatcherDiagnosticMessageContainer(" - << container.sourceRange() << ", " << container.errorTypeText() << ", " + << container.sourceRange() << ", " << container.arguments() << ")"; diff --git a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.h b/src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.h index 8f9581872d..07a21af605 100644 --- a/src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.h +++ b/src/libs/clangbackendipc/dynamicastmatcherdiagnosticmessagecontainer.h @@ -55,7 +55,7 @@ public: return m_errorType; } - Utils::SmallString errorTypeText() const; + CMBIPC_EXPORT Utils::SmallString errorTypeText() const; const Utils::SmallStringVector &arguments() const { diff --git a/src/libs/cplusplus/MatchingText.cpp b/src/libs/cplusplus/MatchingText.cpp index 3fdb573b91..e2f04e4f0f 100644 --- a/src/libs/cplusplus/MatchingText.cpp +++ b/src/libs/cplusplus/MatchingText.cpp @@ -34,6 +34,8 @@ #include <QChar> #include <QDebug> +#include <utils/algorithm.h> + using namespace CPlusPlus; enum { MAX_NUM_LINES = 20 }; @@ -135,16 +137,215 @@ static const Token tokenAtPosition(const Tokens &tokens, const unsigned pos) return Token(); } +static int tokenIndexBeforePosition(const Tokens &tokens, unsigned pos) +{ + for (int i = tokens.size() - 1; i >= 0; --i) { + if (tokens[i].utf16charsBegin() < pos) + return i; + } + return -1; +} + +static bool isCursorAtEndOfLineButMaybeBeforeComment(const Tokens &tokens, int pos) +{ + int index = tokenIndexBeforePosition(tokens, uint(pos)); + if (index == -1 || index >= tokens.size()) + return false; + + do { + ++index; + } while (index < tokens.size() && tokens[index].isComment()); + + return index >= tokens.size(); +} + +// 10.6.1 Attribute syntax and semantics +// This does not handle alignas() since it is not needed for the namespace case. +static int skipAttributeSpecifierSequence(const Tokens &tokens, int index) +{ + // [[ attribute-using-prefixopt attribute-list ]] + if (index >= 1 && tokens[index].is(T_RBRACKET) && tokens[index - 1].is(T_RBRACKET)) { + // Skip everything within [[ ]] + for (int i = index - 2; i >= 0; --i) { + if (i >= 1 && tokens[i].is(T_LBRACKET) && tokens[i - 1].is(T_LBRACKET)) + return i - 2; + } + + return -1; + } + + return index; +} + +static int skipNamespaceName(const Tokens &tokens, int index) +{ + if (index >= tokens.size()) + return -1; + + if (!tokens[index].is(T_IDENTIFIER)) + return index; + + // Accept + // SomeName + // Some::Nested::Name + bool expectIdentifier = false; + for (int i = index - 1; i >= 0; --i) { + if (expectIdentifier) { + if (tokens[i].is(T_IDENTIFIER)) + expectIdentifier = false; + else + return -1; + } else if (tokens[i].is(T_COLON_COLON)) { + expectIdentifier = true; + } else { + return i; + } + } + + return index; +} + +// 10.3.1 Namespace definition +static bool isAfterNamespaceDefinition(const Tokens &tokens, int position) +{ + int index = tokenIndexBeforePosition(tokens, uint(position)); + if (index == -1) + return false; + + // Handle optional name + index = skipNamespaceName(tokens, index); + if (index == -1) + return false; + + // Handle optional attribute specifier sequence + index = skipAttributeSpecifierSequence(tokens, index); + if (index == -1) + return false; + + return index >= 0 && tokens[index].is(T_NAMESPACE); +} + +static int isEmptyOrWhitespace(const QString &text) +{ + return Utils::allOf(text, [](const QChar &c) {return c.isSpace(); }); +} + +static QTextBlock previousNonEmptyBlock(const QTextBlock ¤tBlock) +{ + QTextBlock block = currentBlock.previous(); + forever { + if (!block.isValid() || !isEmptyOrWhitespace(block.text())) + return block; + block = block.previous(); + } +} + +static QTextBlock nextNonEmptyBlock(const QTextBlock ¤tBlock) +{ + QTextBlock block = currentBlock.next(); + forever { + if (!block.isValid() || !isEmptyOrWhitespace(block.text())) + return block; + block = block.next(); + } +} + +static bool allowAutoClosingBraceAtEmptyLine( + const QTextBlock &block, + MatchingText::IsNextBlockDeeperIndented isNextDeeperIndented) +{ + QTextBlock previousBlock = previousNonEmptyBlock(block); + if (!previousBlock.isValid()) + return false; // Nothing before + + QTextBlock nextBlock = nextNonEmptyBlock(block); + if (!nextBlock.isValid()) + return true; // Nothing behind + + if (isNextDeeperIndented && isNextDeeperIndented(previousBlock)) + return false; // Before indented + + const QString trimmedText = previousBlock.text().trimmed(); + return !trimmedText.endsWith(';') + && !trimmedText.endsWith('{') + && !trimmedText.endsWith('}'); +} + +static Tokens getTokens(const QTextCursor &cursor, int &prevState) +{ + LanguageFeatures features; + features.qtEnabled = false; + features.qtKeywordsEnabled = false; + features.qtMocRunEnabled = false; + features.cxx11Enabled = true; + features.cxxEnabled = true; + features.c99Enabled = true; + features.objCEnabled = true; + + SimpleLexer tokenize; + tokenize.setLanguageFeatures(features); + + prevState = BackwardsScanner::previousBlockState(cursor.block()) & 0xFF; + return tokenize(cursor.block().text(), prevState); +} + +static QChar firstNonSpace(const QTextCursor &cursor) +{ + int position = cursor.position(); + QChar ch = cursor.document()->characterAt(position); + while (ch.isSpace()) + ch = cursor.document()->characterAt(++position); + + return ch; +} + +static bool allowAutoClosingBraceByLookahead(const QTextCursor &cursor) +{ + const QChar lookAhead = firstNonSpace(cursor); + if (lookAhead.isNull()) + return true; + + switch (lookAhead.unicode()) { + case ';': case ',': + case ')': case '}': case ']': + return true; + } + + return false; +} + +static bool allowAutoClosingBrace(const QTextCursor &cursor, + MatchingText::IsNextBlockDeeperIndented isNextIndented) +{ + if (MatchingText::isInCommentHelper(cursor)) + return false; + + const QTextBlock block = cursor.block(); + if (isEmptyOrWhitespace(block.text())) + return allowAutoClosingBraceAtEmptyLine(cursor.block(), isNextIndented); + + int prevState; + const Tokens tokens = getTokens(cursor, prevState); + if (isAfterNamespaceDefinition(tokens, cursor.positionInBlock())) + return false; + + if (isCursorAtEndOfLineButMaybeBeforeComment(tokens, cursor.positionInBlock())) + return !(isNextIndented && isNextIndented(block)); + + return allowAutoClosingBraceByLookahead(cursor); +} + bool MatchingText::contextAllowsAutoParentheses(const QTextCursor &cursor, - const QString &textToInsert) + const QString &textToInsert, + IsNextBlockDeeperIndented isNextIndented) { QChar ch; if (!textToInsert.isEmpty()) ch = textToInsert.at(0); - if (ch == QLatin1Char('{') && cursor.block().text().trimmed().isEmpty()) - return false; // User just might want to wrap up some lines. + if (ch == QLatin1Char('{')) + return allowAutoClosingBrace(cursor, isNextIndented); if (!shouldInsertMatchingText(cursor) && ch != QLatin1Char('\'') && ch != QLatin1Char('"')) return false; @@ -198,24 +399,6 @@ bool MatchingText::shouldInsertMatchingText(QChar lookAhead) } // switch } -static Tokens getTokens(const QTextCursor &cursor, int &prevState) -{ - LanguageFeatures features; - features.qtEnabled = false; - features.qtKeywordsEnabled = false; - features.qtMocRunEnabled = false; - features.cxx11Enabled = true; - features.cxxEnabled = true; - features.c99Enabled = true; - features.objCEnabled = true; - - SimpleLexer tokenize; - tokenize.setLanguageFeatures(features); - - prevState = BackwardsScanner::previousBlockState(cursor.block()) & 0xFF; - return tokenize(cursor.block().text(), prevState); -} - bool MatchingText::isInCommentHelper(const QTextCursor &cursor, Token *retToken) { int prevState = 0; diff --git a/src/libs/cplusplus/MatchingText.h b/src/libs/cplusplus/MatchingText.h index 59463917c4..b394e342af 100644 --- a/src/libs/cplusplus/MatchingText.h +++ b/src/libs/cplusplus/MatchingText.h @@ -30,7 +30,10 @@ #include <cplusplus/Token.h> #include <cplusplus/CPlusPlusForwardDeclarations.h> +#include <functional> + QT_FORWARD_DECLARE_CLASS(QTextCursor) +QT_FORWARD_DECLARE_CLASS(QTextBlock) QT_FORWARD_DECLARE_CLASS(QChar) namespace CPlusPlus { @@ -38,8 +41,11 @@ namespace CPlusPlus { class CPLUSPLUS_EXPORT MatchingText { public: + using IsNextBlockDeeperIndented = std::function<bool(const QTextBlock &textBlock)>; static bool contextAllowsAutoParentheses(const QTextCursor &cursor, - const QString &textToInsert); + const QString &textToInsert, + IsNextBlockDeeperIndented isNextIndented + = IsNextBlockDeeperIndented()); static bool contextAllowsAutoQuotes(const QTextCursor &cursor, const QString &textToInsert); static bool contextAllowsElectricCharacters(const QTextCursor &cursor); diff --git a/src/libs/extensionsystem/pluginspec.cpp b/src/libs/extensionsystem/pluginspec.cpp index 19be010c4d..cde1903099 100644 --- a/src/libs/extensionsystem/pluginspec.cpp +++ b/src/libs/extensionsystem/pluginspec.cpp @@ -31,6 +31,7 @@ #include "pluginmanager.h" #include <utils/algorithm.h> +#include <utils/qtcassert.h> #include <QCoreApplication> #include <QDebug> @@ -630,12 +631,9 @@ static inline QString msgInvalidFormat(const char *key, const QString &content) .arg(QLatin1String(key), content); } -static inline bool readMultiLineString(const QJsonValue &value, QString *out) +bool PluginSpec::readMultiLineString(const QJsonValue &value, QString *out) { - if (!out) { - qCWarning(pluginLog) << Q_FUNC_INFO << "missing output parameter"; - return false; - } + QTC_ASSERT(out, return false); if (value.isString()) { *out = value.toString(); } else if (value.isArray()) { @@ -737,7 +735,7 @@ bool PluginSpecPrivate::readMetaData(const QJsonObject &pluginMetaData) copyright = value.toString(); value = metaData.value(QLatin1String(DESCRIPTION)); - if (!value.isUndefined() && !readMultiLineString(value, &description)) + if (!value.isUndefined() && !PluginSpec::readMultiLineString(value, &description)) return reportError(msgValueIsNotAString(DESCRIPTION)); value = metaData.value(QLatin1String(URL)); @@ -751,7 +749,7 @@ bool PluginSpecPrivate::readMetaData(const QJsonObject &pluginMetaData) category = value.toString(); value = metaData.value(QLatin1String(LICENSE)); - if (!value.isUndefined() && !readMultiLineString(value, &license)) + if (!value.isUndefined() && !PluginSpec::readMultiLineString(value, &license)) return reportError(msgValueIsNotAMultilineString(LICENSE)); value = metaData.value(QLatin1String(PLATFORM)); diff --git a/src/libs/extensionsystem/pluginspec.h b/src/libs/extensionsystem/pluginspec.h index 0462acddef..da89ff6029 100644 --- a/src/libs/extensionsystem/pluginspec.h +++ b/src/libs/extensionsystem/pluginspec.h @@ -131,6 +131,8 @@ public: bool hasError() const; QString errorString() const; + static bool readMultiLineString(const QJsonValue &value, QString *out); + private: PluginSpec(); diff --git a/src/libs/utils/images/wizardicon-file.png b/src/libs/utils/images/wizardicon-file.png Binary files differindex fd3f5bdd34..01df966319 100644 --- a/src/libs/utils/images/wizardicon-file.png +++ b/src/libs/utils/images/wizardicon-file.png diff --git a/src/libs/utils/images/wizardicon-file@2x.png b/src/libs/utils/images/wizardicon-file@2x.png Binary files differindex 58a395a7e1..ed7c0cbb69 100644 --- a/src/libs/utils/images/wizardicon-file@2x.png +++ b/src/libs/utils/images/wizardicon-file@2x.png diff --git a/src/plugins/android/Android.json.in b/src/plugins/android/Android.json.in index 43268da1c2..eda39dd3a2 100644 --- a/src/plugins/android/Android.json.in +++ b/src/plugins/android/Android.json.in @@ -17,14 +17,14 @@ \"Url\" : \"http://necessitas.kde.org\", $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\'?> - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> - <mime-type type=\'application/vnd.google.android.android_manifest\'> - <comment>Android manifest file</comment> - <sub-class-of type=\'application/xml\'/> - <glob pattern=\'AndroidManifest.xml\'/> - </mime-type> - </mime-info> - \" + \"Mimetypes\" : [ + \"<?xml version=\'1.0\'?>\", + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", + \" <mime-type type=\'application/vnd.google.android.android_manifest\'>\", + \" <comment>Android manifest file</comment>\", + \" <sub-class-of type=\'application/xml\'/>\", + \" <glob pattern=\'AndroidManifest.xml\'/>\", + \" </mime-type>\", + \"</mime-info>\" + ] } diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index be5f6df961..ccefeef4e2 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -347,8 +347,10 @@ void AndroidConfig::updateAvailableSdkPlatforms() const m_availableSdkPlatforms.clear(); AndroidSdkManager sdkManager(*this); - m_availableSdkPlatforms = sdkManager.availableSdkPlatforms(); - m_availableSdkPlatformsUpToDate = true; + bool success = false; + m_availableSdkPlatforms = sdkManager.availableSdkPlatforms(&success); + if (success) + m_availableSdkPlatformsUpToDate = true; } QStringList AndroidConfig::apiLevelNamesFor(const QList<SdkPlatform> &platforms) @@ -358,7 +360,7 @@ QStringList AndroidConfig::apiLevelNamesFor(const QList<SdkPlatform> &platforms) QString AndroidConfig::apiLevelNameFor(const SdkPlatform &platform) { - return QLatin1String("android-") + QString::number(platform.apiLevel); + return platform.apiLevel > 0 ? QString("android-%1").arg(platform.apiLevel) : ""; } QList<SdkPlatform> AndroidConfig::sdkTargets(int minApiLevel) const diff --git a/src/plugins/android/androidsdkmanager.cpp b/src/plugins/android/androidsdkmanager.cpp index 0ed23660a6..c28fef27a1 100644 --- a/src/plugins/android/androidsdkmanager.cpp +++ b/src/plugins/android/androidsdkmanager.cpp @@ -50,6 +50,8 @@ const char installLocationKey[] = "Installed Location:"; const char apiLevelPropertyKey[] = "AndroidVersion.ApiLevel"; const char abiPropertyKey[] = "SystemImage.Abi"; +const int sdkManagerCmdTimeoutS = 60; + using namespace Utils; /*! @@ -72,11 +74,14 @@ static bool valueForKey(QString key, const QString &line, QString *value = nullp \c true if the command is successfully executed. Output is copied into \a output. The function blocks the calling thread. */ -static bool sdkManagerCommand(const AndroidConfig config, const QStringList &args, QString *output) +static bool sdkManagerCommand(const AndroidConfig config, const QStringList &args, QString *output, + int timeout = sdkManagerCmdTimeoutS) { QString sdkManagerToolPath = config.sdkManagerToolPath().toString(); SynchronousProcess proc; - SynchronousProcessResponse response = proc.runBlocking(sdkManagerToolPath, args); + proc.setTimeoutS(timeout); + proc.setTimeOutMessageBoxEnabled(true); + SynchronousProcessResponse response = proc.run(sdkManagerToolPath, args); if (response.result == SynchronousProcessResponse::Finished) { if (output) *output = response.allOutput(); @@ -132,10 +137,6 @@ AndroidSdkManager::AndroidSdkManager(const AndroidConfig &config): m_config(config), m_parser(new SdkManagerOutputParser) { - QString packageListing; - if (sdkManagerCommand(config, QStringList({"--list", "--verbose"}), &packageListing)) { - m_parser->parsePackageListing(packageListing); - } } AndroidSdkManager::~AndroidSdkManager() @@ -143,13 +144,20 @@ AndroidSdkManager::~AndroidSdkManager() } -SdkPlatformList AndroidSdkManager::availableSdkPlatforms() +SdkPlatformList AndroidSdkManager::availableSdkPlatforms(bool *ok) { + bool success = false; if (m_config.sdkToolsVersion() < sdkManagerIntroVersion) { AndroidToolManager toolManager(m_config); - return toolManager.availableSdkPlatforms(); + return toolManager.availableSdkPlatforms(ok); } + QString packageListing; + if (sdkManagerCommand(m_config, QStringList({"--list", "--verbose"}), &packageListing)) + m_parser->parsePackageListing(packageListing); + + if (ok) + *ok = success; return m_parser->m_installedPlatforms; } diff --git a/src/plugins/android/androidsdkmanager.h b/src/plugins/android/androidsdkmanager.h index 2c11148072..b1da078b6e 100644 --- a/src/plugins/android/androidsdkmanager.h +++ b/src/plugins/android/androidsdkmanager.h @@ -40,7 +40,7 @@ public: AndroidSdkManager(const AndroidConfig &config); ~AndroidSdkManager(); - SdkPlatformList availableSdkPlatforms(); + SdkPlatformList availableSdkPlatforms(bool *ok = nullptr); private: const AndroidConfig &m_config; diff --git a/src/plugins/android/androidtoolmanager.cpp b/src/plugins/android/androidtoolmanager.cpp index 19f7cbc97b..39fa2a2c42 100644 --- a/src/plugins/android/androidtoolmanager.cpp +++ b/src/plugins/android/androidtoolmanager.cpp @@ -97,16 +97,22 @@ AndroidToolManager::~AndroidToolManager() } -SdkPlatformList AndroidToolManager::availableSdkPlatforms() const +SdkPlatformList AndroidToolManager::availableSdkPlatforms(bool *ok) const { + bool success = false; SdkPlatformList list; QString targetListing; if (androidToolCommand(m_config.androidToolPath(), QStringList({"list", "target"}), androidToolEnvironment(), &targetListing)) { m_parser->parseTargetListing(targetListing, m_config.sdkLocation(), &list); + success = true; } else { qCDebug(androidToolLog) << "Android tool target listing failed"; } + + if (ok) + *ok = success; + return list; } diff --git a/src/plugins/android/androidtoolmanager.h b/src/plugins/android/androidtoolmanager.h index befb095b92..faaa9428ab 100644 --- a/src/plugins/android/androidtoolmanager.h +++ b/src/plugins/android/androidtoolmanager.h @@ -48,7 +48,7 @@ public: AndroidToolManager(const AndroidConfig &config); ~AndroidToolManager(); - SdkPlatformList availableSdkPlatforms() const; + SdkPlatformList availableSdkPlatforms(bool *ok = nullptr) const; void launchAvdManager() const; QFuture<AndroidConfig::CreateAvdInfo> createAvd(AndroidConfig::CreateAvdInfo info) const; diff --git a/src/plugins/autotest/autotesticons.h b/src/plugins/autotest/autotesticons.h index b278509dbb..1420be31ad 100644 --- a/src/plugins/autotest/autotesticons.h +++ b/src/plugins/autotest/autotesticons.h @@ -68,6 +68,14 @@ const Utils::Icon RESULT_MESSAGEDEBUG({ const Utils::Icon RESULT_MESSAGEWARN({ {":/utils/images/filledcircle.png", Utils::Theme::OutputPanes_TestWarnTextColor}}, Utils::Icon::Tint); +const Utils::Icon RESULT_MESSAGEPASSWARN({ + {":/utils/images/filledcircle.png", Utils::Theme::OutputPanes_TestPassTextColor}, + {":/utils/images/iconoverlay_warning.png", Utils::Theme::OutputPanes_TestWarnTextColor}}, + Utils::Icon::Tint | Utils::Icon::PunchEdges); +const Utils::Icon RESULT_MESSAGEFAILWARN({ + {":/utils/images/filledcircle.png", Utils::Theme::OutputPanes_TestFailTextColor}, + {":/utils/images/iconoverlay_warning.png", Utils::Theme::OutputPanes_TestWarnTextColor}}, + Utils::Icon::Tint | Utils::Icon::PunchEdges); const Utils::Icon RESULT_MESSAGEFATAL({ {":/utils/images/filledcircle.png", Utils::Theme::OutputPanes_TestFatalTextColor}}, Utils::Icon::Tint); diff --git a/src/plugins/autotest/gtest/gtestoutputreader.cpp b/src/plugins/autotest/gtest/gtestoutputreader.cpp index 96382f5f89..a455282476 100644 --- a/src/plugins/autotest/gtest/gtestoutputreader.cpp +++ b/src/plugins/autotest/gtest/gtestoutputreader.cpp @@ -41,6 +41,7 @@ static QString constructSourceFilePath(const QString &path, const QString &fileP GTestOutputReader::GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface, QProcess *testApplication, const QString &buildDirectory) : TestOutputReader(futureInterface, testApplication, buildDirectory) + , m_executable(testApplication ? testApplication->program() : QString()) { } @@ -75,7 +76,7 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine) m_futureInterface.reportResult(testResult); m_description.clear(); } else if (disabledTests.exactMatch(line)) { - TestResultPtr testResult = TestResultPtr(new GTestResult()); + TestResultPtr testResult = TestResultPtr(new GTestResult); testResult->setResult(Result::MessageDisabledTests); int disabled = disabledTests.cap(1).toInt(); testResult->setDescription(tr("You have %n disabled test(s).", 0, disabled)); @@ -106,7 +107,7 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine) m_futureInterface.reportResult(testResult); } else if (newTestSetStarts.exactMatch(line)) { m_currentTestSet = newTestSetStarts.cap(1); - TestResultPtr testResult = TestResultPtr(new GTestResult()); + TestResultPtr testResult = TestResultPtr(new GTestResult); testResult->setResult(Result::MessageCurrentTest); testResult->setDescription(tr("Entering test set %1").arg(m_currentTestSet)); m_futureInterface.reportResult(testResult); @@ -156,7 +157,7 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine) GTestResult *GTestOutputReader::createDefaultResult() const { - GTestResult *result = new GTestResult(m_currentTestName); + GTestResult *result = new GTestResult(m_executable, m_currentTestName); result->setTestSetName(m_currentTestSet); result->setIteration(m_iteration); return result; diff --git a/src/plugins/autotest/gtest/gtestoutputreader.h b/src/plugins/autotest/gtest/gtestoutputreader.h index 0ed2bf878c..5cedffed00 100644 --- a/src/plugins/autotest/gtest/gtestoutputreader.h +++ b/src/plugins/autotest/gtest/gtestoutputreader.h @@ -47,6 +47,7 @@ protected: private: GTestResult *createDefaultResult() const; + QString m_executable; QString m_currentTestName; QString m_currentTestSet; QString m_description; diff --git a/src/plugins/autotest/gtest/gtestresult.cpp b/src/plugins/autotest/gtest/gtestresult.cpp index 604f5cedaa..cbccaea837 100644 --- a/src/plugins/autotest/gtest/gtestresult.cpp +++ b/src/plugins/autotest/gtest/gtestresult.cpp @@ -33,6 +33,11 @@ GTestResult::GTestResult(const QString &name) { } +GTestResult::GTestResult(const QString &executable, const QString &name) + : TestResult(executable, name) +{ +} + const QString GTestResult::outputString(bool selected) const { const QString &desc = description(); diff --git a/src/plugins/autotest/gtest/gtestresult.h b/src/plugins/autotest/gtest/gtestresult.h index 74a8e1e9c3..491fe41662 100644 --- a/src/plugins/autotest/gtest/gtestresult.h +++ b/src/plugins/autotest/gtest/gtestresult.h @@ -34,6 +34,7 @@ class GTestResult : public TestResult { public: explicit GTestResult(const QString &name = QString()); + GTestResult(const QString &executable, const QString &name); const QString outputString(bool selected) const override; void setTestSetName(const QString &testSetName) { m_testSetName = testSetName; } diff --git a/src/plugins/autotest/qtest/qttestoutputreader.cpp b/src/plugins/autotest/qtest/qttestoutputreader.cpp index e7c7725d02..d1999bba39 100644 --- a/src/plugins/autotest/qtest/qttestoutputreader.cpp +++ b/src/plugins/autotest/qtest/qttestoutputreader.cpp @@ -132,6 +132,7 @@ QtTestOutputReader::QtTestOutputReader(const QFutureInterface<TestResultPtr> &fu QProcess *testApplication, const QString &buildDirectory, OutputMode mode) : TestOutputReader(futureInterface, testApplication, buildDirectory) + , m_executable(testApplication ? testApplication->program() : QString()) , m_mode(mode) { } @@ -419,7 +420,7 @@ void QtTestOutputReader::processSummaryFinishOutput() QtTestResult *QtTestOutputReader::createDefaultResult() const { - QtTestResult *result = new QtTestResult(m_className); + QtTestResult *result = new QtTestResult(m_executable, m_className); result->setFunctionName(m_testCase); result->setDataTag(m_dataTag); return result; diff --git a/src/plugins/autotest/qtest/qttestoutputreader.h b/src/plugins/autotest/qtest/qttestoutputreader.h index 2830516064..75f0b9a42e 100644 --- a/src/plugins/autotest/qtest/qttestoutputreader.h +++ b/src/plugins/autotest/qtest/qttestoutputreader.h @@ -78,6 +78,7 @@ private: }; CDATAMode m_cdataMode = None; + QString m_executable; QString m_className; QString m_testCase; QString m_formerTestCase; diff --git a/src/plugins/autotest/qtest/qttestresult.cpp b/src/plugins/autotest/qtest/qttestresult.cpp index 50d64d7290..68c9f2bf3f 100644 --- a/src/plugins/autotest/qtest/qttestresult.cpp +++ b/src/plugins/autotest/qtest/qttestresult.cpp @@ -35,6 +35,11 @@ QtTestResult::QtTestResult(const QString &className) { } +QtTestResult::QtTestResult(const QString &executable, const QString &className) + : TestResult(executable, className) +{ +} + const QString QtTestResult::outputString(bool selected) const { const QString &desc = description(); @@ -101,14 +106,14 @@ bool QtTestResult::isIntermediateFor(const TestResult *other) const QTC_ASSERT(other, return false); const QtTestResult *qtOther = static_cast<const QtTestResult *>(other); return m_dataTag == qtOther->m_dataTag && m_function == qtOther->m_function - && name() == qtOther->name(); + && name() == qtOther->name() && executable() == qtOther->executable(); } TestResult *QtTestResult::createIntermediateResultFor(const TestResult *other) { QTC_ASSERT(other, return nullptr); const QtTestResult *qtOther = static_cast<const QtTestResult *>(other); - QtTestResult *intermediate = new QtTestResult(qtOther->name()); + QtTestResult *intermediate = new QtTestResult(qtOther->executable(), qtOther->name()); intermediate->m_function = qtOther->m_function; intermediate->m_dataTag = qtOther->m_dataTag; // intermediates will be needed only for data tags diff --git a/src/plugins/autotest/qtest/qttestresult.h b/src/plugins/autotest/qtest/qttestresult.h index 216b6ef332..c7c9e8ae2a 100644 --- a/src/plugins/autotest/qtest/qttestresult.h +++ b/src/plugins/autotest/qtest/qttestresult.h @@ -34,6 +34,7 @@ class QtTestResult : public TestResult { public: explicit QtTestResult(const QString &className = QString()); + QtTestResult(const QString &executable, const QString &className); const QString outputString(bool selected) const override; void setFunctionName(const QString &functionName) { m_function = functionName; } diff --git a/src/plugins/autotest/testresult.cpp b/src/plugins/autotest/testresult.cpp index bfef716403..2dcd9dda70 100644 --- a/src/plugins/autotest/testresult.cpp +++ b/src/plugins/autotest/testresult.cpp @@ -47,6 +47,12 @@ TestResult::TestResult(const QString &name) { } +TestResult::TestResult(const QString &executable, const QString &name) + : m_executable(executable) + , m_name(name) +{ +} + const QString TestResult::outputString(bool selected) const { return selected ? m_description : m_description.split('\n').first(); @@ -97,9 +103,11 @@ QString TestResult::resultToString(const Result::Type type) switch (type) { case Result::Pass: case Result::MessageTestCaseSuccess: + case Result::MessageTestCaseSuccessWarn: return QString("PASS"); case Result::Fail: case Result::MessageTestCaseFail: + case Result::MessageTestCaseFailWarn: return QString("FAIL"); case Result::ExpectedFail: return QString("XFAIL"); @@ -114,7 +122,6 @@ QString TestResult::resultToString(const Result::Type type) case Result::MessageInfo: return QString("INFO"); case Result::MessageWarn: - case Result::MessageTestCaseWarn: return QString("WARN"); case Result::MessageFatal: return QString("FATAL"); @@ -166,26 +173,28 @@ QColor TestResult::colorForType(const Result::Type type) bool TestResult::isMessageCaseStart(const Result::Type type) { return type == Result::MessageTestCaseStart || type == Result::MessageTestCaseSuccess - || type == Result::MessageTestCaseFail || type == Result::MessageTestCaseWarn - || type == Result::MessageIntermediate; + || type == Result::MessageTestCaseFail || type == Result::MessageTestCaseSuccessWarn + || type == Result::MessageTestCaseFailWarn || type == Result::MessageIntermediate; } bool TestResult::isDirectParentOf(const TestResult *other, bool * /*needsIntermediate*/) const { QTC_ASSERT(other, return false); - return m_name == other->m_name; + return !m_executable.isEmpty() && m_executable == other->m_executable + && m_name == other->m_name; } bool TestResult::isIntermediateFor(const TestResult *other) const { QTC_ASSERT(other, return false); - return m_name == other->m_name; + return !m_executable.isEmpty() && m_executable == other->m_executable + && m_name == other->m_name; } TestResult *TestResult::createIntermediateResultFor(const TestResult *other) { QTC_ASSERT(other, return nullptr); - TestResult *intermediate = new TestResult(other->m_name); + TestResult *intermediate = new TestResult(other->m_executable, other->m_name); return intermediate; } diff --git a/src/plugins/autotest/testresult.h b/src/plugins/autotest/testresult.h index e53e6fcce4..a7414f85d3 100644 --- a/src/plugins/autotest/testresult.h +++ b/src/plugins/autotest/testresult.h @@ -55,8 +55,9 @@ enum Type { MessageDisabledTests, MessageTestCaseStart, MessageTestCaseSuccess, - MessageTestCaseWarn, + MessageTestCaseSuccessWarn, MessageTestCaseFail, + MessageTestCaseFailWarn, MessageTestCaseEnd, MessageIntermediate, MessageCurrentTest, INTERNAL_MESSAGES_END = MessageCurrentTest, @@ -69,12 +70,14 @@ enum Type { class TestResult { public: - explicit TestResult(); + TestResult(); explicit TestResult(const QString &name); + TestResult(const QString &executable, const QString &name); virtual ~TestResult() {} virtual const QString outputString(bool selected) const; + QString executable() const { return m_executable; } QString name() const { return m_name; } Result::Type result() const { return m_result; } QString description() const { return m_description; } @@ -97,6 +100,7 @@ public: virtual TestResult *createIntermediateResultFor(const TestResult *other); private: + QString m_executable; QString m_name; Result::Type m_result = Result::Invalid; QString m_description; diff --git a/src/plugins/autotest/testresultdelegate.cpp b/src/plugins/autotest/testresultdelegate.cpp index fb27338440..9bd0192584 100644 --- a/src/plugins/autotest/testresultdelegate.cpp +++ b/src/plugins/autotest/testresultdelegate.cpp @@ -41,8 +41,8 @@ const static int outputLimit = 100000; static bool isSummaryItem(Result::Type type) { - return type == Result::MessageTestCaseSuccess || type == Result::MessageTestCaseFail - || type == Result::MessageTestCaseWarn; + return type == Result::MessageTestCaseSuccess || type == Result::MessageTestCaseSuccessWarn + || type == Result::MessageTestCaseFail || type == Result::MessageTestCaseFailWarn; } TestResultDelegate::TestResultDelegate(QObject *parent) diff --git a/src/plugins/autotest/testresultmodel.cpp b/src/plugins/autotest/testresultmodel.cpp index 3bfdba9357..a41fc64b01 100644 --- a/src/plugins/autotest/testresultmodel.cpp +++ b/src/plugins/autotest/testresultmodel.cpp @@ -61,6 +61,8 @@ static QIcon testResultIcon(Result::Type result) { Icons::RESULT_MESSAGEWARN.icon(), Icons::RESULT_MESSAGEFATAL.icon(), Icons::RESULT_MESSAGEFATAL.icon(), // System gets same handling as Fatal for now + Icons::RESULT_MESSAGEPASSWARN.icon(), + Icons::RESULT_MESSAGEFAILWARN.icon(), }; // provide an icon for unknown?? if (result < 0 || result >= Result::MessageInternal) { @@ -69,8 +71,10 @@ static QIcon testResultIcon(Result::Type result) { return icons[Result::Pass]; case Result::MessageTestCaseFail: return icons[Result::Fail]; - case Result::MessageTestCaseWarn: - return icons[Result::MessageWarn]; + case Result::MessageTestCaseSuccessWarn: + return icons[13]; + case Result::MessageTestCaseFailWarn: + return icons[14]; default: return QIcon(); } @@ -103,6 +107,7 @@ void TestResultItem::updateResult() return; Result::Type newResult = Result::MessageTestCaseSuccess; + bool withWarning = false; for (Utils::TreeItem *child : *this) { const TestResult *current = static_cast<TestResultItem *>(child)->testResult(); if (current) { @@ -111,21 +116,28 @@ void TestResultItem::updateResult() case Result::MessageFatal: case Result::UnexpectedPass: case Result::MessageTestCaseFail: - m_testResult->setResult(Result::MessageTestCaseFail); - return; + newResult = Result::MessageTestCaseFail; + break; case Result::ExpectedFail: case Result::MessageWarn: case Result::Skip: case Result::BlacklistedFail: case Result::BlacklistedPass: - case Result::MessageTestCaseWarn: - newResult = Result::MessageTestCaseWarn; + case Result::MessageTestCaseSuccessWarn: + case Result::MessageTestCaseFailWarn: + withWarning = true; break; default: {} } } } - m_testResult->setResult(newResult); + if (withWarning) { + m_testResult->setResult(newResult == Result::MessageTestCaseSuccess + ? Result::MessageTestCaseSuccessWarn + : Result::MessageTestCaseFailWarn); + } else { + m_testResult->setResult(newResult); + } } void TestResultItem::updateIntermediateChildren() @@ -295,11 +307,13 @@ TestResultItem *TestResultModel::findParentItemFor(const TestResultItem *item, TestResultItem *root = startItem ? const_cast<TestResultItem *>(startItem) : nullptr; const TestResult *result = item->testResult(); const QString &name = result->name(); + const QString &executable = result->executable(); if (root == nullptr && !name.isEmpty()) { for (int row = rootItem()->childCount() - 1; row >= 0; --row) { TestResultItem *tmp = static_cast<TestResultItem *>(rootItem()->childAt(row)); - if (tmp->testResult()->name() == name) { + auto tmpTestResult = tmp->testResult(); + if (tmpTestResult->executable() == executable && tmpTestResult->name() == name) { root = tmp; break; } @@ -344,8 +358,9 @@ void TestResultFilterModel::enableAllResultTypes() << Result::MessageFatal << Result::Invalid << Result::BlacklistedPass << Result::BlacklistedFail << Result::Benchmark << Result::MessageIntermediate << Result::MessageCurrentTest << Result::MessageTestCaseStart - << Result::MessageTestCaseSuccess << Result::MessageTestCaseWarn - << Result::MessageTestCaseFail << Result::MessageTestCaseEnd + << Result::MessageTestCaseSuccess << Result::MessageTestCaseSuccessWarn + << Result::MessageTestCaseFail << Result::MessageTestCaseFailWarn + << Result::MessageTestCaseEnd << Result::MessageInfo << Result::MessageSystem; invalidateFilter(); } @@ -393,7 +408,8 @@ bool TestResultFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &s case Result::MessageTestCaseSuccess: return m_enabled.contains(Result::Pass); case Result::MessageTestCaseFail: - case Result::MessageTestCaseWarn: + case Result::MessageTestCaseSuccessWarn: + case Result::MessageTestCaseFailWarn: return acceptTestCaseResult(index); default: return m_enabled.contains(resultType); @@ -407,7 +423,8 @@ bool TestResultFilterModel::acceptTestCaseResult(const QModelIndex &srcIndex) co Result::Type type = m_sourceModel->testResult(child)->result(); if (type == Result::MessageTestCaseSuccess) type = Result::Pass; - if (type == Result::MessageTestCaseFail || type == Result::MessageTestCaseWarn) { + if (type == Result::MessageTestCaseFail || type == Result::MessageTestCaseFailWarn + || type == Result::MessageTestCaseSuccessWarn) { if (acceptTestCaseResult(child)) return true; } else if (m_enabled.contains(type)) { diff --git a/src/plugins/clangcodemodel/clangcodemodel.qbs b/src/plugins/clangcodemodel/clangcodemodel.qbs index e6a2f1cde2..eb46d8f2bd 100644 --- a/src/plugins/clangcodemodel/clangcodemodel.qbs +++ b/src/plugins/clangcodemodel/clangcodemodel.qbs @@ -43,9 +43,9 @@ QtcPlugin { "clangassistproposalmodel.h", "clangbackendipcintegration.cpp", "clangbackendipcintegration.h", - "clangcodemodel.qrc", "clangcodemodelplugin.cpp", "clangcodemodelplugin.h", + "clangcodemodel.qrc", "clangcompletionassistinterface.cpp", "clangcompletionassistinterface.h", "clangcompletionassistprocessor.cpp", diff --git a/src/plugins/clangrefactoring/clangqueryhighlighter.cpp b/src/plugins/clangrefactoring/clangqueryhighlighter.cpp index 5f9e72d4be..d00bf82d29 100644 --- a/src/plugins/clangrefactoring/clangqueryhighlighter.cpp +++ b/src/plugins/clangrefactoring/clangqueryhighlighter.cpp @@ -72,6 +72,18 @@ bool ClangQueryHighlighter::hasDiagnostics() const return m_marker.hasMessagesOrContexts(); } +ClangBackEnd::DynamicASTMatcherDiagnosticMessageContainers +ClangQueryHighlighter::messagesForLineAndColumn(uint line, uint column) const +{ + return m_marker.messagesForLineAndColumn(line, column); +} + +ClangBackEnd::DynamicASTMatcherDiagnosticContextContainers +ClangQueryHighlighter::contextsForLineAndColumn(uint line, uint column) const +{ + return m_marker.contextsForLineAndColumn(line, column); +} + void ClangQueryHighlighter::highlightBlock(const QString &text) { int currentLineNumber = currentBlock().blockNumber() + 1; diff --git a/src/plugins/clangrefactoring/clangqueryhighlighter.h b/src/plugins/clangrefactoring/clangqueryhighlighter.h index 977f91fd11..7e96a1a5f9 100644 --- a/src/plugins/clangrefactoring/clangqueryhighlighter.h +++ b/src/plugins/clangrefactoring/clangqueryhighlighter.h @@ -44,6 +44,12 @@ public: bool hasDiagnostics() const; + ClangBackEnd::DynamicASTMatcherDiagnosticMessageContainers + messagesForLineAndColumn(uint line, uint column) const; + + ClangBackEnd::DynamicASTMatcherDiagnosticContextContainers + contextsForLineAndColumn(uint line, uint column) const; + protected: void highlightBlock(const QString &text) override; diff --git a/src/plugins/clangrefactoring/clangqueryhighlightmarker.h b/src/plugins/clangrefactoring/clangqueryhighlightmarker.h index 8f53d59538..6ef61627b7 100644 --- a/src/plugins/clangrefactoring/clangqueryhighlightmarker.h +++ b/src/plugins/clangrefactoring/clangqueryhighlightmarker.h @@ -250,6 +250,85 @@ public: return !m_messages.empty() || !m_contexts.empty(); } + static + bool isAfterStartColumn(const SourceRange &sourceRange, uint line, uint column) + { + return sourceRange.start().line() == line && sourceRange.start().column() <= column; + } + + static + bool isBeforeEndColumn(const SourceRange &sourceRange, uint line, uint column) + { + return sourceRange.end().line() == line && sourceRange.end().column() >= column; + } + + static + bool isInBetweenLine(const SourceRange &sourceRange, uint line) + { + return sourceRange.start().line() < line && sourceRange.end().line() > line; + } + + static + bool isSingleLine(const SourceRange &sourceRange) + { + return sourceRange.start().line() == sourceRange.end().line(); + } + + static + bool isInsideMultiLine(const SourceRange &sourceRange, uint line, uint column) + { + return !isSingleLine(sourceRange) + && (isAfterStartColumn(sourceRange, line, column) + || isInBetweenLine(sourceRange, line) + || isBeforeEndColumn(sourceRange, line, column)); + } + + static + bool isInsideSingleLine(const SourceRange &sourceRange, uint line, uint column) + { + return isSingleLine(sourceRange) + && isAfterStartColumn(sourceRange, line, column) + && isBeforeEndColumn(sourceRange, line, column); + } + + static + bool isInsideRange(const SourceRange &sourceRange, uint line, uint column) + { + return isInsideSingleLine(sourceRange, line, column) + || isInsideMultiLine(sourceRange, line, column); + } + + Messages messagesForLineAndColumn(uint line, uint column) const + { + Messages messages; + + auto underPosition = [=] (const Message &message) { + return ClangQueryHighlightMarker::isInsideRange(message.sourceRange(), line, column); + }; + + std::copy_if(m_messages.begin(), + m_messages.end(), + std::back_inserter(messages), + underPosition); + + return messages; + } + + Contexts contextsForLineAndColumn(uint line, uint column) const + { + Contexts contexts; + + auto underPosition = [=] (const Context &context) { + return ClangQueryHighlightMarker::isInsideRange(context.sourceRange(), line, column); + }; + + std::copy_if(m_contexts.begin(), + m_contexts.end(), + std::back_inserter(contexts), + underPosition); + + return contexts; + } private: Contexts m_contexts; diff --git a/src/plugins/clangrefactoring/clangqueryhoverhandler.cpp b/src/plugins/clangrefactoring/clangqueryhoverhandler.cpp new file mode 100644 index 0000000000..47ca0dbe79 --- /dev/null +++ b/src/plugins/clangrefactoring/clangqueryhoverhandler.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "clangqueryhoverhandler.h" + +#include "clangqueryhighlighter.h" + +#include <dynamicastmatcherdiagnosticmessagecontainer.h> + +#include <texteditor/texteditor.h> + +namespace ClangRefactoring { + +ClangQueryHoverHandler::ClangQueryHoverHandler(ClangQueryHighlighter *highligher) + : m_highligher(highligher) +{ +} + +void ClangQueryHoverHandler::identifyMatch(TextEditor::TextEditorWidget *editorWidget, int position) +{ + using Messages = ClangBackEnd::DynamicASTMatcherDiagnosticMessageContainers; + using Contexts = ClangBackEnd::DynamicASTMatcherDiagnosticContextContainers; + + QTextCursor textCursor = editorWidget->textCursor(); + textCursor.setPosition(position); + int line = textCursor.blockNumber() + 1; + int column = textCursor.columnNumber() + 1; + + Messages messages = m_highligher->messagesForLineAndColumn(uint(line), uint(column)); + Contexts contexts = m_highligher->contextsForLineAndColumn(uint(line), uint(column)); + + if (!messages.empty()) + setToolTip(QString("%1: %2").arg(messages[0].errorTypeText()).arg(messages[0].arguments().join(", "))); + else if (!contexts.empty()) + setToolTip(QString("%1: %2").arg(contexts[0].contextTypeText()).arg(contexts[0].arguments().join(", "))); +} + +} // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/clangqueryhoverhandler.h b/src/plugins/clangrefactoring/clangqueryhoverhandler.h new file mode 100644 index 0000000000..7a93bcbf5d --- /dev/null +++ b/src/plugins/clangrefactoring/clangqueryhoverhandler.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 <texteditor/basehoverhandler.h> + +namespace ClangRefactoring { + +class ClangQueryHighlighter; + +class ClangQueryHoverHandler : public TextEditor::BaseHoverHandler +{ +public: + ClangQueryHoverHandler(ClangQueryHighlighter *highligher); + +protected: + void identifyMatch(TextEditor::TextEditorWidget *editorWidget, int position) override; + +private: + ClangQueryHighlighter *m_highligher; +}; + +} // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.cpp b/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.cpp index 2289746db3..d4e210c04e 100644 --- a/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.cpp +++ b/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.cpp @@ -85,7 +85,7 @@ void ClangQueryProjectsFindFilter::requestSourceRangesAndDiagnostics(const QStri ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage message(queryText, {ClangBackEnd::FilePath(filePath), exampleContent, - {"cc", toNative(filePath)}}); + {"cc", "-std=c++1z", toNative(filePath)}}); m_server.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(message)); } diff --git a/src/plugins/clangrefactoring/clangquerytexteditorwidget.cpp b/src/plugins/clangrefactoring/clangquerytexteditorwidget.cpp index 7ca9d90254..2d0552680c 100644 --- a/src/plugins/clangrefactoring/clangquerytexteditorwidget.cpp +++ b/src/plugins/clangrefactoring/clangquerytexteditorwidget.cpp @@ -26,19 +26,24 @@ #include "clangquerytexteditorwidget.h" #include "clangqueryhighlighter.h" +#include "clangqueryhoverhandler.h" #include <texteditor/textdocument.h> namespace ClangRefactoring { ClangQueryTextEditorWidget::ClangQueryTextEditorWidget(QWidget *parent) - : BaseClangQueryTextEditorWidget(parent) + : BaseClangQueryTextEditorWidget(parent), + m_syntaxHighlighter(new ClangQueryHighlighter), + m_hoverHandler(std::make_unique<ClangQueryHoverHandler>(m_syntaxHighlighter)) { - m_syntaxHighlighter = new ClangQueryHighlighter; - textDocument()->setSyntaxHighlighter(m_syntaxHighlighter); + + addHoverHandler(m_hoverHandler.get()); } +ClangQueryTextEditorWidget::~ClangQueryTextEditorWidget() = default; + ClangQueryHighlighter *ClangQueryTextEditorWidget::syntaxHighlighter() const { return m_syntaxHighlighter; diff --git a/src/plugins/clangrefactoring/clangquerytexteditorwidget.h b/src/plugins/clangrefactoring/clangquerytexteditorwidget.h index 85dace1432..a221eb03fe 100644 --- a/src/plugins/clangrefactoring/clangquerytexteditorwidget.h +++ b/src/plugins/clangrefactoring/clangquerytexteditorwidget.h @@ -27,9 +27,12 @@ #include "baseclangquerytexteditorwidget.h" +#include <memory> + namespace ClangRefactoring { class ClangQueryHighlighter; +class ClangQueryHoverHandler; class ClangQueryTextEditorWidget : public BaseClangQueryTextEditorWidget { @@ -37,11 +40,13 @@ class ClangQueryTextEditorWidget : public BaseClangQueryTextEditorWidget public: ClangQueryTextEditorWidget(QWidget *parent); + ~ClangQueryTextEditorWidget(); ClangQueryHighlighter *syntaxHighlighter() const; private: ClangQueryHighlighter *m_syntaxHighlighter; + std::unique_ptr<ClangQueryHoverHandler> m_hoverHandler; }; } // namespace ClangRefactoring diff --git a/src/plugins/clangrefactoring/clangrefactoring.pro b/src/plugins/clangrefactoring/clangrefactoring.pro index 1a8d16e3e3..918398bef0 100644 --- a/src/plugins/clangrefactoring/clangrefactoring.pro +++ b/src/plugins/clangrefactoring/clangrefactoring.pro @@ -14,7 +14,8 @@ HEADERS += \ clangqueryprojectsfindfilterwidget.h \ clangqueryexampletexteditorwidget.h \ clangquerytexteditorwidget.h \ - baseclangquerytexteditorwidget.h + baseclangquerytexteditorwidget.h \ + clangqueryhoverhandler.h SOURCES += \ clangrefactoringplugin.cpp \ @@ -24,7 +25,8 @@ SOURCES += \ clangqueryprojectsfindfilterwidget.cpp \ clangqueryexampletexteditorwidget.cpp \ clangquerytexteditorwidget.cpp \ - baseclangquerytexteditorwidget.cpp + baseclangquerytexteditorwidget.cpp \ + clangqueryhoverhandler.cpp FORMS += \ clangqueryprojectsfindfilter.ui diff --git a/src/plugins/clearcase/ClearCase.json.in b/src/plugins/clearcase/ClearCase.json.in index b9153225d7..24384b8ab6 100644 --- a/src/plugins/clearcase/ClearCase.json.in +++ b/src/plugins/clearcase/ClearCase.json.in @@ -19,13 +19,13 @@ \"Url\" : \"http://www.qt.io\", $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\'?> - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> - <mime-type type=\'application/vnd.audc.text.clearcase.submit\'> - <comment>ClearCase submit template</comment> - <sub-class-of type=\'text/plain\'/> - </mime-type> - </mime-info> - \" + \"Mimetypes\" : [ + \"<?xml version=\'1.0\'?>\", + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", + \" <mime-type type=\'application/vnd.audc.text.clearcase.submit\'>\", + \" <comment>ClearCase submit template</comment>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" </mime-type>\", + \"</mime-info>\" + ] } diff --git a/src/plugins/cmakeprojectmanager/CMakeProjectManager.json.in b/src/plugins/cmakeprojectmanager/CMakeProjectManager.json.in index 5d75c622a8..5bf0dc4ad5 100644 --- a/src/plugins/cmakeprojectmanager/CMakeProjectManager.json.in +++ b/src/plugins/cmakeprojectmanager/CMakeProjectManager.json.in @@ -17,19 +17,19 @@ \"Url\" : \"http://www.qt.io\", $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\'?> - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> - <mime-type type=\'text/x-cmake\'> - <sub-class-of type=\'text/plain\'/> - <comment>CMake Project file</comment> - <glob pattern=\'*.cmake\'/> - </mime-type> - <mime-type type=\'text/x-cmake-project\'> - <sub-class-of type=\'text/x-cmake\'/> - <comment>CMake Project file</comment> - <glob pattern=\'CMakeLists.txt\'/> - </mime-type> - </mime-info> - \" + \"Mimetypes\" : [ + \"<?xml version=\'1.0\'?>\", + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", + \" <mime-type type=\'text/x-cmake\'>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>CMake Project file</comment>\", + \" <glob pattern=\'*.cmake\'/>\", + \" </mime-type>\", + \" <mime-type type=\'text/x-cmake-project\'>\", + \" <sub-class-of type=\'text/x-cmake\'/>\", + \" <comment>CMake Project file</comment>\", + \" <glob pattern=\'CMakeLists.txt\'/>\", + \" </mime-type>\", + \"</mime-info>\" + ] } diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.h b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.h index 99c63d10e1..de3112184a 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.h +++ b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.h @@ -61,6 +61,9 @@ private slots: void testCMakeProjectImporterToolChain_data(); void testCMakeProjectImporterToolChain(); + + void testServerModeReaderProgress_data(); + void testServerModeReaderProgress(); #endif private: diff --git a/src/plugins/cmakeprojectmanager/servermodereader.cpp b/src/plugins/cmakeprojectmanager/servermodereader.cpp index babd478173..7cba11953d 100644 --- a/src/plugins/cmakeprojectmanager/servermodereader.cpp +++ b/src/plugins/cmakeprojectmanager/servermodereader.cpp @@ -417,8 +417,7 @@ void ServerModeReader::handleProgress(int min, int cur, int max, const QString & if (!m_future) return; - int progress = m_progressStepMinimum - + (((max - min) / (cur - min)) * (m_progressStepMaximum - m_progressStepMinimum)); + const int progress = calculateProgress(m_progressStepMinimum, min, cur, max, m_progressStepMaximum); m_future->setProgressValue(progress); } @@ -430,6 +429,14 @@ void ServerModeReader::handleSignal(const QString &signal, const QVariantMap &da emit dirty(); } +int ServerModeReader::calculateProgress(const int minRange, const int min, const int cur, const int max, const int maxRange) +{ + if (minRange == maxRange || min == max) + return minRange; + const int clampedCur = std::min(std::max(cur, min), max); + return minRange + ((clampedCur - min) / (max - min)) * (maxRange - minRange); +} + void ServerModeReader::extractCodeModelData(const QVariantMap &data) { const QVariantList configs = data.value("configurations").toList(); @@ -880,3 +887,59 @@ void ServerModeReader::addHeaderNodes(ProjectNode *root, const QList<FileNode *> } // namespace Internal } // namespace CMakeProjectManager + +#if defined(WITH_TESTS) + +#include "cmakeprojectplugin.h" +#include <QTest> + +namespace CMakeProjectManager { +namespace Internal { + +void CMakeProjectPlugin::testServerModeReaderProgress_data() +{ + QTest::addColumn<int>("minRange"); + QTest::addColumn<int>("min"); + QTest::addColumn<int>("cur"); + QTest::addColumn<int>("max"); + QTest::addColumn<int>("maxRange"); + QTest::addColumn<int>("expected"); + + QTest::newRow("empty range") << 100 << 10 << 11 << 20 << 100 << 100; + QTest::newRow("one range (low)") << 0 << 10 << 11 << 20 << 1 << 0; + QTest::newRow("one range (high)") << 20 << 10 << 19 << 20 << 20 << 20; + QTest::newRow("large range") << 30 << 10 << 11 << 20 << 100000 << 30; + + QTest::newRow("empty progress") << -5 << 10 << 10 << 10 << 99995 << -5; + QTest::newRow("one progress (low)") << 42 << 10 << 10 << 11 << 100042 << 42; + QTest::newRow("one progress (high)") << 0 << 10 << 11 << 11 << 100000 << 100000; + QTest::newRow("large progress") << 0 << 10 << 10 << 11 << 100000 << 0; + + QTest::newRow("cur too low") << 0 << 10 << 9 << 100 << 100000 << 0; + QTest::newRow("cur too high") << 0 << 10 << 101 << 100 << 100000 << 100000; + QTest::newRow("cur much too low") << 0 << 10 << -1000 << 100 << 100000 << 0; + QTest::newRow("cur much too high") << 0 << 10 << 1110000 << 100 << 100000 << 100000; +} + +void CMakeProjectPlugin::testServerModeReaderProgress() +{ + QFETCH(int, minRange); + QFETCH(int, min); + QFETCH(int, cur); + QFETCH(int, max); + QFETCH(int, maxRange); + QFETCH(int, expected); + + ServerModeReader reader; + const int r = reader.calculateProgress(minRange, min, cur, max, maxRange); + + QCOMPARE(r, expected); + + QVERIFY(r <= maxRange); + QVERIFY(r >= minRange); +} + +} // namespace Internal +} // namespace CMakeProjectManager + +#endif diff --git a/src/plugins/cmakeprojectmanager/servermodereader.h b/src/plugins/cmakeprojectmanager/servermodereader.h index f94e4d9223..8dc4f5e353 100644 --- a/src/plugins/cmakeprojectmanager/servermodereader.h +++ b/src/plugins/cmakeprojectmanager/servermodereader.h @@ -69,6 +69,10 @@ private: void handleProgress(int min, int cur, int max, const QString &inReplyTo); void handleSignal(const QString &signal, const QVariantMap &data); + int calculateProgress(const int minRange, const int min, + const int cur, + const int max, const int maxRange); + struct Target; struct Project; @@ -175,6 +179,10 @@ private: QList<FileGroup *> m_fileGroups; CMakeParser m_parser; + +#if defined(WITH_TESTS) + friend class CMakeProjectPlugin; +#endif }; } // namespace Internal diff --git a/src/plugins/coreplugin/coreplugin.cpp b/src/plugins/coreplugin/coreplugin.cpp index fed19490ca..a51d418a6c 100644 --- a/src/plugins/coreplugin/coreplugin.cpp +++ b/src/plugins/coreplugin/coreplugin.cpp @@ -131,8 +131,9 @@ bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage) continue; const QJsonObject metaData = plugin->metaData(); const QJsonValue mimetypes = metaData.value("Mimetypes"); - if (mimetypes.isString()) - Utils::addMimeTypes(plugin->name() + ".mimetypes", mimetypes.toString().trimmed().toUtf8()); + QString mimetypeString; + if (ExtensionSystem::PluginSpec::readMultiLineString(mimetypes, &mimetypeString)) + Utils::addMimeTypes(plugin->name() + ".mimetypes", mimetypeString.trimmed().toUtf8()); } if (ThemeEntry::availableThemes().isEmpty()) { diff --git a/src/plugins/coreplugin/dialogs/newdialog.cpp b/src/plugins/coreplugin/dialogs/newdialog.cpp index 66e794b2e4..2254f6c5b6 100644 --- a/src/plugins/coreplugin/dialogs/newdialog.cpp +++ b/src/plugins/coreplugin/dialogs/newdialog.cpp @@ -369,6 +369,28 @@ IWizardFactory *NewDialog::currentWizardFactory() const return factoryOfItem(m_model->itemFromIndex(index)); } +static QIcon iconWithText(const QIcon &icon, const QString &text) +{ + if (text.isEmpty()) + return icon; + QIcon iconWithText; + for (const QSize &pixmapSize : icon.availableSizes()) { + QPixmap pixmap = icon.pixmap(pixmapSize); + const int fontSize = pixmap.height() / 4; + const int margin = pixmap.height() / 8; + QFont font; + font.setPixelSize(fontSize); + font.setStretch(85); + QPainter p(&pixmap); + p.setFont(font); + QTextOption textOption(Qt::AlignHCenter | Qt::AlignBottom); + textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); + p.drawText(pixmap.rect().adjusted(margin, margin, -margin, -margin), text, textOption); + iconWithText.addPixmap(pixmap); + } + return iconWithText; +} + void NewDialog::addItem(QStandardItem *topLevelCategoryItem, IWizardFactory *factory) { const QString categoryName = factory->category(); @@ -394,7 +416,7 @@ void NewDialog::addItem(QStandardItem *topLevelCategoryItem, IWizardFactory *fac wizardIcon = m_dummyIcon; else wizardIcon = factory->icon(); - wizardItem->setIcon(wizardIcon); + wizardItem->setIcon(iconWithText(wizardIcon, factory->iconText())); wizardItem->setData(QVariant::fromValue(WizardFactoryContainer(factory, 0)), Qt::UserRole); wizardItem->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable); categoryItem->appendRow(wizardItem); diff --git a/src/plugins/coreplugin/find/findtoolwindow.cpp b/src/plugins/coreplugin/find/findtoolwindow.cpp index 8647b7b2e9..05704437eb 100644 --- a/src/plugins/coreplugin/find/findtoolwindow.cpp +++ b/src/plugins/coreplugin/find/findtoolwindow.cpp @@ -264,12 +264,12 @@ void FindToolWindow::setCurrentFilter(int index) void FindToolWindow::acceptAndGetParameters(QString *term, IFindFilter **filter) { - if (filter) - *filter = 0; + QTC_ASSERT(filter, return); + *filter = 0; Find::updateFindCompletion(m_ui.searchTerm->text()); int index = m_ui.filterList->currentIndex(); QString searchTerm = m_ui.searchTerm->text(); - if (filter && index >= 0) + if (index >= 0) *filter = m_filters.at(index); if (term) *term = searchTerm; diff --git a/src/plugins/coreplugin/iwizardfactory.h b/src/plugins/coreplugin/iwizardfactory.h index 30b6cb164a..d1f218c133 100644 --- a/src/plugins/coreplugin/iwizardfactory.h +++ b/src/plugins/coreplugin/iwizardfactory.h @@ -60,6 +60,7 @@ public: Id id() const { return m_id; } WizardKind kind() const { return m_supportedProjectTypes.isEmpty() ? FileWizard : ProjectWizard; } QIcon icon() const { return m_icon; } + QString iconText() const { return m_iconText; } QString description() const { return m_description; } QString displayName() const { return m_displayName; } QString category() const { return m_category; } @@ -72,6 +73,7 @@ public: void setId(const Id id) { m_id = id; } void setSupportedProjectTypes(const QSet<Id> &projectTypes) { m_supportedProjectTypes = projectTypes; } void setIcon(const QIcon &icon) { m_icon = icon; } + void setIconText(const QString &iconText) { m_iconText = iconText; } void setDescription(const QString &description) { m_description = description; } void setDisplayName(const QString &displayName) { m_displayName = displayName; } void setCategory(const QString &category) { m_category = category; } @@ -123,6 +125,7 @@ private: QAction *m_action = 0; QIcon m_icon; + QString m_iconText; QString m_description; QString m_displayName; QString m_category; diff --git a/src/plugins/cppeditor/cppautocompleter.cpp b/src/plugins/cppeditor/cppautocompleter.cpp index a1b5ca5900..2f6a2fc46f 100644 --- a/src/plugins/cppeditor/cppautocompleter.cpp +++ b/src/plugins/cppeditor/cppautocompleter.cpp @@ -27,15 +27,20 @@ #include <cplusplus/MatchingText.h> +#include <texteditor/tabsettings.h> + +#include <QTextBlock> #include <QTextCursor> using namespace CppEditor; using namespace Internal; bool CppAutoCompleter::contextAllowsAutoBrackets(const QTextCursor &cursor, - const QString &textToInsert) const + const QString &textToInsert) const { - return CPlusPlus::MatchingText::contextAllowsAutoParentheses(cursor, textToInsert); + const CPlusPlus::MatchingText::IsNextBlockDeeperIndented isIndented + = [this](const QTextBlock &b) { return isNextBlockIndented(b); }; + return CPlusPlus::MatchingText::contextAllowsAutoParentheses(cursor, textToInsert, isIndented); } bool CppAutoCompleter::contextAllowsAutoQuotes(const QTextCursor &cursor, diff --git a/src/plugins/cppeditor/cpplocalrenaming.cpp b/src/plugins/cppeditor/cpplocalrenaming.cpp index d14a5832f2..fd989c782c 100644 --- a/src/plugins/cppeditor/cpplocalrenaming.cpp +++ b/src/plugins/cppeditor/cpplocalrenaming.cpp @@ -70,7 +70,9 @@ CppLocalRenaming::CppLocalRenaming(TextEditor::TextEditorWidget *editorWidget) void CppLocalRenaming::updateSelectionsForVariableUnderCursor( const QList<QTextEdit::ExtraSelection> &selections) { - QTC_ASSERT(!isActive(), return); + if (isActive()) + return; + m_selections = selections; } diff --git a/src/plugins/cppeditor/cppuseselectionsupdater.cpp b/src/plugins/cppeditor/cppuseselectionsupdater.cpp index 81e1436ccd..4e13fee597 100644 --- a/src/plugins/cppeditor/cppuseselectionsupdater.cpp +++ b/src/plugins/cppeditor/cppuseselectionsupdater.cpp @@ -94,6 +94,7 @@ void CppUseSelectionsUpdater::update(CallType callType) m_runnerWatcher->setFuture(cppEditorDocument->cursorInfo(params)); } else { // synchronous case + const int startRevision = cppEditorDocument->document()->revision(); QFuture<CursorInfo> future = cppEditorDocument->cursorInfo(params); // QFuture::waitForFinished seems to block completely, not even @@ -102,6 +103,7 @@ void CppUseSelectionsUpdater::update(CallType callType) if (future.isCanceled()) return; + QTC_ASSERT(startRevision == cppEditorDocument->document()->revision(), return); QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); } diff --git a/src/plugins/cpptools/CppTools.json.in b/src/plugins/cpptools/CppTools.json.in index a9af2e54d6..c95a262683 100644 --- a/src/plugins/cpptools/CppTools.json.in +++ b/src/plugins/cpptools/CppTools.json.in @@ -18,101 +18,101 @@ \"Url\" : \"http://www.qt.io\", $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\' encoding=\'UTF-8\'?> - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> - <mime-type type=\'text/x-csrc\'> - <comment>C source code</comment> - <sub-class-of type=\'text/plain\'/> - <alias type=\'text/x-c\'/> - <glob pattern=\'*.c\' case-sensitive=\'true\' weight=\'70\'/> - </mime-type> + \"Mimetypes\" : [ + \"<?xml version=\'1.0\' encoding=\'UTF-8\'?>\", + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", + \" <mime-type type=\'text/x-csrc\'>\", + \" <comment>C source code</comment>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <alias type=\'text/x-c\'/>\", + \" <glob pattern=\'*.c\' case-sensitive=\'true\' weight=\'70\'/>\", + \" </mime-type>\", - <mime-type type=\'text/vnd.nvidia.cuda.csrc\'> - <sub-class-of type=\'text/x-csrc\'/> - <comment>NVIDIA CUDA C source code</comment> - <glob pattern=\'*.cu\'/> - </mime-type> + \" <mime-type type=\'text/vnd.nvidia.cuda.csrc\'>\", + \" <sub-class-of type=\'text/x-csrc\'/>\", + \" <comment>NVIDIA CUDA C source code</comment>\", + \" <glob pattern=\'*.cu\'/>\", + \" </mime-type>\", - <mime-type type=\'text/x-chdr\'> - <comment>C header</comment> - <sub-class-of type=\'text/x-csrc\'/> - <!-- reduce weight from freedesktop to avoid conflict with text/x-c++hdr --> - <glob pattern=\'*.h\' weight=\'30\'/> - </mime-type> + \" <mime-type type=\'text/x-chdr\'>\", + \" <comment>C header</comment>\", + \" <sub-class-of type=\'text/x-csrc\'/>\", + \" <!-- reduce weight from freedesktop to avoid conflict with text/x-c++hdr -->\", + \" <glob pattern=\'*.h\' weight=\'30\'/>\", + \" </mime-type>\", - <!-- Those are used to find matching headers by the CppTools plugin, - so, they should match --> - <mime-type type=\'text/x-c++hdr\'> - <sub-class-of type=\'text/x-chdr\'/> - <comment>C++ header</comment> - <glob pattern=\'*.hh\' weight=\'70\'/> - <glob pattern=\'*.hxx\' weight=\'70\'/> - <glob pattern=\'*.h++\' weight=\'70\'/> - <glob pattern=\'*.hpp\' weight=\'70\'/> - <glob pattern=\'*.hp\' weight=\'70\'/> - <!-- Additions to freedesktop: --> - <glob pattern=\'*.h\' weight=\'70\'/> - <glob pattern=\'*.H\' weight=\'70\'/> - <!-- Find include guards of header files without extension, for - example, STL ones like <string>. Those can have a big initial - comment exceeding 1000 chars, though. --> - <magic priority=\'50\'> - <match value=\'#ifndef \' type=\'string\' offset=\'0:2000\'/> - <match value=\'#if \' type=\'string\' offset=\'0:2000\'/> - <match value=\'#include \' type=\'string\' offset=\'0:2000\'/> - </magic> - </mime-type> + \" <!-- Those are used to find matching headers by the CppTools plugin,\", + \" so, they should match -->\", + \" <mime-type type=\'text/x-c++hdr\'>\", + \" <sub-class-of type=\'text/x-chdr\'/>\", + \" <comment>C++ header</comment>\", + \" <glob pattern=\'*.hh\' weight=\'70\'/>\", + \" <glob pattern=\'*.hxx\' weight=\'70\'/>\", + \" <glob pattern=\'*.h++\' weight=\'70\'/>\", + \" <glob pattern=\'*.hpp\' weight=\'70\'/>\", + \" <glob pattern=\'*.hp\' weight=\'70\'/>\", + \" <!-- Additions to freedesktop: -->\", + \" <glob pattern=\'*.h\' weight=\'70\'/>\", + \" <glob pattern=\'*.H\' weight=\'70\'/>\", + \" <!-- Find include guards of header files without extension, for\", + \" example, STL ones like <string>. Those can have a big initial\", + \" comment exceeding 1000 chars, though. -->\", + \" <magic priority=\'50\'>\", + \" <match value=\'#ifndef \' type=\'string\' offset=\'0:2000\'/>\", + \" <match value=\'#if \' type=\'string\' offset=\'0:2000\'/>\", + \" <match value=\'#include \' type=\'string\' offset=\'0:2000\'/>\", + \" </magic>\", + \" </mime-type>\", - <mime-type type=\'text/x-c++src\'> - <comment>C++ source code</comment> - <sub-class-of type=\'text/x-csrc\'/> - <glob pattern=\'*.cpp\' weight=\'70\'/> - <glob pattern=\'*.cxx\' weight=\'70\'/> - <glob pattern=\'*.cc\' weight=\'70\'/> - <glob pattern=\'*.C\' case-sensitive=\'true\' weight=\'70\'/> - <glob pattern=\'*.c++\' weight=\'70\'/> - <!-- Additions to freedesktop: --> - <glob pattern=\'*.cp\' weight=\'70\'/> - <glob pattern=\'*.inl\' weight=\'70\'/> - <glob pattern=\'*.tcc\' weight=\'70\'/> - <glob pattern=\'*.tpp\' weight=\'70\'/> - <glob pattern=\'*.t++\' weight=\'70\'/> - <glob pattern=\'*.txx\' weight=\'70\'/> - <magic priority=\'30\'> - <match value=\'-*- C++ -*-\' type=\'string\' offset=\'0:30\'/> - </magic> - </mime-type> + \" <mime-type type=\'text/x-c++src\'>\", + \" <comment>C++ source code</comment>\", + \" <sub-class-of type=\'text/x-csrc\'/>\", + \" <glob pattern=\'*.cpp\' weight=\'70\'/>\", + \" <glob pattern=\'*.cxx\' weight=\'70\'/>\", + \" <glob pattern=\'*.cc\' weight=\'70\'/>\", + \" <glob pattern=\'*.C\' case-sensitive=\'true\' weight=\'70\'/>\", + \" <glob pattern=\'*.c++\' weight=\'70\'/>\", + \" <!-- Additions to freedesktop: -->\", + \" <glob pattern=\'*.cp\' weight=\'70\'/>\", + \" <glob pattern=\'*.inl\' weight=\'70\'/>\", + \" <glob pattern=\'*.tcc\' weight=\'70\'/>\", + \" <glob pattern=\'*.tpp\' weight=\'70\'/>\", + \" <glob pattern=\'*.t++\' weight=\'70\'/>\", + \" <glob pattern=\'*.txx\' weight=\'70\'/>\", + \" <magic priority=\'30\'>\", + \" <match value=\'-*- C++ -*-\' type=\'string\' offset=\'0:30\'/>\", + \" </magic>\", + \" </mime-type>\", - <mime-type type=\'text/x-qdoc\'> - <comment>Qt documentation file</comment> - <sub-class-of type=\'text/plain\'/> - <glob pattern=\'*.qdoc\' weight=\'70\'/> - </mime-type> + \" <mime-type type=\'text/x-qdoc\'>\", + \" <comment>Qt documentation file</comment>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <glob pattern=\'*.qdoc\' weight=\'70\'/>\", + \" </mime-type>\", - <mime-type type=\'text/x-moc\'> - <comment>Qt MOC file</comment> - <!-- Fix to freedesktop: moc is C++ source --> - <sub-class-of type=\'text/x-c++src\'/> - <glob pattern=\'*.moc\' weight=\'70\'/> - </mime-type> + \" <mime-type type=\'text/x-moc\'>\", + \" <comment>Qt MOC file</comment>\", + \" <!-- Fix to freedesktop: moc is C++ source -->\", + \" <sub-class-of type=\'text/x-c++src\'/>\", + \" <glob pattern=\'*.moc\' weight=\'70\'/>\", + \" </mime-type>\", - <mime-type type=\'text/x-objc++src\'> - <comment>Objective-C++ source code</comment> - <sub-class-of type=\'text/x-c++src\'/> - <sub-class-of type=\'text/x-objcsrc\'/> - <glob pattern=\'*.mm\' weight=\'70\'/> - </mime-type> + \" <mime-type type=\'text/x-objc++src\'>\", + \" <comment>Objective-C++ source code</comment>\", + \" <sub-class-of type=\'text/x-c++src\'/>\", + \" <sub-class-of type=\'text/x-objcsrc\'/>\", + \" <glob pattern=\'*.mm\' weight=\'70\'/>\", + \" </mime-type>\", - <mime-type type=\'text/x-objcsrc\'> - <comment>Objective-C source code</comment> - <sub-class-of type=\'text/x-csrc\'/> - <glob pattern=\'*.m\' weight=\'70\'/> - <magic priority=\'30\'> - <match value=\'#import\' type=\'string\' offset=\'0\'/> - </magic> - </mime-type> + \" <mime-type type=\'text/x-objcsrc\'>\", + \" <comment>Objective-C source code</comment>\", + \" <sub-class-of type=\'text/x-csrc\'/>\", + \" <glob pattern=\'*.m\' weight=\'70\'/>\", + \" <magic priority=\'30\'>\", + \" <match value=\'#import\' type=\'string\' offset=\'0\'/>\", + \" </magic>\", + \" </mime-type>\", - </mime-info> - \" + \"</mime-info>\" + ] } diff --git a/src/plugins/cpptools/clangdiagnosticconfigsmodel.cpp b/src/plugins/cpptools/clangdiagnosticconfigsmodel.cpp index 972f82c2d0..44187b6a10 100644 --- a/src/plugins/cpptools/clangdiagnosticconfigsmodel.cpp +++ b/src/plugins/cpptools/clangdiagnosticconfigsmodel.cpp @@ -83,6 +83,7 @@ static void addConfigForAlmostEveryWarning(ClangDiagnosticConfigsModel &model) QStringLiteral("-Wno-gnu-zero-variadic-macro-arguments"), QStringLiteral("-Wno-documentation"), QStringLiteral("-Wno-shadow"), + QStringLiteral("-Wno-switch-enum"), QStringLiteral("-Wno-missing-prototypes"), // Not optimal for C projects. QStringLiteral("-Wno-used-but-marked-unused"), // e.g. QTest::qWait } + commonWarnings()); diff --git a/src/plugins/cvs/CVS.json.in b/src/plugins/cvs/CVS.json.in index d18e228f1d..1efdd73d48 100644 --- a/src/plugins/cvs/CVS.json.in +++ b/src/plugins/cvs/CVS.json.in @@ -17,13 +17,13 @@ \"Url\" : \"http://www.qt.io\", $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\'?> - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> - <mime-type type=\'text/vnd.qtcreator.cvs.submit\'> - <comment>CVS submit template</comment> - <sub-class-of type=\'text/plain\'/> - </mime-type> - </mime-info> - \" + \"Mimetypes\" : [ + \"<?xml version=\'1.0\'?>\", + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", + \" <mime-type type=\'text/vnd.qtcreator.cvs.submit\'>\", + \" <comment>CVS submit template</comment>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" </mime-type>\", + \"</mime-info>\" + ] } diff --git a/src/plugins/debugger/Debugger.json.in b/src/plugins/debugger/Debugger.json.in index 458d1a8456..c4ed7f18e3 100644 --- a/src/plugins/debugger/Debugger.json.in +++ b/src/plugins/debugger/Debugger.json.in @@ -41,20 +41,20 @@ ], $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\'?> - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> - <mime-type type=\'text/x-asm\'> - <sub-class-of type=\'text/plain\'/> - <comment>Assembler</comment> - <glob pattern=\'*.asm\'/> - </mime-type> - <!-- Catch-all for assemblers --> - <mime-type type=\'text/x-qtcreator-generic-asm\'> - <sub-class-of type=\'text/x-asm\'/> - <comment>Qt Creator Generic Assembler</comment> - <glob pattern=\'*.asm\'/> - </mime-type> - </mime-info> - \" + \"Mimetypes\" : [ + \"<?xml version=\'1.0\'?>\", + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", + \" <mime-type type=\'text/x-asm\'>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>Assembler</comment>\", + \" <glob pattern=\'*.asm\'/>\", + \" </mime-type>\", + \" <!-- Catch-all for assemblers -->\", + \" <mime-type type=\'text/x-qtcreator-generic-asm\'>\", + \" <sub-class-of type=\'text/x-asm\'/>\", + \" <comment>Qt Creator Generic Assembler</comment>\", + \" <glob pattern=\'*.asm\'/>\", + \" </mime-type>\", + \"</mime-info>\" + ] } diff --git a/src/plugins/designer/formeditorplugin.cpp b/src/plugins/designer/formeditorplugin.cpp index 1abc12a803..8a4f0af3de 100644 --- a/src/plugins/designer/formeditorplugin.cpp +++ b/src/plugins/designer/formeditorplugin.cpp @@ -87,6 +87,7 @@ bool FormEditorPlugin::initialize(const QStringList &arguments, QString *error) wizard->setCategory(QLatin1String(Core::Constants::WIZARD_CATEGORY_QT)); wizard->setDisplayCategory(QCoreApplication::translate("Core", Core::Constants::WIZARD_TR_CATEGORY_QT)); wizard->setDisplayName(tr("Qt Designer Form Class")); + wizard->setIconText("ui/h"); wizard->setId("C.FormClass"); wizard->setDescription(tr("Creates a Qt Designer form along with a matching class (C++ header and source file) " "for implementation purposes. You can add the form and class to an existing Qt Widget Project.")); diff --git a/src/plugins/genericprojectmanager/GenericProjectManager.json.in b/src/plugins/genericprojectmanager/GenericProjectManager.json.in index cc9ce119d4..306d2fcaa4 100644 --- a/src/plugins/genericprojectmanager/GenericProjectManager.json.in +++ b/src/plugins/genericprojectmanager/GenericProjectManager.json.in @@ -17,34 +17,34 @@ \"Url\" : \"http://www.qt.io\", $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\'?> + \"Mimetypes\" : [ + \"<?xml version=\'1.0\'?>\", - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> - <mime-type type=\'text/x-generic-project\'> - <sub-class-of type=\'text/plain\'/> - <comment>Generic Qt Creator Project file</comment> - <glob pattern=\'*.creator\'/> - </mime-type> + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", + \" <mime-type type=\'text/x-generic-project\'>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>Generic Qt Creator Project file</comment>\", + \" <glob pattern=\'*.creator\'/>\", + \" </mime-type>\", - <mime-type type=\'application/vnd.qtcreator.generic.files\'> - <sub-class-of type=\'text/plain\'/> - <comment>Generic Project Files</comment> - <glob pattern=\'*.files\'/> - </mime-type> + \" <mime-type type=\'application/vnd.qtcreator.generic.files\'>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>Generic Project Files</comment>\", + \" <glob pattern=\'*.files\'/>\", + \" </mime-type>\", - <mime-type type=\'application/vnd.qtcreator.generic.includes\'> - <sub-class-of type=\'text/plain\'/> - <comment>Generic Project Include Paths</comment> - <glob pattern=\'*.includes\'/> - </mime-type> + \" <mime-type type=\'application/vnd.qtcreator.generic.includes\'>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>Generic Project Include Paths</comment>\", + \" <glob pattern=\'*.includes\'/>\", + \" </mime-type>\", - <mime-type type=\'application/vnd.qtcreator.generic.config\'> - <sub-class-of type=\'text/plain\'/> - <comment>Generic Project Configuration File</comment> - <glob pattern=\'*.config\'/> - </mime-type> + \" <mime-type type=\'application/vnd.qtcreator.generic.config\'>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>Generic Project Configuration File</comment>\", + \" <glob pattern=\'*.config\'/>\", + \" </mime-type>\", - </mime-info> - \" + \"</mime-info>\" + ] } diff --git a/src/plugins/git/Git.json.in b/src/plugins/git/Git.json.in index c2680577ba..ebbee5d409 100644 --- a/src/plugins/git/Git.json.in +++ b/src/plugins/git/Git.json.in @@ -17,20 +17,20 @@ \"Url\" : \"http://www.qt.io\", $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\'?> - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> - <mime-type type=\'text/vnd.qtcreator.git.commit\'> - <sub-class-of type=\'text/plain\'/> - <comment>Git Commit File</comment> - <glob pattern=\'COMMIT_MSG\'/> - <glob pattern=\'COMMIT_EDITMSG\'/> - </mime-type> - <mime-type type=\'text/vnd.qtcreator.git.rebase\'> - <sub-class-of type=\'text/plain\'/> - <comment>Git Commit File</comment> - <glob pattern=\'git-rebase-todo\'/> - </mime-type> - </mime-info> - \" + \"Mimetypes\" : [ + \"<?xml version=\'1.0\'?>\", + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", + \" <mime-type type=\'text/vnd.qtcreator.git.commit\'>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>Git Commit File</comment>\", + \" <glob pattern=\'COMMIT_MSG\'/>\", + \" <glob pattern=\'COMMIT_EDITMSG\'/>\", + \" </mime-type>\", + \" <mime-type type=\'text/vnd.qtcreator.git.rebase\'>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>Git Commit File</comment>\", + \" <glob pattern=\'git-rebase-todo\'/>\", + \" </mime-type>\", + \"</mime-info>\" + ] } diff --git a/src/plugins/git/gitgrep.cpp b/src/plugins/git/gitgrep.cpp index 3c0096921f..59b1fb9566 100644 --- a/src/plugins/git/gitgrep.cpp +++ b/src/plugins/git/gitgrep.cpp @@ -141,11 +141,12 @@ public: void exec() { - QStringList arguments; - arguments << "-c" << "color.grep.match=bold red" - << "grep" << "-zn" - << "--no-full-name" - << "--color=always"; + GitClient *client = GitPlugin::client(); + QStringList arguments = { + "-c", "color.grep.match=bold red", + "-c", "color.grep=always", + "grep", "-zn", "--no-full-name" + }; if (!(m_parameters.flags & FindCaseSensitively)) arguments << "-i"; if (m_parameters.flags & FindWholeWords) @@ -154,6 +155,8 @@ public: arguments << "-P"; else arguments << "-F"; + if (client->gitVersion() >= 0x021300) + arguments << "--recurse-submodules"; arguments << "-e" << m_parameters.text; GitGrepParameters params = m_parameters.searchEngineParameters.value<GitGrepParameters>(); if (!params.ref.isEmpty()) { @@ -168,7 +171,7 @@ public: return QString(":!" + filter); }); arguments << "--" << filterArgs << exclusionArgs; - QScopedPointer<VcsCommand> command(GitPlugin::client()->createCommand(m_directory)); + QScopedPointer<VcsCommand> command(client->createCommand(m_directory)); command->addFlags(VcsCommand::SilentOutput | VcsCommand::SuppressFailMessage); command->setProgressiveOutput(true); QFutureWatcher<FileSearchResultList> watcher; @@ -176,7 +179,7 @@ public: connect(&watcher, &QFutureWatcher<FileSearchResultList>::canceled, command.data(), &VcsCommand::cancel); connect(command.data(), &VcsCommand::stdOutText, this, &GitGrepRunner::read); - SynchronousProcessResponse resp = command->runCommand(GitPlugin::client()->vcsBinary(), arguments, 0); + SynchronousProcessResponse resp = command->runCommand(client->vcsBinary(), arguments, 0); switch (resp.result) { case SynchronousProcessResponse::TerminatedAbnormally: case SynchronousProcessResponse::StartFailed: diff --git a/src/plugins/glsleditor/GLSLEditor.json.in b/src/plugins/glsleditor/GLSLEditor.json.in index 915ae7ae02..09814901a2 100644 --- a/src/plugins/glsleditor/GLSLEditor.json.in +++ b/src/plugins/glsleditor/GLSLEditor.json.in @@ -17,48 +17,48 @@ \"Url\" : \"http://www.qt.io\", $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\'?> - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> + \"Mimetypes\" : [ + \"<?xml version=\'1.0\'?>\", + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", - <mime-type type=\'application/x-glsl\'> - <alias type=\'text/x-glsl\'/> - <sub-class-of type=\'text/plain\'/> - <comment>GLSL Shader file</comment> - <glob pattern=\'*.glsl\'/> - <glob pattern=\'*.shader\'/> - </mime-type> + \" <mime-type type=\'application/x-glsl\'>\", + \" <alias type=\'text/x-glsl\'/>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>GLSL Shader file</comment>\", + \" <glob pattern=\'*.glsl\'/>\", + \" <glob pattern=\'*.shader\'/>\", + \" </mime-type>\", - <mime-type type=\'text/x-glsl-frag\'> - <sub-class-of type=\'text/x-glsl\'/> - <comment>GLSL Fragment Shader file</comment> - <glob pattern=\'*.frag\'/> - </mime-type> + \" <mime-type type=\'text/x-glsl-frag\'>\", + \" <sub-class-of type=\'text/x-glsl\'/>\", + \" <comment>GLSL Fragment Shader file</comment>\", + \" <glob pattern=\'*.frag\'/>\", + \" </mime-type>\", - <mime-type type=\'text/x-glsl-es-frag\'> - <sub-class-of type=\'text/x-glsl\'/> - <comment>GLSL/ES Fragment Shader file</comment> - <glob pattern=\'*.fsh\'/> - </mime-type> + \" <mime-type type=\'text/x-glsl-es-frag\'>\", + \" <sub-class-of type=\'text/x-glsl\'/>\", + \" <comment>GLSL/ES Fragment Shader file</comment>\", + \" <glob pattern=\'*.fsh\'/>\", + \" </mime-type>\", - <mime-type type=\'text/x-glsl-vert\'> - <sub-class-of type=\'text/x-glsl\'/> - <comment>GLSL Vertex Shader file</comment> - <glob pattern=\'*.vert\'/> - </mime-type> + \" <mime-type type=\'text/x-glsl-vert\'>\", + \" <sub-class-of type=\'text/x-glsl\'/>\", + \" <comment>GLSL Vertex Shader file</comment>\", + \" <glob pattern=\'*.vert\'/>\", + \" </mime-type>\", - <mime-type type=\'text/x-glsl-es-vert\'> - <sub-class-of type=\'text/x-glsl\'/> - <comment>GLSL/ES Vertex Shader file</comment> - <glob pattern=\'*.vsh\'/> - </mime-type> + \" <mime-type type=\'text/x-glsl-es-vert\'>\", + \" <sub-class-of type=\'text/x-glsl\'/>\", + \" <comment>GLSL/ES Vertex Shader file</comment>\", + \" <glob pattern=\'*.vsh\'/>\", + \" </mime-type>\", - <mime-type type=\'text/x-glsl-es-geometry\'> - <sub-class-of type=\'text/x-glsl\'/> - <comment>GLSL/ES Geometry Shader file</comment> - <glob pattern=\'*.gsh\'/> - </mime-type> + \" <mime-type type=\'text/x-glsl-es-geometry\'>\", + \" <sub-class-of type=\'text/x-glsl\'/>\", + \" <comment>GLSL/ES Geometry Shader file</comment>\", + \" <glob pattern=\'*.gsh\'/>\", + \" </mime-type>\", - </mime-info> - \" + \"</mime-info>\" + ] } diff --git a/src/plugins/imageviewer/ImageViewer.json.in b/src/plugins/imageviewer/ImageViewer.json.in index 685dff9a9f..59fa5f7282 100644 --- a/src/plugins/imageviewer/ImageViewer.json.in +++ b/src/plugins/imageviewer/ImageViewer.json.in @@ -17,15 +17,15 @@ \"Url\" : \"http://www.qt.io\", $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\'?> - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> + \"Mimetypes\" : [ + \"<?xml version=\'1.0\'?>\", + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", - <mime-type type=\'image/webp\'> - <comment>WebP Image file</comment> - <glob pattern=\'*.webp\'/> - </mime-type> + \" <mime-type type=\'image/webp\'>\", + \" <comment>WebP Image file</comment>\", + \" <glob pattern=\'*.webp\'/>\", + \" </mime-type>\", - </mime-info> - \" + \"</mime-info>\" + ] } diff --git a/src/plugins/modeleditor/ModelEditor.json.in b/src/plugins/modeleditor/ModelEditor.json.in index 44558589be..8fc6c019cb 100644 --- a/src/plugins/modeleditor/ModelEditor.json.in +++ b/src/plugins/modeleditor/ModelEditor.json.in @@ -18,14 +18,14 @@ \"Experimental\" : true, $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\' encoding=\'UTF-8\'?> - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> - <mime-type type=\'text/vnd.qtcreator.model\'> - <sub-class-of type=\'text/xml\'/> - <comment>Qt Creator Model File</comment> - <glob pattern=\'*.qmodel\'/> - </mime-type> - </mime-info> - \" + \"Mimetypes\" : [ + \"<?xml version=\'1.0\' encoding=\'UTF-8\'?>\", + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", + \" <mime-type type=\'text/vnd.qtcreator.model\'>\", + \" <sub-class-of type=\'text/xml\'/>\", + \" <comment>Qt Creator Model File</comment>\", + \" <glob pattern=\'*.qmodel\'/>\", + \" </mime-type>\", + \"</mime-info>\" + ] } diff --git a/src/plugins/nim/Nim.json.in b/src/plugins/nim/Nim.json.in index 3fc6a65135..9f44b2ce45 100644 --- a/src/plugins/nim/Nim.json.in +++ b/src/plugins/nim/Nim.json.in @@ -18,27 +18,27 @@ \"Experimental\" : true, $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\'?> - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> + \"Mimetypes\" : [ + \"<?xml version=\'1.0\'?>\", + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", - <mime-type type=\'text/x-nim-project\'> - <sub-class-of type=\'text/plain\'/> - <comment>Nim project file</comment> - <glob pattern=\'*.nimproject\'/> - </mime-type> + \" <mime-type type=\'text/x-nim-project\'>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>Nim project file</comment>\", + \" <glob pattern=\'*.nimproject\'/>\", + \" </mime-type>\", - <mime-type type=\'text/x-nim\'> - <sub-class-of type=\'text/plain\'/> - <comment>Nim source file </comment> - <glob pattern=\'*.nim\'/> - </mime-type> + \" <mime-type type=\'text/x-nim\'>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>Nim source file </comment>\", + \" <glob pattern=\'*.nim\'/>\", + \" </mime-type>\", - <mime-type type=\'text/x-nim-script\'> - <sub-class-of type=\'text/plain\'/> - <comment>Nim script file </comment> - <glob pattern=\'*.nims\'/> - </mime-type> - </mime-info> - \" + \" <mime-type type=\'text/x-nim-script\'>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>Nim script file </comment>\", + \" <glob pattern=\'*.nims\'/>\", + \" </mime-type>\", + \"</mime-info>\" + ] } diff --git a/src/plugins/perforce/Perforce.json.in b/src/plugins/perforce/Perforce.json.in index 7d408c00e4..cb92d2542d 100644 --- a/src/plugins/perforce/Perforce.json.in +++ b/src/plugins/perforce/Perforce.json.in @@ -17,16 +17,16 @@ \"Url\" : \"http://www.qt.io\", $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\'?> - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> - <mime-type type=\'text/vnd.qtcreator.p4.submit\'> - <comment>Perforce submit template</comment> - <sub-class-of type=\'text/plain\'/> - <magic priority=\'50\'> - <match value=\'# A Perforce Change Specification.\' type=\'string\' offset=\'0\'/> - </magic> - </mime-type> - </mime-info> - \" + \"Mimetypes\" : [ + \"<?xml version=\'1.0\'?>\", + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", + \" <mime-type type=\'text/vnd.qtcreator.p4.submit\'>\", + \" <comment>Perforce submit template</comment>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <magic priority=\'50\'>\", + \" <match value=\'# A Perforce Change Specification.\' type=\'string\' offset=\'0\'/>\", + \" </magic>\", + \" </mime-type>\", + \"</mime-info>\" + ] } diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index 66caca2b08..603e473613 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -434,7 +434,7 @@ static Utils::FileName findLocalCompiler(const Utils::FileName &compilerPath, && !pathEntry.contains("distcc"); }); - QTC_ASSERT(path != FileName(), return compilerPath); + QTC_ASSERT(!path.isEmpty(), return compilerPath); return path; } diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp index 7856a08b28..5faa25902d 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp +++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp @@ -70,6 +70,7 @@ static const char CATEGORY_KEY[] = "category"; static const char CATEGORY_NAME_KEY[] = "trDisplayCategory"; static const char DISPLAY_NAME_KEY[] = "trDisplayName"; static const char ICON_KEY[] = "icon"; +static const char ICON_TEXT_KEY[] = "iconText"; static const char IMAGE_KEY[] = "image"; static const char DESCRIPTION_KEY[] = "trDescription"; static const char REQUIRED_FEATURES_KEY[] = "featuresRequired"; @@ -559,6 +560,10 @@ bool JsonWizardFactory::initialize(const QVariantMap &data, const QDir &baseDir, setIcon(QIcon(strVal)); } + strVal = data.value(QLatin1String(ICON_TEXT_KEY)).toString(); + if (!strVal.isEmpty()) + setIconText(strVal); + strVal = data.value(QLatin1String(IMAGE_KEY)).toString(); if (!strVal.isEmpty()) { strVal = baseDir.absoluteFilePath(strVal); diff --git a/src/plugins/pythoneditor/PythonEditor.json.in b/src/plugins/pythoneditor/PythonEditor.json.in index 5f3709887d..5416dbfa63 100644 --- a/src/plugins/pythoneditor/PythonEditor.json.in +++ b/src/plugins/pythoneditor/PythonEditor.json.in @@ -17,19 +17,19 @@ \"Url\" : \"http://www.qt.io\", $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\'?> - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> - <mime-type type=\'text/x-python-gui\'> - <sub-class-of type=\'text/x-python\'/> - <comment>Python source file without console</comment> - <glob pattern=\'*.pyw\'/> - </mime-type> - <mime-type type=\'text/x-python-project\'> - <sub-class-of type=\'text/x-python\'/> - <comment>Qt Creator Python project file</comment> - <glob pattern=\'*.pyqtc\'/> - </mime-type> - </mime-info> - \" + \"Mimetypes\" : [ + \"<?xml version=\'1.0\'?>\", + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", + \" <mime-type type=\'text/x-python-gui\'>\", + \" <sub-class-of type=\'text/x-python\'/>\", + \" <comment>Python source file without console</comment>\", + \" <glob pattern=\'*.pyw\'/>\", + \" </mime-type>\", + \" <mime-type type=\'text/x-python-project\'>\", + \" <sub-class-of type=\'text/x-python\'/>\", + \" <comment>Qt Creator Python project file</comment>\", + \" <glob pattern=\'*.pyqtc\'/>\", + \" </mime-type>\", + \"</mime-info>\" + ] } diff --git a/src/plugins/qmakeandroidsupport/qmakeandroidbuildapkstep.cpp b/src/plugins/qmakeandroidsupport/qmakeandroidbuildapkstep.cpp index ce087ff9df..4ca9ef9653 100644 --- a/src/plugins/qmakeandroidsupport/qmakeandroidbuildapkstep.cpp +++ b/src/plugins/qmakeandroidsupport/qmakeandroidbuildapkstep.cpp @@ -158,6 +158,13 @@ bool QmakeAndroidBuildApkStep::init(QList<const BuildStep *> &earlierSteps) return true; } + QString buildTargetSdk = AndroidManager::buildTargetSDK(target()); + if (buildTargetSdk.isEmpty()) { + emit addOutput(tr("Android build SDK not defined. Check Android settings."), + OutputFormat::Stderr); + return false; + } + QStringList arguments; arguments << QLatin1String("--input") << inputFile diff --git a/src/plugins/qmakeprojectmanager/QmakeProjectManager.json.in b/src/plugins/qmakeprojectmanager/QmakeProjectManager.json.in index ae3d11d8c0..6f4826ed55 100644 --- a/src/plugins/qmakeprojectmanager/QmakeProjectManager.json.in +++ b/src/plugins/qmakeprojectmanager/QmakeProjectManager.json.in @@ -17,39 +17,39 @@ \"Url\" : \"http://www.qt.io\", $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\'?> - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> - <mime-type type=\'application/vnd.qt.qmakeprofile\'> - <sub-class-of type=\'text/plain\'/> - <comment>Qt Project file</comment> - <glob pattern=\'*.pro\'/> - </mime-type> - <mime-type type=\'application/vnd.qt.qmakeproincludefile\'> - <sub-class-of type=\'text/plain\'/> - <comment>Qt Project include file</comment> - <glob pattern=\'*.pri\'/> - </mime-type> - <mime-type type=\'application/vnd.qt.qmakeprofeaturefile\'> - <sub-class-of type=\'text/plain\'/> - <comment>Qt Project feature file</comment> - <glob pattern=\'*.prf\'/> - </mime-type> - <mime-type type=\'application/vnd.qt.qmakeproconfigurationfile\'> - <sub-class-of type=\'text/plain\'/> - <comment>Qt Project configuration file</comment> - <glob pattern=\'.qmake.conf\'/> - </mime-type> - <mime-type type=\'application/vnd.qt.qmakeprocachefile\'> - <sub-class-of type=\'text/plain\'/> - <comment>Qt Project cache file</comment> - <glob pattern=\'.qmake.cache\'/> - </mime-type> - <mime-type type=\'application/vnd.qt.qmakeprostashfile\'> - <sub-class-of type=\'text/plain\'/> - <comment>Qt Project stash file</comment> - <glob pattern=\'.qmake.stash\'/> - </mime-type> - </mime-info> - \" + \"Mimetypes\" : [ + \"<?xml version=\'1.0\'?>\", + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", + \" <mime-type type=\'application/vnd.qt.qmakeprofile\'>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>Qt Project file</comment>\", + \" <glob pattern=\'*.pro\'/>\", + \" </mime-type>\", + \" <mime-type type=\'application/vnd.qt.qmakeproincludefile\'>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>Qt Project include file</comment>\", + \" <glob pattern=\'*.pri\'/>\", + \" </mime-type>\", + \" <mime-type type=\'application/vnd.qt.qmakeprofeaturefile\'>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>Qt Project feature file</comment>\", + \" <glob pattern=\'*.prf\'/>\", + \" </mime-type>\", + \" <mime-type type=\'application/vnd.qt.qmakeproconfigurationfile\'>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>Qt Project configuration file</comment>\", + \" <glob pattern=\'.qmake.conf\'/>\", + \" </mime-type>\", + \" <mime-type type=\'application/vnd.qt.qmakeprocachefile\'>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>Qt Project cache file</comment>\", + \" <glob pattern=\'.qmake.cache\'/>\", + \" </mime-type>\", + \" <mime-type type=\'application/vnd.qt.qmakeprostashfile\'>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>Qt Project stash file</comment>\", + \" <glob pattern=\'.qmake.stash\'/>\", + \" </mime-type>\", + \"</mime-info>\" + ] } diff --git a/src/plugins/qmldesigner/components/formeditor/movetool.cpp b/src/plugins/qmldesigner/components/formeditor/movetool.cpp index fba74d9b3c..5fb29ac88d 100644 --- a/src/plugins/qmldesigner/components/formeditor/movetool.cpp +++ b/src/plugins/qmldesigner/components/formeditor/movetool.cpp @@ -124,23 +124,26 @@ void MoveTool::mouseMoveEvent(const QList<QGraphicsItem*> &itemList, void MoveTool::hoverMoveEvent(const QList<QGraphicsItem*> &itemList, QGraphicsSceneMouseEvent * event) { - if (itemList.isEmpty()) { - view()->changeToSelectionTool(); - return; - } - ResizeHandleItem* resizeHandle = ResizeHandleItem::fromGraphicsItem(itemList.first()); if (resizeHandle) { view()->changeToResizeTool(); return; } + if (view()->hasSingleSelectedModelNode() && selectedItemCursorInMovableArea(event->scenePos())) + return; + + if (itemList.isEmpty()) { + view()->changeToSelectionTool(); + return; + } + if (!topSelectedItemIsMovable(itemList)) { view()->changeToSelectionTool(); return; } - if (view()->hasSingleSelectedModelNode() && !selectedItemCursorInMovableArea(event->scenePos())) { + if (view()->hasSingleSelectedModelNode()) { view()->changeToSelectionTool(); return; } diff --git a/src/plugins/qmldesigner/components/formeditor/resizehandleitem.cpp b/src/plugins/qmldesigner/components/formeditor/resizehandleitem.cpp index abdbd2d60b..d40e4067f9 100644 --- a/src/plugins/qmldesigner/components/formeditor/resizehandleitem.cpp +++ b/src/plugins/qmldesigner/components/formeditor/resizehandleitem.cpp @@ -50,7 +50,7 @@ void ResizeHandleItem::setHandlePosition(const QPointF & globalPosition, const Q QRectF ResizeHandleItem::boundingRect() const { - return QRectF(- 3., - 3., 7., 7.); + return QRectF(- 5., - 5., 9., 9.); } void ResizeHandleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /* option */, QWidget * /* widget */) diff --git a/src/plugins/qmldesigner/switchsplittabwidget.cpp b/src/plugins/qmldesigner/switchsplittabwidget.cpp index c9e5ec4993..8b36f0e7e3 100644 --- a/src/plugins/qmldesigner/switchsplittabwidget.cpp +++ b/src/plugins/qmldesigner/switchsplittabwidget.cpp @@ -81,7 +81,7 @@ SwitchSplitTabWidget::SwitchSplitTabWidget(QWidget *parent) QToolButton *horizontalButton = new QToolButton; horizontalButton->setObjectName("centralTabBar"); horizontalButton->setIcon(Utils::Icon({{QLatin1String(":/qmldesigner/images/spliteditorvertically.png"), - Utils::Theme::TextColorNormal}}, Utils::Icon::Tint).icon()); + Utils::Theme::IconsBaseColor}}).icon()); horizontalButton->setIconSize(QSize(8, 16)); connect(horizontalButton, &QToolButton::clicked, [this] () { m_splitter->setOrientation(Qt::Vertical); @@ -91,7 +91,7 @@ SwitchSplitTabWidget::SwitchSplitTabWidget(QWidget *parent) QToolButton *verticalButton = new QToolButton; verticalButton->setObjectName("centralTabBar"); verticalButton->setIcon(Utils::Icon({{QLatin1String(":/qmldesigner/images/spliteditorhorizontally.png"), - Utils::Theme::TextColorNormal}}, Utils::Icon::Tint).icon()); + Utils::Theme::IconsBaseColor}}).icon()); verticalButton->setIconSize(QSize(8, 16)); connect(verticalButton, &QToolButton::clicked, [this] () { m_splitter->setOrientation(Qt::Horizontal); diff --git a/src/plugins/qmljstools/QmlJSTools.json.in b/src/plugins/qmljstools/QmlJSTools.json.in index 1d50eae3c4..1861e87513 100644 --- a/src/plugins/qmljstools/QmlJSTools.json.in +++ b/src/plugins/qmljstools/QmlJSTools.json.in @@ -18,45 +18,45 @@ \"Url\" : \"http://www.qt.io\", $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\'?> - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> - <mime-type type=\'text/x-qml\'> - <alias type=\'application/x-qml\'/> - <!-- sub class is missing in the freedesktop.org definition --> - <sub-class-of type=\'text/plain\'/> - <comment>QML file</comment> - <glob pattern=\'*.qml\' weight=\'70\'/> - </mime-type> - <mime-type type=\'application/x-qt.qbs+qml\'> - <alias type=\'text/x-qt.qbs+qml\'/> - <sub-class-of type=\'text/x-qml\'/> - <comment>Qt Build Suite file</comment> - <glob pattern=\'*.qbs\' weight=\'70\'/> - </mime-type> - <mime-type type=\'application/x-qt.ui+qml\'> - <alias type=\'text/x-qt.ui+qml\'/> - <sub-class-of type=\'text/x-qml\'/> - <comment>QtQuick Designer ui file</comment> - <glob pattern=\'*.ui.qml\' weight=\'70\'/> - </mime-type> - <mime-type type=\'application/x-qmlproject\'> - <alias type=\'text/x-qmlproject\'/> - <sub-class-of type=\'text/x-qml\'/> - <comment>Qt Creator Qt UI project file</comment> - <glob pattern=\'*.qmlproject\' weight=\'70\'/> - </mime-type> - <mime-type type=\'application/x-qt.meta-info+qml\'> - <alias type=\'text/x-qt.meta-info+qml\'/> - <sub-class-of type=\'text/x-qml\'/> - <comment>QML file</comment> - <glob pattern=\'*.qmltypes\' weight=\'70\'/> - </mime-type> - <mime-type type=\'application/json\'> - <sub-class-of type=\'text/plain\'/> - <comment>JSON file</comment> - <glob pattern=\'*.json\' weight=\'70\'/> - </mime-type> - </mime-info> - \" + \"Mimetypes\" : [ + \"<?xml version=\'1.0\'?>\", + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", + \" <mime-type type=\'text/x-qml\'>\", + \" <alias type=\'application/x-qml\'/>\", + \" <!-- sub class is missing in the freedesktop.org definition -->\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>QML file</comment>\", + \" <glob pattern=\'*.qml\' weight=\'70\'/>\", + \" </mime-type>\", + \" <mime-type type=\'application/x-qt.qbs+qml\'>\", + \" <alias type=\'text/x-qt.qbs+qml\'/>\", + \" <sub-class-of type=\'text/x-qml\'/>\", + \" <comment>Qt Build Suite file</comment>\", + \" <glob pattern=\'*.qbs\' weight=\'70\'/>\", + \" </mime-type>\", + \" <mime-type type=\'application/x-qt.ui+qml\'>\", + \" <alias type=\'text/x-qt.ui+qml\'/>\", + \" <sub-class-of type=\'text/x-qml\'/>\", + \" <comment>QtQuick Designer ui file</comment>\", + \" <glob pattern=\'*.ui.qml\' weight=\'70\'/>\", + \" </mime-type>\", + \" <mime-type type=\'application/x-qmlproject\'>\", + \" <alias type=\'text/x-qmlproject\'/>\", + \" <sub-class-of type=\'text/x-qml\'/>\", + \" <comment>Qt Creator Qt UI project file</comment>\", + \" <glob pattern=\'*.qmlproject\' weight=\'70\'/>\", + \" </mime-type>\", + \" <mime-type type=\'application/x-qt.meta-info+qml\'>\", + \" <alias type=\'text/x-qt.meta-info+qml\'/>\", + \" <sub-class-of type=\'text/x-qml\'/>\", + \" <comment>QML file</comment>\", + \" <glob pattern=\'*.qmltypes\' weight=\'70\'/>\", + \" </mime-type>\", + \" <mime-type type=\'application/json\'>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>JSON file</comment>\", + \" <glob pattern=\'*.json\' weight=\'70\'/>\", + \" </mime-type>\", + \"</mime-info>\" + ] } diff --git a/src/plugins/qmlprojectmanager/QmlProjectManager.json.in b/src/plugins/qmlprojectmanager/QmlProjectManager.json.in index fcd607a228..329e4b603d 100644 --- a/src/plugins/qmlprojectmanager/QmlProjectManager.json.in +++ b/src/plugins/qmlprojectmanager/QmlProjectManager.json.in @@ -17,15 +17,15 @@ \"Url\" : \"http://www.qt.io\", $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\'?> + \"Mimetypes\" : [ + \"<?xml version=\'1.0\'?>\", - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> - <mime-type type=\'application/x-qmlproject\'> - <sub-class-of type=\'text/x-qml\'/> - <comment>QML Project file</comment> - <glob pattern=\'*.qmlproject\'/> - </mime-type> - </mime-info> - \" + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", + \" <mime-type type=\'application/x-qmlproject\'>\", + \" <sub-class-of type=\'text/x-qml\'/>\", + \" <comment>QML Project file</comment>\", + \" <glob pattern=\'*.qmlproject\'/>\", + \" </mime-type>\", + \"</mime-info>\" + ] } diff --git a/src/plugins/qtsupport/QtSupport.json.in b/src/plugins/qtsupport/QtSupport.json.in index b62bb1b29d..1447c9c14b 100644 --- a/src/plugins/qtsupport/QtSupport.json.in +++ b/src/plugins/qtsupport/QtSupport.json.in @@ -18,25 +18,25 @@ \"Url\" : \"http://www.qt.io\", $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\'?> - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> - <mime-type type=\'application/x-linguist-translation\'> - <comment>Linguist compiled translations</comment> - <glob pattern=\'*.qm\'/> - </mime-type> - <mime-type type=\'application/x-linguist\'> - <comment>Linguist source translations</comment> - <magic> - <match value=\'<TS\' type=\'string\' offset=\'0:256\'/> - </magic> - <glob pattern=\'*.ts\' weight=\'70\'/> - </mime-type> - <mime-type type=\'application/scxml+xml\'> - <comment>SCXML State Chart</comment> - <sub-class-of type=\'application/xml\'/> - <glob pattern=\'*.scxml\'/> - </mime-type> - </mime-info> - \" + \"Mimetypes\" : [ + \"<?xml version=\'1.0\'?>\", + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", + \" <mime-type type=\'application/x-linguist-translation\'>\", + \" <comment>Linguist compiled translations</comment>\", + \" <glob pattern=\'*.qm\'/>\", + \" </mime-type>\", + \" <mime-type type=\'application/x-linguist\'>\", + \" <comment>Linguist source translations</comment>\", + \" <magic>\", + \" <match value=\'<TS\' type=\'string\' offset=\'0:256\'/>\", + \" </magic>\", + \" <glob pattern=\'*.ts\' weight=\'70\'/>\", + \" </mime-type>\", + \" <mime-type type=\'application/scxml+xml\'>\", + \" <comment>SCXML State Chart</comment>\", + \" <sub-class-of type=\'application/xml\'/>\", + \" <glob pattern=\'*.scxml\'/>\", + \" </mime-type>\", + \"</mime-info>\" + ] } diff --git a/src/plugins/qtsupport/images/icons/videotutorialicon.png b/src/plugins/qtsupport/images/icons/videotutorialicon.png Binary files differnew file mode 100644 index 0000000000..71b5a91cf2 --- /dev/null +++ b/src/plugins/qtsupport/images/icons/videotutorialicon.png diff --git a/src/plugins/qtsupport/qtcreator_tutorials.xml b/src/plugins/qtsupport/qtcreator_tutorials.xml index fb0be7dd3f..003ee88755 100644 --- a/src/plugins/qtsupport/qtcreator_tutorials.xml +++ b/src/plugins/qtsupport/qtcreator_tutorials.xml @@ -25,6 +25,33 @@ <description><![CDATA[Developing Qt Quick applications using QML and C++.]]></description> <tags>qt quick,qml,c++</tags> </tutorial> + + <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Digital Instrument Cluster with Qt Quick Designer and Qt Safe Renderer" isVideo="true" videoUrl="https://www.youtube.com/watch?v=9RxxsOCeZHk" videoLength="4:06"> + <description><![CDATA[Creating a digital instrument cluster with Qt Quick Designer and Qt Safe Renderer.]]></description> + <tags>qt creator,qt quick,automotive,safe renderer,controls</tags> + </tutorial> + <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Qt for Device Creation" isVideo="true" videoUrl="https://www.youtube.com/watch?v=PercN_GtVJA" videoLength="3:01"> + <description><![CDATA[Creating a Qt widget based application.]]></description> + <tags>qt creator,embedded,device creation</tags> + </tutorial> + + <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Qt Quick Designer - The Coffee Machine" isVideo="true" videoUrl="https://www.youtube.com/watch?v=Ko3YPM_tStM" videoLength="3:06"> + <description><![CDATA[Creating a UI for embedded devices.]]></description> + <tags>qt creator,qt quick,embedded</tags> + </tutorial> + + <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Getting started with Qt: Hello Widget World " isVideo="true" videoUrl="https://www.youtube.com/watch?v=TIUTO8GjSGo" videoLength="9:10"> + <description><![CDATA[Creating a Qt widget based application.]]></description> + <tags>qt creator,widgets</tags> + </tutorial> + <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Getting started with Qt: Hello Quick World" isVideo="true" videoUrl="https://www.youtube.com/watch?v=nepoVgVvWEI" videoLength="13:28"> + <description><![CDATA[Creating a Qt Quick application.]]></description> + <tags>qt creator,qt quick</tags> + </tutorial> + <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Qt SCXML and State Machine Tooling in Qt Creator" isVideo="true" videoUrl="https://youtu.be/9xqhq9nDiOg" videoLength="4:53"> + <description><![CDATA[Creating state machines.]]></description> + <tags>qt creator,SCXML</tags> + </tutorial> <tutorial imageUrl=":qtsupport/images/icons/worldsummit15.png" difficulty="" projectPath="" name="Introduction to Qt Creator" isVideo="true" videoUrl="https://www.youtube.com/watch?v=nGFmjOiT22Y" videoLength="50:36"> <description><![CDATA[Getting started with using Qt Creator for cross-platform development.]]></description> <tags>qt creator</tags> @@ -47,7 +74,7 @@ </tutorial> <tutorial imageUrl=":qtsupport/images/icons/worldsummit15.png" difficulty="" projectPath="" name="CPU Usage Analyzer for Device Creation" isVideo="true" videoUrl="https://www.youtube.com/watch?v=G0AbgVHGdXI" videoLength="22:30"> <description><![CDATA[Using the Linux perf tool to generate data for code analysis.]]></description> - <tags>qt creator,cpu usage analyzer,perf</tags> + <tags>qt creator,cpu usage analyzer,perf,embedded,device creation</tags> </tutorial> <tutorial imageUrl=":qtsupport/images/icons/worldsummit16.png" difficulty="" projectPath="" name="Qt SCXML: State Machines Made Easier" isVideo="true" videoUrl="https://youtu.be/X0kEkB0ewyw" videoLength="42:22"> <description><![CDATA[Using the Qt SCXML module and Qt Creator SCXML editor.]]></description> @@ -77,14 +104,7 @@ <description><![CDATA[Qt support for Universal Windows Platform on desktop, mobile, and embedded devices.]]></description> <tags>windows</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Qt SCXML and State Machine Tooling in Qt Creator" isVideo="true" videoUrl="https://youtu.be/9xqhq9nDiOg" videoLength="4:53"> - <description><![CDATA[Creating state machines.]]></description> - <tags>qt creator,SCXML</tags> - </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/worldsummit15.png" difficulty="" projectPath="" name="Qt for Device Creation" isVideo="true" videoUrl="https://www.youtube.com/watch?v=nRf1e-AYk0o" videoLength="57:45"> - <description><![CDATA[Creating your own embedded devices that run Qt applications.]]></description> - <tags>qt,embedded,device creation</tags> - </tutorial> + <tutorial imageUrl=":qtsupport/images/icons/worldsummit16.png" difficulty="" projectPath="" name="Developing UIs with Qt Quick Controls 2" isVideo="true" videoUrl="https://youtu.be/ozpSl7WbVt4" videoLength="23:13"> <description><![CDATA[Using Qt Quick Controls 2 to create UIs.]]></description> <tags>qt quick designer,controls</tags> @@ -97,10 +117,6 @@ <description><![CDATA[Running Qt apps on Android Wear devices.]]></description> <tags>qt creator,android</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/worldsummit15.png" difficulty="" projectPath="" name="Effective QML" isVideo="true" videoUrl="https://www.youtube.com/watch?v=vzs5VPTf4QQ" videoLength="55:25"> - <description><![CDATA[Improving your QML code by using tools and by understanding the QML system.]]></description> - <tags>qml,qml profiler</tags> - </tutorial> <tutorial imageUrl=":qtsupport/images/icons/worldsummit16.png" difficulty="" projectPath="" name="Qt on macOS Updates" isVideo="true" videoUrl="https://youtu.be/qfyxXxeC73Y" videoLength="25:51"> <description><![CDATA[Using Qt with macOS native windows.]]></description> <tags>macos</tags> @@ -113,10 +129,6 @@ <description><![CDATA[Using the Qt WebEngine module.]]></description> <tags>qt webengine</tags> </tutorial> - <tutorial imageUrl=":qtsupport/images/icons/worldsummit16.png" difficulty="" projectPath="" name="Qt Automotive Suite" isVideo="true" videoUrl="https://youtu.be/Ohzr1reeGDM" videoLength="26:15"> - <description><![CDATA[Overview of the future of Qt in automotive.]]></description> - <tags>automotive</tags> - </tutorial> <tutorial imageUrl=":qtsupport/images/icons/worldsummit16.png" difficulty="" projectPath="" name="Developing for Multiple Screen Resolutions and Platforms" isVideo="true" videoUrl="https://youtu.be/qclquZ99ZVQ" videoLength="27:44"> <description><![CDATA[Best practices for an efficient app lifecycle.]]></description> <tags>qt,qt quick,screen resolution</tags> diff --git a/src/plugins/qtsupport/qtsupport.qrc b/src/plugins/qtsupport/qtsupport.qrc index ff9d929b61..50d90e55d8 100644 --- a/src/plugins/qtsupport/qtsupport.qrc +++ b/src/plugins/qtsupport/qtsupport.qrc @@ -15,5 +15,6 @@ <file>images/icons/tutorialicon.png</file> <file>images/icons/worldsummit15.png</file> <file>images/icons/worldsummit16.png</file> + <file>images/icons/videotutorialicon.png</file> </qresource> </RCC> diff --git a/src/plugins/resourceeditor/ResourceEditor.json.in b/src/plugins/resourceeditor/ResourceEditor.json.in index 6bf2776a0c..dc0a5c8822 100644 --- a/src/plugins/resourceeditor/ResourceEditor.json.in +++ b/src/plugins/resourceeditor/ResourceEditor.json.in @@ -17,14 +17,14 @@ \"Url\" : \"http://www.qt.io\", $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\'?> - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> - <mime-type type=\'application/vnd.qt.xml.resource\'> - <sub-class-of type=\'text/xml\'/> - <comment>Qt Resource file</comment> - <glob pattern=\'*.qrc\'/> - </mime-type> - </mime-info> - \" + \"Mimetypes\" : [ + \"<?xml version=\'1.0\'?>\", + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", + \" <mime-type type=\'application/vnd.qt.xml.resource\'>\", + \" <sub-class-of type=\'text/xml\'/>\", + \" <comment>Qt Resource file</comment>\", + \" <glob pattern=\'*.qrc\'/>\", + \" </mime-type>\", + \"</mime-info>\" + ] } diff --git a/src/plugins/scxmleditor/ScxmlEditor.json.in b/src/plugins/scxmleditor/ScxmlEditor.json.in index 1e48677f5f..1218f4129b 100644 --- a/src/plugins/scxmleditor/ScxmlEditor.json.in +++ b/src/plugins/scxmleditor/ScxmlEditor.json.in @@ -18,14 +18,14 @@ \"Experimental\" : true, $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\'?> - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> - <mime-type type=\'application/scxml+xml\'> - <sub-class-of type=\'text/xml\'/> - <comment>SCXML file</comment> - <glob pattern=\'*.scxml\'/> - </mime-type> - </mime-info> - \" + \"Mimetypes\" : [ + \"<?xml version=\'1.0\'?>\", + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", + \" <mime-type type=\'application/scxml+xml\'>\", + \" <sub-class-of type=\'text/xml\'/>\", + \" <comment>SCXML file</comment>\", + \" <glob pattern=\'*.scxml\'/>\", + \" </mime-type>\", + \"</mime-info>\" + ] } diff --git a/src/plugins/subversion/Subversion.json.in b/src/plugins/subversion/Subversion.json.in index a31c9dd38b..8196061d64 100644 --- a/src/plugins/subversion/Subversion.json.in +++ b/src/plugins/subversion/Subversion.json.in @@ -17,13 +17,13 @@ \"Url\" : \"http://www.qt.io\", $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\'?> - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> - <mime-type type=\'text/vnd.qtcreator.svn.submit\'> - <comment>Subversion submit template</comment> - <sub-class-of type=\'text/plain\'/> - </mime-type> - </mime-info> - \" + \"Mimetypes\" : [ + \"<?xml version=\'1.0\'?>\", + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", + \" <mime-type type=\'text/vnd.qtcreator.svn.submit\'>\", + \" <comment>Subversion submit template</comment>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" </mime-type>\", + \"</mime-info>\" + ] } diff --git a/src/plugins/tasklist/TaskList.json.in b/src/plugins/tasklist/TaskList.json.in index 202bf41b2a..7c1f6f4ee2 100644 --- a/src/plugins/tasklist/TaskList.json.in +++ b/src/plugins/tasklist/TaskList.json.in @@ -16,15 +16,15 @@ \"Url\" : \"http://www.qt.io\", $$dependencyList, - \"Mimetypes\" : \" - <?xml version=\'1.0\' encoding=\'UTF-8\'?> - <mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'> - <mime-type type=\'text/x-tasklist\'> - <sub-class-of type=\'text/plain\'/> - <comment>Qt Creator task list file</comment> - <glob pattern=\'*.tasks\'/> - <glob pattern=\'*.tasks.txt\'/> - </mime-type> - </mime-info> - \" + \"Mimetypes\" : [ + \"<?xml version=\'1.0\' encoding=\'UTF-8\'?>\", + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", + \" <mime-type type=\'text/x-tasklist\'>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>Qt Creator task list file</comment>\", + \" <glob pattern=\'*.tasks\'/>\", + \" <glob pattern=\'*.tasks.txt\'/>\", + \" </mime-type>\", + \"</mime-info>\" + ] } diff --git a/src/plugins/texteditor/autocompleter.cpp b/src/plugins/texteditor/autocompleter.cpp index 8ac7bbb6b3..08ce56bd48 100644 --- a/src/plugins/texteditor/autocompleter.cpp +++ b/src/plugins/texteditor/autocompleter.cpp @@ -150,6 +150,24 @@ bool AutoCompleter::isQuote(const QString &text) return text == QLatin1String("\"") || text == QLatin1String("'"); } +bool AutoCompleter::isNextBlockIndented(const QTextBlock ¤tBlock) const +{ + QTextBlock block = currentBlock; + int indentation = m_tabSettings.indentationColumn(block.text()); + + if (block.next().isValid()) { // not the last block + block = block.next(); + //skip all empty blocks + while (block.isValid() && m_tabSettings.onlySpace(block.text())) + block = block.next(); + if (block.isValid() + && m_tabSettings.indentationColumn(block.text()) > indentation) + return true; + } + + return false; +} + QString AutoCompleter::replaceSelection(QTextCursor &cursor, const QString &textToInsert) const { if (!cursor.hasSelection()) @@ -301,17 +319,8 @@ int AutoCompleter::paragraphSeparatorAboutToBeInserted(QTextCursor &cursor) if (condition) {| statement; */ - int indentation = m_tabSettings.indentationColumn(block.text()); - - if (block.next().isValid()) { // not the last block - block = block.next(); - //skip all empty blocks - while (block.isValid() && m_tabSettings.onlySpace(block.text())) - block = block.next(); - if (block.isValid() - && m_tabSettings.indentationColumn(block.text()) > indentation) - return 0; - } + if (isNextBlockIndented(block)) + return 0; const QString &textToInsert = insertParagraphSeparator(cursor); int pos = cursor.position(); diff --git a/src/plugins/texteditor/autocompleter.h b/src/plugins/texteditor/autocompleter.h index 5d12b63b83..4847f50476 100644 --- a/src/plugins/texteditor/autocompleter.h +++ b/src/plugins/texteditor/autocompleter.h @@ -31,6 +31,7 @@ #include <QString> QT_BEGIN_NAMESPACE +class QTextBlock; class QTextCursor; QT_END_NAMESPACE @@ -90,6 +91,7 @@ public: virtual QString insertParagraphSeparator(const QTextCursor &cursor) const; static bool isQuote(const QString &text); + bool isNextBlockIndented(const QTextBlock ¤tBlock) const; private: QString replaceSelection(QTextCursor &cursor, const QString &textToInsert) const; diff --git a/src/plugins/texteditor/displaysettings.cpp b/src/plugins/texteditor/displaysettings.cpp index 196b9434c2..3d2eb5c084 100644 --- a/src/plugins/texteditor/displaysettings.cpp +++ b/src/plugins/texteditor/displaysettings.cpp @@ -45,6 +45,8 @@ static const char scrollBarHighlightsKey[] = "ScrollBarHighlights"; static const char animateNavigationWithinFileKey[] = "AnimateNavigationWithinFile"; static const char animateWithinFileTimeMaxKey[] = "AnimateWithinFileTimeMax"; static const char displayAnnotationsKey[] = "DisplayAnnotations"; +static const char annotationAlignmentKey[] = "AnnotationAlignment"; +static const char minimalAnnotationContentKey[] = "MinimalAnnotationContent"; static const char groupPostfix[] = "DisplaySettings"; namespace TextEditor { @@ -71,6 +73,7 @@ void DisplaySettings::toSettings(const QString &category, QSettings *s) const s->setValue(QLatin1String(scrollBarHighlightsKey), m_scrollBarHighlights); s->setValue(QLatin1String(animateNavigationWithinFileKey), m_animateNavigationWithinFile); s->setValue(QLatin1String(displayAnnotationsKey), m_displayAnnotations); + s->setValue(QLatin1String(annotationAlignmentKey), static_cast<int>(m_annotationAlignment)); s->endGroup(); } @@ -100,6 +103,10 @@ void DisplaySettings::fromSettings(const QString &category, const QSettings *s) m_animateNavigationWithinFile = s->value(group + QLatin1String(animateNavigationWithinFileKey), m_animateNavigationWithinFile).toBool(); m_animateWithinFileTimeMax = s->value(group + QLatin1String(animateWithinFileTimeMaxKey), m_animateWithinFileTimeMax).toInt(); m_displayAnnotations = s->value(group + QLatin1String(displayAnnotationsKey), m_displayAnnotations).toBool(); + m_annotationAlignment = static_cast<TextEditor::AnnotationAlignment>( + s->value(group + QLatin1String(annotationAlignmentKey), + static_cast<int>(m_annotationAlignment)).toInt()); + m_minimalAnnotationContent = s->value(group + QLatin1String(minimalAnnotationContentKey), m_minimalAnnotationContent).toInt(); } bool DisplaySettings::equals(const DisplaySettings &ds) const @@ -122,6 +129,8 @@ bool DisplaySettings::equals(const DisplaySettings &ds) const && m_animateNavigationWithinFile == ds.m_animateNavigationWithinFile && m_animateWithinFileTimeMax == ds.m_animateWithinFileTimeMax && m_displayAnnotations == ds.m_displayAnnotations + && m_annotationAlignment == ds.m_annotationAlignment + && m_minimalAnnotationContent == ds.m_minimalAnnotationContent ; } diff --git a/src/plugins/texteditor/displaysettings.h b/src/plugins/texteditor/displaysettings.h index a37343bb48..326f9aad06 100644 --- a/src/plugins/texteditor/displaysettings.h +++ b/src/plugins/texteditor/displaysettings.h @@ -27,12 +27,21 @@ #include "texteditor_global.h" +#include "QMetaType" + QT_BEGIN_NAMESPACE class QSettings; QT_END_NAMESPACE namespace TextEditor { +enum class AnnotationAlignment +{ + NextToContent, + NextToMargin, + RightSide +}; + class TEXTEDITOR_EXPORT DisplaySettings { public: @@ -59,6 +68,8 @@ public: bool m_animateNavigationWithinFile = false; int m_animateWithinFileTimeMax = 333; // read only setting bool m_displayAnnotations = true; + AnnotationAlignment m_annotationAlignment = AnnotationAlignment::RightSide; + int m_minimalAnnotationContent = 15; bool equals(const DisplaySettings &ds) const; }; @@ -67,3 +78,5 @@ inline bool operator==(const DisplaySettings &t1, const DisplaySettings &t2) { r inline bool operator!=(const DisplaySettings &t1, const DisplaySettings &t2) { return !t1.equals(t2); } } // namespace TextEditor + +Q_DECLARE_METATYPE(TextEditor::AnnotationAlignment) diff --git a/src/plugins/texteditor/displaysettingspage.cpp b/src/plugins/texteditor/displaysettingspage.cpp index 7ae27e11d7..2289ba2135 100644 --- a/src/plugins/texteditor/displaysettingspage.cpp +++ b/src/plugins/texteditor/displaysettingspage.cpp @@ -120,6 +120,12 @@ void DisplaySettingsPage::settingsFromUI(DisplaySettings &displaySettings, displaySettings.m_scrollBarHighlights = d->m_page->scrollBarHighlights->isChecked(); displaySettings.m_animateNavigationWithinFile = d->m_page->animateNavigationWithinFile->isChecked(); displaySettings.m_displayAnnotations = d->m_page->displayAnnotations->isChecked(); + if (d->m_page->leftAligned->isChecked()) + displaySettings.m_annotationAlignment = AnnotationAlignment::NextToContent; + else if (d->m_page->atMargin->isChecked()) + displaySettings.m_annotationAlignment = AnnotationAlignment::NextToMargin; + else if (d->m_page->rightAligned->isChecked()) + displaySettings.m_annotationAlignment = AnnotationAlignment::RightSide; } void DisplaySettingsPage::settingsToUI() @@ -144,6 +150,11 @@ void DisplaySettingsPage::settingsToUI() d->m_page->scrollBarHighlights->setChecked(displaySettings.m_scrollBarHighlights); d->m_page->animateNavigationWithinFile->setChecked(displaySettings.m_animateNavigationWithinFile); d->m_page->displayAnnotations->setChecked(displaySettings.m_displayAnnotations); + switch (displaySettings.m_annotationAlignment) { + case AnnotationAlignment::NextToContent: d->m_page->leftAligned->setChecked(true); break; + case AnnotationAlignment::NextToMargin: d->m_page->atMargin->setChecked(true); break; + case AnnotationAlignment::RightSide: d->m_page->rightAligned->setChecked(true); break; + } } const DisplaySettings &DisplaySettingsPage::displaySettings() const diff --git a/src/plugins/texteditor/displaysettingspage.ui b/src/plugins/texteditor/displaysettingspage.ui index 1663840272..aa8dd2cd44 100644 --- a/src/plugins/texteditor/displaysettingspage.ui +++ b/src/plugins/texteditor/displaysettingspage.ui @@ -6,11 +6,24 @@ <rect> <x>0</x> <y>0</y> - <width>501</width> - <height>339</height> + <width>452</width> + <height>458</height> </rect> </property> <layout class="QGridLayout" name="gridLayout_3"> + <item row="3" column="0"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>8</height> + </size> + </property> + </spacer> + </item> <item row="0" column="0"> <widget class="QGroupBox" name="groupBoxText"> <property name="title"> @@ -61,43 +74,30 @@ </layout> </widget> </item> - <item row="2" column="0"> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>8</height> - </size> - </property> - </spacer> - </item> <item row="1" column="0"> <widget class="QGroupBox" name="groupBoxDisplay"> <property name="title"> <string>Display</string> </property> <layout class="QGridLayout" name="gridLayout_2"> - <item row="4" column="1"> - <widget class="QCheckBox" name="highlightMatchingParentheses"> + <item row="6" column="1"> + <widget class="QCheckBox" name="displayFileEncoding"> <property name="text"> - <string>&Highlight matching parentheses</string> + <string>Display file encoding</string> </property> </widget> </item> - <item row="1" column="1"> - <widget class="QCheckBox" name="highlightBlocks"> + <item row="2" column="1"> + <widget class="QCheckBox" name="animateMatchingParentheses"> <property name="text"> - <string>Highlight &blocks</string> + <string>&Animate matching parentheses</string> </property> </widget> </item> - <item row="0" column="1"> - <widget class="QCheckBox" name="highlightCurrentLine"> + <item row="5" column="0"> + <widget class="QCheckBox" name="centerOnScroll"> <property name="text"> - <string>Highlight current &line</string> + <string>Center &cursor on scroll</string> </property> </widget> </item> @@ -108,17 +108,10 @@ </property> </widget> </item> - <item row="6" column="0"> - <widget class="QCheckBox" name="autoFoldFirstComment"> - <property name="text"> - <string>Auto-fold first &comment</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QCheckBox" name="animateMatchingParentheses"> + <item row="4" column="1"> + <widget class="QCheckBox" name="highlightMatchingParentheses"> <property name="text"> - <string>&Animate matching parentheses</string> + <string>&Highlight matching parentheses</string> </property> </widget> </item> @@ -129,27 +122,34 @@ </property> </widget> </item> - <item row="6" column="1"> - <widget class="QCheckBox" name="displayFileEncoding"> + <item row="4" column="0"> + <widget class="QCheckBox" name="visualizeWhitespace"> + <property name="toolTip"> + <string>Shows tabs and spaces.</string> + </property> <property name="text"> - <string>Display file encoding</string> + <string>&Visualize whitespace</string> </property> </widget> </item> - <item row="5" column="0"> - <widget class="QCheckBox" name="centerOnScroll"> + <item row="0" column="1"> + <widget class="QCheckBox" name="highlightCurrentLine"> <property name="text"> - <string>Center &cursor on scroll</string> + <string>Highlight current &line</string> </property> </widget> </item> - <item row="4" column="0"> - <widget class="QCheckBox" name="visualizeWhitespace"> - <property name="toolTip"> - <string>Shows tabs and spaces.</string> + <item row="6" column="0"> + <widget class="QCheckBox" name="autoFoldFirstComment"> + <property name="text"> + <string>Auto-fold first &comment</string> </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QCheckBox" name="highlightBlocks"> <property name="text"> - <string>&Visualize whitespace</string> + <string>Highlight &blocks</string> </property> </widget> </item> @@ -181,10 +181,39 @@ </property> </widget> </item> - <item row="8" column="0"> - <widget class="QCheckBox" name="displayAnnotations"> + </layout> + </widget> + </item> + <item row="2" column="0"> + <widget class="QGroupBox" name="displayAnnotations"> + <property name="title"> + <string>Annotations next to lines</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QRadioButton" name="leftAligned"> + <property name="text"> + <string>Next to editor content</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="atMargin"> + <property name="text"> + <string>Next to right margin</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="rightAligned"> <property name="text"> - <string>Display annotations behind lines</string> + <string>Aligned at right side</string> + </property> + <property name="checked"> + <bool>true</bool> </property> </widget> </item> @@ -204,7 +233,6 @@ <tabstop>centerOnScroll</tabstop> <tabstop>autoFoldFirstComment</tabstop> <tabstop>scrollBarHighlights</tabstop> - <tabstop>displayAnnotations</tabstop> <tabstop>highlightCurrentLine</tabstop> <tabstop>highlightBlocks</tabstop> <tabstop>animateMatchingParentheses</tabstop> diff --git a/src/plugins/texteditor/generichighlighter/highlighter.cpp b/src/plugins/texteditor/generichighlighter/highlighter.cpp index 418d58de89..b2a12fb02f 100644 --- a/src/plugins/texteditor/generichighlighter/highlighter.cpp +++ b/src/plugins/texteditor/generichighlighter/highlighter.cpp @@ -109,6 +109,11 @@ static TextStyle styleForFormat(int format) case Highlighter::Others: return C_TEXT; case Highlighter::Identifier: return C_LOCAL; case Highlighter::Documentation: return C_DOXYGEN_COMMENT; + case Highlighter::ControlFlow: return C_KEYWORD; + case Highlighter::Preprocessor: return C_PREPROCESSOR; + case Highlighter::VerbatimString: return C_STRING; + case Highlighter::SpecialString: return C_STRING; + case Highlighter::Constant: return C_KEYWORD; case Highlighter::TextFormatIdCount: QTC_CHECK(false); // should never get here return C_TEXT; @@ -168,6 +173,11 @@ KateFormatMap::KateFormatMap() m_ids.insert(QLatin1String("dsOthers"), Highlighter::Others); m_ids.insert(QLatin1String("dsIdentifier"), Highlighter::Identifier); m_ids.insert(QLatin1String("dsDocumentation"), Highlighter::Documentation); + m_ids.insert(QLatin1String("dsControlFlow"), Highlighter::ControlFlow); + m_ids.insert(QLatin1String("dsPreprocessor"), Highlighter::Preprocessor); + m_ids.insert(QLatin1String("dsVerbatimString"), Highlighter::VerbatimString); + m_ids.insert(QLatin1String("dsSpecialString"), Highlighter::SpecialString); + m_ids.insert(QLatin1String("dsConstant"), Highlighter::Constant); } Q_GLOBAL_STATIC(KateFormatMap, kateFormatMap) diff --git a/src/plugins/texteditor/generichighlighter/highlighter.h b/src/plugins/texteditor/generichighlighter/highlighter.h index 0baa0c03ad..4c69d9977b 100644 --- a/src/plugins/texteditor/generichighlighter/highlighter.h +++ b/src/plugins/texteditor/generichighlighter/highlighter.h @@ -91,6 +91,11 @@ public: Others, Identifier, Documentation, + ControlFlow, + Preprocessor, + VerbatimString, + SpecialString, + Constant, TextFormatIdCount }; diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index afb0284672..c7554dd677 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -393,7 +393,7 @@ public: bool expanded, bool active, bool hovered) const; - void drawLineAnnotation(QPainter &painter, const QTextBlock &block); + void drawLineAnnotation(QPainter &painter, const QTextBlock &block, qreal start); void toggleBlockVisible(const QTextBlock &block); QRect foldBox(); @@ -484,6 +484,7 @@ public: Id m_tabSettingsId; ICodeStylePreferences *m_codeStylePreferences = nullptr; DisplaySettings m_displaySettings; + bool m_annotationsrRight = true; MarginSettings m_marginSettings; // apply when making visible the first time, for the split case bool m_fontSettingsNeedsApply = true; @@ -506,6 +507,7 @@ public: const TextMark *mark; }; QMap<int, QList<AnnotationRect>> m_annotationRects; + QRectF getLastLineLineRect(const QTextBlock &block); RefactorOverlay *m_refactorOverlay = nullptr; QString m_contextHelpId; @@ -3788,7 +3790,41 @@ static QTextLayout::FormatRange createBlockCursorCharFormatRange(int pos, const return o; } -void TextEditorWidgetPrivate::drawLineAnnotation(QPainter &painter, const QTextBlock &block) +static TextMarks availableMarks(const TextMarks &marks, + QRectF &boundingRect, + const QFontMetrics &fm, + const qreal itemOffset) +{ + TextMarks ret; + bool first = true; + for (TextMark *mark : marks) { + const TextMark::AnnotationRects &rects = mark->annotationRects( + boundingRect, fm, first ? 0 : itemOffset, 0); + if (rects.annotationRect.isEmpty()) + break; + boundingRect.setLeft(rects.fadeOutRect.right()); + ret.append(mark); + if (boundingRect.isEmpty()) + break; + first = false; + } + return ret; +} + +QRectF TextEditorWidgetPrivate::getLastLineLineRect(const QTextBlock &block) +{ + const QTextLayout *layout = block.layout(); + const int lineCount = layout->lineCount(); + if (lineCount < 1) + return QRectF(); + const QTextLine line = layout->lineAt(lineCount - 1); + const QPointF contentOffset = q->contentOffset(); + const qreal top = q->blockBoundingGeometry(block).translated(contentOffset).top(); + return line.naturalTextRect().translated(contentOffset.x(), top).adjusted(0, 0, -1, -1); +} + +void TextEditorWidgetPrivate::drawLineAnnotation( + QPainter &painter, const QTextBlock &block, qreal rightMargin) { if (!m_displaySettings.m_displayAnnotations) return; @@ -3801,30 +3837,44 @@ void TextEditorWidgetPrivate::drawLineAnnotation(QPainter &painter, const QTextB if (marks.isEmpty()) return; - const QTextLayout *layout = block.layout(); - const int lineCount = layout->lineCount(); - if (lineCount < 1) + const QRectF lineRect = getLastLineLineRect(block); + if (lineRect.isNull()) return; - const QTextLine line = layout->lineAt(lineCount - 1); - const QPointF contentOffset = q->contentOffset(); - const qreal top = q->blockBoundingGeometry(block).translated(contentOffset).top(); - const QRectF lineRect = - line.naturalTextRect().translated(contentOffset.x(), top).adjusted(0, 0, -1, -1); Utils::sort(marks, [](const TextMark* mark1, const TextMark* mark2){ return mark1->priority() > mark2->priority(); }); const qreal itemOffset = q->fontMetrics().lineSpacing(); - qreal x = lineRect.right() + itemOffset * 2; + const qreal initialOffset = itemOffset * 2; + const qreal minimalContentWidth = q->fontMetrics().width('X') + * m_displaySettings.m_minimalAnnotationContent; + QRectF boundingRect(lineRect.topLeft().x(), lineRect.topLeft().y(), + q->viewport()->width() - lineRect.right(), lineRect.height()); + qreal offset = initialOffset; + if (marks.isEmpty()) + return; + if (m_displaySettings.m_annotationAlignment == AnnotationAlignment::NextToMargin + && rightMargin > lineRect.right() + offset + && q->viewport()->width() > rightMargin + minimalContentWidth) { + offset = rightMargin - lineRect.right(); + } else if (m_displaySettings.m_annotationAlignment != AnnotationAlignment::NextToContent) { + marks = availableMarks(marks, boundingRect, q->fontMetrics(), itemOffset); + if (boundingRect.width() > 0) + offset = qMax(boundingRect.width(), initialOffset); + } + qreal x = lineRect.right(); for (const TextMark *mark : marks) { - QRectF annotationRect(x, lineRect.top(), q->viewport()->width() - x, lineRect.height()); - if (annotationRect.width() <= 0) + boundingRect = QRectF(x, lineRect.top(), q->viewport()->width() - x, lineRect.height()); + if (boundingRect.isEmpty()) break; - mark->paintAnnotation(&painter, &annotationRect); - x += annotationRect.width() + itemOffset; - m_annotationRects[block.blockNumber()].append({annotationRect, mark}); + + // paint annotation + mark->paintAnnotation(painter, &boundingRect, offset, itemOffset / 2); + x = boundingRect.right(); + offset = itemOffset / 2; + m_annotationRects[block.blockNumber()].append({boundingRect, mark}); } } @@ -4469,7 +4519,7 @@ void TextEditorWidget::paintEvent(QPaintEvent *e) painter.restore(); } } - d->drawLineAnnotation(painter, block); + d->drawLineAnnotation(painter, block, lineX < viewportRect.width() ? lineX : 0); block = nextVisibleBlock; top = bottom; @@ -5289,6 +5339,11 @@ void TextEditorWidget::showDefaultContextMenu(QContextMenuEvent *e, Id menuConte menu.exec(e->globalPos()); } +void TextEditorWidget::addHoverHandler(BaseHoverHandler *handler) +{ + d->m_hoverHandlers.append(handler); +} + void TextEditorWidget::extraAreaLeaveEvent(QEvent *) { d->extraAreaPreviousMarkTooltipRequestedLine = -1; diff --git a/src/plugins/texteditor/texteditor.h b/src/plugins/texteditor/texteditor.h index 0c2e83e1e8..f6fb864404 100644 --- a/src/plugins/texteditor/texteditor.h +++ b/src/plugins/texteditor/texteditor.h @@ -512,6 +512,8 @@ protected: virtual void finalizeInitializationAfterDuplication(TextEditorWidget *) {} static QTextCursor flippedCursor(const QTextCursor &cursor); + void addHoverHandler(BaseHoverHandler *handler); + public: struct Link { diff --git a/src/plugins/texteditor/textmark.cpp b/src/plugins/texteditor/textmark.cpp index b2859642c6..d4f9db7c50 100644 --- a/src/plugins/texteditor/textmark.cpp +++ b/src/plugins/texteditor/textmark.cpp @@ -121,43 +121,58 @@ void TextMark::paintIcon(QPainter *painter, const QRect &rect) const m_icon.paint(painter, rect, Qt::AlignCenter); } -void TextMark::paintAnnotation(QPainter *painter, QRectF *annotationRect) const +void TextMark::paintAnnotation(QPainter &painter, QRectF *annotationRect, + const qreal fadeInOffset, const qreal fadeOutOffset) const { QString text = lineAnnotation(); if (text.isEmpty()) return; - const AnnotationRects &rects = annotationRects(*annotationRect, painter->fontMetrics()); - - const QColor markColor = m_hasColor ? Utils::creatorTheme()->color(m_color).toHsl() - : painter->pen().color(); - const AnnotationColors &colors = - AnnotationColors::getAnnotationColors(markColor, painter->background().color()); - - painter->save(); - painter->setPen(colors.rectColor); - painter->setBrush(colors.rectColor); - painter->drawRect(rects.annotationRect); - painter->setPen(colors.textColor); - paintIcon(painter, rects.iconRect.toAlignedRect()); - painter->drawText(rects.textRect, Qt::AlignLeft, rects.text); - painter->restore(); - *annotationRect = rects.annotationRect; + const AnnotationRects &rects = annotationRects(*annotationRect, painter.fontMetrics(), + fadeInOffset, fadeOutOffset); + const QColor &markColor = m_hasColor ? Utils::creatorTheme()->color(m_color).toHsl() + : painter.pen().color(); + const AnnotationColors &colors = AnnotationColors::getAnnotationColors( + markColor, painter.background().color()); + + painter.save(); + QLinearGradient grad(rects.fadeInRect.topLeft(), rects.fadeInRect.topRight()); + grad.setColorAt(0.0, Qt::transparent); + grad.setColorAt(1.0, colors.rectColor); + painter.fillRect(rects.fadeInRect, grad); + painter.fillRect(rects.annotationRect, colors.rectColor); + painter.setPen(colors.textColor); + paintIcon(&painter, rects.iconRect.toAlignedRect()); + painter.drawText(rects.textRect, Qt::AlignLeft, rects.text); + if (rects.fadeOutRect.isValid()) { + grad = QLinearGradient(rects.fadeOutRect.topLeft(), rects.fadeOutRect.topRight()); + grad.setColorAt(0.0, colors.rectColor); + grad.setColorAt(1.0, Qt::transparent); + painter.fillRect(rects.fadeOutRect, grad); + } + painter.restore(); + annotationRect->setRight(rects.fadeOutRect.right()); } TextMark::AnnotationRects TextMark::annotationRects(const QRectF &boundingRect, - const QFontMetrics &fm) const + const QFontMetrics &fm, + const qreal fadeInOffset, + const qreal fadeOutOffset) const { AnnotationRects rects; - rects.annotationRect = boundingRect; rects.text = lineAnnotation(); + if (rects.text.isEmpty()) + return rects; + rects.fadeInRect = boundingRect; + rects.fadeInRect.setWidth(fadeInOffset); + rects.annotationRect = boundingRect; + rects.annotationRect.setLeft(rects.fadeInRect.right()); const bool drawIcon = !m_icon.isNull(); constexpr qreal margin = 1; - rects.iconRect = QRectF(boundingRect.left() + margin, boundingRect.top() + margin, 0, 0); - if (drawIcon) { - rects.iconRect.setHeight(boundingRect.height() - 2 * margin); + rects.iconRect = QRectF(rects.annotationRect.left(), boundingRect.top(), + 0, boundingRect.height()); + if (drawIcon) rects.iconRect.setWidth(rects.iconRect.height() * m_widthFactor); - } rects.textRect = QRectF(rects.iconRect.right() + margin, boundingRect.top(), qreal(fm.width(rects.text)), boundingRect.height()); rects.annotationRect.setRight(rects.textRect.right() + margin); @@ -165,6 +180,12 @@ TextMark::AnnotationRects TextMark::annotationRects(const QRectF &boundingRect, rects.textRect.setRight(boundingRect.right() - margin); rects.text = fm.elidedText(rects.text, Qt::ElideRight, int(rects.textRect.width())); rects.annotationRect.setRight(boundingRect.right()); + rects.fadeOutRect = QRectF(rects.annotationRect.topRight(), + rects.annotationRect.bottomRight()); + } else { + rects.fadeOutRect = boundingRect; + rects.fadeOutRect.setLeft(rects.annotationRect.right()); + rects.fadeOutRect.setWidth(fadeOutOffset); } return rects; } diff --git a/src/plugins/texteditor/textmark.h b/src/plugins/texteditor/textmark.h index 317fb31de9..f8cd36b131 100644 --- a/src/plugins/texteditor/textmark.h +++ b/src/plugins/texteditor/textmark.h @@ -64,15 +64,19 @@ public: int lineNumber() const; virtual void paintIcon(QPainter *painter, const QRect &rect) const; - virtual void paintAnnotation(QPainter *painter, QRectF *annotationRect) const; + virtual void paintAnnotation(QPainter &painter, QRectF *annotationRect, + const qreal fadeInOffset, const qreal fadeOutOffset) const; struct AnnotationRects { + QRectF fadeInRect; QRectF annotationRect; QRectF iconRect; QRectF textRect; + QRectF fadeOutRect; QString text; }; - virtual AnnotationRects annotationRects(const QRectF &boundingRect, const QFontMetrics &fm) const; + AnnotationRects annotationRects(const QRectF &boundingRect, const QFontMetrics &fm, + const qreal fadeInOffset, const qreal fadeOutOffset) const; /// called if the filename of the document changed virtual void updateFileName(const QString &fileName); virtual void updateLineNumber(int lineNumber); diff --git a/src/shared/qbs b/src/shared/qbs -Subproject ed9b5833894f24e2cfbf4c432497d48844a97d1 +Subproject 4db6418abaefe23795984a48025ede6a54ba34d diff --git a/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri b/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri index c598eece8b..06be9be18d 100644 --- a/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri +++ b/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri @@ -1,101 +1,103 @@ INCLUDEPATH += $$PWD -HEADERS += $$PWD/clangcodemodelserver.h \ - $$PWD/codecompleter.h \ - $$PWD/clangstring.h \ - $$PWD/clangcodecompleteresults.h \ - $$PWD/codecompletionsextractor.h \ - $$PWD/unsavedfile.h \ - $$PWD/unsavedfiles.h \ - $$PWD/projects.h \ - $$PWD/clangdocuments.h \ - $$PWD/projectpart.h \ - $$PWD/codecompletionchunkconverter.h \ - $$PWD/diagnosticset.h \ - $$PWD/diagnostic.h \ - $$PWD/sourcelocation.h \ - $$PWD/sourcerange.h \ - $$PWD/fixit.h \ - $$PWD/diagnosticsetiterator.h \ - $$PWD/clangfilesystemwatcher.h \ - $$PWD/commandlinearguments.h \ - $$PWD/cursor.h \ - $$PWD/skippedsourceranges.h \ - $$PWD/clangdocument.h \ - $$PWD/clangtranslationunitupdater.h \ - $$PWD/clangtype.h \ - $$PWD/highlightingmark.h \ - $$PWD/highlightingmarks.h \ - $$PWD/highlightingmarksiterator.h \ - $$PWD/utf8positionfromlinecolumn.h \ +HEADERS += \ $$PWD/clangasyncjob.h \ $$PWD/clangbackend_global.h \ + $$PWD/clangclock.h \ + $$PWD/clangcodecompleteresults.h \ + $$PWD/clangcodemodelserver.h \ $$PWD/clangcompletecodejob.h \ $$PWD/clangcreateinitialdocumentpreamblejob.h \ + $$PWD/clangdocument.h \ + $$PWD/clangdocumentprocessor.h \ + $$PWD/clangdocumentprocessors.h \ + $$PWD/clangdocuments.h \ + $$PWD/clangexceptions.h \ $$PWD/clangfilepath.h \ + $$PWD/clangfilesystemwatcher.h \ $$PWD/clangiasyncjob.h \ $$PWD/clangjobcontext.h \ $$PWD/clangjobqueue.h \ $$PWD/clangjobrequest.h \ $$PWD/clangjobs.h \ + $$PWD/clangparsesupportivetranslationunitjob.h \ + $$PWD/clangreferencescollector.h \ + $$PWD/clangreparsesupportivetranslationunitjob.h \ $$PWD/clangrequestdocumentannotationsjob.h \ + $$PWD/clangrequestreferencesjob.h \ + $$PWD/clangstring.h \ + $$PWD/clangsupportivetranslationunitinitializer.h \ $$PWD/clangtranslationunit.h \ + $$PWD/clangtranslationunits.h \ + $$PWD/clangtranslationunitupdater.h \ + $$PWD/clangtype.h \ $$PWD/clangunsavedfilesshallowarguments.h \ $$PWD/clangupdatedocumentannotationsjob.h \ - $$PWD/clangexceptions.h \ - $$PWD/clangdocumentprocessor.h \ - $$PWD/clangdocumentprocessors.h \ - $$PWD/clangtranslationunits.h \ - $$PWD/clangclock.h \ - $$PWD/clangsupportivetranslationunitinitializer.h \ - $$PWD/clangparsesupportivetranslationunitjob.h \ - $$PWD/clangreparsesupportivetranslationunitjob.h \ - $$PWD/clangrequestreferencesjob.h \ - $$PWD/clangreferencescollector.h + $$PWD/codecompleter.h \ + $$PWD/codecompletionchunkconverter.h \ + $$PWD/codecompletionsextractor.h \ + $$PWD/commandlinearguments.h \ + $$PWD/cursor.h \ + $$PWD/diagnostic.h \ + $$PWD/diagnosticset.h \ + $$PWD/diagnosticsetiterator.h \ + $$PWD/fixit.h \ + $$PWD/highlightingmark.h \ + $$PWD/highlightingmarks.h \ + $$PWD/highlightingmarksiterator.h \ + $$PWD/projectpart.h \ + $$PWD/projects.h \ + $$PWD/skippedsourceranges.h \ + $$PWD/sourcelocation.h \ + $$PWD/sourcerange.h \ + $$PWD/unsavedfile.h \ + $$PWD/unsavedfiles.h \ + $$PWD/utf8positionfromlinecolumn.h \ -SOURCES += $$PWD/clangcodemodelserver.cpp \ - $$PWD/codecompleter.cpp \ +SOURCES += \ $$PWD/clangcodecompleteresults.cpp \ - $$PWD/codecompletionsextractor.cpp \ - $$PWD/unsavedfile.cpp \ - $$PWD/unsavedfiles.cpp \ - $$PWD/projects.cpp \ - $$PWD/clangdocuments.cpp \ - $$PWD/projectpart.cpp \ - $$PWD/codecompletionchunkconverter.cpp \ - $$PWD/diagnosticset.cpp \ - $$PWD/diagnostic.cpp \ - $$PWD/sourcelocation.cpp \ - $$PWD/sourcerange.cpp \ - $$PWD/fixit.cpp \ - $$PWD/clangfilesystemwatcher.cpp \ - $$PWD/commandlinearguments.cpp \ - $$PWD/cursor.cpp \ - $$PWD/skippedsourceranges.cpp \ - $$PWD/clangdocument.cpp \ - $$PWD/clangtranslationunitupdater.cpp \ - $$PWD/clangtype.cpp \ - $$PWD/highlightingmark.cpp \ - $$PWD/highlightingmarks.cpp \ - $$PWD/utf8positionfromlinecolumn.cpp \ + $$PWD/clangcodemodelserver.cpp \ $$PWD/clangcompletecodejob.cpp \ $$PWD/clangcreateinitialdocumentpreamblejob.cpp \ + $$PWD/clangdocument.cpp \ + $$PWD/clangdocumentprocessor.cpp \ + $$PWD/clangdocumentprocessors.cpp \ + $$PWD/clangdocuments.cpp \ + $$PWD/clangexceptions.cpp \ $$PWD/clangfilepath.cpp \ + $$PWD/clangfilesystemwatcher.cpp \ $$PWD/clangiasyncjob.cpp \ $$PWD/clangjobcontext.cpp \ $$PWD/clangjobqueue.cpp \ $$PWD/clangjobrequest.cpp \ $$PWD/clangjobs.cpp \ + $$PWD/clangparsesupportivetranslationunitjob.cpp \ + $$PWD/clangreferencescollector.cpp \ + $$PWD/clangreparsesupportivetranslationunitjob.cpp \ $$PWD/clangrequestdocumentannotationsjob.cpp \ + $$PWD/clangrequestreferencesjob.cpp \ + $$PWD/clangsupportivetranslationunitinitializer.cpp \ $$PWD/clangtranslationunit.cpp \ + $$PWD/clangtranslationunits.cpp \ + $$PWD/clangtranslationunitupdater.cpp \ + $$PWD/clangtype.cpp \ $$PWD/clangunsavedfilesshallowarguments.cpp \ $$PWD/clangupdatedocumentannotationsjob.cpp \ - $$PWD/clangexceptions.cpp \ - $$PWD/clangdocumentprocessor.cpp \ - $$PWD/clangdocumentprocessors.cpp \ - $$PWD/clangtranslationunits.cpp \ - $$PWD/clangsupportivetranslationunitinitializer.cpp \ - $$PWD/clangparsesupportivetranslationunitjob.cpp \ - $$PWD/clangreparsesupportivetranslationunitjob.cpp \ - $$PWD/clangrequestreferencesjob.cpp \ - $$PWD/clangreferencescollector.cpp + $$PWD/codecompleter.cpp \ + $$PWD/codecompletionchunkconverter.cpp \ + $$PWD/codecompletionsextractor.cpp \ + $$PWD/commandlinearguments.cpp \ + $$PWD/cursor.cpp \ + $$PWD/diagnostic.cpp \ + $$PWD/diagnosticset.cpp \ + $$PWD/fixit.cpp \ + $$PWD/highlightingmark.cpp \ + $$PWD/highlightingmarks.cpp \ + $$PWD/projectpart.cpp \ + $$PWD/projects.cpp \ + $$PWD/skippedsourceranges.cpp \ + $$PWD/sourcelocation.cpp \ + $$PWD/sourcerange.cpp \ + $$PWD/unsavedfile.cpp \ + $$PWD/unsavedfiles.cpp \ + $$PWD/utf8positionfromlinecolumn.cpp \ diff --git a/src/tools/clangbackend/ipcsource/clangtype.cpp b/src/tools/clangbackend/ipcsource/clangtype.cpp index dd0e192f7a..8fc09d8c4a 100644 --- a/src/tools/clangbackend/ipcsource/clangtype.cpp +++ b/src/tools/clangbackend/ipcsource/clangtype.cpp @@ -76,7 +76,7 @@ bool Type::isReferencingConstant() const bool Type::isOutputArgument() const { - return (isPointer() || isLValueReference()) && !pointeeType().isConstant(); + return isLValueReference() && !pointeeType().isConstant(); } bool Type::isBuiltinType() const diff --git a/src/tools/clangbackend/ipcsource/highlightingmark.cpp b/src/tools/clangbackend/ipcsource/highlightingmark.cpp index 58a8a298ce..bc918326a7 100644 --- a/src/tools/clangbackend/ipcsource/highlightingmark.cpp +++ b/src/tools/clangbackend/ipcsource/highlightingmark.cpp @@ -43,69 +43,69 @@ HighlightingMark::HighlightingMark(const CXCursor &cxCursor, CXToken *cxToken, CXTranslationUnit cxTranslationUnit, std::vector<CXSourceRange> ¤tOutputArgumentRanges) - : currentOutputArgumentRanges(¤tOutputArgumentRanges), - originalCursor(cxCursor) + : m_currentOutputArgumentRanges(¤tOutputArgumentRanges), + m_originalCursor(cxCursor) { const SourceRange sourceRange = clang_getTokenExtent(cxTranslationUnit, *cxToken); const auto start = sourceRange.start(); const auto end = sourceRange.end(); - line = start.line(); - column = start.column(); - offset = start.offset(); - length = end.offset() - start.offset(); - collectKinds(cxTranslationUnit, cxToken, originalCursor); + m_line = start.line(); + m_column = start.column(); + m_offset = start.offset(); + m_length = end.offset() - start.offset(); + collectKinds(cxTranslationUnit, cxToken, m_originalCursor); } HighlightingMark::HighlightingMark(uint line, uint column, uint length, HighlightingTypes types) - : line(line), - column(column), - length(length), - types(types) + : m_line(line), + m_column(column), + m_length(length), + m_types(types) { } HighlightingMark::HighlightingMark(uint line, uint column, uint length, HighlightingType type) - : line(line), - column(column), - length(length), - types(HighlightingTypes()) + : m_line(line), + m_column(column), + m_length(length), + m_types(HighlightingTypes()) { - types.mainHighlightingType = type; + m_types.mainHighlightingType = type; } bool HighlightingMark::hasInvalidMainType() const { - return types.mainHighlightingType == HighlightingType::Invalid; + return m_types.mainHighlightingType == HighlightingType::Invalid; } bool HighlightingMark::hasMainType(HighlightingType type) const { - return types.mainHighlightingType == type; + return m_types.mainHighlightingType == type; } bool HighlightingMark::hasMixinType(HighlightingType type) const { - auto found = std::find(types.mixinHighlightingTypes.begin(), - types.mixinHighlightingTypes.end(), + auto found = std::find(m_types.mixinHighlightingTypes.begin(), + m_types.mixinHighlightingTypes.end(), type); - return found != types.mixinHighlightingTypes.end(); + return found != m_types.mixinHighlightingTypes.end(); } bool HighlightingMark::hasOnlyType(HighlightingType type) const { - return types.mixinHighlightingTypes.size() == 0 && hasMainType(type); + return m_types.mixinHighlightingTypes.size() == 0 && hasMainType(type); } bool HighlightingMark::hasFunctionArguments() const { - return originalCursor.argumentCount() > 0; + return m_originalCursor.argumentCount() > 0; } HighlightingMark::operator HighlightingMarkContainer() const { - return HighlightingMarkContainer(line, column, length, types); + return HighlightingMarkContainer(m_line, m_column, m_length, m_types); } namespace { @@ -133,9 +133,9 @@ void HighlightingMark::memberReferenceKind(const Cursor &cursor) { if (cursor.isDynamicCall()) { if (isFinalFunction(cursor) || isFunctionInFinalClass(cursor)) - types.mainHighlightingType = HighlightingType::Function; + m_types.mainHighlightingType = HighlightingType::Function; else - types.mainHighlightingType = HighlightingType::VirtualFunction; + m_types.mainHighlightingType = HighlightingType::VirtualFunction; } else { identifierKind(cursor.referenced(), Recursion::RecursivePass); } @@ -152,47 +152,47 @@ void HighlightingMark::referencedTypeKind(const Cursor &cursor) case CXCursor_TypedefDecl: case CXCursor_TemplateTypeParameter: case CXCursor_TypeAliasDecl: - case CXCursor_EnumDecl: types.mainHighlightingType = HighlightingType::Type; break; - default: types.mainHighlightingType = HighlightingType::Invalid; break; + case CXCursor_EnumDecl: m_types.mainHighlightingType = HighlightingType::Type; break; + default: m_types.mainHighlightingType = HighlightingType::Invalid; break; } } void HighlightingMark::overloadedDeclRefKind(const Cursor &cursor) { - types.mainHighlightingType = HighlightingType::Function; + m_types.mainHighlightingType = HighlightingType::Function; // CLANG-UPGRADE-CHECK: Workaround still needed? // Workaround https://bugs.llvm.org//show_bug.cgi?id=33256 - SomeType in // "using N::SomeType" is mistakenly considered as a CXCursor_OverloadedDeclRef. if (cursor.overloadedDeclarationsCount() >= 1 && cursor.overloadedDeclaration(0).kind() != CXCursor_FunctionDecl) { - types.mainHighlightingType = HighlightingType::Type; + m_types.mainHighlightingType = HighlightingType::Type; } } void HighlightingMark::variableKind(const Cursor &cursor) { if (cursor.isLocalVariable()) - types.mainHighlightingType = HighlightingType::LocalVariable; + m_types.mainHighlightingType = HighlightingType::LocalVariable; else - types.mainHighlightingType = HighlightingType::GlobalVariable; + m_types.mainHighlightingType = HighlightingType::GlobalVariable; if (isOutputArgument()) - types.mixinHighlightingTypes.push_back(HighlightingType::OutputArgument); + m_types.mixinHighlightingTypes.push_back(HighlightingType::OutputArgument); } void HighlightingMark::fieldKind(const Cursor &) { - types.mainHighlightingType = HighlightingType::Field; + m_types.mainHighlightingType = HighlightingType::Field; if (isOutputArgument()) - types.mixinHighlightingTypes.push_back(HighlightingType::OutputArgument); + m_types.mixinHighlightingTypes.push_back(HighlightingType::OutputArgument); } bool HighlightingMark::isVirtualMethodDeclarationOrDefinition(const Cursor &cursor) const { return cursor.isVirtualMethod() - && (originalCursor.isDeclaration() || originalCursor.isDefinition()); + && (m_originalCursor.isDeclaration() || m_originalCursor.isDefinition()); } namespace { bool isNotFinalFunction(const Cursor &cursor) @@ -203,37 +203,37 @@ bool isNotFinalFunction(const Cursor &cursor) } bool HighlightingMark::isRealDynamicCall(const Cursor &cursor) const { - return originalCursor.isDynamicCall() && isNotFinalFunction(cursor); + return m_originalCursor.isDynamicCall() && isNotFinalFunction(cursor); } void HighlightingMark::addExtraTypeIfFirstPass(HighlightingType type, Recursion recursion) { if (recursion == Recursion::FirstPass) - types.mixinHighlightingTypes.push_back(type); + m_types.mixinHighlightingTypes.push_back(type); } bool HighlightingMark::isArgumentInCurrentOutputArgumentLocations() const { - auto originalSourceLocation = originalCursor.cxSourceLocation(); + auto originalSourceLocation = m_originalCursor.cxSourceLocation(); const auto isNotSameOutputArgument = [&] (const CXSourceRange ¤tSourceRange) { return originalSourceLocation.int_data >= currentSourceRange.begin_int_data && originalSourceLocation.int_data <= currentSourceRange.end_int_data; }; - auto found = std::find_if(currentOutputArgumentRanges->begin(), - currentOutputArgumentRanges->end(), - isNotSameOutputArgument); + auto found = std::find_if(m_currentOutputArgumentRanges->begin(), + m_currentOutputArgumentRanges->end(), + isNotSameOutputArgument); - bool isOutputArgument = found != currentOutputArgumentRanges->end(); + bool isOutputArgument = found != m_currentOutputArgumentRanges->end(); return isOutputArgument; } bool HighlightingMark::isOutputArgument() const { - if (currentOutputArgumentRanges->empty()) + if (m_currentOutputArgumentRanges->empty()) return false; return isArgumentInCurrentOutputArgumentLocations(); @@ -241,43 +241,46 @@ bool HighlightingMark::isOutputArgument() const void HighlightingMark::collectOutputArguments(const Cursor &cursor) { - cursor.collectOutputArgumentRangesTo(*currentOutputArgumentRanges); + cursor.collectOutputArgumentRangesTo(*m_currentOutputArgumentRanges); filterOutPreviousOutputArguments(); } namespace { -uint getStart(CXSourceRange cxSourceRange) +uint getEnd(CXSourceRange cxSourceRange) { - CXSourceLocation startSourceLocation = clang_getRangeStart(cxSourceRange); + CXSourceLocation startSourceLocation = clang_getRangeEnd(cxSourceRange); - uint startOffset; + uint endOffset; - clang_getFileLocation(startSourceLocation, nullptr, nullptr, nullptr, &startOffset); + clang_getFileLocation(startSourceLocation, nullptr, nullptr, nullptr, &endOffset); - return startOffset; + return endOffset; } } void HighlightingMark::filterOutPreviousOutputArguments() { auto isAfterLocation = [this] (CXSourceRange outputRange) { - return getStart(outputRange) > offset; + return getEnd(outputRange) > m_offset; }; - auto precedingBegin = std::partition(currentOutputArgumentRanges->begin(), - currentOutputArgumentRanges->end(), + auto precedingBegin = std::partition(m_currentOutputArgumentRanges->begin(), + m_currentOutputArgumentRanges->end(), isAfterLocation); - currentOutputArgumentRanges->erase(precedingBegin, currentOutputArgumentRanges->end()); + m_currentOutputArgumentRanges->erase(precedingBegin, m_currentOutputArgumentRanges->end()); } void HighlightingMark::functionKind(const Cursor &cursor, Recursion recursion) { if (isRealDynamicCall(cursor) || isVirtualMethodDeclarationOrDefinition(cursor)) - types.mainHighlightingType = HighlightingType::VirtualFunction; + m_types.mainHighlightingType = HighlightingType::VirtualFunction; else - types.mainHighlightingType = HighlightingType::Function; + m_types.mainHighlightingType = HighlightingType::Function; + + if (isOutputArgument()) + m_types.mixinHighlightingTypes.push_back(HighlightingType::OutputArgument); addExtraTypeIfFirstPass(HighlightingType::Declaration, recursion); } @@ -291,7 +294,7 @@ void HighlightingMark::identifierKind(const Cursor &cursor, Recursion recursion) case CXCursor_CallExpr: case CXCursor_CXXMethod: functionKind(cursor, recursion); break; case CXCursor_NonTypeTemplateParameter: - case CXCursor_CompoundStmt: types.mainHighlightingType = HighlightingType::LocalVariable; break; + case CXCursor_CompoundStmt: m_types.mainHighlightingType = HighlightingType::LocalVariable; break; case CXCursor_ParmDecl: case CXCursor_VarDecl: variableKind(cursor); break; case CXCursor_DeclRefExpr: identifierKind(cursor.referenced(), Recursion::RecursivePass); break; @@ -303,7 +306,7 @@ void HighlightingMark::identifierKind(const Cursor &cursor, Recursion recursion) case CXCursor_ObjCClassMethodDecl: case CXCursor_ObjCInstanceMethodDecl: case CXCursor_ObjCSynthesizeDecl: - case CXCursor_ObjCDynamicDecl: types.mainHighlightingType = HighlightingType::Field; break; + case CXCursor_ObjCDynamicDecl: m_types.mainHighlightingType = HighlightingType::Field; break; case CXCursor_TypeRef: referencedTypeKind(cursor); break; case CXCursor_ClassDecl: case CXCursor_ClassTemplatePartialSpecialization: @@ -328,16 +331,16 @@ void HighlightingMark::identifierKind(const Cursor &cursor, Recursion recursion) case CXCursor_ObjCProtocolDecl: case CXCursor_ObjCProtocolRef: case CXCursor_ObjCClassRef: - case CXCursor_ObjCSuperClassRef: types.mainHighlightingType = HighlightingType::Type; break; + case CXCursor_ObjCSuperClassRef: m_types.mainHighlightingType = HighlightingType::Type; break; case CXCursor_OverloadedDeclRef: overloadedDeclRefKind(cursor); break; - case CXCursor_FunctionTemplate: types.mainHighlightingType = HighlightingType::Function; break; - case CXCursor_EnumConstantDecl: types.mainHighlightingType = HighlightingType::Enumeration; break; - case CXCursor_PreprocessingDirective: types.mainHighlightingType = HighlightingType::Preprocessor; break; - case CXCursor_MacroExpansion: types.mainHighlightingType = HighlightingType::PreprocessorExpansion; break; - case CXCursor_MacroDefinition: types.mainHighlightingType = HighlightingType::PreprocessorDefinition; break; - case CXCursor_InclusionDirective: types.mainHighlightingType = HighlightingType::StringLiteral; break; + case CXCursor_FunctionTemplate: m_types.mainHighlightingType = HighlightingType::Function; break; + case CXCursor_EnumConstantDecl: m_types.mainHighlightingType = HighlightingType::Enumeration; break; + case CXCursor_PreprocessingDirective: m_types.mainHighlightingType = HighlightingType::Preprocessor; break; + case CXCursor_MacroExpansion: m_types.mainHighlightingType = HighlightingType::PreprocessorExpansion; break; + case CXCursor_MacroDefinition: m_types.mainHighlightingType = HighlightingType::PreprocessorDefinition; break; + case CXCursor_InclusionDirective: m_types.mainHighlightingType = HighlightingType::StringLiteral; break; case CXCursor_LabelRef: - case CXCursor_LabelStmt: types.mainHighlightingType = HighlightingType::Label; break; + case CXCursor_LabelStmt: m_types.mainHighlightingType = HighlightingType::Label; break; default: break; } } @@ -384,6 +387,9 @@ HighlightingType HighlightingMark::punctuationKind(const Cursor &cursor) default: break; } + if (isOutputArgument()) + m_types.mixinHighlightingTypes.push_back(HighlightingType::OutputArgument); + return highlightingType; } @@ -422,23 +428,23 @@ void HighlightingMark::collectKinds(CXTranslationUnit cxTranslationUnit, { auto cxTokenKind = clang_getTokenKind(*cxToken); - types = HighlightingTypes(); + m_types = HighlightingTypes(); switch (cxTokenKind) { - case CXToken_Keyword: types.mainHighlightingType = highlightingTypeForKeyword(cxTranslationUnit, cxToken, originalCursor); break; - case CXToken_Punctuation: types.mainHighlightingType = punctuationKind(cursor); break; + case CXToken_Keyword: m_types.mainHighlightingType = highlightingTypeForKeyword(cxTranslationUnit, cxToken, m_originalCursor); break; + case CXToken_Punctuation: m_types.mainHighlightingType = punctuationKind(cursor); break; case CXToken_Identifier: identifierKind(cursor, Recursion::FirstPass); break; - case CXToken_Comment: types.mainHighlightingType = HighlightingType::Comment; break; - case CXToken_Literal: types.mainHighlightingType = literalKind(cursor); break; + case CXToken_Comment: m_types.mainHighlightingType = HighlightingType::Comment; break; + case CXToken_Literal: m_types.mainHighlightingType = literalKind(cursor); break; } } std::ostream &operator<<(std::ostream &os, const HighlightingMark& highlightingMark) { - os << "(type: " << highlightingMark.types << ", " - << " line: " << highlightingMark.line << ", " - << " column: " << highlightingMark.column << ", " - << " length: " << highlightingMark.length + os << "(type: " << highlightingMark.m_types << ", " + << " line: " << highlightingMark.m_line << ", " + << " column: " << highlightingMark.m_column << ", " + << " length: " << highlightingMark.m_length << ")"; return os; diff --git a/src/tools/clangbackend/ipcsource/highlightingmark.h b/src/tools/clangbackend/ipcsource/highlightingmark.h index 9d3f2f8fee..a749a5c922 100644 --- a/src/tools/clangbackend/ipcsource/highlightingmark.h +++ b/src/tools/clangbackend/ipcsource/highlightingmark.h @@ -47,9 +47,9 @@ public: HighlightingMark(const CXCursor &cxCursor, CXToken *cxToken, CXTranslationUnit cxTranslationUnit, - std::vector<CXSourceRange> ¤tOutputArgumentRanges); - HighlightingMark(uint line, uint column, uint length, HighlightingTypes types); - HighlightingMark(uint line, uint column, uint length, HighlightingType type); + std::vector<CXSourceRange> &m_currentOutputArgumentRanges); + HighlightingMark(uint m_line, uint m_column, uint m_length, HighlightingTypes m_types); + HighlightingMark(uint m_line, uint m_column, uint m_length, HighlightingType type); bool hasInvalidMainType() const; bool hasMainType(HighlightingType type) const; @@ -80,22 +80,22 @@ private: friend std::ostream &operator<<(std::ostream &os, const HighlightingMark& highlightingMark); private: - std::vector<CXSourceRange> *currentOutputArgumentRanges = nullptr; - Cursor originalCursor; - uint line; - uint column; - uint length; - uint offset = 0; - HighlightingTypes types; + std::vector<CXSourceRange> *m_currentOutputArgumentRanges = nullptr; + Cursor m_originalCursor; + uint m_line; + uint m_column; + uint m_length; + uint m_offset = 0; + HighlightingTypes m_types; }; inline bool operator==(const HighlightingMark &first, const HighlightingMark &second) { - return first.line == second.line - && first.column == second.column - && first.length == second.length - && first.types == second.types; + return first.m_line == second.m_line + && first.m_column == second.m_column + && first.m_length == second.m_length + && first.m_types == second.m_types; } } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/highlightingmarks.cpp b/src/tools/clangbackend/ipcsource/highlightingmarks.cpp index 725e6eb316..2e157ff835 100644 --- a/src/tools/clangbackend/ipcsource/highlightingmarks.cpp +++ b/src/tools/clangbackend/ipcsource/highlightingmarks.cpp @@ -109,4 +109,16 @@ HighlightingMark HighlightingMarks::operator[](size_t index) const currentOutputArgumentRanges); } +std::ostream &operator<<(std::ostream &out, const HighlightingMarks &marks) +{ + out << "["; + + for (const HighlightingMark entry : marks) + out << entry; + + out << "]"; + + return out; +} + } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/highlightingmarks.h b/src/tools/clangbackend/ipcsource/highlightingmarks.h index 6904bb3184..e573dc267e 100644 --- a/src/tools/clangbackend/ipcsource/highlightingmarks.h +++ b/src/tools/clangbackend/ipcsource/highlightingmarks.h @@ -69,4 +69,6 @@ private: std::vector<CXCursor> cxCursor; }; +std::ostream &operator<<(std::ostream &out, const HighlightingMarks &marks); + } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/clangquery.cpp b/src/tools/clangrefactoringbackend/source/clangquery.cpp index be93b61a1a..b625e9e197 100644 --- a/src/tools/clangrefactoringbackend/source/clangquery.cpp +++ b/src/tools/clangrefactoringbackend/source/clangquery.cpp @@ -92,7 +92,7 @@ SourceRangesContainer ClangQuery::takeSourceRanges() return std::move(sourceRangesContainer); } -std::vector<DynamicASTMatcherDiagnosticContainer> ClangQuery::takeDiagnosticContainers() +DynamicASTMatcherDiagnosticContainers ClangQuery::takeDiagnosticContainers() { return std::move(diagnosticContainers_); } diff --git a/src/tools/clangrefactoringbackend/source/clangquery.h b/src/tools/clangrefactoringbackend/source/clangquery.h index 20b38a7ab1..faa5821ca3 100644 --- a/src/tools/clangrefactoringbackend/source/clangquery.h +++ b/src/tools/clangrefactoringbackend/source/clangquery.h @@ -58,7 +58,7 @@ public: void findLocations(); SourceRangesContainer takeSourceRanges(); - std::vector<DynamicASTMatcherDiagnosticContainer> takeDiagnosticContainers(); + DynamicASTMatcherDiagnosticContainers takeDiagnosticContainers(); private: void parseDiagnostics(const clang::ast_matchers::dynamic::Diagnostics &diagnostics); diff --git a/src/tools/icons/qtcreatoricons.svg b/src/tools/icons/qtcreatoricons.svg index b4ee6b5b54..4e1fbadcd2 100644 --- a/src/tools/icons/qtcreatoricons.svg +++ b/src/tools/icons/qtcreatoricons.svg @@ -1723,13 +1723,13 @@ sodipodi:nodetypes="cccccc" inkscape:connector-curvature="0" id="rect8115-9-7-8-0" - d="m 211.99412,158.98972 10,10 v 32 h -32 v -42 z" + d="m 212.99412,157.98972 10,10 v 34 h -34 v -44 z" style="fill:#dfe0e3;stroke:#6b7080;stroke-width:2;fill-opacity:1" /> <path sodipodi:nodetypes="cccc" inkscape:connector-curvature="0" id="rect8151-5-6-4" - d="m 210.99412,158.98972 11,11 h -11 z" + d="m 211.99412,157.98972 11,11 h -11 z" style="fill:#6b7080;fill-opacity:1" /> </g> <g diff --git a/tests/unit/unittest/clangqueryhighlightmarker-test.cpp b/tests/unit/unittest/clangqueryhighlightmarker-test.cpp index 01d9f848f2..05e657b9ea 100644 --- a/tests/unit/unittest/clangqueryhighlightmarker-test.cpp +++ b/tests/unit/unittest/clangqueryhighlightmarker-test.cpp @@ -32,12 +32,16 @@ namespace { using testing::AllOf; using testing::Contains; +using testing::ElementsAre; +using testing::Pointwise; using testing::IsEmpty; using testing::Not; using testing::InSequence; using testing::_; using SourceRange = ClangBackEnd::V2::SourceRangeContainer; +using Message = ClangBackEnd::DynamicASTMatcherDiagnosticMessageContainer; +using Context = ClangBackEnd::DynamicASTMatcherDiagnosticContextContainer; using Messages = ClangBackEnd::DynamicASTMatcherDiagnosticMessageContainers; using Contexts = ClangBackEnd::DynamicASTMatcherDiagnosticContextContainers; using Marker = ClangRefactoring::ClangQueryHighlightMarker<MockSyntaxHighlighter>; @@ -54,7 +58,6 @@ protected: QTextCharFormat contextTextFormat; MockSyntaxHighlighter highlighter; Marker marker{highlighter}; - }; TEST_F(ClangQueryHighlightMarker, NoCallForNoMessagesAndContexts) @@ -120,6 +123,262 @@ TEST_F(ClangQueryHighlightMarker, CallForMessagesAndContextForAMultiLine) marker.highlightBlock(3, " ) "); } +TEST_F(ClangQueryHighlightMarker, NoMessagesIfEmpty) +{ + Messages messages; + Contexts contexts; + marker.setMessagesAndContexts(std::move(messages), std::move(contexts)); + + auto foundMessages = marker.messagesForLineAndColumn(1, 1); + + ASSERT_THAT(foundMessages, IsEmpty()); +} + +TEST_F(ClangQueryHighlightMarker, NoMessagesForBeforePosition) +{ + Messages messages{{{1, 1, 5, 0, 3, 3, 0}, + ErrorType::RegistryMatcherNotFound, + {"foo"}}}; + Contexts contexts; + marker.setMessagesAndContexts(std::move(messages), std::move(contexts)); + + auto foundMessages = marker.messagesForLineAndColumn(1, 4); + + ASSERT_THAT(foundMessages, IsEmpty()); +} + +TEST_F(ClangQueryHighlightMarker, NoMessagesForAfterPosition) +{ + Messages messages{{{1, 1, 5, 0, 3, 3, 0}, + ErrorType::RegistryMatcherNotFound, + {"foo"}}}; + Contexts contexts; + marker.setMessagesAndContexts(std::move(messages), std::move(contexts)); + + auto foundMessages = marker.messagesForLineAndColumn(3, 4); + + ASSERT_THAT(foundMessages, IsEmpty()); +} + +TEST_F(ClangQueryHighlightMarker, OneMessagesForInsidePosition) +{ + Message message{{1, 1, 5, 0, 3, 3, 0}, + ErrorType::RegistryMatcherNotFound, + {"foo"}}; + Messages messages{message.clone()}; + Contexts contexts; + marker.setMessagesAndContexts(std::move(messages), std::move(contexts)); + + auto foundMessages = marker.messagesForLineAndColumn(2, 3); + + ASSERT_THAT(foundMessages, ElementsAre(message)); +} + +TEST_F(ClangQueryHighlightMarker, NoMessagesForOutsidePosition) +{ + Message message{{1, 1, 5, 0, 3, 3, 0}, + ErrorType::RegistryMatcherNotFound, + {"foo"}}; + Messages messages{message.clone()}; + Contexts contexts; + marker.setMessagesAndContexts(std::move(messages), std::move(contexts)); + + auto foundMessages = marker.messagesForLineAndColumn(3, 4); + + ASSERT_THAT(foundMessages, IsEmpty()); +} + +TEST_F(ClangQueryHighlightMarker, AfterStartColumnBeforeLine) +{ + SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; + + bool isAfterStartColumn = marker.isInsideRange(sourceRange, 1, 6); + + ASSERT_FALSE(isAfterStartColumn); +} + +TEST_F(ClangQueryHighlightMarker, AfterStartColumnBeforeColumn) +{ + SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; + + bool isAfterStartColumn = marker.isInsideRange(sourceRange, 2, 4); + + ASSERT_FALSE(isAfterStartColumn); +} + +TEST_F(ClangQueryHighlightMarker, AfterStartColumnAtColumn) +{ + SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; + + bool isAfterStartColumn = marker.isInsideRange(sourceRange, 2, 5); + + ASSERT_TRUE(isAfterStartColumn); +} + +TEST_F(ClangQueryHighlightMarker, AfterStartColumnAfterColumn) +{ + SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; + + bool isAfterStartColumn = marker.isInsideRange(sourceRange, 2, 6); + + ASSERT_TRUE(isAfterStartColumn); +} + +TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAfterLine) +{ + SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; + + bool isBeforeEndColumn = marker.isInsideRange(sourceRange, 4, 1); + + ASSERT_FALSE(isBeforeEndColumn); +} + +TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAfterColumn) +{ + SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; + + bool isBeforeEndColumn = marker.isInsideRange(sourceRange, 3, 4); + + ASSERT_FALSE(isBeforeEndColumn); +} + +TEST_F(ClangQueryHighlightMarker, BeforeEndColumnAtColumn) +{ + SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; + + bool isBeforeEndColumn = marker.isInsideRange(sourceRange, 3, 3); + + ASSERT_TRUE(isBeforeEndColumn); +} + +TEST_F(ClangQueryHighlightMarker, BeforeEndColumnBeforeColumn) +{ + SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; + + bool isBeforeEndColumn = marker.isInsideRange(sourceRange, 3, 2); + + ASSERT_TRUE(isBeforeEndColumn); +} + +TEST_F(ClangQueryHighlightMarker, InBetweenLineBeforeLine) +{ + SourceRange sourceRange{1, 2, 5, 0, 3, 3, 0}; + + bool isInBetween = marker.isInsideRange(sourceRange, 1, 6); + + ASSERT_FALSE(isInBetween); +} + +TEST_F(ClangQueryHighlightMarker, InBetweenLineAfterLine) +{ + SourceRange sourceRange{1, 2, 5, 0, 4, 3, 0}; + + bool isInBetween = marker.isInsideRange(sourceRange, 5, 1); + + ASSERT_FALSE(isInBetween); +} + +TEST_F(ClangQueryHighlightMarker, InBetweenLine) +{ + SourceRange sourceRange{1, 2, 5, 0, 4, 3, 0}; + + bool isInBetween = marker.isInsideRange(sourceRange, 3, 1); + + ASSERT_TRUE(isInBetween); +} + +TEST_F(ClangQueryHighlightMarker, SingleLineBefore) +{ + SourceRange sourceRange{1, 2, 5, 0, 2, 10, 0}; + + bool isInRange = marker.isInsideRange(sourceRange, 2, 4); + + ASSERT_FALSE(isInRange); +} + +TEST_F(ClangQueryHighlightMarker, SingleLineAfter) +{ + SourceRange sourceRange{1, 2, 5, 0, 2, 10, 0}; + + bool isInRange = marker.isInsideRange(sourceRange, 2, 11); + + ASSERT_FALSE(isInRange); +} + +TEST_F(ClangQueryHighlightMarker, SingleLineInRange) +{ + SourceRange sourceRange{1, 2, 5, 0, 2, 10, 0}; + + bool isInRange = marker.isInsideRange(sourceRange, 2, 6); + + ASSERT_TRUE(isInRange); +} + +TEST_F(ClangQueryHighlightMarker, NoContextsIfEmpty) +{ + Messages messages; + Contexts contexts; + marker.setMessagesAndContexts(std::move(messages), std::move(contexts)); + + auto foundContexts = marker.contextsForLineAndColumn(1, 1); + + ASSERT_THAT(foundContexts, IsEmpty()); +} + +TEST_F(ClangQueryHighlightMarker, NoContextsForBeforePosition) +{ + Messages messages; + Contexts contexts{{{1, 1, 5, 0, 3, 3, 0}, + ContextType::MatcherArg, + {"foo"}}}; + marker.setMessagesAndContexts(std::move(messages), std::move(contexts)); + + auto foundContexts = marker.contextsForLineAndColumn(1, 4); + + ASSERT_THAT(foundContexts, IsEmpty()); +} + +TEST_F(ClangQueryHighlightMarker, NoContextsForAfterPosition) +{ + Messages messages; + Contexts contexts{{{1, 1, 5, 0, 3, 3, 0}, + ContextType::MatcherArg, + {"foo"}}}; + marker.setMessagesAndContexts(std::move(messages), std::move(contexts)); + + auto foundContexts = marker.contextsForLineAndColumn(3, 4); + + ASSERT_THAT(foundContexts, IsEmpty()); +} + +TEST_F(ClangQueryHighlightMarker, OneContextsForInsidePosition) +{ + Context context{{1, 1, 5, 0, 3, 3, 0}, + ContextType::MatcherArg, + {"foo"}}; + Messages messages; + Contexts contexts{context.clone()}; + marker.setMessagesAndContexts(std::move(messages), std::move(contexts)); + + auto foundContexts = marker.contextsForLineAndColumn(2, 3); + + ASSERT_THAT(foundContexts, ElementsAre(context)); +} + +TEST_F(ClangQueryHighlightMarker, NoContextsForOutsidePosition) +{ + Context context{{1, 1, 5, 0, 3, 3, 0}, + ContextType::MatcherArg, + {"foo"}}; + Messages messages; + Contexts contexts{context.clone()}; + marker.setMessagesAndContexts(std::move(messages), std::move(contexts)); + + auto foundContexts = marker.contextsForLineAndColumn(3, 4); + + ASSERT_THAT(foundContexts, IsEmpty()); +} + void ClangQueryHighlightMarker::SetUp() { messageTextFormat.setFontItalic(true); diff --git a/tests/unit/unittest/data/highlightingmarks.cpp b/tests/unit/unittest/data/highlightingmarks.cpp index a954df3e97..5b3374d582 100644 --- a/tests/unit/unittest/data/highlightingmarks.cpp +++ b/tests/unit/unittest/data/highlightingmarks.cpp @@ -482,12 +482,12 @@ void f25() NonConstPointerArgument(x); } -void ConstPointerArgument(const int *argument); - +void PointerToConstArgument(const int *argument); +void ConstPointerArgument(int *const argument); void f26() { int *x; - + PointerToConstArgument(x); ConstPointerArgument(x); } @@ -565,3 +565,17 @@ void g(OtherOperator o, int var) { o(var); } + +void NonConstPointerArgument(int &argument); + +struct PointerGetterClass +{ + int &getter(); +}; + +void f32() +{ + PointerGetterClass x; + + NonConstPointerArgument(x.getter()); +} diff --git a/tests/unit/unittest/highlightingmarks-test.cpp b/tests/unit/unittest/highlightingmarks-test.cpp index e72d25c971..8592bb67be 100644 --- a/tests/unit/unittest/highlightingmarks-test.cpp +++ b/tests/unit/unittest/highlightingmarks-test.cpp @@ -60,6 +60,8 @@ using testing::IsNull; using testing::NotNull; using testing::Gt; using testing::Contains; +using testing::ElementsAre; +using testing::_; using testing::EndsWith; using testing::AllOf; using testing::Not; @@ -96,6 +98,14 @@ MATCHER_P2(HasTwoTypes, firstType, secondType, return arg.hasMainType(firstType) && arg.hasMixinType(secondType); } +MATCHER_P(HasMixin, firstType, + std::string(negation ? "isn't " : "is ") + + PrintToString(firstType) + ) +{ + return arg.hasMixinType(firstType); +} + struct Data { Data() { @@ -998,7 +1008,17 @@ TEST_F(HighlightingMarks, NonConstPointerArgument) infos[1]; ASSERT_THAT(infos[2], - HasTwoTypes(HighlightingType::LocalVariable, HighlightingType::OutputArgument)); + HasOnlyType(HighlightingType::LocalVariable)); +} + +TEST_F(HighlightingMarks, PointerToConstArgument) +{ + const auto infos = translationUnit.highlightingMarksInRange(sourceRange(490, 31)); + + infos[1]; + + ASSERT_THAT(infos[2], + HasOnlyType(HighlightingType::LocalVariable)); } TEST_F(HighlightingMarks, ConstPointerArgument) @@ -1011,6 +1031,23 @@ TEST_F(HighlightingMarks, ConstPointerArgument) HasOnlyType(HighlightingType::LocalVariable)); } +TEST_F(HighlightingMarks, NonConstPointerGetterAsArgument) +{ + const auto infos = translationUnit.highlightingMarksInRange(sourceRange(580, 41)); + + ASSERT_THAT(infos, + ElementsAre(_, + _, + HasMixin(HighlightingType::OutputArgument), + HasMixin(HighlightingType::OutputArgument), + HasMixin(HighlightingType::OutputArgument), + HasMixin(HighlightingType::OutputArgument), + HasMixin(HighlightingType::OutputArgument), + _, + _, + _)); +} + TEST_F(HighlightingMarks, NonConstReferenceArgumentCallInsideCall) { const auto infos = translationUnit.highlightingMarksInRange(sourceRange(501, 64)); @@ -1048,7 +1085,7 @@ TEST_F(HighlightingMarks, NonConstPointerArgumentAsExpression) infos[1]; ASSERT_THAT(infos[3], - HasTwoTypes(HighlightingType::LocalVariable, HighlightingType::OutputArgument)); + HasOnlyType(HighlightingType::LocalVariable)); } TEST_F(HighlightingMarks, NonConstPointerArgumentAsInstanceWithMember) diff --git a/tests/unit/unittest/matchingtext-test.cpp b/tests/unit/unittest/matchingtext-test.cpp new file mode 100644 index 0000000000..d5bfcaddef --- /dev/null +++ b/tests/unit/unittest/matchingtext-test.cpp @@ -0,0 +1,259 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "googletest.h" + +#include <cplusplus/MatchingText.h> + +#include <QTextDocument> +#include <QTextCursor> + +#include <memory> + +#include <utils/qtcassert.h> + +namespace { + +class Document { +public: + Document(const QString &documentText, char marker = '@') + { + QString text = documentText; + const int markerIndex = documentText.indexOf(marker); + if (markerIndex == -1) + return; + + text.replace(markerIndex, 1, ""); + + document.reset(new QTextDocument(text)); + cursor = QTextCursor(document.get()); + cursor.setPosition(markerIndex); + } + + std::unique_ptr<QTextDocument> document; + QTextCursor cursor; +}; + +using MT = CPlusPlus::MatchingText; +using IsNextBlockDeeperIndented = MT::IsNextBlockDeeperIndented; + +class MatchingText : public testing::Test { +protected: + const IsNextBlockDeeperIndented nextBlockIsIndented = [](const QTextBlock &) { return true; }; +}; + +TEST_F(MatchingText, ContextAllowsAutoParentheses_ForNoInput) +{ + const Document document("@"); + + ASSERT_TRUE(MT::contextAllowsAutoParentheses(document.cursor, "")); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_NotInEmptyLine) +{ + const Document document("@"); + + ASSERT_FALSE(MT::contextAllowsAutoParentheses(document.cursor, "{")); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_Initializer) +{ + const Document document("Type object@"); + + ASSERT_TRUE(MT::contextAllowsAutoParentheses(document.cursor, "{")); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_AfterFunctionDeclaratorSameLine) +{ + const Document document("void g() @"); + + ASSERT_TRUE(MT::contextAllowsAutoParentheses(document.cursor, "{")); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_AfterFunctionDeclaratorNewLine) +{ + const Document document("void g()\n" + "@"); + + ASSERT_TRUE(MT::contextAllowsAutoParentheses(document.cursor, "{")); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_AfterFunctionDeclaratorNewLineAndMore) +{ + const Document document("void g()\n" + "@\n" + "1+1;"); + + ASSERT_TRUE(MT::contextAllowsAutoParentheses(document.cursor, "{")); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_AfterLambdaDeclarator) +{ + const Document document("[]() @"); + + ASSERT_TRUE(MT::contextAllowsAutoParentheses(document.cursor, "{")); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_NotBeforeOpeningCurlyBrace) +{ + const Document document("@{"); + + ASSERT_FALSE(MT::contextAllowsAutoParentheses(document.cursor, "{")); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_BeforeClosingCurlyBrace) +{ + const Document document("@}"); + + ASSERT_TRUE(MT::contextAllowsAutoParentheses(document.cursor, "{")); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_BeforeClosingBracket) +{ + const Document document("@]"); + + ASSERT_TRUE(MT::contextAllowsAutoParentheses(document.cursor, "{")); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_BeforeClosingParen) +{ + const Document document("@)"); + + ASSERT_TRUE(MT::contextAllowsAutoParentheses(document.cursor, "{")); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_BeforeSemicolon) +{ + const Document document("@;"); + + ASSERT_TRUE(MT::contextAllowsAutoParentheses(document.cursor, "{")); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_BeforeComma) +{ + const Document document("@,"); + + ASSERT_TRUE(MT::contextAllowsAutoParentheses(document.cursor, "{")); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_NotInCppComment) +{ + const Document document("// @"); + + ASSERT_FALSE(MT::contextAllowsAutoParentheses(document.cursor, "{")); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_NotInCppDoxygenComment) +{ + const Document document("//! @"); + + ASSERT_FALSE(MT::contextAllowsAutoParentheses(document.cursor, "{")); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_NotBeforeIndented) +{ + const Document document("@\n" + " 1+1;"); + + ASSERT_FALSE(MT::contextAllowsAutoParentheses(document.cursor, "{", nextBlockIsIndented)); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_NotBeforeIndentedWithFollowingComment) +{ + const Document document("@\n // comment" + " 1+1;"); + + ASSERT_FALSE(MT::contextAllowsAutoParentheses(document.cursor, "{", nextBlockIsIndented)); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_NotBeforeIndentedWithTextInFront) +{ + const Document document("if (true) @\n" + " 1+1;"); + + ASSERT_FALSE(MT::contextAllowsAutoParentheses(document.cursor, "{", nextBlockIsIndented)); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_NotBeforeIndentedOnEmptyLine1) +{ + const Document document("if (true)\n" + "@\n" + " 1+1;"); + + ASSERT_FALSE(MT::contextAllowsAutoParentheses(document.cursor, "{", nextBlockIsIndented)); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_NotBeforeIndentedOnEmptyLine2) +{ + const Document document("if (true)\n" + " @\n" + " 1+1;"); + + ASSERT_FALSE(MT::contextAllowsAutoParentheses(document.cursor, "{", nextBlockIsIndented)); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_NotInTheMiddle) +{ + const Document document("if (true) @ true;"); + + ASSERT_FALSE(MT::contextAllowsAutoParentheses(document.cursor, "{")); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_NotBeforeNamedNamespace) +{ + const Document document("namespace X @"); + + ASSERT_FALSE(MT::contextAllowsAutoParentheses(document.cursor, "{")); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_NotBeforeNamedNamespaceWithAttributeSpecifier) +{ + const Document document("namespace [[xyz]] X @"); + + ASSERT_FALSE(MT::contextAllowsAutoParentheses(document.cursor, "{")); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_NotBeforeUnnamedNamespace) +{ + const Document document("namespace @"); + + ASSERT_FALSE(MT::contextAllowsAutoParentheses(document.cursor, "{")); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_NotBeforeUnnamedNamespaceWithAttributeSpecifier) +{ + const Document document("namespace [[xyz]] @"); + + ASSERT_FALSE(MT::contextAllowsAutoParentheses(document.cursor, "{")); +} + +TEST_F(MatchingText, ContextAllowsAutoParentheses_CurlyBrace_NotBeforeNestedNamespace) +{ + const Document document("namespace X::Y::Z @"); + + ASSERT_FALSE(MT::contextAllowsAutoParentheses(document.cursor, "{")); +} + +} // anonymous diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index c227eaede2..be7632ecd5 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -36,37 +36,38 @@ QMAKE_SUBSTITUTES += cpptoolsjson DEFINES += CPPTOOLS_JSON=\"R\\\"xxx($${cpptoolsjson.output})xxx\\\"\" SOURCES += \ + changedfilepathcompressor-test.cpp \ + clangpathwatcher-test.cpp \ + clangqueryexamplehighlightmarker-test.cpp \ + clangqueryhighlightmarker-test.cpp \ clientserverinprocess-test.cpp \ - lineprefixer-test.cpp \ + clientserveroutsideprocess-test.cpp \ cppprojectfilecategorizer-test.cpp \ cppprojectinfogenerator-test.cpp \ cppprojectpartchooser-test.cpp \ - processevents-utilities.cpp \ + fakeprocess.cpp \ + faketimer.cpp \ + filepath-test.cpp \ + gtest-creator-printing.cpp \ + gtest-qt-printing.cpp \ + lineprefixer-test.cpp \ + matchingtext-test.cpp \ mimedatabase-utilities.cpp \ + pchgenerator-test.cpp \ + pchmanagerclientserverinprocess-test.cpp \ + pchmanagerclient-test.cpp \ + pchmanagerserver-test.cpp \ + processevents-utilities.cpp \ + projectparts-test.cpp \ + projectupdater-test.cpp \ readandwritemessageblock-test.cpp \ sizedarray-test.cpp \ smallstring-test.cpp \ + sourcerangefilter-test.cpp \ spydummy.cpp \ + stringcache-test.cpp \ unittests-main.cpp \ utf8-test.cpp \ - gtest-qt-printing.cpp \ - gtest-creator-printing.cpp \ - clientserveroutsideprocess-test.cpp \ - clangpathwatcher-test.cpp \ - projectparts-test.cpp \ - stringcache-test.cpp \ - changedfilepathcompressor-test.cpp \ - faketimer.cpp \ - pchgenerator-test.cpp \ - fakeprocess.cpp \ - pchmanagerclient-test.cpp \ - projectupdater-test.cpp \ - pchmanagerserver-test.cpp \ - pchmanagerclientserverinprocess-test.cpp \ - filepath-test.cpp \ - sourcerangefilter-test.cpp \ - clangqueryexamplehighlightmarker-test.cpp \ - clangqueryhighlightmarker-test.cpp !isEmpty(LIBCLANG_LIBS) { SOURCES += \ @@ -80,21 +81,25 @@ SOURCES += \ clangcompletioncontextanalyzer-test.cpp \ clangcreateinitialdocumentpreamblejob-test.cpp \ clangdiagnosticfilter-test.cpp \ + clangdocumentprocessors-test.cpp \ + clangdocumentprocessor-test.cpp \ clangdocuments-test.cpp \ clangdocument-test.cpp \ - clangdocumentprocessor-test.cpp \ - clangdocumentprocessors-test.cpp \ clangfixitoperation-test.cpp \ clangisdiagnosticrelatedtolocation-test.cpp \ clangjobqueue-test.cpp \ clangjobs-test.cpp \ + clangparsesupportivetranslationunitjob-test.cpp \ + clangreferencescollector-test.cpp \ + clangreparsesupportivetranslationunitjob-test.cpp \ clangrequestdocumentannotationsjob-test.cpp \ clangrequestreferencesjob-test.cpp \ - clangreferencescollector-test.cpp \ clangstring-test.cpp \ - clangtranslationunit-test.cpp \ + clangsupportivetranslationunitinitializer-test.cpp \ clangtranslationunits-test.cpp \ + clangtranslationunit-test.cpp \ clangupdatedocumentannotationsjob-test.cpp \ + codecompleter-test.cpp \ codecompletionsextractor-test.cpp \ completionchunkstotextconverter-test.cpp \ createtablesqlstatementbuilder-test.cpp \ @@ -119,28 +124,24 @@ SOURCES += \ unsavedfiles-test.cpp \ unsavedfile-test.cpp \ utf8positionfromlinecolumn-test.cpp \ - clangparsesupportivetranslationunitjob-test.cpp \ - clangreparsesupportivetranslationunitjob-test.cpp \ - clangsupportivetranslationunitinitializer-test.cpp \ - codecompleter-test.cpp } !isEmpty(LIBTOOLING_LIBS) { SOURCES += \ - clangquery-test.cpp \ clangquerygatherer-test.cpp \ clangqueryprojectfindfilter-test.cpp \ + clangquery-test.cpp \ + gtest-clang-printing.cpp \ + includecollector-test.cpp \ + pchcreator-test.cpp \ refactoringclientserverinprocess-test.cpp \ refactoringclient-test.cpp \ refactoringcompilationdatabase-test.cpp \ refactoringengine-test.cpp \ refactoringserver-test.cpp \ - symbolfinder-test.cpp \ sourcerangeextractor-test.cpp \ - gtest-clang-printing.cpp \ + symbolfinder-test.cpp \ testclangtool.cpp \ - includecollector-test.cpp \ - pchcreator-test.cpp } exists($$GOOGLEBENCHMARK_DIR) { @@ -149,53 +150,53 @@ SOURCES += \ } HEADERS += \ + compare-operators.h \ + conditionally-disabled-tests.h \ + dummyclangipcclient.h \ + dynamicastmatcherdiagnosticcontainer-matcher.h \ + fakeprocess.h \ + faketimer.h \ filesystem-utilities.h \ googletest.h \ + gtest-creator-printing.h \ gtest-qt-printing.h \ - processevents-utilities.h \ mimedatabase-utilities.h \ - spydummy.h \ - sourcerangecontainer-matcher.h \ - dynamicastmatcherdiagnosticcontainer-matcher.h \ - mocksearchresult.h \ - mocksearch.h \ - mocksearchhandle.h \ - compare-operators.h \ - gtest-creator-printing.h \ - conditionally-disabled-tests.h \ - mockqfilesystemwatcher.h \ + mockchangedfilepathcompressor.h \ + mockclangcodemodelclient.h \ + mockclangcodemodelserver.h \ mockclangpathwatcher.h \ - mockprojectparts.h \ mockclangpathwatchernotifier.h \ - mockchangedfilepathcompressor.h \ - faketimer.h \ + mockpchcreator.h \ mockpchgeneratornotifier.h \ - fakeprocess.h \ - mockpchmanagerserver.h \ mockpchmanagerclient.h \ - testenvironment.h \ mockpchmanagernotifier.h \ - mockpchcreator.h \ - dummyclangipcclient.h \ - mockclangcodemodelclient.h \ - mockclangcodemodelserver.h \ - mocksyntaxhighligher.h + mockpchmanagerserver.h \ + mockprojectparts.h \ + mockqfilesystemwatcher.h \ + mocksearch.h \ + mocksearchhandle.h \ + mocksearchresult.h \ + mocksyntaxhighligher.h \ + processevents-utilities.h \ + sourcerangecontainer-matcher.h \ + spydummy.h \ + testenvironment.h \ !isEmpty(LIBCLANG_LIBS) { HEADERS += \ chunksreportedmonitor.h \ clangasyncjob-base.h \ + clangcompareoperators.h \ diagnosticcontainer-matcher.h \ - clangcompareoperators.h } !isEmpty(LIBTOOLING_LIBS) { HEADERS += \ + gtest-clang-printing.h \ mockrefactoringclientcallback.h \ mockrefactoringclient.h \ mockrefactoringserver.h \ - gtest-clang-printing.h \ - testclangtool.h + testclangtool.h \ } OTHER_FILES += $$files(data/*) |