Merge "Merge remote-tracking branch 'origin/4.9'"

This commit is contained in:
Orgad Shaneh
2019-02-15 12:08:30 +00:00
committed by The Qt Project
164 changed files with 7476 additions and 1069 deletions

View File

@@ -287,6 +287,44 @@ http://llvm.org/docs/GettingStarted.html#git-mirror:
Qt Creator includes the following third-party components,
we thank the authors who made this possible:
### KSyntaxHighlighting
Syntax highlighting engine for Kate syntax definitions
This is a stand-alone implementation of the Kate syntax highlighting
engine. It's meant as a building block for text editors as well as
for simple highlighted text rendering (e.g. as HTML), supporting both
integration with a custom editor as well as a ready-to-use
QSyntaxHighlighter sub-class.
Distributed under the:
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
The source code of KSyntaxHighlighting can be found here:
https://cgit.kde.org/syntax-highlighting.git
QtCreator/src/libs/3rdparty/syntax-highlighting
https://code.qt.io/cgit/qt-creator/qt-creator.git/tree/src/libs/3rdparty/syntax-highlighting
### Clazy
https://github.com/KDE/clazy

240
dist/changes-4.9.0.md vendored Normal file
View File

@@ -0,0 +1,240 @@
Qt Creator version 4.9 contains bug fixes and new features.
The most important changes are listed in this document. For a complete
list of changes, see the Git log for the Qt Creator sources that
you can check out from the public Git repository. For example:
git clone git://code.qt.io/qt-creator/qt-creator.git
git log --cherry-pick --pretty=oneline origin/4.8..v4.9.0
General
* Added high-level introduction to Qt Creator's UI for first-time users
(QTCREATORBUG-21585)
* Added option to run external tools in build or run environment of
active project (QTCREATORBUG-18394, QTCREATORBUG-19892)
* Improved selection colors in dark themes (QTCREATORBUG-18888)
Editing
* Language Client
* Added support for document outline (QTCREATORBUG-21573)
* Added support for `Find Usages` (QTCREATORBUG-21577)
* Added support for code actions
* Highlighter
* Replaced custom highlighting file parser with `KSyntaxHighlighting`
(QTCREATORBUG-21029)
* Made it possible to filter bookmarks by line and text content in Locator
(QTCREATORBUG-21771)
* Fixed document sort order after rename (QTCREATORBUG-21565)
Help
* Improved context help in case of code errors or diagnostics
(QTCREATORBUG-15959, QTCREATORBUG-21686)
* Improved lookup performance for context help
All Projects
* Added `Expand All` to context menu (QTCREATORBUG-17243)
* Added `Close All Files in Project` action (QTCREATORBUG-15593)
* Added closing of all files of a project when project is closed
(QTCREATORBUG-15721)
* Added display of command line parameters to `Application Output`
(QTCREATORBUG-20577)
* Fixed that dragging file from `Projects` view to desktop moved the file
(QTCREATORBUG-14494)
QMake Projects
* Fixed that adding files did not respect alphabetic sorting and indentation
with tabs (QTCREATORBUG-553, QTCREATORBUG-21807)
* Fixed updating of `LD_LIBRARY_PATH` environment variable (QTCREATORBUG-21475)
* Fixed updating of project tree in case of wildcards in corresponding QMake
variable (QTCREATORBUG-21603)
CMake Projects
* Fixed that default build directory names contained spaces (QTCREATORBUG-18442)
* Fixed that build targets were reset on CMake parse error (QTCREATORBUG-21617)
* Fixed scroll behavior when adding configuration item
Qbs Projects
* Fixed crash when switching kits (QTCREATORBUG-21544)
Generic Projects
* Added deployment via `QtCreatorDeployment.txt` file (QTCREATORBUG-19202)
* Added setting C/C++ flags for the code model via `.cflags` and `.cxxflags`
files (QTCREATORBUG-19668)
* Fixed `Apply Filter` when editing file list (QTCREATORBUG-16237)
C++ Support
* Added code snippet for range-based `for` loops
* Added option to synchronize `Include Hierarchy` with current document
(QTCREATORBUG-12022)
* Clang Code Model
* Added buttons for copying and ignoring diagnostics to tooltip
* Fixed issue with high memory consumption (QTCREATORBUG-19543)
* Clang Format
* Added option to format code instead of only indenting code
QML Support
* Updated to parser from Qt 5.12, adding support for ECMAScript 7
(QTCREATORBUG-20341, QTCREATORBUG-21301)
* Improved error handling in Qt Quick Application project template (QTBUG-39469)
* Fixed crash on `Find Usages`
Python
* Added project templates for Qt for Python
Nim Support
* Added code completion based on `NimSuggest`
Debugging
* GDB
* Added support for rvalue references in function arguments
* LLDB
* Fixed `Source Paths Mappings` functionality (QTCREATORBUG-17468)
Clang Analyzer Tools
* Made Clazy configuration options more fine grained (QTCREATORBUG-21120)
* Improved Fix-its handling in case of selecting multiple diagnostics and
after editing files
* Added diagnostics from header files (QTCREATORBUG-21452)
* Added sorting to result list (QTCREATORBUG-20660)
* Fixed that files were analyzed that are not part of current build
configuration (QTCREATORBUG-16016)
Perf Profiler
* Made Perf profiler integration opensource
Qt Quick Designer
* Made QML Live Preview integration opensource
Version Control Systems
* Git
* Improved messages when submit editor validation fails and when editor
is closed
* Added `Subversion` > `DCommit`
* `Branches` View
* Added `Push` action
* Added entry for detached `HEAD` (QTCREATORBUG-21311)
* Added tracking of external changes to `HEAD` (QTCREATORBUG-21089)
* Subversion
* Improved handling of commit errors (QTCREATORBUG-15227)
* Perforce
* Disabled by default
* Fixed issue with setting P4 environment variables (QTCREATORBUG-21573)
* Mercurial
* Added side-by-side diff viewer (QTCREATORBUG-21124)
Test Integration
* Added `Uncheck All Filters`
* Added grouping results by application (QTCREATORBUG-21740)
* QTest
* Added support for `BXPASS` and `BXFAIL`
* Fixed parsing of `BFAIL` and `BPASS`
FakeVim
* Added option for blinking cursor (QTCREATORBUG-21613)
* Added closing completion popups with `Ctrl+[` (QTCREATORBUG-21886)
Model Editor
* Added display of base class names
Serial Terminal
* Improved error message on connection failure
Platform Specific
Windows
* Added support for MSVC 2019
* Changed toolchain detection to use `vswhere` by default, which is recommended
by Microsoft
Linux
macOS
* Added support for Touch Bar (QTCREATORBUG-21263)
Android
* Removed separate `QmakeAndroidSupport` plugin and merged functionality into
other plugins
Remote Linux
* Removed use of Botan, exchanging it by use of separately installed OpenSSH
tools (QTCREATORBUG-15744, QTCREATORBUG-15807, QTCREATORBUG-19306,
QTCREATORBUG-20210)
* Added support for `ssh-askpass`
* Added optional deployment of public key for authentication to device setup
wizard
* Added support for X11 forwarding
* Added `rsync` based deployment method
* Added support for `Run in Terminal`
* Added support for opening a remote terminal from device settings
* Fixed incremental deployment when target directory is changed
(QTCREATORBUG-21225)
* Fixed issue with killing remote process (QTCREATORBUG-19941)
Credits for these changes go to:
Aaron Barany
Alessandro Portale
Andre Hartmann
André Pönitz
Asit Dhal
Bernhard Beschow
Chris Rizzitello
Christian Kandeler
Christian Stenger
Cristian Adam
Cristian Maureira-Fredes
Daniel Wingerd
David Schulz
Eike Ziller
Filip Bucek
Filippo Cucchetto
Frank Meerkoetter
Friedemann Kleint
Ivan Donchevskii
James McDonnell
Jochen Becher
Kai Köhne
Leena Miettinen
Marco Benelli
Marco Bubke
Michael Kopp
Michael Weghorn
Miklós Márton
Mitch Curtis
Nikolai Kosjar
Oliver Wolff
Orgad Shaneh
Przemyslaw Gorszkowski
Robert Löhning
Thiago Macieira
Thomas Hartmann
Tim Jenssen
Tobias Hunger
Ulf Hermann
Vikas Pachdha
Ville Nummela
Xiaofeng Wang

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -90,6 +90,39 @@
\li \l{https://code.qt.io/cgit/qt-creator/qt-creator.git/tree/src/libs/3rdparty/syntax-highlighting}
\endlist
\li \b{Clazy}
\l {https://github.com/KDE/clazy}
Copyright (C) 2015-2019 Clazy Team
Distributed under the \l {https://www.gnu.org/licenses/old-licenses/lgpl-2.0.html}
{GNU LIBRARY GENERAL PUBLIC LICENSE Version 2 (LGPL2)}.
Integrated with patches from
\list
\li \l{http://code.qt.io/cgit/clang/clang-tools-extra.git}
\endlist
\li \b{LLVM/Clang}
\list
\li \l{http://llvm.org/svn/llvm-project/llvm}
\li \l{http://llvm.org/svn/llvm-project/cfe/trunk}
\li \l{http://llvm.org/svn/llvm-project/clang-tools-extra/trunk}
\endlist
Copyright (C) 2003-2019 LLVM Team
Distributed under the \l {https://github.com/llvm-mirror/llvm/blob/master/LICENSE.TXT}
{University of Illinois/NCSA Open Source License (NCSA)}.
With backported/additional patches from
\list
\li \l{http://code.qt.io/cgit/clang/llvm.git}
\li \l{http://code.qt.io/cgit/clang/clang.git}
\endlist
\li \b{Reference implementation for std::experimental::optional}
Copyright (C) 2011-2012 Andrzej Krzemienski

View File

@@ -19,6 +19,7 @@ Module {
exports: [ "qbs/Depends 1.0" ]
prototype: "QQuickItem"
Property { name: "condition"; type: "bool" }
Property { name: "enableFallback"; type: "bool" }
Property { name: "limitToSubProject"; type: "bool" }
Property { name: "multiplexConfigurationIds"; type: "string"; isList: true }
Property { name: "name"; type: "string" }
@@ -66,6 +67,14 @@ Module {
Property { name: "overrideTags"; type: "bool" }
Property { name: "prefix"; type: "string" }
}
Component {
name: "JobLimit"
exports: [ "qbs/JobLimit 1.0" ]
prototype: "QQuickItem"
Property { name: "condition"; type: "bool" }
Property { name: "jobCount"; type: "int" }
Property { name: "jobPool"; type: "string" }
}
Component {
name: "Module"
exports: [ "qbs/Module 1.0" ]
@@ -80,6 +89,14 @@ Module {
Property { name: "validate"; type: "bool" }
Property { name: "version"; type: "string" }
}
Component {
name: "ModuleProvider"
exports: [ "qbs/ModuleProvider 1.0" ]
prototype: "QQuickItem"
Property { name: "name"; type: "string" }
Property { name: "outputBaseDir"; type: "string" }
Property { name: "relativeSearchPaths"; type: "string"; isList: true }
}
Component {
name: "Parameter"
exports: [ "qbs/Parameter 1.0" ]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 527 B

After

Width:  |  Height:  |  Size: 511 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 487 B

After

Width:  |  Height:  |  Size: 515 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 790 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 790 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 55 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,389 @@
From c9f4bdaa0902c0fdb5ea750d11935e15777a090d Mon Sep 17 00:00:00 2001
From: Alessandro Portale <alessandro.portale@qt.io>
Date: Tue, 12 Feb 2019 19:45:08 +0100
Subject: [PATCH 3/6] Add qmake/Qbs files and files generated by CMake
---
autogenerated/autogenerated.pri | 9 ++
autogenerated/ksyntaxhighlighting_version.h | 12 +++
autogenerated/src/lib/AbstractHighlighter | 1 +
autogenerated/src/lib/Definition | 1 +
autogenerated/src/lib/FoldingRegion | 1 +
autogenerated/src/lib/Format | 1 +
autogenerated/src/lib/Repository | 1 +
autogenerated/src/lib/State | 1 +
autogenerated/src/lib/SyntaxHighlighter | 1 +
autogenerated/src/lib/Theme | 1 +
.../src/lib/ksyntaxhighlighting_logging.cpp | 11 +++
.../src/lib/ksyntaxhighlighting_logging.h | 11 +++
data/data.pro | 11 +++
src/lib/ksyntaxhighlighting_export.h | 34 +++++++
syntax-highlighting.pro | 55 ++++++++++++
syntax-highlighting.qbs | 88 +++++++++++++++++++
syntax-highlighting_dependencies.pri | 3 +
17 files changed, 242 insertions(+)
create mode 100644 autogenerated/autogenerated.pri
create mode 100644 autogenerated/ksyntaxhighlighting_version.h
create mode 100644 autogenerated/src/lib/AbstractHighlighter
create mode 100644 autogenerated/src/lib/Definition
create mode 100644 autogenerated/src/lib/FoldingRegion
create mode 100644 autogenerated/src/lib/Format
create mode 100644 autogenerated/src/lib/Repository
create mode 100644 autogenerated/src/lib/State
create mode 100644 autogenerated/src/lib/SyntaxHighlighter
create mode 100644 autogenerated/src/lib/Theme
create mode 100644 autogenerated/src/lib/ksyntaxhighlighting_logging.cpp
create mode 100644 autogenerated/src/lib/ksyntaxhighlighting_logging.h
create mode 100644 data/data.pro
create mode 100644 src/lib/ksyntaxhighlighting_export.h
create mode 100644 syntax-highlighting.pro
create mode 100644 syntax-highlighting.qbs
create mode 100644 syntax-highlighting_dependencies.pri
diff --git a/autogenerated/autogenerated.pri b/autogenerated/autogenerated.pri
new file mode 100644
index 0000000..aee620a
--- /dev/null
+++ b/autogenerated/autogenerated.pri
@@ -0,0 +1,9 @@
+INCLUDEPATH *= $$PWD/src/lib
+INCLUDEPATH *= $$PWD
+
+SOURCES += \
+ $$PWD/src/lib/ksyntaxhighlighting_logging.cpp
+
+HEADERS += \
+ $$PWD/ksyntaxhighlighting_version.h \
+ $$PWD/src/lib/ksyntaxhighlighting_logging.h
diff --git a/autogenerated/ksyntaxhighlighting_version.h b/autogenerated/ksyntaxhighlighting_version.h
new file mode 100644
index 0000000..bd31a4d
--- /dev/null
+++ b/autogenerated/ksyntaxhighlighting_version.h
@@ -0,0 +1,12 @@
+// This file was generated by ecm_setup_version(): DO NOT EDIT!
+
+#ifndef SyntaxHighlighting_VERSION_H
+#define SyntaxHighlighting_VERSION_H
+
+#define SyntaxHighlighting_VERSION_STRING "5.52.0"
+#define SyntaxHighlighting_VERSION_MAJOR 5
+#define SyntaxHighlighting_VERSION_MINOR 52
+#define SyntaxHighlighting_VERSION_PATCH 0
+#define SyntaxHighlighting_VERSION ((5<<16)|(52<<8)|(0))
+
+#endif
diff --git a/autogenerated/src/lib/AbstractHighlighter b/autogenerated/src/lib/AbstractHighlighter
new file mode 100644
index 0000000..b787873
--- /dev/null
+++ b/autogenerated/src/lib/AbstractHighlighter
@@ -0,0 +1 @@
+#include "abstracthighlighter.h"
diff --git a/autogenerated/src/lib/Definition b/autogenerated/src/lib/Definition
new file mode 100644
index 0000000..2c3241f
--- /dev/null
+++ b/autogenerated/src/lib/Definition
@@ -0,0 +1 @@
+#include "definition.h"
diff --git a/autogenerated/src/lib/FoldingRegion b/autogenerated/src/lib/FoldingRegion
new file mode 100644
index 0000000..005b829
--- /dev/null
+++ b/autogenerated/src/lib/FoldingRegion
@@ -0,0 +1 @@
+#include "foldingregion.h"
diff --git a/autogenerated/src/lib/Format b/autogenerated/src/lib/Format
new file mode 100644
index 0000000..b0d6a10
--- /dev/null
+++ b/autogenerated/src/lib/Format
@@ -0,0 +1 @@
+#include "format.h"
diff --git a/autogenerated/src/lib/Repository b/autogenerated/src/lib/Repository
new file mode 100644
index 0000000..189dbc2
--- /dev/null
+++ b/autogenerated/src/lib/Repository
@@ -0,0 +1 @@
+#include "repository.h"
diff --git a/autogenerated/src/lib/State b/autogenerated/src/lib/State
new file mode 100644
index 0000000..e148d70
--- /dev/null
+++ b/autogenerated/src/lib/State
@@ -0,0 +1 @@
+#include "state.h"
diff --git a/autogenerated/src/lib/SyntaxHighlighter b/autogenerated/src/lib/SyntaxHighlighter
new file mode 100644
index 0000000..b429824
--- /dev/null
+++ b/autogenerated/src/lib/SyntaxHighlighter
@@ -0,0 +1 @@
+#include "syntaxhighlighter.h"
diff --git a/autogenerated/src/lib/Theme b/autogenerated/src/lib/Theme
new file mode 100644
index 0000000..34a3e98
--- /dev/null
+++ b/autogenerated/src/lib/Theme
@@ -0,0 +1 @@
+#include "theme.h"
diff --git a/autogenerated/src/lib/ksyntaxhighlighting_logging.cpp b/autogenerated/src/lib/ksyntaxhighlighting_logging.cpp
new file mode 100644
index 0000000..4082ac4
--- /dev/null
+++ b/autogenerated/src/lib/ksyntaxhighlighting_logging.cpp
@@ -0,0 +1,11 @@
+// This file was generated by ecm_qt_declare_logging_category(): DO NOT EDIT!
+
+#include "ksyntaxhighlighting_logging.h"
+
+ namespace KSyntaxHighlighting {
+#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
+Q_LOGGING_CATEGORY(Log, "org.kde.ksyntaxhighlighting", QtInfoMsg)
+#else
+Q_LOGGING_CATEGORY(Log, "org.kde.ksyntaxhighlighting")
+#endif
+}
diff --git a/autogenerated/src/lib/ksyntaxhighlighting_logging.h b/autogenerated/src/lib/ksyntaxhighlighting_logging.h
new file mode 100644
index 0000000..c351b2c
--- /dev/null
+++ b/autogenerated/src/lib/ksyntaxhighlighting_logging.h
@@ -0,0 +1,11 @@
+// This file was generated by ecm_qt_declare_logging_category(): DO NOT EDIT!
+
+#ifndef ECM_QLOGGINGCATEGORY_KSYNTAXHIGHLIGHTING_LOG_KSYNTAXHIGHLIGHTING_LOGGING_H
+#define ECM_QLOGGINGCATEGORY_KSYNTAXHIGHLIGHTING_LOG_KSYNTAXHIGHLIGHTING_LOGGING_H
+
+#include <QLoggingCategory>
+ namespace KSyntaxHighlighting {
+Q_DECLARE_LOGGING_CATEGORY(Log)
+}
+
+#endif
diff --git a/data/data.pro b/data/data.pro
new file mode 100644
index 0000000..1028ea1
--- /dev/null
+++ b/data/data.pro
@@ -0,0 +1,11 @@
+TEMPLATE = aux
+
+include(../../../../../qtcreator.pri)
+
+STATIC_BASE = $$PWD
+STATIC_OUTPUT_BASE = $$IDE_DATA_PATH/generic-highlighter
+STATIC_INSTALL_BASE = $$INSTALL_DATA_PATH/generic-highlighter
+
+STATIC_FILES += $$files($$PWD/syntax/*, true)
+
+include(../../../../../qtcreatordata.pri)
diff --git a/src/lib/ksyntaxhighlighting_export.h b/src/lib/ksyntaxhighlighting_export.h
new file mode 100644
index 0000000..a39adb5
--- /dev/null
+++ b/src/lib/ksyntaxhighlighting_export.h
@@ -0,0 +1,34 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QtGlobal>
+
+#if defined(KSYNTAXHIGHLIGHTING_LIBRARY)
+# define KSYNTAXHIGHLIGHTING_EXPORT Q_DECL_EXPORT
+#else
+# define KSYNTAXHIGHLIGHTING_EXPORT Q_DECL_IMPORT
+#endif
diff --git a/syntax-highlighting.pro b/syntax-highlighting.pro
new file mode 100644
index 0000000..38127e1
--- /dev/null
+++ b/syntax-highlighting.pro
@@ -0,0 +1,55 @@
+include(../../../qtcreatorlibrary.pri)
+include(autogenerated/autogenerated.pri)
+
+QT += network
+
+DEFINES += KSYNTAXHIGHLIGHTING_LIBRARY
+
+RESOURCES += \
+ data/themes/theme-data.qrc
+
+HEADERS += \
+ src/lib/abstracthighlighter.h \
+ src/lib/abstracthighlighter_p.h \
+ src/lib/context_p.h \
+ src/lib/contextswitch_p.h \
+ src/lib/definition.h \
+ src/lib/definition_p.h \
+ src/lib/definitiondownloader.h \
+ src/lib/definitionref_p.h \
+ src/lib/foldingregion.h \
+ src/lib/format.h \
+ src/lib/format_p.h \
+ src/lib/htmlhighlighter.h \
+ src/lib/keywordlist_p.h \
+ src/lib/ksyntaxhighlighting_export.h \
+ src/lib/matchresult_p.h \
+ src/lib/repository.h \
+ src/lib/repository_p.h \
+ src/lib/rule_p.h \
+ src/lib/state.h \
+ src/lib/state_p.h \
+ src/lib/syntaxhighlighter.h \
+ src/lib/textstyledata_p.h \
+ src/lib/theme.h \
+ src/lib/themedata_p.h \
+ src/lib/wildcardmatcher_p.h \
+ src/lib/xml_p.h \
+
+SOURCES += \
+ src/lib/abstracthighlighter.cpp \
+ src/lib/context.cpp \
+ src/lib/contextswitch.cpp \
+ src/lib/definition.cpp \
+ src/lib/definitiondownloader.cpp \
+ src/lib/foldingregion.cpp \
+ src/lib/format.cpp \
+ src/lib/htmlhighlighter.cpp \
+ src/lib/keywordlist.cpp \
+ src/lib/repository.cpp \
+ src/lib/rule.cpp \
+ src/lib/state.cpp \
+ src/lib/syntaxhighlighter.cpp \
+ src/lib/theme.cpp \
+ src/lib/themedata.cpp \
+ src/lib/wildcardmatcher.cpp \
diff --git a/syntax-highlighting.qbs b/syntax-highlighting.qbs
new file mode 100644
index 0000000..248ebe0
--- /dev/null
+++ b/syntax-highlighting.qbs
@@ -0,0 +1,88 @@
+import qbs 1.0
+import qbs.File
+import qbs.FileInfo
+import qbs.Environment
+
+Project {
+ QtcDevHeaders {
+ productName: "syntax-highlighting (3rd party)"
+ baseDir: sourceDirectory + "/src/lib"
+ }
+ QtcDevHeaders {
+ productName: "syntax-highlighting autogenerated (3rd party)"
+ baseDir: sourceDirectory + "/autogenerated/src/lib"
+ Group {
+ prefix: baseDir + '/'
+ files: [
+ "AbstractHighlighter",
+ "Definition",
+ "FoldingRegion",
+ "Format",
+ "Repository",
+ "State",
+ "SyntaxHighlighter",
+ "Theme"
+ ]
+ qbs.install: true
+ qbs.installDir: qtc.ide_include_path + '/' + FileInfo.fileName(product.sourceDirectory)
+ qbs.installSourceBase: baseDir
+ }
+ }
+
+ QtcLibrary {
+ name: "KSyntaxHighlighting"
+
+ cpp.defines: base.concat("KSYNTAXHIGHLIGHTING_LIBRARY")
+ cpp.includePaths: [
+ product.sourceDirectory + "/src/lib/",
+ product.sourceDirectory + "/autogenerated/src/lib/",
+ product.sourceDirectory + "/autogenerated/"
+ ]
+
+ Depends { name: "Qt.gui" }
+ Depends { name: "Qt.network" }
+
+ Group {
+ name: "lib"
+ prefix: "src/lib/"
+ files: [
+ "*.h",
+ "*.cpp"
+ ]
+ }
+
+ Group {
+ name: "KSyntaxHighlighting data"
+ qbs.install: true
+ qbs.installDir: qtc.ide_data_path + "/generic-highlighter/"
+ qbs.installSourceBase: project.ide_source_tree + "/src/libs/3rdparty/syntax-highlighting/data/"
+ prefix: project.ide_source_tree + "/src/libs/3rdparty/syntax-highlighting/data/"
+ files: [
+ "syntax/**/*"
+ ]
+ }
+
+ Group {
+ name: "autogenerated lib"
+ prefix: "autogenerated/src/lib/"
+ files: [
+ "*.h",
+ "*.cpp"
+ ]
+ }
+
+ Group {
+ name: "theme data"
+ prefix: "data/themes/"
+ files: [ "theme-data.qrc" ]
+ }
+
+ Export {
+ Depends { name: "cpp" }
+ cpp.includePaths: [
+ product.sourceDirectory + "/src/lib/",
+ product.sourceDirectory + "/autogenerated/src/lib/",
+ ]
+ }
+ }
+}
diff --git a/syntax-highlighting_dependencies.pri b/syntax-highlighting_dependencies.pri
new file mode 100644
index 0000000..f2fd3e6
--- /dev/null
+++ b/syntax-highlighting_dependencies.pri
@@ -0,0 +1,3 @@
+QTC_LIB_NAME = KSyntaxHighlighting
+INCLUDEPATH *= $$PWD/src/lib
+INCLUDEPATH *= $$PWD/autogenerated/src/lib
--
2.20.1.windows.1

View File

@@ -0,0 +1,281 @@
From 916af0204a45c91092e53241e6a867cadb9dedec Mon Sep 17 00:00:00 2001
From: Alessandro Portale <alessandro.portale@qt.io>
Date: Tue, 12 Feb 2019 19:21:57 +0100
Subject: [PATCH 4/6] Compile with namespaced Qt
---
src/lib/abstracthighlighter.h | 4 ++++
src/lib/abstracthighlighter_p.h | 2 ++
src/lib/context_p.h | 2 ++
src/lib/definition.h | 4 ++++
src/lib/foldingregion.h | 2 ++
src/lib/format.h | 5 ++++-
src/lib/htmlhighlighter.h | 2 ++
src/lib/keywordlist_p.h | 2 ++
src/lib/repository.h | 2 ++
src/lib/repository_p.h | 2 ++
src/lib/rule_p.h | 2 ++
src/lib/state.h | 2 ++
src/lib/theme.h | 2 ++
src/lib/themedata_p.h | 2 ++
src/lib/wildcardmatcher.cpp | 2 +-
src/lib/wildcardmatcher_p.h | 4 ++++
16 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/src/lib/abstracthighlighter.h b/src/lib/abstracthighlighter.h
index 056f65b..2b88729 100644
--- a/src/lib/abstracthighlighter.h
+++ b/src/lib/abstracthighlighter.h
@@ -30,7 +30,9 @@
#include <memory>
+QT_BEGIN_NAMESPACE
class QString;
+QT_END_NAMESPACE
namespace KSyntaxHighlighting {
@@ -186,6 +188,8 @@ private:
};
}
+QT_BEGIN_NAMESPACE
Q_DECLARE_INTERFACE(KSyntaxHighlighting::AbstractHighlighter, "org.kde.SyntaxHighlighting.AbstractHighlighter")
+QT_END_NAMESPACE
#endif // KSYNTAXHIGHLIGHTING_ABSTRACTHIGHLIGHTERM_H
diff --git a/src/lib/abstracthighlighter_p.h b/src/lib/abstracthighlighter_p.h
index 1690eb0..bdfdf23 100644
--- a/src/lib/abstracthighlighter_p.h
+++ b/src/lib/abstracthighlighter_p.h
@@ -27,7 +27,9 @@
#include "definition.h"
#include "theme.h"
+QT_BEGIN_NAMESPACE
class QStringList;
+QT_END_NAMESPACE
namespace KSyntaxHighlighting {
diff --git a/src/lib/context_p.h b/src/lib/context_p.h
index 3e3ab97..a034d0e 100644
--- a/src/lib/context_p.h
+++ b/src/lib/context_p.h
@@ -34,7 +34,9 @@
#include <vector>
+QT_BEGIN_NAMESPACE
class QXmlStreamReader;
+QT_END_NAMESPACE
namespace KSyntaxHighlighting {
diff --git a/src/lib/definition.h b/src/lib/definition.h
index 25996dd..6f0dba9 100644
--- a/src/lib/definition.h
+++ b/src/lib/definition.h
@@ -31,10 +31,12 @@
#include <memory>
+QT_BEGIN_NAMESPACE
class QChar;
class QString;
class QStringList;
template <typename T> class QVector;
+QT_END_NAMESPACE
namespace KSyntaxHighlighting {
@@ -391,6 +393,8 @@ private:
}
+QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(KSyntaxHighlighting::Definition, Q_MOVABLE_TYPE);
+QT_END_NAMESPACE
#endif
diff --git a/src/lib/foldingregion.h b/src/lib/foldingregion.h
index baf65d1..074b947 100644
--- a/src/lib/foldingregion.h
+++ b/src/lib/foldingregion.h
@@ -101,6 +101,8 @@ private:
}
+QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(KSyntaxHighlighting::FoldingRegion, Q_PRIMITIVE_TYPE);
+QT_END_NAMESPACE
#endif
diff --git a/src/lib/format.h b/src/lib/format.h
index ba85f0d..24c58e7 100644
--- a/src/lib/format.h
+++ b/src/lib/format.h
@@ -30,10 +30,11 @@
#include <QExplicitlySharedDataPointer>
#include <QTypeInfo>
-
+QT_BEGIN_NAMESPACE
class QColor;
class QString;
class QXmlStreamReader;
+QT_END_NAMESPACE
namespace KSyntaxHighlighting {
@@ -144,6 +145,8 @@ private:
};
}
+QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(KSyntaxHighlighting::Format, Q_MOVABLE_TYPE);
+QT_END_NAMESPACE
#endif // KSYNTAXHIGHLIGHTING_FORMAT_H
diff --git a/src/lib/htmlhighlighter.h b/src/lib/htmlhighlighter.h
index 22d33ad..b7eda02 100644
--- a/src/lib/htmlhighlighter.h
+++ b/src/lib/htmlhighlighter.h
@@ -32,8 +32,10 @@
#include <memory>
+QT_BEGIN_NAMESPACE
class QFile;
class QTextStream;
+QT_END_NAMESPACE
namespace KSyntaxHighlighting {
diff --git a/src/lib/keywordlist_p.h b/src/lib/keywordlist_p.h
index fa70f11..8c41aab 100644
--- a/src/lib/keywordlist_p.h
+++ b/src/lib/keywordlist_p.h
@@ -30,7 +30,9 @@
#include <vector>
+QT_BEGIN_NAMESPACE
class QXmlStreamReader;
+QT_END_NAMESPACE
namespace KSyntaxHighlighting {
diff --git a/src/lib/repository.h b/src/lib/repository.h
index 2c32d02..c35da5e 100644
--- a/src/lib/repository.h
+++ b/src/lib/repository.h
@@ -29,8 +29,10 @@
#include <qglobal.h>
#include <memory>
+QT_BEGIN_NAMESPACE
class QString;
template <typename T> class QVector;
+QT_END_NAMESPACE
/**
* @namespace KSyntaxHighlighting
diff --git a/src/lib/repository_p.h b/src/lib/repository_p.h
index da765a2..9db876b 100644
--- a/src/lib/repository_p.h
+++ b/src/lib/repository_p.h
@@ -27,7 +27,9 @@
#include <QHash>
#include <QVector>
+QT_BEGIN_NAMESPACE
class QString;
+QT_END_NAMESPACE
namespace KSyntaxHighlighting {
diff --git a/src/lib/rule_p.h b/src/lib/rule_p.h
index eccf0df..538fded 100644
--- a/src/lib/rule_p.h
+++ b/src/lib/rule_p.h
@@ -38,7 +38,9 @@
#include <memory>
+QT_BEGIN_NAMESPACE
class QXmlStreamReader;
+QT_END_NAMESPACE
namespace KSyntaxHighlighting {
diff --git a/src/lib/state.h b/src/lib/state.h
index c6e5344..fce4bc7 100644
--- a/src/lib/state.h
+++ b/src/lib/state.h
@@ -79,6 +79,8 @@ private:
}
+QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(KSyntaxHighlighting::State, Q_MOVABLE_TYPE);
+QT_END_NAMESPACE
#endif // KSYNTAXHIGHLIGHTING_STATE_H
diff --git a/src/lib/theme.h b/src/lib/theme.h
index 5277429..adb8431 100644
--- a/src/lib/theme.h
+++ b/src/lib/theme.h
@@ -371,6 +371,8 @@ private:
}
+QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(KSyntaxHighlighting::Theme, Q_MOVABLE_TYPE);
+QT_END_NAMESPACE
#endif // KSYNTAXHIGHLIGHTING_THEME_H
diff --git a/src/lib/themedata_p.h b/src/lib/themedata_p.h
index 68cb873..3b5f463 100644
--- a/src/lib/themedata_p.h
+++ b/src/lib/themedata_p.h
@@ -163,6 +163,8 @@ private:
}
+QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(KSyntaxHighlighting::TextStyleData, Q_MOVABLE_TYPE);
+QT_END_NAMESPACE
#endif // KSYNTAXHIGHLIGHTING_THEMEDATA_P_H
diff --git a/src/lib/wildcardmatcher.cpp b/src/lib/wildcardmatcher.cpp
index 963e78d..167295a 100644
--- a/src/lib/wildcardmatcher.cpp
+++ b/src/lib/wildcardmatcher.cpp
@@ -79,5 +79,5 @@ static bool exactMatch(const QString &candidate, const QString &wildcard, int ca
bool WildcardMatcher::exactMatch(const QString &candidate, const QString &wildcard,
bool caseSensitive)
{
- return exactMatch(candidate, wildcard, candidate.length() - 1, wildcard.length() - 1, caseSensitive);
+ return ::exactMatch(candidate, wildcard, candidate.length() - 1, wildcard.length() - 1, caseSensitive);
}
diff --git a/src/lib/wildcardmatcher_p.h b/src/lib/wildcardmatcher_p.h
index 823dbd5..016b10f 100644
--- a/src/lib/wildcardmatcher_p.h
+++ b/src/lib/wildcardmatcher_p.h
@@ -24,7 +24,11 @@
#ifndef KSYNTAXHIGHLIGHTING_WILDCARDMATCHER_P_H
#define KSYNTAXHIGHLIGHTING_WILDCARDMATCHER_P_H
+#include <QtGlobal>
+
+QT_BEGIN_NAMESPACE
class QString;
+QT_END_NAMESPACE
namespace KSyntaxHighlighting {
--
2.20.1.windows.1

View File

@@ -0,0 +1,29 @@
From 3c05e92c71f6675fa2071036dafbc8d337bd2d01 Mon Sep 17 00:00:00 2001
From: Alessandro Portale <alessandro.portale@qt.io>
Date: Tue, 12 Feb 2019 19:27:46 +0100
Subject: [PATCH 5/6] Prevent assertion in RegExpr::doLoad
---
src/lib/rule.cpp | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/lib/rule.cpp b/src/lib/rule.cpp
index a201375..c48753b 100644
--- a/src/lib/rule.cpp
+++ b/src/lib/rule.cpp
@@ -575,7 +575,11 @@ bool RegExpr::doLoad(QXmlStreamReader& reader)
}
// always using m_regexp.isValid() would be better, but parses the regexp and thus is way too expensive for release builds
- Q_ASSERT(m_regexp.isValid());
+
+ if (Log().isDebugEnabled()) {
+ if (!m_regexp.isValid())
+ qCDebug(Log) << "Invalid regexp:" << m_regexp.pattern();
+ }
return !m_regexp.pattern().isEmpty();
}
--
2.20.1.windows.1

View File

@@ -0,0 +1,101 @@
From 4b64058fe7d788ac79c16a08b280ce05d500e9fb Mon Sep 17 00:00:00 2001
From: Alessandro Portale <alessandro.portale@qt.io>
Date: Tue, 12 Feb 2019 19:32:54 +0100
Subject: [PATCH 6/6] Syntax Highlighter: return all definitions for a file
name/mimetype
Can be used to create user controls to switch between
multiple definitions for a file or mime type.
Change-Id: I5fd3744db1e819d0d6f8448a53adaf9d2c7c168d
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
---
src/lib/repository.cpp | 17 +++++++++++++----
src/lib/repository.h | 12 ++++++++++++
2 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/src/lib/repository.cpp b/src/lib/repository.cpp
index 6b2fabd..922225a 100644
--- a/src/lib/repository.cpp
+++ b/src/lib/repository.cpp
@@ -78,7 +78,7 @@ Definition Repository::definitionForName(const QString& defName) const
return d->m_defs.value(defName);
}
-static Definition bestCandidate(QVector<Definition>& candidates)
+static Definition bestCandidate(QVector<Definition> &&candidates)
{
if (candidates.isEmpty())
return Definition();
@@ -91,6 +91,11 @@ static Definition bestCandidate(QVector<Definition>& candidates)
}
Definition Repository::definitionForFileName(const QString& fileName) const
+{
+ return bestCandidate(definitionsForFileName(fileName));
+}
+
+QVector<Definition> Repository::definitionsForFileName(const QString &fileName) const
{
QFileInfo fi(fileName);
const auto name = fi.fileName();
@@ -106,10 +111,15 @@ Definition Repository::definitionForFileName(const QString& fileName) const
}
}
- return bestCandidate(candidates);
+ return candidates;
}
Definition Repository::definitionForMimeType(const QString& mimeType) const
+{
+ return bestCandidate(definitionsForMimeType(mimeType));
+}
+
+QVector<Definition> Repository::definitionsForMimeType(const QString &mimeType) const
{
QVector<Definition> candidates;
for (auto it = d->m_defs.constBegin(); it != d->m_defs.constEnd(); ++it) {
@@ -121,8 +131,7 @@ Definition Repository::definitionForMimeType(const QString& mimeType) const
}
}
}
-
- return bestCandidate(candidates);
+ return candidates;
}
QVector<Definition> Repository::definitions() const
diff --git a/src/lib/repository.h b/src/lib/repository.h
index c35da5e..e4e9bed 100644
--- a/src/lib/repository.h
+++ b/src/lib/repository.h
@@ -166,6 +166,13 @@ public:
*/
Definition definitionForFileName(const QString &fileName) const;
+ /**
+ * Returns all Definition%s for the file named @p fileName.
+ * The match is performed based on the \e extensions and @e mimetype of
+ * the definition files.
+ */
+ QVector<Definition> definitionsForFileName(const QString &fileName) const;
+
/**
* Returns the best matching Definition to the type named @p mimeType
*
@@ -176,6 +183,11 @@ public:
*/
Definition definitionForMimeType(const QString &mimeType) const;
+ /**
+ * Returns all Definition%s to the type named @p mimeType
+ */
+ QVector<Definition> definitionsForMimeType(const QString &mimeType) const;
+
/**
* Returns all available Definition%s.
* Definition%ss are ordered by translated section and translated names,
--
2.20.1.windows.1

View File

@@ -35,12 +35,15 @@
namespace ClangBackEnd {
enum class InputFileType : unsigned char { Header, Source };
template<typename ProjectInfo, typename OutputContainer = Utils::SmallStringVector>
class CommandLineBuilder
{
public:
CommandLineBuilder(const ProjectInfo &projectInfo,
const Utils::SmallStringVector &toolChainArguments = {},
InputFileType sourceType = InputFileType::Header,
FilePathView sourcePath = {},
FilePathView outputPath = {},
FilePathView includePchPath = {})
@@ -49,9 +52,9 @@ public:
addCompiler(projectInfo.language);
addToolChainArguments(toolChainArguments);
addLanguage(projectInfo);
addLanguage(projectInfo, sourceType);
addLanguageVersion(projectInfo);
addNoStdIncAndNoStdLibInc();
addNoStdIncAndNoStdLibInc(projectInfo.language);
addCompilerMacros(projectInfo.compilerMacros);
addProjectIncludeSearchPaths(
sortedIncludeSearchPaths(projectInfo.projectIncludeSearchPaths));
@@ -76,26 +79,27 @@ public:
commandLine.emplace_back(argument);
}
static const char *language(const ProjectInfo &projectInfo)
static const char *language(const ProjectInfo &projectInfo, InputFileType sourceType)
{
switch (projectInfo.language) {
case Utils::Language::C:
if (projectInfo.languageExtension && Utils::LanguageExtension::ObjectiveC)
return "objective-c-header";
return sourceType == InputFileType::Header ? "objective-c-header" : "objective-c";
return "c-header";
return sourceType == InputFileType::Header ? "c-header" : "c";
case Utils::Language::Cxx:
if (projectInfo.languageExtension && Utils::LanguageExtension::ObjectiveC)
return "objective-c++-header";
return sourceType == InputFileType::Header ? "objective-c++-header"
: "objective-c++";
}
return "c++-header";
return sourceType == InputFileType::Header ? "c++-header" : "c++";
}
void addLanguage(const ProjectInfo &projectInfo)
void addLanguage(const ProjectInfo &projectInfo, InputFileType sourceType)
{
commandLine.emplace_back("-x");
commandLine.emplace_back(language(projectInfo));
commandLine.emplace_back(language(projectInfo, sourceType));
}
const char *standardLanguageVersion(Utils::LanguageVersion languageVersion)
@@ -108,7 +112,7 @@ public:
case Utils::LanguageVersion::C11:
return "-std=c11";
case Utils::LanguageVersion::C18:
return "-std=c18";
return "-std=c17";
case Utils::LanguageVersion::CXX98:
return "-std=c++98";
case Utils::LanguageVersion::CXX03:
@@ -136,7 +140,7 @@ public:
case Utils::LanguageVersion::C11:
return "-std=gnu11";
case Utils::LanguageVersion::C18:
return "-std=gnu18";
return "-std=gnu17";
case Utils::LanguageVersion::CXX98:
return "-std=gnu++98";
case Utils::LanguageVersion::CXX03:
@@ -268,10 +272,11 @@ public:
}
}
void addNoStdIncAndNoStdLibInc()
void addNoStdIncAndNoStdLibInc(Utils::Language language)
{
commandLine.emplace_back("-nostdinc");
commandLine.emplace_back("-nostdinc++");
if (language == Utils::Language::Cxx)
commandLine.emplace_back("-nostdinc++");
}
public:

View File

@@ -26,6 +26,7 @@
#pragma once
#include <functional>
#include <mutex>
namespace ClangBackEnd {
@@ -33,6 +34,7 @@ class ProgressCounter
{
public:
using SetProgressCallback = std::function<void(int, int)>;
using Lock = std::lock_guard<std::mutex>;
ProgressCounter(SetProgressCallback &&progressCallback)
: m_progressCallback(std::move(progressCallback))
@@ -40,6 +42,8 @@ public:
void addTotal(int total)
{
Lock lock(m_mutex);
if (total) {
m_total += total;
@@ -49,6 +53,8 @@ public:
void removeTotal(int total)
{
Lock lock(m_mutex);
if (total) {
m_total -= total;
@@ -58,6 +64,8 @@ public:
void addProgress(int progress)
{
Lock lock(m_mutex);
if (progress) {
m_progress += progress;
@@ -65,6 +73,21 @@ public:
}
}
int total() const
{
Lock lock(m_mutex);
return m_total;
}
int progress() const
{
Lock lock(m_mutex);
return m_total;
}
private:
void sendProgress()
{
m_progressCallback(m_progress, m_total);
@@ -75,17 +98,8 @@ public:
}
}
int total() const
{
return m_total;
}
int progress() const
{
return m_total;
}
private:
mutable std::mutex m_mutex;
std::function<void(int, int)> m_progressCallback;
int m_progress = 0;
int m_total = 0;

View File

@@ -27,14 +27,15 @@
#include "lsputils.h"
#include <utils/mimetypes/mimedatabase.h>
#include <utils/textutils.h>
#include <QFile>
#include <QHash>
#include <QTextBlock>
#include <QTextDocument>
#include <QJsonArray>
#include <QMap>
#include <QTextBlock>
#include <QTextDocument>
#include <QVector>
#include <QFile>
namespace LanguageServerProtocol {
@@ -340,6 +341,24 @@ Range::Range(const Position &start, const Position &end)
setEnd(end);
}
Range::Range(const QTextCursor &cursor)
{
int line, character = 0;
Utils::Text::convertPosition(cursor.document(), cursor.selectionStart(), &line, &character);
if (line <= 0 || character <= 0)
return;
setStart(Position(line - 1, character - 1));
Utils::Text::convertPosition(cursor.document(), cursor.selectionEnd(), &line, &character);
if (line <= 0 || character <= 0)
return;
setEnd(Position(line - 1, character - 1));
}
bool Range::overlaps(const Range &range) const
{
return contains(range.start()) || contains(range.end());
}
bool DocumentFilter::applies(const Utils::FileName &fileName, const Utils::MimeType &mimeType) const
{
if (Utils::optional<QString> _scheme = scheme()) {

View File

@@ -100,6 +100,7 @@ class LANGUAGESERVERPROTOCOL_EXPORT Range : public JsonObject
public:
Range() = default;
Range(const Position &start, const Position &end);
explicit Range(const QTextCursor &cursor);
using JsonObject::JsonObject;
// The range's start position.
@@ -111,6 +112,7 @@ public:
void setEnd(const Position &end) { insert(endKey, end); }
bool contains(const Position &pos) const { return start() <= pos && pos <= end(); }
bool overlaps(const Range &range) const;
bool isValid(QStringList *error) const override
{ return check<Position>(error, startKey) && check<Position>(error, endKey); }

View File

@@ -0,0 +1,99 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "jsontreeitem.h"
#include <QJsonArray>
#include <QJsonObject>
Utils::JsonTreeItem::JsonTreeItem(const QString &displayName, const QJsonValue &value)
: m_name(displayName)
, m_value(value)
{ }
static QString typeName(QJsonValue::Type type)
{
switch (type) {
case QJsonValue::Null:
return Utils::JsonTreeItem::tr("Null");
case QJsonValue::Bool:
return Utils::JsonTreeItem::tr("Bool");
case QJsonValue::Double:
return Utils::JsonTreeItem::tr("Double");
case QJsonValue::String:
return Utils::JsonTreeItem::tr("String");
case QJsonValue::Array:
return Utils::JsonTreeItem::tr("Array");
case QJsonValue::Object:
return Utils::JsonTreeItem::tr("Object");
case QJsonValue::Undefined:
return Utils::JsonTreeItem::tr("Undefined");
}
return {};
}
QVariant Utils::JsonTreeItem::data(int column, int role) const
{
if (role != Qt::DisplayRole)
return {};
if (column == 0)
return m_name;
if (column == 2)
return typeName(m_value.type());
if (m_value.isObject())
return QString('[' + QString::number(m_value.toObject().size()) + ' ' + tr("Items") + ']');
if (m_value.isArray())
return QString('[' + QString::number(m_value.toArray().size()) + ' ' + tr("Items") + ']');
return m_value.toVariant();
}
bool Utils::JsonTreeItem::canFetchMore() const
{
return canFetchObjectChildren() || canFetchArrayChildren();
}
void Utils::JsonTreeItem::fetchMore()
{
if (canFetchObjectChildren()) {
const QJsonObject &object = m_value.toObject();
for (const QString &key : object.keys())
appendChild(new JsonTreeItem(key, object.value(key)));
} else if (canFetchArrayChildren()) {
int index = 0;
const QJsonArray &array = m_value.toArray();
for (const QJsonValue &val : array)
appendChild(new JsonTreeItem(QString::number(index++), val));
}
}
bool Utils::JsonTreeItem::canFetchObjectChildren() const
{
return m_value.isObject() && m_value.toObject().size() > childCount();
}
bool Utils::JsonTreeItem::canFetchArrayChildren() const
{
return m_value.isArray() && m_value.toArray().size() > childCount();
}

View File

@@ -0,0 +1,56 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "treemodel.h"
#include "utils_global.h"
#include <QJsonValue>
#include <QCoreApplication>
namespace Utils {
class QTCREATOR_UTILS_EXPORT JsonTreeItem : public TypedTreeItem<JsonTreeItem>
{
Q_DECLARE_TR_FUNCTIONS(JsonTreeModelItem)
public:
JsonTreeItem() = default;
JsonTreeItem(const QString &displayName, const QJsonValue &value);
QVariant data(int column, int role) const override;
bool canFetchMore() const override;
void fetchMore() override;
private:
bool canFetchObjectChildren() const;
bool canFetchArrayChildren() const;
QString m_name;
QJsonValue m_value;
};
} // namespace Utils

View File

@@ -263,6 +263,7 @@ void ToolTip::showInternal(const QPoint &pos, const QVariant &content,
m_tip = new WidgetTip(target);
break;
}
m_tip->setObjectName("qcToolTip");
m_tip->setContent(content);
m_tip->setContextHelp(contextHelp);
setUp(pos, w, rect);

View File

@@ -124,7 +124,9 @@ SOURCES += \
$$PWD/filecrumblabel.cpp \
$$PWD/fixedsizeclicklabel.cpp \
$$PWD/removefiledialog.cpp \
$$PWD/differ.cpp
$$PWD/differ.cpp \
$$PWD/jsontreeitem.cpp
win32:SOURCES += $$PWD/consoleprocess_win.cpp
else:SOURCES += $$PWD/consoleprocess_unix.cpp
@@ -265,7 +267,8 @@ HEADERS += \
$$PWD/fixedsizeclicklabel.h \
$$PWD/removefiledialog.h \
$$PWD/differ.h \
$$PWD/cpplanguage_details.h
$$PWD/cpplanguage_details.h \
$$PWD/jsontreeitem.h
FORMS += $$PWD/filewizardpage.ui \
$$PWD/newclasswidget.ui \

View File

@@ -142,6 +142,8 @@ Project {
"itemviews.h",
"json.cpp",
"json.h",
"jsontreeitem.cpp",
"jsontreeitem.h",
"linecolumn.h",
"link.h",
"listutils.h",

View File

@@ -93,79 +93,6 @@ ClangHoverHandler::~ClangHoverHandler()
abort();
}
static int skipChars(QTextCursor *tc,
QTextCursor::MoveOperation op,
int offset,
std::function<bool(const QChar &)> skip)
{
const QTextDocument *doc = tc->document();
QChar ch = doc->characterAt(tc->position() + offset);
if (ch.isNull())
return 0;
int count = 0;
while (skip(ch)) {
if (tc->movePosition(op))
++count;
else
break;
ch = doc->characterAt(tc->position() + offset);
}
return count;
}
static int skipCharsForward(QTextCursor *tc, std::function<bool(const QChar &)> skip)
{
return skipChars(tc, QTextCursor::NextCharacter, 0, skip);
}
static int skipCharsBackward(QTextCursor *tc, std::function<bool(const QChar &)> skip)
{
return skipChars(tc, QTextCursor::PreviousCharacter, -1, skip);
}
static QStringList fallbackWords(QTextDocument *document, int pos)
{
const auto isSpace = [](const QChar &c) { return c.isSpace(); };
const auto isColon = [](const QChar &c) { return c == ':'; };
const auto isValidIdentifierChar = [document](const QTextCursor &tc) {
return CppTools::isValidIdentifierChar(document->characterAt(tc.position()));
};
// move to the end
QTextCursor endCursor(document);
endCursor.setPosition(pos);
do {
CppTools::moveCursorToEndOfIdentifier(&endCursor);
// possibly skip ::
QTextCursor temp(endCursor);
skipCharsForward(&temp, isSpace);
const int colons = skipCharsForward(&temp, isColon);
skipCharsForward(&temp, isSpace);
if (colons == 2 && isValidIdentifierChar(temp))
endCursor = temp;
} while (isValidIdentifierChar(endCursor));
QStringList results;
QTextCursor startCursor(endCursor);
do {
CppTools::moveCursorToStartOfIdentifier(&startCursor);
if (startCursor.position() == endCursor.position())
break;
QTextCursor temp(endCursor);
temp.setPosition(startCursor.position(), QTextCursor::KeepAnchor);
results.append(temp.selectedText().remove(QRegularExpression("\\s")));
// possibly skip ::
temp = startCursor;
skipCharsBackward(&temp, isSpace);
const int colons = skipCharsBackward(&temp, isColon);
skipCharsBackward(&temp, isSpace);
if (colons == 2
&& CppTools::isValidIdentifierChar(document->characterAt(temp.position() - 1))) {
startCursor = temp;
}
} while (!isValidIdentifierChar(startCursor));
return results;
}
void ClangHoverHandler::identifyMatch(TextEditorWidget *editorWidget,
int pos,
BaseHoverHandler::ReportPriority report)
@@ -187,7 +114,9 @@ void ClangHoverHandler::identifyMatch(TextEditorWidget *editorWidget,
qCDebug(hoverLog) << "Requesting tooltip info at" << pos;
m_reportPriority = report;
m_futureWatcher.reset(new QFutureWatcher<CppTools::ToolTipInfo>());
const QStringList fallback = fallbackWords(editorWidget->document(), pos);
QTextCursor tc(editorWidget->document());
tc.setPosition(pos);
const QStringList fallback = CppTools::identifierWordsUnderCursor(tc);
QObject::connect(m_futureWatcher.data(),
&QFutureWatcherBase::finished,
[this, fallback]() {

View File

@@ -36,16 +36,27 @@
namespace ClangFormat {
static void adjustFormatStyleForLineBreak(clang::format::FormatStyle &style)
static void adjustFormatStyleForLineBreak(clang::format::FormatStyle &style,
ReplacementsToKeep replacementsToKeep)
{
if (replacementsToKeep == ReplacementsToKeep::All)
return;
style.MaxEmptyLinesToKeep = 2;
style.SortIncludes = false;
style.SortUsingDeclarations = false;
// This is a separate pass, don't do it unless it's the full formatting.
style.FixNamespaceComments = false;
if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore)
return;
style.DisableFormat = false;
style.ColumnLimit = 0;
#ifdef KEEP_LINE_BREAKS_FOR_NON_EMPTY_LINES_BACKPORTED
style.KeepLineBreaksForNonEmptyLines = true;
#endif
style.MaxEmptyLinesToKeep = 2;
style.SortIncludes = false;
style.SortUsingDeclarations = false;
}
static llvm::StringRef clearExtraNewline(llvm::StringRef text)
@@ -59,7 +70,6 @@ static clang::tooling::Replacements filteredReplacements(
const clang::tooling::Replacements &replacements,
int offset,
int utf8LineLengthBeforeCursor,
int extraOffsetFromStartOfFile,
int extraEmptySpaceOffset,
ReplacementsToKeep replacementsToKeep)
{
@@ -69,14 +79,13 @@ static clang::tooling::Replacements filteredReplacements(
const bool replacementDoesNotMatchRestriction
= (replacementsToKeep == ReplacementsToKeep::OnlyIndent
&& replacementOffset != offset - 1)
|| (replacementsToKeep == ReplacementsToKeep::OnlyBeforeIndent
&& replacementOffset >= offset + utf8LineLengthBeforeCursor - 1);
|| (replacementsToKeep == ReplacementsToKeep::IndentAndBefore
&& replacementOffset > offset + utf8LineLengthBeforeCursor - 1);
if (replacementDoesNotMatchRestriction)
continue;
if (replacementOffset >= offset - 1)
replacementOffset += extraEmptySpaceOffset;
replacementOffset += extraOffsetFromStartOfFile;
llvm::StringRef text = replacementsToKeep == ReplacementsToKeep::OnlyIndent
? clearExtraNewline(replacement.getReplacementText())
@@ -128,18 +137,6 @@ static void trimFirstNonEmptyBlock(const QTextBlock &currentBlock)
cursor.endEditBlock();
}
static void trimCurrentBlock(const QTextBlock &currentBlock)
{
if (currentBlock.text().trimmed().isEmpty()) {
// Clear the block containing only spaces
QTextCursor cursor(currentBlock);
cursor.beginEditBlock();
cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
cursor.removeSelectedText();
cursor.endEditBlock();
}
}
// Returns the total langth of previous lines with pure whitespace.
static int previousEmptyLinesLength(const QTextBlock &currentBlock)
{
@@ -167,7 +164,7 @@ static void modifyToIndentEmptyLines(
if (firstNonWhitespace < 0 || closingParenBlock) {
//This extra text works for the most cases.
QByteArray dummyText("a;");
QByteArray dummyText("a;a;");
// Search for previous character
QTextBlock prevBlock = block.previous();
@@ -198,8 +195,6 @@ static void modifyToIndentEmptyLines(
}
}
static const int kMaxLinesFromCurrentBlock = 200;
static Utils::LineColumn utf16LineColumn(const QTextBlock &block,
int blockOffsetUtf8,
const QByteArray &utf8Buffer,
@@ -388,24 +383,21 @@ TextEditor::Replacements ClangFormatBaseIndenter::format(
return format(cursor, cursorPositionInEditor);
}
int ClangFormatBaseIndenter::indentBeforeCursor(const QTextBlock &block,
const QChar &typedChar,
int cursorPositionInEditor)
void ClangFormatBaseIndenter::indentBeforeCursor(const QTextBlock &block,
const QChar &typedChar,
int cursorPositionInEditor)
{
const QByteArray buffer = m_doc->toPlainText().toUtf8();
const int utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
QTC_ASSERT(utf8Offset >= 0, return cursorPositionInEditor;);
QTC_ASSERT(utf8Offset >= 0, return;);
const TextEditor::Replacements toReplace = replacements(buffer,
utf8Offset,
0,
block,
cursorPositionInEditor,
ReplacementsToKeep::OnlyBeforeIndent,
ReplacementsToKeep::IndentAndBefore,
typedChar);
applyReplacements(block, toReplace);
for (const TextEditor::Replacement &replacement : toReplace)
cursorPositionInEditor += replacement.text.length() - replacement.length;
return cursorPositionInEditor;
}
static bool doNotIndentInContext(QTextDocument *doc, int pos)
@@ -466,11 +458,10 @@ void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
else
cursorPositionInEditor = currentBlock.position();
cursorPositionInEditor = indentBeforeCursor(currentBlock, typedChar, cursorPositionInEditor);
currentBlock = m_doc->findBlock(cursorPositionInEditor);
indentBeforeCursor(currentBlock, typedChar, cursorPositionInEditor);
return;
}
trimCurrentBlock(currentBlock);
const QByteArray buffer = m_doc->toPlainText().toUtf8();
const int utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
QTC_ASSERT(utf8Offset >= 0, return;);
@@ -496,7 +487,6 @@ void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
int ClangFormatBaseIndenter::indentFor(const QTextBlock &block, int cursorPositionInEditor)
{
trimFirstNonEmptyBlock(block);
trimCurrentBlock(block);
const QByteArray buffer = m_doc->toPlainText().toUtf8();
const int utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
QTC_ASSERT(utf8Offset >= 0, return 0;);
@@ -571,8 +561,7 @@ static int formattingRangeStart(const QTextBlock &currentBlock,
{
QTextBlock prevBlock = currentBlock.previous();
while ((prevBlock.position() > 0 || prevBlock.length() > 0)
&& prevBlock.revision() != documentRevision
&& (currentBlock.blockNumber() - prevBlock.blockNumber() < kMaxLinesFromCurrentBlock)) {
&& prevBlock.revision() != documentRevision) {
// Find the first block with not matching revision.
prevBlock = prevBlock.previous();
}
@@ -604,41 +593,27 @@ TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer
= block.text().left(cursorPositionInEditor - block.position()).toUtf8().size();
}
int extraOffsetFromStartOfFile = 0;
int extraEmptySpaceOffset = 0;
int rangeStart = 0;
if (replacementsToKeep != ReplacementsToKeep::All) {
if (block.blockNumber() > kMaxLinesFromCurrentBlock) {
extraOffsetFromStartOfFile
= Utils::Text::utf8NthLineOffset(block.document(),
buffer,
block.blockNumber() - kMaxLinesFromCurrentBlock);
}
int endOffset = Utils::Text::utf8NthLineOffset(block.document(),
buffer,
block.blockNumber()
+ kMaxLinesFromCurrentBlock);
if (endOffset == -1)
endOffset = buffer.size();
if (replacementsToKeep == ReplacementsToKeep::OnlyBeforeIndent)
if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore)
rangeStart = formattingRangeStart(block, buffer, lastSaveRevision());
buffer = buffer.mid(extraOffsetFromStartOfFile, endOffset - extraOffsetFromStartOfFile);
utf8Offset -= extraOffsetFromStartOfFile;
rangeStart -= extraOffsetFromStartOfFile;
extraEmptySpaceOffset = previousEmptyLinesLength(block);
utf8Offset -= extraEmptySpaceOffset;
buffer.remove(utf8Offset, extraEmptySpaceOffset);
if (replacementsToKeep == ReplacementsToKeep::OnlyIndent)
adjustFormatStyleForLineBreak(style);
adjustFormatStyleForLineBreak(style, replacementsToKeep);
modifyToIndentEmptyLines(buffer, utf8Offset, utf8Length, block, secondTry);
if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore) {
buffer.insert(utf8Offset - 1, " //");
extraEmptySpaceOffset -= 3;
utf8Offset += 3;
}
}
if (replacementsToKeep != ReplacementsToKeep::OnlyBeforeIndent || utf8Offset < rangeStart)
if (replacementsToKeep != ReplacementsToKeep::IndentAndBefore || utf8Offset < rangeStart)
rangeStart = utf8Offset;
unsigned int rangeLength = static_cast<unsigned int>(utf8Offset + utf8Length - rangeStart);
@@ -658,7 +633,6 @@ TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer
filtered = filteredReplacements(clangReplacements,
utf8Offset,
utf8LineLengthBeforeCursor,
extraOffsetFromStartOfFile,
extraEmptySpaceOffset,
replacementsToKeep);
}

View File

@@ -31,7 +31,7 @@
namespace ClangFormat {
enum class ReplacementsToKeep { OnlyIndent, OnlyBeforeIndent, All };
enum class ReplacementsToKeep { OnlyIndent, IndentAndBefore, All };
class ClangFormatBaseIndenter : public TextEditor::Indenter
{
@@ -79,9 +79,9 @@ private:
void indent(const QTextCursor &cursor, const QChar &typedChar, int cursorPositionInEditor);
void indentBlock(const QTextBlock &block, const QChar &typedChar, int cursorPositionInEditor);
int indentFor(const QTextBlock &block, int cursorPositionInEditor);
int indentBeforeCursor(const QTextBlock &block,
const QChar &typedChar,
int cursorPositionInEditor);
void indentBeforeCursor(const QTextBlock &block,
const QChar &typedChar,
int cursorPositionInEditor);
TextEditor::Replacements replacements(QByteArray buffer,
int utf8Offset,
int utf8Length,

View File

@@ -52,7 +52,7 @@
</layout>
</item>
<item>
<widget class="ClangTools::ClangToolsBasicSettings" name="clangToolsBasicSettings" native="true"/>
<widget class="ClangTools::Internal::ClangToolsBasicSettings" name="clangToolsBasicSettings" native="true"/>
</item>
</layout>
</widget>
@@ -87,7 +87,7 @@
</widget>
<customwidgets>
<customwidget>
<class>ClangTools::ClangToolsBasicSettings</class>
<class>ClangTools::Internal::ClangToolsBasicSettings</class>
<extends>QWidget</extends>
<header>clangtools/clangtoolsbasicsettings.h</header>
</customwidget>

View File

@@ -219,7 +219,7 @@ ClangTidyClazyTool::ClangTidyClazyTool()
m_diagnosticView->sortByColumn(Debugger::DetailedErrorView::DiagnosticColumn,
Qt::AscendingOrder);
m_diagnosticView->setObjectName(QLatin1String("ClangTidyClazyIssuesView"));
m_diagnosticView->setWindowTitle(tr("Clang-Tidy and Clazy Issues"));
m_diagnosticView->setWindowTitle(tr("Clang-Tidy and Clazy Diagnostics"));
foreach (auto * const model,
QList<QAbstractItemModel *>({m_diagnosticModel, m_diagnosticFilterModel})) {
@@ -281,7 +281,7 @@ ClangTidyClazyTool::ClangTidyClazyTool()
// Filter line edit
m_filterLineEdit = new Utils::FancyLineEdit();
m_filterLineEdit->setFiltering(true);
m_filterLineEdit->setPlaceholderText(tr("Filter Issues"));
m_filterLineEdit->setPlaceholderText(tr("Filter Diagnostics"));
m_filterLineEdit->setHistoryCompleter("CppTools.ClangTidyClazyIssueFilter", true);
connect(m_filterLineEdit, &Utils::FancyLineEdit::filterChanged, [this](const QString &filter) {
m_diagnosticFilterModel->setFilterRegExp(
@@ -309,7 +309,7 @@ ClangTidyClazyTool::ClangTidyClazyTool()
ActionContainer *menu = ActionManager::actionContainer(Debugger::Constants::M_DEBUG_ANALYZER);
const QString toolTip = tr("Clang-Tidy and Clazy use a customized Clang executable from the "
"Clang project to search for errors and warnings.");
"Clang project to search for diagnostics.");
m_perspective.addWindow(m_diagnosticView, Perspective::SplitVertical, nullptr);
@@ -450,14 +450,14 @@ void ClangTidyClazyTool::handleStateUpdate()
QString message;
if (m_running) {
if (issuesFound)
message = tr("Running - %n issues found", nullptr, issuesFound);
message = tr("Running - %n diagnostics", nullptr, issuesFound);
else
message = tr("Running - No issues found", nullptr, issuesFound);
message = tr("Running - No diagnostics", nullptr, issuesFound);
} else {
if (issuesFound)
message = tr("Finished - %n issues found", nullptr, issuesFound);
message = tr("Finished - %n diagnostics", nullptr, issuesFound);
else
message = tr("Finished - No issues found", nullptr, issuesFound);
message = tr("Finished - No diagnostics", nullptr, issuesFound);
}
Debugger::showPermanentStatusMessage(message);

View File

@@ -46,6 +46,7 @@
#include <projectexplorer/target.h>
#include <projectexplorer/session.h>
#include <utils/algorithm.h>
#include <utils/fancymainwindow.h>
#include <utils/utilsicons.h>
@@ -137,7 +138,10 @@ void ClangTool::initDiagnosticView()
QSet<Diagnostic> ClangTool::diagnostics() const
{
return m_diagnosticModel->diagnostics();
return Utils::filtered(m_diagnosticModel->diagnostics(), [](const Diagnostic &diagnostic) {
using CppTools::ProjectFile;
return ProjectFile::isSource(ProjectFile::classify(diagnostic.location.filePath));
});
}
void ClangTool::onNewDiagnosticsAvailable(const QList<Diagnostic> &diagnostics)

View File

@@ -267,6 +267,8 @@ void ClangToolRunControl::init()
void ClangToolRunControl::start()
{
TaskHub::clearTasks(Debugger::Constants::ANALYZERTASK_ID);
if (ClangToolsSettings::instance()->savedBuildBeforeAnalysis()) {
QTC_ASSERT(m_projectBuilder, return;);
if (!m_projectBuilder->success()) {
@@ -441,7 +443,7 @@ void ClangToolRunControl::onRunnerFinishedWithFailure(const QString &errorMessag
m_success = false;
appendMessage(message, Utils::StdErrFormat);
appendMessage(errorDetails, Utils::StdErrFormat);
TaskHub::addTask(Task::Warning, message, Debugger::Constants::ANALYZERTASK_ID);
TaskHub::addTask(Task::Error, message, Debugger::Constants::ANALYZERTASK_ID);
handleFinished();
}

View File

@@ -29,6 +29,7 @@
#include "clangtoolsutils.h"
namespace ClangTools {
namespace Internal {
ClangToolsBasicSettings::ClangToolsBasicSettings(QWidget *parent)
: QWidget(parent)
@@ -47,4 +48,5 @@ Ui::ClangToolsBasicSettings *ClangToolsBasicSettings::ui()
return m_ui;
}
} // namespace Internal
} // namespace ClangTools

View File

@@ -28,6 +28,7 @@
#include <QWidget>
namespace ClangTools {
namespace Internal {
namespace Ui { class ClangToolsBasicSettings; }
@@ -46,4 +47,5 @@ private:
Ui::ClangToolsBasicSettings *m_ui;
};
} // namespace Internal
} // namespace ClangTools

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ClangTools::ClangToolsBasicSettings</class>
<widget class="QWidget" name="ClangTools::ClangToolsBasicSettings">
<class>ClangTools::Internal::ClangToolsBasicSettings</class>
<widget class="QWidget" name="ClangTools::Internal::ClangToolsBasicSettings">
<property name="geometry">
<rect>
<x>0</x>

View File

@@ -21,7 +21,7 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="ClangTools::ClangToolsBasicSettings" name="clangToolsBasicSettings" native="true"/>
<widget class="ClangTools::Internal::ClangToolsBasicSettings" name="clangToolsBasicSettings" native="true"/>
</item>
<item>
<layout class="QHBoxLayout" name="processesLayout">
@@ -77,7 +77,7 @@
</widget>
<customwidgets>
<customwidget>
<class>ClangTools::ClangToolsBasicSettings</class>
<class>ClangTools::Internal::ClangToolsBasicSettings</class>
<extends>QWidget</extends>
<header>clangtools/clangtoolsbasicsettings.h</header>
</customwidget>

View File

@@ -84,7 +84,7 @@ ClangToolsDiagnosticModel::ClangToolsDiagnosticModel(QObject *parent)
: Utils::TreeModel<>(parent)
, m_filesWatcher(std::make_unique<QFileSystemWatcher>())
{
setHeader({tr("Issue"), tr("Fixit Status")});
setHeader({tr("Diagnostic")});
connectFileWatcher();
}
@@ -192,7 +192,26 @@ void ClangToolsDiagnosticModel::addWatchedPath(const QString &path)
m_filesWatcher->addPath(path);
}
static QString createDiagnosticToolTipString(const Diagnostic &diagnostic)
static QString fixitStatus(FixitStatus status)
{
switch (status) {
case FixitStatus::NotAvailable:
return ClangToolsDiagnosticModel::tr("No Fixits");
case FixitStatus::NotScheduled:
return ClangToolsDiagnosticModel::tr("Not Scheduled");
case FixitStatus::Invalidated:
return ClangToolsDiagnosticModel::tr("Invalidated");
case FixitStatus::Scheduled:
return ClangToolsDiagnosticModel::tr("Scheduled");
case FixitStatus::FailedToApply:
return ClangToolsDiagnosticModel::tr("Failed to Apply");
case FixitStatus::Applied:
return ClangToolsDiagnosticModel::tr("Applied");
}
return QString();
}
static QString createDiagnosticToolTipString(const Diagnostic &diagnostic, FixitStatus fixItStatus)
{
using StringPair = QPair<QString, QString>;
QList<StringPair> lines;
@@ -226,6 +245,10 @@ static QString createDiagnosticToolTipString(const Diagnostic &diagnostic)
QCoreApplication::translate("ClangTools::Diagnostic", "Location:"),
createFullLocationString(diagnostic.location));
lines << qMakePair(
QCoreApplication::translate("ClangTools::Diagnostic", "Fixit Status:"),
fixitStatus(fixItStatus));
QString html = QLatin1String("<html>"
"<head>"
"<style>dt { font-weight:bold; } dd { font-family: monospace; }</style>\n"
@@ -364,19 +387,8 @@ DiagnosticItem::~DiagnosticItem()
Qt::ItemFlags DiagnosticItem::flags(int column) const
{
const Qt::ItemFlags itemFlags = TreeItem::flags(column);
if (column == DiagnosticView::FixItColumn) {
switch (m_fixitStatus) {
case FixitStatus::NotAvailable:
case FixitStatus::Applied:
case FixitStatus::FailedToApply:
case FixitStatus::Invalidated:
return itemFlags & ~Qt::ItemIsEnabled;
case FixitStatus::Scheduled:
case FixitStatus::NotScheduled:
return itemFlags | Qt::ItemIsUserCheckable;
}
}
if (column == DiagnosticView::DiagnosticColumn)
return itemFlags | Qt::ItemIsUserCheckable;
return itemFlags;
}
@@ -395,35 +407,7 @@ static QVariant iconData(const QString &type)
QVariant DiagnosticItem::data(int column, int role) const
{
if (column == DiagnosticView::FixItColumn) {
if (role == Qt::CheckStateRole) {
switch (m_fixitStatus) {
case FixitStatus::NotAvailable:
case FixitStatus::NotScheduled:
case FixitStatus::Invalidated:
case FixitStatus::Applied:
case FixitStatus::FailedToApply:
return Qt::Unchecked;
case FixitStatus::Scheduled:
return Qt::Checked;
}
} else if (role == Qt::DisplayRole) {
switch (m_fixitStatus) {
case FixitStatus::NotAvailable:
return ClangToolsDiagnosticModel::tr("No Fixits");
case FixitStatus::NotScheduled:
return ClangToolsDiagnosticModel::tr("Not Scheduled");
case FixitStatus::Invalidated:
return ClangToolsDiagnosticModel::tr("Invalidated");
case FixitStatus::Scheduled:
return ClangToolsDiagnosticModel::tr("Scheduled");
case FixitStatus::FailedToApply:
return ClangToolsDiagnosticModel::tr("Failed to Apply");
case FixitStatus::Applied:
return ClangToolsDiagnosticModel::tr("Applied");
}
}
} else if (column == DiagnosticView::DiagnosticColumn) {
if (column == DiagnosticView::DiagnosticColumn) {
switch (role) {
case Debugger::DetailedErrorView::LocationRole:
return QVariant::fromValue(m_diagnostic.location);
@@ -433,11 +417,36 @@ QVariant DiagnosticItem::data(int column, int role) const
return QVariant::fromValue(m_diagnostic);
case ClangToolsDiagnosticModel::TextRole:
return m_diagnostic.description;
case ClangToolsDiagnosticModel::CheckBoxEnabledRole:
switch (m_fixitStatus) {
case FixitStatus::NotAvailable:
case FixitStatus::Applied:
case FixitStatus::FailedToApply:
case FixitStatus::Invalidated:
return false;
case FixitStatus::Scheduled:
case FixitStatus::NotScheduled:
return true;
}
break;
case Qt::CheckStateRole: {
switch (m_fixitStatus) {
case FixitStatus::NotAvailable:
case FixitStatus::Invalidated:
case FixitStatus::Applied:
case FixitStatus::FailedToApply:
case FixitStatus::NotScheduled:
return Qt::Unchecked;
case FixitStatus::Scheduled:
return Qt::Checked;
}
break;
}
case Qt::DisplayRole:
return QString("%1: %2").arg(lineColumnString(m_diagnostic.location),
m_diagnostic.description);
case Qt::ToolTipRole:
return createDiagnosticToolTipString(m_diagnostic);
return createDiagnosticToolTipString(m_diagnostic, m_fixitStatus);
case Qt::DecorationRole:
return iconData(m_diagnostic.type);
default:
@@ -450,7 +459,7 @@ QVariant DiagnosticItem::data(int column, int role) const
bool DiagnosticItem::setData(int column, const QVariant &data, int role)
{
if (column == DiagnosticView::FixItColumn && role == Qt::CheckStateRole) {
if (column == DiagnosticView::DiagnosticColumn && role == Qt::CheckStateRole) {
if (m_fixitStatus != FixitStatus::Scheduled && m_fixitStatus != FixitStatus::NotScheduled)
return false;
@@ -494,15 +503,6 @@ ExplainingStepItem::ExplainingStepItem(const ExplainingStep &step, int index)
, m_index(index)
{}
// We expect something like "note: ..."
static QVariant iconForExplainingStepMessage(const QString &message)
{
const int index = message.indexOf(':');
if (index == -1)
return QVariant();
return iconData(message.mid(0, index));
}
static QString rangeString(const QVector<Debugger::DiagnosticLocation> &ranges)
{
return QString("%1-%2").arg(lineColumnString(ranges[0]), lineColumnString(ranges[1]));
@@ -510,9 +510,6 @@ static QString rangeString(const QVector<Debugger::DiagnosticLocation> &ranges)
QVariant ExplainingStepItem::data(int column, int role) const
{
if (column == DiagnosticView::FixItColumn)
return QVariant();
if (column == DiagnosticView::DiagnosticColumn) {
// DiagnosticColumn
switch (role) {
@@ -555,7 +552,7 @@ QVariant ExplainingStepItem::data(int column, int role) const
case Qt::DecorationRole:
if (m_step.isFixIt)
return Utils::Icons::CODEMODEL_FIXIT.icon();
return iconForExplainingStepMessage(m_step.message);
return Utils::Icons::INFO.icon();
default:
return QVariant();
}

View File

@@ -112,7 +112,11 @@ public:
void addDiagnostics(const QList<Diagnostic> &diagnostics);
QSet<Diagnostic> diagnostics() const;
enum ItemRole { DiagnosticRole = Debugger::DetailedErrorView::FullTextRole + 1, TextRole };
enum ItemRole {
DiagnosticRole = Debugger::DetailedErrorView::FullTextRole + 1,
TextRole,
CheckBoxEnabledRole
};
void clear();
void removeWatchedPath(const QString &path);

View File

@@ -30,11 +30,13 @@
#include "clangtoolsutils.h"
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/manhattanstyle.h>
#include <utils/fileutils.h>
#include <utils/qtcassert.h>
#include <QAction>
#include <QApplication>
#include <QDebug>
#include <QHeaderView>
#include <QPainter>
@@ -44,21 +46,22 @@ using namespace Debugger;
namespace ClangTools {
namespace Internal {
class ClickableFixItHeader : public QHeaderView
// A header view that puts a check box in front of a given column.
class HeaderWithCheckBoxInColumn : public QHeaderView
{
Q_OBJECT
public:
ClickableFixItHeader(Qt::Orientation orientation, QWidget *parent = nullptr)
HeaderWithCheckBoxInColumn(Qt::Orientation orientation,
int column = 0,
QWidget *parent = nullptr)
: QHeaderView(orientation, parent)
, m_column(column)
{
setDefaultAlignment(Qt::AlignLeft);
}
void setState(QFlags<QStyle::StateFlag> newState)
{
state = newState;
}
void setState(QFlags<QStyle::StateFlag> newState) { state = newState; }
protected:
void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const override
@@ -66,7 +69,7 @@ protected:
painter->save();
QHeaderView::paintSection(painter, rect, logicalIndex);
painter->restore();
if (logicalIndex == DiagnosticView::FixItColumn) {
if (logicalIndex == m_column) {
QStyleOptionButton option;
const int side = sizeHint().height();
option.rect = QRect(rect.left() + 1, 1, side - 3, side - 3);
@@ -83,34 +86,111 @@ protected:
void mouseReleaseEvent(QMouseEvent *event) override
{
const int x = event->localPos().x();
const int fixItColumnX = sectionPosition(DiagnosticView::FixItColumn);
const bool isWithinFixitCheckBox = x > fixItColumnX
&& x < fixItColumnX + sizeHint().height() - 3;
if (isWithinFixitCheckBox) {
const int columnX = sectionPosition(m_column);
const bool isWithinCheckBox = x > columnX && x < columnX + sizeHint().height() - 3;
if (isWithinCheckBox) {
state = (state != QStyle::State_On) ? QStyle::State_On : QStyle::State_Off;
viewport()->update();
emit fixItColumnClicked(state == QStyle::State_On);
emit checkBoxClicked(state == QStyle::State_On);
return; // Avoid changing sort order
}
QHeaderView::mouseReleaseEvent(event);
}
signals:
void fixItColumnClicked(bool checked);
void checkBoxClicked(bool checked);
private:
const int m_column = 0;
QFlags<QStyle::StateFlag> state = QStyle::State_Off;
};
static QString getBaseStyleName()
{
QStyle *style = QApplication::style();
if (auto proxyStyle = qobject_cast<QProxyStyle *>(style))
style = proxyStyle->baseStyle();
return style->objectName();
}
// Paints the check box indicator disabled if requested by client.
class DiagnosticViewStyle : public ManhattanStyle
{
public:
DiagnosticViewStyle(const QString &baseStyleName = getBaseStyleName())
: ManhattanStyle(baseStyleName)
{}
void setPaintCheckBoxDisabled(bool paintDisabledCheckbox)
{
m_paintCheckBoxDisabled = paintDisabledCheckbox;
}
void drawPrimitive(PrimitiveElement element,
const QStyleOption *option,
QPainter *painter,
const QWidget *widget = nullptr) const final
{
if (element == QStyle::PE_IndicatorCheckBox && m_paintCheckBoxDisabled) {
if (const QStyleOptionButton *o = qstyleoption_cast<const QStyleOptionButton *>(
option)) {
QStyleOptionButton myOption = *o;
myOption.palette.setCurrentColorGroup(QPalette::Disabled);
ManhattanStyle::drawPrimitive(element, &myOption, painter, widget);
return;
}
}
ManhattanStyle::drawPrimitive(element, option, painter, widget);
}
private:
bool m_paintCheckBoxDisabled = false;
};
// A delegate that allows to paint a disabled check box (indicator).
// This is useful if the rest of the item should not be disabled.
class DiagnosticViewDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
DiagnosticViewDelegate(DiagnosticViewStyle *style)
: m_style(style)
{}
void paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const final
{
const bool paintDisabled = !index.data(ClangToolsDiagnosticModel::CheckBoxEnabledRole)
.toBool();
if (paintDisabled)
m_style->setPaintCheckBoxDisabled(true);
QStyledItemDelegate::paint(painter, option, index);
if (paintDisabled)
m_style->setPaintCheckBoxDisabled(false);
}
private:
DiagnosticViewStyle *m_style = nullptr;
};
DiagnosticView::DiagnosticView(QWidget *parent)
: Debugger::DetailedErrorView(parent)
, m_style(new DiagnosticViewStyle)
, m_delegate(new DiagnosticViewDelegate(m_style.get()))
{
m_suppressAction = new QAction(tr("Suppress This Diagnostic"), this);
connect(m_suppressAction, &QAction::triggered,
this, &DiagnosticView::suppressCurrentDiagnostic);
installEventFilter(this);
setStyle(m_style.get());
setItemDelegate(m_delegate.get());
}
DiagnosticView::~DiagnosticView() = default;
void DiagnosticView::suppressCurrentDiagnostic()
{
const QModelIndexList indexes = selectionModel()->selectedRows();
@@ -199,7 +279,6 @@ bool DiagnosticView::eventFilter(QObject *watched, QEvent *event)
switch (key) {
case Qt::Key_Return:
case Qt::Key_Enter:
case Qt::Key_Space:
openEditorForCurrentIndex();
}
return true;
@@ -219,11 +298,11 @@ void DiagnosticView::setSelectedFixItsCount(int fixItsCount)
{
if (m_ignoreSetSelectedFixItsCount)
return;
auto *clickableFixItHeader = static_cast<ClickableFixItHeader *>(header());
clickableFixItHeader->setState(fixItsCount
? (QStyle::State_NoChange | QStyle::State_On | QStyle::State_Off)
: QStyle::State_Off);
clickableFixItHeader->viewport()->update();
auto checkBoxHeader = static_cast<HeaderWithCheckBoxInColumn *>(header());
checkBoxHeader->setState(fixItsCount
? (QStyle::State_NoChange | QStyle::State_On | QStyle::State_Off)
: QStyle::State_Off);
checkBoxHeader->viewport()->update();
}
void DiagnosticView::openEditorForCurrentIndex()
@@ -237,28 +316,31 @@ void DiagnosticView::openEditorForCurrentIndex()
void DiagnosticView::setModel(QAbstractItemModel *theProxyModel)
{
const auto proxyModel = static_cast<QSortFilterProxyModel *>(theProxyModel);
const auto sourceModel = static_cast<ClangToolsDiagnosticModel *>(proxyModel->sourceModel());
Debugger::DetailedErrorView::setModel(proxyModel);
auto *clickableFixItHeader = new ClickableFixItHeader(Qt::Horizontal, this);
connect(clickableFixItHeader, &ClickableFixItHeader::fixItColumnClicked, this, [=](bool checked) {
auto *header = new HeaderWithCheckBoxInColumn(Qt::Horizontal,
DiagnosticView::DiagnosticColumn,
this);
connect(header, &HeaderWithCheckBoxInColumn::checkBoxClicked, this, [=](bool checked) {
m_ignoreSetSelectedFixItsCount = true;
sourceModel->rootItem()->forChildrenAtLevel(2, [&](::Utils::TreeItem *item) {
auto diagnosticItem = static_cast<DiagnosticItem *>(item);
diagnosticItem->setData(FixItColumn,
checked ? Qt::Checked : Qt::Unchecked,
Qt::CheckStateRole);
});
for (int i = 0, count = proxyModel->rowCount(); i < count; ++i) {
const QModelIndex filePathItemIndex = proxyModel->index(i, 0);
for (int j = 0, count = proxyModel->rowCount(filePathItemIndex); j < count; ++j) {
const QModelIndex proxyIndex = proxyModel->index(j, 0, filePathItemIndex);
const QModelIndex diagnosticItemIndex = proxyModel->mapToSource(proxyIndex);
auto item = static_cast<DiagnosticItem *>(diagnosticItemIndex.internalPointer());
item->setData(DiagnosticView::DiagnosticColumn,
checked ? Qt::Checked : Qt::Unchecked,
Qt::CheckStateRole);
}
}
m_ignoreSetSelectedFixItsCount = false;
});
setHeader(clickableFixItHeader);
clickableFixItHeader->setStretchLastSection(false);
clickableFixItHeader->setSectionResizeMode(0, QHeaderView::Stretch);
clickableFixItHeader->setSectionResizeMode(1, QHeaderView::ResizeToContents);
const int fixitColumnWidth = clickableFixItHeader->sectionSizeHint(DiagnosticView::FixItColumn);
const int checkboxWidth = clickableFixItHeader->height();
clickableFixItHeader->setMinimumSectionSize(fixitColumnWidth + 1.2 * checkboxWidth);
setHeader(header);
header->setSectionResizeMode(DiagnosticView::DiagnosticColumn, QHeaderView::Stretch);
const int columnWidth = header->sectionSizeHint(DiagnosticView::DiagnosticColumn);
const int checkboxWidth = header->height();
header->setMinimumSectionSize(columnWidth + 1.2 * checkboxWidth);
}
} // namespace Internal

View File

@@ -27,19 +27,21 @@
#include <debugger/analyzer/detailederrorview.h>
#include <memory>
namespace ClangTools {
namespace Internal {
class DiagnosticViewStyle;
class DiagnosticViewDelegate;
class DiagnosticView : public Debugger::DetailedErrorView
{
Q_OBJECT
public:
DiagnosticView(QWidget *parent = nullptr);
enum ExtraColumn {
FixItColumn = DiagnosticColumn + 1,
};
~DiagnosticView() override;
void setSelectedFixItsCount(int fixItsCount);
@@ -59,6 +61,8 @@ private:
void setModel(QAbstractItemModel *theProxyModel) override;
QAction *m_suppressAction;
std::unique_ptr<DiagnosticViewStyle> m_style;
std::unique_ptr<DiagnosticViewDelegate> m_delegate;
bool m_ignoreSetSelectedFixItsCount = false;
};

View File

@@ -94,7 +94,7 @@ static ExplainingStep buildChildDiagnostic(const CXDiagnostic cxDiagnostic)
const CXSourceLocation cxLocation = clang_getDiagnosticLocation(cxDiagnostic);
diagnosticStep.location = diagLocationFromSourceLocation(cxLocation);
diagnosticStep.message = type + ": " + fromCXString(clang_getDiagnosticSpelling(cxDiagnostic));
diagnosticStep.message = fromCXString(clang_getDiagnosticSpelling(cxDiagnostic));
return diagnosticStep;
}

View File

@@ -270,7 +270,7 @@ static const HelpItem::Links getBestLink(const HelpItem::Links &links)
const HelpItem::Links HelpItem::bestLinks() const
{
if (m_isFuzzyMatch)
if (isFuzzyMatch())
return getBestLinks(links());
return getBestLink(links());
}
@@ -279,3 +279,10 @@ const QString HelpItem::keyword() const
{
return m_keyword;
}
bool HelpItem::isFuzzyMatch() const
{
// make sure m_isFuzzyMatch is correct
links();
return m_isFuzzyMatch;
}

View File

@@ -86,6 +86,8 @@ public:
const QString keyword() const;
private:
bool isFuzzyMatch() const;
QUrl m_helpUrl;
QStringList m_helpIds;
QString m_docMark;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 487 B

After

Width:  |  Height:  |  Size: 515 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 650 B

After

Width:  |  Height:  |  Size: 557 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 976 B

After

Width:  |  Height:  |  Size: 790 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -41,6 +41,7 @@
#include <QDir>
#include <QRegularExpression>
#include <QtGlobal>
namespace CppTools {
@@ -701,6 +702,10 @@ void CompilerOptionsBuilder::reset()
// QMakeProject: -pipe -Whello -g -std=gnu++11 -Wall -W -D_REENTRANT -fPIC
void CompilerOptionsBuilder::evaluateCompilerFlags()
{
static QStringList userBlackList = QString::fromLocal8Bit(
qgetenv("QTC_CLANG_CMD_OPTIONS_BLACKLIST"))
.split(';', QString::SkipEmptyParts);
bool containsDriverMode = false;
bool skipNext = false;
for (const QString &option : m_projectPart.compilerFlags) {
@@ -709,6 +714,9 @@ void CompilerOptionsBuilder::evaluateCompilerFlags()
continue;
}
if (userBlackList.contains(option))
continue;
// Ignore warning flags as these interfere with our user-configured diagnostics.
// Note that once "-w" is provided, no warnings will be emitted, even if "-Wall" follows.
if (m_useBuildSystemWarnings == UseBuildSystemWarnings::No

View File

@@ -26,6 +26,7 @@
#include "cpphoverhandler.h"
#include "cppelementevaluator.h"
#include "cpptoolsreuse.h"
#include <coreplugin/helpmanager.h>
#include <texteditor/texteditor.h>
@@ -56,14 +57,16 @@ void CppHoverHandler::identifyMatch(TextEditorWidget *editorWidget, int pos, Rep
tip += evaluator.diagnosis();
setPriority(Priority_Diagnostic);
}
const QStringList fallback = identifierWordsUnderCursor(tc);
if (evaluator.identifiedCppElement()) {
const QSharedPointer<CppElement> &cppElement = evaluator.cppElement();
QStringList candidates = cppElement->helpIdCandidates;
candidates.removeDuplicates();
const HelpItem helpItem(candidates, cppElement->helpMark, cppElement->helpCategory);
const QStringList candidates = cppElement->helpIdCandidates;
const HelpItem helpItem(candidates + fallback, cppElement->helpMark, cppElement->helpCategory);
setLastHelpItemIdentified(helpItem); // tool tip appended by decorateToolTip
if (!helpItem.isValid())
tip += cppElement->tooltip;
} else {
setLastHelpItemIdentified({fallback, {}, HelpItem::Unknown});
}
setToolTip(tip);
}

View File

@@ -41,6 +41,7 @@
#include <utils/qtcassert.h>
#include <QDebug>
#include <QRegularExpression>
#include <QSet>
#include <QStringRef>
#include <QTextCursor>
@@ -50,29 +51,91 @@ using namespace CPlusPlus;
namespace CppTools {
static void moveCursorToStartOrEndOfIdentifier(QTextCursor *tc,
QTextCursor::MoveOperation op,
int posDiff = 0)
static int skipChars(QTextCursor *tc,
QTextCursor::MoveOperation op,
int offset,
std::function<bool(const QChar &)> skip)
{
QTextDocument *doc = tc->document();
const QTextDocument *doc = tc->document();
if (!doc)
return;
QChar ch = doc->characterAt(tc->position() - posDiff);
while (isValidIdentifierChar(ch)) {
tc->movePosition(op);
ch = doc->characterAt(tc->position() - posDiff);
return 0;
QChar ch = doc->characterAt(tc->position() + offset);
if (ch.isNull())
return 0;
int count = 0;
while (skip(ch)) {
if (tc->movePosition(op))
++count;
else
break;
ch = doc->characterAt(tc->position() + offset);
}
return count;
}
static int skipCharsForward(QTextCursor *tc, std::function<bool(const QChar &)> skip)
{
return skipChars(tc, QTextCursor::NextCharacter, 0, skip);
}
static int skipCharsBackward(QTextCursor *tc, std::function<bool(const QChar &)> skip)
{
return skipChars(tc, QTextCursor::PreviousCharacter, -1, skip);
}
QStringList identifierWordsUnderCursor(const QTextCursor &tc)
{
const QTextDocument *document = tc.document();
if (!document)
return {};
const auto isSpace = [](const QChar &c) { return c.isSpace(); };
const auto isColon = [](const QChar &c) { return c == ':'; };
const auto isValidIdentifierCharAt = [document](const QTextCursor &tc) {
return isValidIdentifierChar(document->characterAt(tc.position()));
};
// move to the end
QTextCursor endCursor(tc);
do {
moveCursorToEndOfIdentifier(&endCursor);
// possibly skip ::
QTextCursor temp(endCursor);
skipCharsForward(&temp, isSpace);
const int colons = skipCharsForward(&temp, isColon);
skipCharsForward(&temp, isSpace);
if (colons == 2 && isValidIdentifierCharAt(temp))
endCursor = temp;
} while (isValidIdentifierCharAt(endCursor));
QStringList results;
QTextCursor startCursor(endCursor);
do {
moveCursorToStartOfIdentifier(&startCursor);
if (startCursor.position() == endCursor.position())
break;
QTextCursor temp(endCursor);
temp.setPosition(startCursor.position(), QTextCursor::KeepAnchor);
results.append(temp.selectedText().remove(QRegularExpression("\\s")));
// possibly skip ::
temp = startCursor;
skipCharsBackward(&temp, isSpace);
const int colons = skipCharsBackward(&temp, isColon);
skipCharsBackward(&temp, isSpace);
if (colons == 2
&& isValidIdentifierChar(document->characterAt(temp.position() - 1))) {
startCursor = temp;
}
} while (!isValidIdentifierCharAt(startCursor));
return results;
}
void moveCursorToEndOfIdentifier(QTextCursor *tc)
{
moveCursorToStartOrEndOfIdentifier(tc, QTextCursor::NextCharacter);
skipCharsForward(tc, isValidIdentifierChar);
}
void moveCursorToStartOfIdentifier(QTextCursor *tc)
{
moveCursorToStartOrEndOfIdentifier(tc, QTextCursor::PreviousCharacter, 1);
skipCharsBackward(tc, isValidIdentifierChar);
}
static bool isOwnershipRAIIName(const QString &name)

View File

@@ -58,6 +58,7 @@ bool CPPTOOLS_EXPORT isValidFirstIdentifierChar(const QChar &ch);
bool CPPTOOLS_EXPORT isValidIdentifierChar(const QChar &ch);
bool CPPTOOLS_EXPORT isValidIdentifier(const QString &s);
QStringList CPPTOOLS_EXPORT identifierWordsUnderCursor(const QTextCursor &tc);
QString CPPTOOLS_EXPORT identifierUnderCursor(QTextCursor *cursor);
bool CPPTOOLS_EXPORT isOwnershipRAIIType(CPlusPlus::Symbol *symbol,

View File

@@ -69,6 +69,7 @@ class TextMark : public TextEditor::TextMark
public:
TextMark(const Utils::FileName &fileName, const Diagnostic &diag)
: TextEditor::TextMark(fileName, diag.range().start().line() + 1, "lspmark")
, m_diagnostic(diag)
{
using namespace Utils;
setLineAnnotation(diag.message());
@@ -81,11 +82,17 @@ public:
setIcon(isError ? Icons::CODEMODEL_ERROR.icon()
: Icons::CODEMODEL_WARNING.icon());
}
const Diagnostic &diagnostic() const { return m_diagnostic; }
private:
const Diagnostic m_diagnostic;
};
Client::Client(BaseClientInterface *clientInterface)
: m_id(Core::Id::fromString(QUuid::createUuid().toString()))
, m_completionProvider(this)
, m_quickFixProvider(this)
, m_clientInterface(clientInterface)
{
m_contentHandler.insert(JsonRpcMessageHandler::jsonRpcMimeType(),
@@ -101,8 +108,10 @@ Client::~Client()
using namespace TextEditor;
// FIXME: instead of replacing the completion provider in the text document store the
// completion provider as a prioritised list in the text document
for (TextDocument *document : m_resetCompletionProvider)
for (TextDocument *document : m_resetAssistProvider) {
document->setCompletionAssistProvider(nullptr);
document->setQuickFixAssistProvider(nullptr);
}
for (Core::IEditor * editor : Core::DocumentModel::editorsForOpenedDocuments()) {
if (auto textEditor = qobject_cast<BaseTextEditor *>(editor)) {
TextEditorWidget *widget = textEditor->editorWidget();
@@ -192,10 +201,12 @@ void Client::openDocument(Core::IDocument *document)
documentContentsChanged(document);
});
if (textDocument) {
m_resetCompletionProvider << textDocument;
textDocument->completionAssistProvider();
m_resetAssistProvider << textDocument;
textDocument->setCompletionAssistProvider(&m_completionProvider);
textDocument->setQuickFixAssistProvider(&m_quickFixProvider);
connect(textDocument, &QObject::destroyed, this, [this, textDocument]{
m_resetCompletionProvider.remove(textDocument);
m_resetAssistProvider.remove(textDocument);
});
if (BaseTextEditor *editor = BaseTextEditor::textEditorForDocument(textDocument)) {
if (QPointer<TextEditorWidget> widget = editor->editorWidget()) {
@@ -543,25 +554,10 @@ void Client::cursorPositionChanged(TextEditor::TextEditorWidget *widget)
void Client::requestCodeActions(const DocumentUri &uri, const QList<Diagnostic> &diagnostics)
{
const Utils::FileName fileName = uri.toFileName();
TextEditor::TextDocument *doc = textDocumentForFileName(fileName);
TextEditor::TextDocument *doc = TextEditor::TextDocument::textDocumentForFileName(fileName);
if (!doc)
return;
const QString method(CodeActionRequest::methodName);
if (Utils::optional<bool> registered = m_dynamicCapabilities.isRegistered(method)) {
if (!registered.value())
return;
const TextDocumentRegistrationOptions option(
m_dynamicCapabilities.option(method).toObject());
if (option.isValid(nullptr) && !option.filterApplies(fileName))
return;
} else {
Utils::variant<bool, CodeActionOptions> provider
= m_serverCapabilities.codeActionProvider().value_or(false);
if (!(Utils::holds_alternative<CodeActionOptions>(provider) || Utils::get<bool>(provider)))
return;
}
CodeActionParams codeActionParams;
CodeActionParams::CodeActionContext context;
context.setDiagnostics(diagnostics);
@@ -577,6 +573,32 @@ void Client::requestCodeActions(const DocumentUri &uri, const QList<Diagnostic>
if (self)
self->handleCodeActionResponse(response, uri);
});
requestCodeActions(request);
}
void Client::requestCodeActions(const CodeActionRequest &request)
{
if (!request.isValid(nullptr))
return;
const Utils::FileName fileName
= request.params().value_or(CodeActionParams()).textDocument().uri().toFileName();
const QString method(CodeActionRequest::methodName);
if (Utils::optional<bool> registered = m_dynamicCapabilities.isRegistered(method)) {
if (!registered.value())
return;
const TextDocumentRegistrationOptions option(
m_dynamicCapabilities.option(method).toObject());
if (option.isValid(nullptr) && !option.filterApplies(fileName))
return;
} else {
Utils::variant<bool, CodeActionOptions> provider
= m_serverCapabilities.codeActionProvider().value_or(false);
if (!(Utils::holds_alternative<CodeActionOptions>(provider) || Utils::get<bool>(provider)))
return;
}
sendContent(request);
}
@@ -682,6 +704,17 @@ bool Client::needsRestart(const BaseSettings *settings) const
|| m_languagFilter.filePattern != settings->m_languageFilter.filePattern;
}
QList<Diagnostic> Client::diagnosticsAt(const DocumentUri &uri, const Range &range) const
{
QList<Diagnostic> diagnostics;
for (const TextMark *mark : m_diagnostics[uri]) {
const Diagnostic diagnostic = mark->diagnostic();
if (diagnostic.range().overlaps(range))
diagnostics << diagnostic;
}
return diagnostics;
}
bool Client::start()
{
return m_clientInterface->start();
@@ -778,7 +811,8 @@ void Client::showMessageBox(const ShowMessageRequestParams &message, const Messa
void Client::showDiagnostics(const DocumentUri &uri)
{
if (TextEditor::TextDocument *doc = textDocumentForFileName(uri.toFileName())) {
if (TextEditor::TextDocument *doc
= TextEditor::TextDocument::textDocumentForFileName(uri.toFileName())) {
for (TextMark *mark : m_diagnostics.value(uri))
doc->addMark(mark);
}
@@ -786,7 +820,8 @@ void Client::showDiagnostics(const DocumentUri &uri)
void Client::removeDiagnostics(const DocumentUri &uri)
{
TextEditor::TextDocument *doc = textDocumentForFileName(uri.toFileName());
TextEditor::TextDocument *doc
= TextEditor::TextDocument::textDocumentForFileName(uri.toFileName());
for (TextMark *mark : m_diagnostics.take(uri)) {
if (doc)

View File

@@ -26,7 +26,8 @@
#pragma once
#include "dynamiccapabilities.h"
#include "languageclientcodeassist.h"
#include "languageclientcompletionassist.h"
#include "languageclientquickfix.h"
#include "languageclientsettings.h"
#include <coreplugin/id.h>
@@ -104,6 +105,7 @@ public:
void requestCodeActions(const LanguageServerProtocol::DocumentUri &uri,
const QList<LanguageServerProtocol::Diagnostic> &diagnostics);
void requestCodeActions(const LanguageServerProtocol::CodeActionRequest &request);
void handleCodeActionResponse(const LanguageServerProtocol::CodeActionRequest::Response &response,
const LanguageServerProtocol::DocumentUri &uri);
void executeCommand(const LanguageServerProtocol::Command &command);
@@ -129,6 +131,10 @@ public:
bool needsRestart(const BaseSettings *) const;
QList<LanguageServerProtocol::Diagnostic> diagnosticsAt(
const LanguageServerProtocol::DocumentUri &uri,
const LanguageServerProtocol::Range &range) const;
bool start();
bool reset();
@@ -184,7 +190,8 @@ private:
LanguageServerProtocol::ServerCapabilities m_serverCapabilities;
DynamicCapabilities m_dynamicCapabilities;
LanguageClientCompletionAssistProvider m_completionProvider;
QSet<TextEditor::TextDocument *> m_resetCompletionProvider;
LanguageClientQuickFixProvider m_quickFixProvider;
QSet<TextEditor::TextDocument *> m_resetAssistProvider;
QHash<LanguageServerProtocol::DocumentUri, LanguageServerProtocol::MessageId> m_highlightRequests;
int m_restartsLeft = 5;
QScopedPointer<BaseClientInterface> m_clientInterface;

View File

@@ -6,11 +6,12 @@ HEADERS += \
client.h \
dynamiccapabilities.h \
languageclient_global.h \
languageclientcodeassist.h \
languageclientcompletionassist.h \
languageclientinterface.h \
languageclientmanager.h \
languageclientoutline.h \
languageclientplugin.h \
languageclientquickfix.h \
languageclientsettings.h \
languageclientutils.h
@@ -18,11 +19,12 @@ HEADERS += \
SOURCES += \
client.cpp \
dynamiccapabilities.cpp \
languageclientcodeassist.cpp \
languageclientcompletionassist.cpp \
languageclientinterface.cpp \
languageclientmanager.cpp \
languageclientoutline.cpp \
languageclientplugin.cpp \
languageclientquickfix.cpp \
languageclientsettings.cpp \
languageclientutils.cpp

View File

@@ -20,16 +20,18 @@ QtcPlugin {
"dynamiccapabilities.h",
"languageclient.qrc",
"languageclient_global.h",
"languageclientcodeassist.cpp",
"languageclientcodeassist.h",
"languageclientinterface.cpp",
"languageclientinterface.h",
"languageclientcompletionassist.cpp",
"languageclientcompletionassist.h",
"languageclientmanager.cpp",
"languageclientmanager.h",
"languageclientoutline.cpp",
"languageclientoutline.h",
"languageclientplugin.cpp",
"languageclientplugin.h",
"languageclientquickfix.cpp",
"languageclientquickfix.h",
"languageclientsettings.cpp",
"languageclientsettings.h",
"languageclientutils.cpp",

View File

@@ -23,7 +23,7 @@
**
****************************************************************************/
#include "languageclientcodeassist.h"
#include "languageclientcompletionassist.h"
#include "client.h"
#include "languageclientutils.h"

View File

@@ -48,7 +48,7 @@ public:
private:
QList<QString> m_triggerChars;
int m_activationCharSequenceLength = 0;
Client *m_client;
Client *m_client = nullptr; // not owned
};
} // namespace LanguageClient

View File

@@ -0,0 +1,166 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "languageclientquickfix.h"
#include "client.h"
#include "languageclientutils.h"
#include <texteditor/codeassist/assistinterface.h>
#include <texteditor/codeassist/genericproposal.h>
#include <texteditor/codeassist/iassistprocessor.h>
#include <texteditor/quickfix.h>
using namespace LanguageServerProtocol;
using namespace TextEditor;
namespace LanguageClient {
class CodeActionQuickFixOperation : public QuickFixOperation
{
public:
CodeActionQuickFixOperation(const CodeAction &action, Client *client)
: m_action(action)
, m_client(client)
{ setDescription(action.title()); }
void perform() override
{
if (Utils::optional<WorkspaceEdit> edit = m_action.edit()) {
applyWorkspaceEdit(*edit);
} else if (Utils::optional<Command> command = m_action.command()) {
if (m_client)
m_client->executeCommand(*command);
}
}
private:
CodeAction m_action;
QPointer<Client> m_client;
};
class CommandQuickFixOperation : public QuickFixOperation
{
public:
CommandQuickFixOperation(const Command &command, Client *client)
: m_command(command)
, m_client(client)
{ setDescription(command.title()); }
void perform() override
{
if (m_client)
m_client->executeCommand(m_command);
}
private:
Command m_command;
QPointer<Client> m_client;
};
class LanguageClientQuickFixAssistProcessor : public IAssistProcessor
{
public:
explicit LanguageClientQuickFixAssistProcessor(Client *client) : m_client(client) {}
bool running() override { return m_running; }
IAssistProposal *perform(const AssistInterface *interface) override;
private:
void handleCodeActionResponse(const CodeActionRequest::Response &response);
QSharedPointer<const AssistInterface> m_assistInterface;
Client *m_client = nullptr; // not owned
bool m_running = false;
};
IAssistProposal *LanguageClientQuickFixAssistProcessor::perform(const AssistInterface *interface)
{
m_assistInterface = QSharedPointer<const AssistInterface>(interface);
CodeActionParams params;
params.setContext({});
QTextCursor cursor(interface->textDocument());
cursor.setPosition(interface->position());
if (cursor.atBlockEnd() || cursor.atBlockStart())
cursor.select(QTextCursor::LineUnderCursor);
else
cursor.select(QTextCursor::WordUnderCursor);
if (!cursor.hasSelection())
cursor.select(QTextCursor::LineUnderCursor);
Range range(cursor);
params.setRange(range);
auto uri = DocumentUri::fromFileName(Utils::FileName::fromString(interface->fileName()));
params.setTextDocument(uri);
CodeActionParams::CodeActionContext context;
context.setDiagnostics(m_client->diagnosticsAt(uri, range));
params.setContext(context);
CodeActionRequest request(params);
request.setResponseCallback([this](const CodeActionRequest::Response &response){
handleCodeActionResponse(response);
});
m_client->requestCodeActions(request);
m_running = true;
return nullptr;
}
void LanguageClientQuickFixAssistProcessor::handleCodeActionResponse(
const CodeActionRequest::Response &response)
{
m_running = false;
if (const Utils::optional<CodeActionRequest::Response::Error> &error = response.error())
m_client->log(*error);
QuickFixOperations ops;
if (const Utils::optional<CodeActionResult> &_result = response.result()) {
const CodeActionResult &result = _result.value();
if (auto list = Utils::get_if<QList<Utils::variant<Command, CodeAction>>>(&result)) {
for (const Utils::variant<Command, CodeAction> &item : *list) {
if (auto action = Utils::get_if<CodeAction>(&item))
ops << new CodeActionQuickFixOperation(*action, m_client);
else if (auto command = Utils::get_if<Command>(&item))
ops << new CommandQuickFixOperation(*command, m_client);
}
}
}
setAsyncProposalAvailable(GenericProposal::createProposal(m_assistInterface.data(), ops));
}
LanguageClientQuickFixProvider::LanguageClientQuickFixProvider(Client *client) : m_client(client)
{
QTC_CHECK(client);
}
IAssistProvider::RunType LanguageClientQuickFixProvider::runType() const
{
return Asynchronous;
}
IAssistProcessor *LanguageClientQuickFixProvider::createProcessor() const
{
return new LanguageClientQuickFixAssistProcessor(m_client);
}
} // namespace LanguageClient

View File

@@ -0,0 +1,45 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <texteditor/codeassist/iassistprovider.h>
namespace LanguageClient {
class Client;
class LanguageClientQuickFixProvider : public TextEditor::IAssistProvider
{
public:
explicit LanguageClientQuickFixProvider(Client *client);
IAssistProvider::RunType runType() const override;
TextEditor::IAssistProcessor *createProcessor() const override;
private:
Client *m_client = nullptr; // not owned
};
} // namespace LanguageClient

View File

@@ -34,9 +34,8 @@
#include <utils/algorithm.h>
#include <utils/delegates.h>
#include <utils/fancylineedit.h>
#include <utils/qtcprocess.h>
#include <utils/mimetypes/mimedatabase.h>
#include <languageserverprotocol/lsptypes.h>
#include <utils/jsontreeitem.h>
#include <QBoxLayout>
#include <QCheckBox>
@@ -150,7 +149,6 @@ LanguageClientSettingsPageWidget::LanguageClientSettingsPageWidget(LanguageClien
connect(addButton, &QPushButton::pressed, this, &LanguageClientSettingsPageWidget::addItem);
auto deleteButton = new QPushButton(LanguageClientSettingsPage::tr("&Delete"));
connect(deleteButton, &QPushButton::pressed, this, &LanguageClientSettingsPageWidget::deleteItem);
mainLayout->addLayout(layout);
setLayout(mainLayout);
layout->addWidget(m_view);
@@ -505,6 +503,24 @@ BaseClientInterface *StdIOSettings::createInterface() const
return new StdIOClientInterface(m_executable, m_arguments);
}
static QWidget *createCapabilitiesView(
const LanguageServerProtocol::ServerCapabilities &capabilities)
{
auto root = new Utils::JsonTreeItem("Capabilities", QJsonValue(capabilities));
if (root->canFetchMore())
root->fetchMore();
auto capabilitiesModel = new Utils::TreeModel<Utils::JsonTreeItem>(root);
capabilitiesModel->setHeader({BaseSettingsWidget::tr("Name"),
BaseSettingsWidget::tr("Value"),
BaseSettingsWidget::tr("Type")});
auto capabilitiesView = new QTreeView();
capabilitiesView->setModel(capabilitiesModel);
capabilitiesView->setAlternatingRowColors(true);
capabilitiesView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
return capabilitiesView;
}
BaseSettingsWidget::BaseSettingsWidget(const BaseSettings *settings, QWidget *parent)
: QWidget(parent)
, m_name(new QLineEdit(settings->m_name, this))
@@ -528,6 +544,30 @@ BaseSettingsWidget::BaseSettingsWidget(const BaseSettings *settings, QWidget *pa
connect(addMimeTypeButton, &QPushButton::pressed,
this, &BaseSettingsWidget::showAddMimeTypeDialog);
auto createInfoLabel = []() {
return new QLabel(tr("Available after server was initialized"));
};
mainLayout->addWidget(new QLabel(tr("Capabilities:")), ++row, 0, Qt::AlignTop);
if (Client *client = settings->m_client.data()) {
if (client->state() == Client::Initialized)
mainLayout->addWidget(createCapabilitiesView(client->capabilities()));
else
mainLayout->addWidget(createInfoLabel(), row, 1);
connect(client, &Client::finished, mainLayout, [mainLayout, row, createInfoLabel]() {
delete mainLayout->itemAtPosition(row, 1)->widget();
mainLayout->addWidget(createInfoLabel(), row, 1);
});
connect(client, &Client::initialized, mainLayout,
[mainLayout, row](
const LanguageServerProtocol::ServerCapabilities &capabilities) {
delete mainLayout->itemAtPosition(row, 1)->widget();
mainLayout->addWidget(createCapabilitiesView(capabilities), row, 1);
});
} else {
mainLayout->addWidget(createInfoLabel());
}
setLayout(mainLayout);
}

View File

@@ -40,6 +40,7 @@
using namespace LanguageServerProtocol;
using namespace Utils;
using namespace TextEditor;
namespace LanguageClient {
@@ -72,7 +73,7 @@ bool applyTextDocumentEdit(const TextDocumentEdit &edit)
if (edits.isEmpty())
return true;
const DocumentUri &uri = edit.id().uri();
if (TextEditor::TextDocument* doc = textDocumentForFileName(uri.toFileName())) {
if (TextDocument* doc = TextDocument::textDocumentForFileName(uri.toFileName())) {
LanguageClientValue<int> version = edit.id().version();
if (!version.isNull() && version.value(0) < doc->document()->revision())
return false;
@@ -84,14 +85,14 @@ bool applyTextEdits(const DocumentUri &uri, const QList<TextEdit> &edits)
{
if (edits.isEmpty())
return true;
TextEditor::RefactoringChanges changes;
TextEditor::RefactoringFilePtr file;
RefactoringChanges changes;
RefactoringFilePtr file;
file = changes.file(uri.toFileName().toString());
file->setChangeSet(editsToChangeSet(edits, file->document()));
return file->apply();
}
void applyTextEdit(TextEditor::TextDocumentManipulatorInterface &manipulator, const TextEdit &edit)
void applyTextEdit(TextDocumentManipulatorInterface &manipulator, const TextEdit &edit)
{
using namespace Utils::Text;
const Range range = edit.range();
@@ -118,12 +119,6 @@ bool applyWorkspaceEdit(const WorkspaceEdit &edit)
return result;
}
TextEditor::TextDocument *textDocumentForFileName(const FileName &fileName)
{
return qobject_cast<TextEditor::TextDocument *>(
Core::DocumentModel::documentForFilePath(fileName.toString()));
}
QTextCursor endOfLineCursor(const QTextCursor &cursor)
{
QTextCursor ret = cursor;
@@ -135,8 +130,7 @@ void updateCodeActionRefactoringMarker(Client *client,
const CodeAction &action,
const DocumentUri &uri)
{
using namespace TextEditor;
TextDocument* doc = textDocumentForFileName(uri.toFileName());
TextDocument* doc = TextDocument::textDocumentForFileName(uri.toFileName());
if (!doc)
return;
BaseTextEditor *editor = BaseTextEditor::textEditorForDocument(doc);

View File

@@ -45,7 +45,6 @@ bool applyTextEdits(const LanguageServerProtocol::DocumentUri &uri,
const QList<LanguageServerProtocol::TextEdit> &edits);
void applyTextEdit(TextEditor::TextDocumentManipulatorInterface &manipulator,
const LanguageServerProtocol::TextEdit &edit);
TextEditor::TextDocument *textDocumentForFileName(const Utils::FileName &fileName);
void updateCodeActionRefactoringMarker(Client *client,
const LanguageServerProtocol::CodeAction &action,
const LanguageServerProtocol::DocumentUri &uri);

View File

@@ -77,7 +77,8 @@ PerfDataReader::PerfDataReader(QObject *parent) :
QMessageBox::warning(Core::ICore::mainWindow(),
tr("Perf data parser failed"),
tr("The perf data parser failed to process all the samples. "
"Your trace is incomplete."));
"Your trace is incomplete. The exit code was %1.")
.arg(exitCode));
}
});
@@ -120,6 +121,7 @@ PerfDataReader::PerfDataReader(QObject *parent) :
qWarning() << "Cannot send data to perfparser";
break;
case QProcess::Timedout:
qWarning() << "QProcess::Timedout";
default:
break;
}
@@ -349,8 +351,10 @@ void PerfDataReader::writeChunk()
"Your trace is incomplete."));
}
}
} else if (m_dataFinished) {
m_input.closeWriteChannel();
} else if (m_dataFinished && m_input.isWritable()) {
// Delay closing of the write channel. Closing the channel from within a handler
// for bytesWritten() is dangerous on windows.
QTimer::singleShot(0, &m_input, &QProcess::closeWriteChannel);
}
}

View File

@@ -46,7 +46,6 @@
#include <QVariantMap>
#include <qbs.h>
#include <qtprofilesetup.h>
const QChar sep = QLatin1Char('.');
@@ -166,45 +165,9 @@ void QbsManager::addProfile(const QString &name, const QVariantMap &data)
void QbsManager::addQtProfileFromKit(const QString &profileName, const ProjectExplorer::Kit *k)
{
const QtSupport::BaseQtVersion * const qt = QtSupport::QtKitAspect::qtVersion(k);
if (!qt)
return;
qbs::QtEnvironment qtEnv;
const QList<ProjectExplorer::Abi> abi = qt->qtAbis();
if (!abi.empty()) {
qtEnv.architecture = ProjectExplorer::Abi::toString(abi.first().architecture());
if (abi.first().wordWidth() == 64)
qtEnv.architecture.append(QLatin1String("_64"));
}
qtEnv.binaryPath = qt->binPath().toString();
qtEnv.documentationPath = qt->docsPath().toString();
qtEnv.includePath = qt->headerPath().toString();
qtEnv.libraryPath = qt->libraryPath().toString();
qtEnv.pluginPath = qt->pluginPath().toString();
qtEnv.mkspecBasePath = qt->mkspecsPath().toString();
qtEnv.mkspecName = qt->mkspec().toString();
qtEnv.mkspecPath = qt->mkspecPath().toString();
qtEnv.qtNameSpace = qt->qtNamespace();
qtEnv.qtLibInfix = qt->qtLibInfix();
qtEnv.qtVersion = qt->qtVersionString();
qtEnv.qtMajorVersion = qt->qtVersion().majorVersion;
qtEnv.qtMinorVersion = qt->qtVersion().minorVersion;
qtEnv.qtPatchVersion = qt->qtVersion().patchVersion;
qtEnv.frameworkBuild = qt->isFrameworkBuild();
qtEnv.configItems = qt->configValues();
qtEnv.qtConfigItems = qt->qtConfigValues();
foreach (const QString &buildVariant,
QStringList() << QLatin1String("debug") << QLatin1String("release")) {
if (qtEnv.qtConfigItems.contains(buildVariant))
qtEnv.buildVariant << buildVariant;
}
qtEnv.qmlPath = qt->qmlPath().toString();
qtEnv.qmlImportPath = qt->qmakeProperty("QT_INSTALL_IMPORTS");
const qbs::ErrorInfo errorInfo = qbs::setupQtProfile(profileName, settings(), qtEnv);
if (errorInfo.hasError()) {
Core::MessageManager::write(tr("Failed to set up kit for Qbs: %1")
.arg(errorInfo.toString()), Core::MessageManager::ModeSwitch);
if (const QtSupport::BaseQtVersion * const qt = QtSupport::QtKitAspect::qtVersion(k)) {
qbs::Profile(profileName, settings()).setValue("moduleProviders.Qt.qmakeFilePaths",
qt->qmakeCommand().toString());
}
}

View File

@@ -5,11 +5,9 @@ isEmpty(QBS_INSTALL_DIR): QBS_INSTALL_DIR = $$(QBS_INSTALL_DIR)
isEmpty(QBS_INSTALL_DIR) {
QBS_SOURCE_DIR = $$PWD/../../shared/qbs
include($$QBS_SOURCE_DIR/src/lib/corelib/use_corelib.pri)
include($$QBS_SOURCE_DIR/src/lib/qtprofilesetup/use_qtprofilesetup.pri)
osx:QMAKE_LFLAGS += -Wl,-rpath,@loader_path/../Frameworks # OS X: fix rpath for qbscore soname
} else {
include($${QBS_INSTALL_DIR}/include/qbs/use_installed_corelib.pri)
include($${QBS_INSTALL_DIR}/include/qbs/use_installed_qtprofilesetup.pri)
}
QBS_INSTALL_DIR_FWD_SLASHES = $$replace(QBS_INSTALL_DIR, \\\\, /)
DEFINES += QBS_INSTALL_DIR=\\\"$$QBS_INSTALL_DIR_FWD_SLASHES\\\"

View File

@@ -20,7 +20,7 @@ QtcPlugin {
if (qbs.enableDebugCode)
suffix = "d";
}
libs.push("qbscore" + suffix, "qbsqtprofilesetup" + suffix);
libs.push("qbscore" + suffix);
return libs
}
@@ -33,10 +33,6 @@ QtcPlugin {
name: "qbscore"
condition: product.useInternalQbsProducts
}
Depends {
name: "qbsqtprofilesetup"
condition: product.useInternalQbsProducts
}
Depends { name: "QmlJS" }
Depends { name: "Utils" }

View File

@@ -322,10 +322,12 @@ protected:
bool visit(AST::UiPublicMember *node) override
{
if (node->memberType->name == _name){
const ObjectValue * tVal = _context->lookupType(_doc.data(), QStringList(_name));
if (tVal == _typeValue)
_usages.append(node->typeToken);
if (UiQualifiedId *memberType = node->memberType) {
if (memberType->name == _name) {
const ObjectValue * tVal = _context->lookupType(_doc.data(), QStringList(_name));
if (tVal == _typeValue)
_usages.append(node->typeToken);
}
}
if (AST::cast<Block *>(node->statement)) {
_builder.push(node);

View File

@@ -42,6 +42,9 @@ LinuxDeviceProcess::LinuxDeviceProcess(const QSharedPointer<const ProjectExplore
: ProjectExplorer::SshDeviceProcess(device, parent), m_processId(0)
{
connect(this, &DeviceProcess::finished, this, [this]() {
m_processId = -1;
});
connect(this, &DeviceProcess::started, this, [this]() {
m_processId = 0;
});
}
@@ -70,7 +73,7 @@ QByteArray LinuxDeviceProcess::readAllStandardOutput()
qint64 LinuxDeviceProcess::processId() const
{
return m_processId;
return m_processId < 0 ? 0 : m_processId;
}
QString LinuxDeviceProcess::fullCommandLine(const Runnable &runnable) const

View File

@@ -100,6 +100,7 @@ public:
QTextDocument m_document;
SyntaxHighlighter *m_highlighter = nullptr;
CompletionAssistProvider *m_completionAssistProvider = nullptr;
IAssistProvider *m_quickFixProvider = nullptr;
QScopedPointer<Indenter> m_indenter;
bool m_fileIsReadOnly = false;
@@ -298,6 +299,11 @@ TextDocument *TextDocument::currentTextDocument()
return qobject_cast<TextDocument *>(EditorManager::currentDocument());
}
TextDocument *TextDocument::textDocumentForFileName(const Utils::FileName &fileName)
{
return qobject_cast<TextDocument *>(DocumentModel::documentForFilePath(fileName.toString()));
}
QString TextDocument::plainText() const
{
return document()->toPlainText();
@@ -388,9 +394,14 @@ CompletionAssistProvider *TextDocument::completionAssistProvider() const
return d->m_completionAssistProvider;
}
void TextDocument::setQuickFixAssistProvider(IAssistProvider *provider) const
{
d->m_quickFixProvider = provider;
}
IAssistProvider *TextDocument::quickFixAssistProvider() const
{
return nullptr;
return d->m_quickFixProvider;
}
void TextDocument::applyFontSettings()

View File

@@ -70,6 +70,7 @@ public:
static QMap<QString, QString> openedTextDocumentContents();
static QMap<QString, QTextCodec *> openedTextDocumentEncodings();
static TextDocument *currentTextDocument();
static TextDocument *textDocumentForFileName(const Utils::FileName &fileName);
virtual QString plainText() const;
virtual QString textAt(int pos, int length) const;
@@ -140,6 +141,7 @@ public:
void setCompletionAssistProvider(CompletionAssistProvider *provider);
virtual CompletionAssistProvider *completionAssistProvider() const;
void setQuickFixAssistProvider(IAssistProvider *provider) const;
virtual IAssistProvider *quickFixAssistProvider() const;
void setTabSettings(const TextEditor::TabSettings &tabSettings);

View File

@@ -361,11 +361,8 @@ TextMarkRegistry::TextMarkRegistry(QObject *parent)
void TextMarkRegistry::add(TextMark *mark)
{
instance()->m_marks[mark->fileName()].insert(mark);
auto document = qobject_cast<TextDocument *>(
DocumentModel::documentForFilePath(mark->fileName().toString()));
if (!document)
return;
document->addMark(mark);
if (TextDocument *document = TextDocument::textDocumentForFileName(mark->fileName()))
document->addMark(mark);
}
bool TextMarkRegistry::remove(TextMark *mark)

View File

@@ -31,6 +31,7 @@
#include <utils/stylehelper.h>
#include <QEvent>
#include <QGuiApplication>
#include <QKeyEvent>
#include <QLabel>
#include <QPainter>
@@ -349,8 +350,17 @@ void IntroductionWidget::keyPressEvent(QKeyEvent *ke)
{
if (ke->key() == Qt::Key_Escape)
finish();
else if (ke->modifiers() == Qt::NoModifier)
step();
else if ((ke->modifiers()
& (Qt::ControlModifier | Qt::AltModifier | Qt::ShiftModifier | Qt::MetaModifier))
== Qt::NoModifier) {
const Qt::Key backKey = QGuiApplication::isLeftToRight() ? Qt::Key_Left : Qt::Key_Right;
if (ke->key() == backKey) {
if (m_step > 0)
setStep(m_step - 1);
} else {
step();
}
}
}
void IntroductionWidget::mouseReleaseEvent(QMouseEvent *me)

View File

@@ -27,6 +27,8 @@
#include "prowriter.h"
#include "proitems.h"
#include <utils/algorithm.h>
#include <QDir>
#include <QPair>
#include <QRegularExpression>
@@ -36,7 +38,7 @@ using namespace QmakeProjectManager::Internal;
static uint getBlockLen(const ushort *&tokPtr)
{
uint len = *tokPtr++;
len |= (uint)*tokPtr++ << 16;
len |= uint(*tokPtr++ << 16);
return len;
}
@@ -51,10 +53,10 @@ static bool getLiteral(const ushort *tokPtr, const ushort *tokEnd, QString &tmp)
break;
case TokHashLiteral:
tokPtr += 2;
// fallthrough
Q_FALLTHROUGH();
case TokLiteral: {
uint len = *tokPtr++;
tmp.setRawData((const QChar *)tokPtr, len);
int len = *tokPtr++;
tmp.setRawData(reinterpret_cast<const QChar *>(tokPtr), len);
count++;
tokPtr += len;
break; }
@@ -87,7 +89,7 @@ static void skipBlock(const ushort *&tokPtr)
static void skipExpression(const ushort *&pTokPtr, int &lineNo)
{
const ushort *tokPtr = pTokPtr;
forever {
for (;;) {
ushort tok = *tokPtr++;
switch (tok) {
case TokLine:
@@ -136,13 +138,13 @@ static const ushort *skipToken(ushort tok, const ushort *&tokPtr, int &lineNo)
case TokRemove:
case TokReplace:
tokPtr++;
// fallthrough
Q_FALLTHROUGH();
case TokTestCall:
skipExpression(tokPtr, lineNo);
break;
case TokForLoop:
skipHashStr(tokPtr);
// fallthrough
Q_FALLTHROUGH();
case TokBranch:
skipBlock(tokPtr);
skipBlock(tokPtr);
@@ -168,14 +170,14 @@ static const ushort *skipToken(ushort tok, const ushort *&tokPtr, int &lineNo)
}
Q_ASSERT_X(false, "skipToken", "unexpected item type");
}
return 0;
return nullptr;
}
QString ProWriter::compileScope(const QString &scope)
{
if (scope.isEmpty())
return QString();
QMakeParser parser(0, 0, 0);
QMakeParser parser(nullptr, nullptr, nullptr);
ProFile *includeFile = parser.parsedProBlock(QStringRef(&scope), 0, QLatin1String("no-file"), 1);
if (!includeFile)
return QString();
@@ -204,11 +206,11 @@ bool ProWriter::locateVarValues(const ushort *tokPtr, const ushort *tokPtrEnd,
const bool inScope = scope.isEmpty();
int lineNo = *scopeStart + 1;
QString tmp;
const ushort *lastXpr = 0;
const ushort *lastXpr = nullptr;
bool fresh = true;
QString compiledScope = compileScope(scope);
const ushort *cTokPtr = (const ushort *)compiledScope.constData();
const ushort *cTokPtr = reinterpret_cast<const ushort *>(compiledScope.constData());
while (ushort tok = *tokPtr++) {
if (inScope && (tok == TokAssign || tok == TokAppend || tok == TokAppendUnique)) {
@@ -323,7 +325,7 @@ void ProWriter::putVarValues(ProFile *profile, QStringList *lines, const QString
if (eqs >= 0) // If this is not true, we mess up the file a bit.
line.truncate(eqs + 1);
// put new values
foreach (const QString &v, values) {
for (const QString &v : values) {
line += ((flags & MultiLine) ? QLatin1String(" \\\n") + effectiveContIndent(contInfo)
: QString::fromLatin1(" ")) + v;
}
@@ -388,9 +390,10 @@ void ProWriter::putVarValues(ProFile *profile, QStringList *lines, const QString
if (lNo != scopeStart + 1)
added += QLatin1Char('\n');
added += indent + var + QLatin1String((flags & AppendOperator) ? " +=" : " =");
foreach (const QString &v, values)
for (const QString &v : values) {
added += ((flags & MultiLine) ? QLatin1String(" \\\n") + effectiveContIndent(contInfo)
: QString::fromLatin1(" ")) + v;
}
if (!scope.isEmpty() && scopeStart < 0)
added += QLatin1String("\n}");
lines->insert(lNo, added);
@@ -405,7 +408,7 @@ void ProWriter::addFiles(ProFile *profile, QStringList *lines, const QStringList
QDir baseDir = QFileInfo(profile->fileName()).absoluteDir();
if (profile->fileName().endsWith(QLatin1String(".pri")))
prefixPwd = QLatin1String("$$PWD/");
foreach (const QString &v, values)
for (const QString &v : values)
valuesToWrite << (prefixPwd + baseDir.relativeFilePath(v));
putVarValues(profile, lines, valuesToWrite, var, AppendValues | MultiLine | AppendOperator,
@@ -417,7 +420,7 @@ static void findProVariables(const ushort *tokPtr, const QStringList &vars,
{
int lineNo = firstLine;
QString tmp;
const ushort *lastXpr = 0;
const ushort *lastXpr = nullptr;
while (ushort tok = *tokPtr++) {
if (tok == TokBranch) {
uint blockLen = getBlockLen(tokPtr);
@@ -453,7 +456,7 @@ QList<int> ProWriter::removeVarValues(ProFile *profile, QStringList *lines,
// This code expects proVars to be sorted by the variables' appearance in the file.
int delta = 1;
foreach (int ln, varLines) {
for (int ln : qAsConst(varLines)) {
bool first = true;
int lineNo = ln - delta;
typedef QPair<int, int> ContPos;
@@ -467,7 +470,7 @@ QList<int> ProWriter::removeVarValues(ProFile *profile, QStringList *lines,
if (idx >= 0)
lineLen = idx;
QChar *chars = line.data();
forever {
for (;;) {
if (!lineLen) {
if (idx >= 0)
goto nextLine;
@@ -530,7 +533,7 @@ QList<int> ProWriter::removeVarValues(ProFile *profile, QStringList *lines,
// Entries existed, but were all removed
if (contCol < 0) {
// This is the last line, so clear continuations leading to it
foreach (const ContPos &pos, contPos) {
for (const ContPos &pos : qAsConst(contPos)) {
QString &bline = (*lines)[pos.first];
bline.remove(pos.second, 1);
if (pos.second == bline.length())
@@ -564,12 +567,12 @@ QStringList ProWriter::removeFiles(ProFile *profile, QStringList *lines,
// This is a tad stupid - basically, it can remove only entries which
// the above code added.
QStringList valuesToFind;
foreach (const QString &absoluteFilePath, values)
for (const QString &absoluteFilePath : values)
valuesToFind << proFileDir.relativeFilePath(absoluteFilePath);
QStringList notYetChanged;
foreach (int i, removeVarValues(profile, lines, valuesToFind, vars))
notYetChanged.append(values.at(i));
const QStringList notYetChanged =
Utils::transform(removeVarValues(profile, lines, valuesToFind, vars),
[values](int i) { return values.at(i); });
if (!profile->fileName().endsWith(QLatin1String(".pri")))
return notYetChanged;
@@ -580,12 +583,12 @@ QStringList ProWriter::removeFiles(ProFile *profile, QStringList *lines,
valuesToFind.clear();
const QDir baseDir = QFileInfo(profile->fileName()).absoluteDir();
const QString prefixPwd = QLatin1String("$$PWD/");
foreach (const QString &absoluteFilePath, notYetChanged)
for (const QString &absoluteFilePath : notYetChanged)
valuesToFind << (prefixPwd + baseDir.relativeFilePath(absoluteFilePath));
QStringList notChanged;
foreach (int i, removeVarValues(profile, lines, valuesToFind, vars))
notChanged.append(notYetChanged.at(i));
const QStringList notChanged =
Utils::transform(removeVarValues(profile, lines, valuesToFind, vars),
[notYetChanged](int i) { return notYetChanged.at(i); });
return notChanged;
}

View File

@@ -2,17 +2,14 @@ TEMPLATE = subdirs
QBS_DIRS = \
qbscorelib \
qbsqtprofilesetup \
qbsapps \
qbslibexec \
qbsplugins \
qbsstatic
qbscorelib.subdir = qbs/src/lib/corelib
qbsqtprofilesetup.subdir = qbs/src/lib/qtprofilesetup
qbsqtprofilesetup.depends = qbscorelib
qbsapps.subdir = qbs/src/app
qbsapps.depends = qbsqtprofilesetup
qbsapps.depends = qbscorelib
qbslibexec.subdir = qbs/src/libexec
qbslibexec.depends = qbscorelib
qbsplugins.subdir = qbs/src/plugins

View File

@@ -72,6 +72,48 @@ using ClangBackEnd::FilePathCache;
using ClangBackEnd::FilePathView;
using ClangBackEnd::TimeStamp;
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
template<typename CallableType>
class CallableEvent : public QEvent
{
public:
using Callable = std::decay_t<CallableType>;
CallableEvent(Callable &&callable)
: QEvent(QEvent::None)
, callable(std::move(callable))
{}
CallableEvent(const Callable &callable)
: QEvent(QEvent::None)
, callable(callable)
{}
~CallableEvent() { callable(); }
public:
Callable callable;
};
template<typename Callable>
void executeInLoop(Callable &&callable, QObject *object = QCoreApplication::instance())
{
if (QThread *thread = qobject_cast<QThread *>(object))
object = QAbstractEventDispatcher::instance(thread);
QCoreApplication::postEvent(object,
new CallableEvent<Callable>(std::forward<Callable>(callable)),
Qt::HighEventPriority);
}
#else
template<typename Callable>
void executeInLoop(Callable &&callable, QObject *object = QCoreApplication::instance())
{
if (QThread *thread = qobject_cast<QThread *>(object))
object = QAbstractEventDispatcher::instance(thread);
QMetaObject::invokeMethod(object, std::forward<Callable>(callable));
}
#endif
class PchManagerApplication final : public QCoreApplication
{
public:
@@ -182,8 +224,9 @@ struct Data // because we have a cycle dependency
clangPchManagerServer,
includeWatcher};
PrecompiledHeaderStorage<> preCompiledHeaderStorage{database};
ClangBackEnd::ProgressCounter progressCounter{
[&](int progress, int total) { clangPchManagerServer.setProgress(progress, total); }};
ClangBackEnd::ProgressCounter progressCounter{[&](int progress, int total) {
executeInLoop([&] { clangPchManagerServer.setProgress(progress, total); });
}};
ClangBackEnd::PchTaskQueue pchTaskQueue{systemTaskScheduler,
projectTaskScheduler,
progressCounter,
@@ -191,7 +234,9 @@ struct Data // because we have a cycle dependency
database};
ClangBackEnd::PchTasksMerger pchTaskMerger{pchTaskQueue};
ClangBackEnd::BuildDependenciesStorage<> buildDependencyStorage{database};
ClangBackEnd::BuildDependencyCollector buildDependencyCollector{filePathCache, generatedFiles};
ClangBackEnd::BuildDependencyCollector buildDependencyCollector{filePathCache,
generatedFiles,
environment};
std::function<TimeStamp(FilePathView filePath)> getModifiedTime{
[&](ClangBackEnd::FilePathView path) -> TimeStamp {
return QFileInfo(QString(path)).lastModified().toSecsSinceEpoch();

View File

@@ -28,10 +28,12 @@
#include "collectbuilddependencytoolaction.h"
#include "commandlinebuilder.h"
#include <environment.h>
#include <utils/smallstring.h>
#include <algorithm>
#include <iostream>
namespace ClangBackEnd {
namespace {
@@ -47,10 +49,10 @@ FilePathIds operator+(const FilePathIds &first, const FilePathIds &second)
BuildDependency BuildDependencyCollector::create(const ProjectPartContainer &projectPart)
{
CommandLineBuilder<ProjectPartContainer, Utils::SmallStringVector> builder{
projectPart, projectPart.toolChainArguments};
CommandLineBuilder<ProjectPartContainer, Utils::SmallStringVector>
builder{projectPart, projectPart.toolChainArguments, InputFileType::Source};
addFiles(projectPart.sourcePathIds, builder.commandLine);
addFiles(projectPart.sourcePathIds, std::move(builder.commandLine));
setExcludedFilePaths(
m_filePathCache.filePaths(projectPart.headerPathIds + projectPart.sourcePathIds));
@@ -66,6 +68,33 @@ BuildDependency BuildDependencyCollector::create(const ProjectPartContainer &pro
return buildDependency;
}
namespace {
std::size_t contentSize(const FilePaths &includes)
{
auto countIncludeSize = [](std::size_t size, const auto &include) {
return size + include.size();
};
return std::accumulate(includes.begin(), includes.end(), std::size_t(0), countIncludeSize);
}
} // namespace
Utils::SmallString BuildDependencyCollector::generateFakeFileContent(
const FilePathIds &includeIds) const
{
Utils::SmallString fileContent;
const std::size_t lineTemplateSize = 12;
auto includes = m_filePathCache.filePaths(includeIds);
fileContent.reserve(includes.size() * lineTemplateSize + contentSize(includes));
for (Utils::SmallStringView include : includes)
fileContent += {"#include \"", include, "\"\n"};
return fileContent;
}
void BuildDependencyCollector::collect()
{
clang::tooling::ClangTool tool = m_clangTool.createTool();
@@ -96,25 +125,26 @@ void BuildDependencyCollector::setExcludedFilePaths(ClangBackEnd::FilePaths &&ex
}
void BuildDependencyCollector::addFiles(const FilePathIds &filePathIds,
const Utils::SmallStringVector &arguments)
Utils::SmallStringVector &&arguments)
{
m_clangTool.addFiles(m_filePathCache.filePaths(filePathIds), arguments);
m_clangTool.addFile(FilePath{m_environment.pchBuildDirectory().toStdString(), "dummy.cpp"},
generateFakeFileContent(filePathIds),
std::move(arguments));
m_buildDependency.sourceFiles.insert(m_buildDependency.sourceFiles.end(),
filePathIds.begin(),
filePathIds.end());
}
void BuildDependencyCollector::addFile(FilePathId filePathId,
const Utils::SmallStringVector &arguments)
void BuildDependencyCollector::addFile(FilePathId filePathId, Utils::SmallStringVector &&arguments)
{
addFiles({filePathId}, arguments);
addFiles({filePathId}, std::move(arguments));
}
void BuildDependencyCollector::addFile(FilePath filePath,
const FilePathIds &sourceFileIds,
const Utils::SmallStringVector &arguments)
Utils::SmallStringVector &&arguments)
{
m_clangTool.addFiles({filePath}, arguments);
m_clangTool.addFiles({filePath}, std::move(arguments));
m_buildDependency.sourceFiles.insert(m_buildDependency.sourceFiles.end(),
sourceFileIds.begin(),
sourceFileIds.end());

View File

@@ -34,33 +34,35 @@
#include <filepathcachingfwd.h>
namespace ClangBackEnd {
class Environment;
class BuildDependencyCollector : public BuildDependencyGeneratorInterface
{
public:
BuildDependencyCollector(const FilePathCachingInterface &filePathCache,
const GeneratedFilesInterface &generatedFiles)
const GeneratedFilesInterface &generatedFiles,
const Environment &environment)
: m_filePathCache(filePathCache)
, m_generatedFiles(generatedFiles)
{
}
, m_environment(environment)
{}
BuildDependency create(const ProjectPartContainer &projectPart) override;
void collect();
void setExcludedFilePaths(ClangBackEnd::FilePaths &&excludedIncludes);
void addFiles(const FilePathIds &filePathIds,
const Utils::SmallStringVector &arguments);
void addFile(FilePathId filePathId,
const Utils::SmallStringVector &arguments);
void addFiles(const FilePathIds &filePathIds, Utils::SmallStringVector &&arguments);
void addFile(FilePathId filePathId, Utils::SmallStringVector &&arguments);
void addFile(FilePath filePath,
const FilePathIds &sourceFileIds,
const Utils::SmallStringVector &arguments);
Utils::SmallStringVector &&arguments);
void addUnsavedFiles(const V2::FileContainers &unsavedFiles);
void clear();
Utils::SmallString generateFakeFileContent(const FilePathIds &includeIds) const;
const FileStatuses &fileStatuses() const
{
return m_buildDependency.fileStatuses;
@@ -96,6 +98,7 @@ private:
SourcesManager m_sourcesManager;
const FilePathCachingInterface &m_filePathCache;
const GeneratedFilesInterface &m_generatedFiles;
const Environment &m_environment;
};
} // namespace ClangBackEnd

View File

@@ -54,27 +54,28 @@ public:
bool BeginSourceFileAction(clang::CompilerInstance &compilerInstance) override
{
if (clang::PreprocessOnlyAction::BeginSourceFileAction(compilerInstance)) {
auto &preprocessor = compilerInstance.getPreprocessor();
if (clang::PreprocessOnlyAction::BeginSourceFileAction(compilerInstance)) {
auto &preprocessor = compilerInstance.getPreprocessor();
preprocessor.SetSuppressIncludeNotFoundError(true);
preprocessor.SetMacroExpansionOnlyInDirectives();
preprocessor.SetSuppressIncludeNotFoundError(true);
preprocessor.SetMacroExpansionOnlyInDirectives();
auto macroPreprocessorCallbacks = new CollectBuildDependencyPreprocessorCallbacks(
m_buildDependency,
m_filePathCache,
m_excludedIncludeUID,
m_alreadyIncludedFileUIDs,
compilerInstance.getSourceManager(),
m_sourcesManager,
compilerInstance.getPreprocessorPtr());
auto macroPreprocessorCallbacks = new CollectBuildDependencyPreprocessorCallbacks(
m_buildDependency,
m_filePathCache,
m_excludedIncludeUID,
m_alreadyIncludedFileUIDs,
compilerInstance.getSourceManager(),
m_sourcesManager,
compilerInstance.getPreprocessorPtr());
preprocessor.addPPCallbacks(std::unique_ptr<clang::PPCallbacks>(macroPreprocessorCallbacks));
preprocessor.addPPCallbacks(
std::unique_ptr<clang::PPCallbacks>(macroPreprocessorCallbacks));
return true;
}
return true;
}
return false;
return false;
}
void EndSourceFileAction() override

View File

@@ -72,15 +72,27 @@ public:
void FileChanged(clang::SourceLocation sourceLocation,
clang::PPCallbacks::FileChangeReason reason,
clang::SrcMgr::CharacteristicKind,
clang::FileID) override
clang::FileID previousFileId) override
{
if (reason == clang::PPCallbacks::EnterFile)
{
const clang::FileEntry *fileEntry = m_sourceManager->getFileEntryForID(
m_sourceManager->getFileID(sourceLocation));
if (fileEntry) {
addFileStatus(fileEntry);
addSourceFile(fileEntry);
if (reason == clang::PPCallbacks::EnterFile) {
clang::FileID currentFileId = m_sourceManager->getFileID(sourceLocation);
if (m_mainFileId.isInvalid()) {
m_mainFileId = currentFileId;
} else {
const clang::FileEntry *fileEntry = m_sourceManager->getFileEntryForID(
currentFileId);
if (fileEntry) {
if (previousFileId == m_mainFileId) {
uint sourceFileUID = fileEntry->getUID();
auto notAlreadyIncluded = isNotAlreadyIncluded(sourceFileUID);
if (notAlreadyIncluded.first)
m_alreadyIncludedFileUIDs.insert(notAlreadyIncluded.second,
sourceFileUID);
} else {
addFileStatus(fileEntry);
addSourceFile(fileEntry);
}
}
}
}
}
@@ -96,7 +108,8 @@ public:
const clang::Module * /*imported*/,
clang::SrcMgr::CharacteristicKind fileType) override
{
if (file) {
clang::FileID currentFileId = m_sourceManager->getFileID(hashLocation);
if (file && currentFileId != m_mainFileId) {
addSourceDependency(file, hashLocation);
auto fileUID = file->getUID();
auto sourceFileUID = m_sourceManager
@@ -343,6 +356,7 @@ private:
BuildDependency &m_buildDependency;
const std::vector<uint> &m_excludedIncludeUID;
std::vector<uint> &m_alreadyIncludedFileUIDs;
clang::FileID m_mainFileId;
};
} // namespace ClangBackEnd

Some files were not shown because too many files have changed in this diff Show More