forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/master' into 12.0
Change-Id: Iae9b2f871a3d9ae9cda4689b68cf0bc815cb1057
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -56,6 +56,7 @@ CMakeLists.txt.user*
|
|||||||
/share/qtcreator/qmldesigner/QtProject/
|
/share/qtcreator/qmldesigner/QtProject/
|
||||||
/src/app/Info.plist
|
/src/app/Info.plist
|
||||||
/src/plugins/**/*.json
|
/src/plugins/**/*.json
|
||||||
|
!/src/plugins/**/wizard.json
|
||||||
/src/plugins/coreplugin/ide_version.h
|
/src/plugins/coreplugin/ide_version.h
|
||||||
/src/libs/qt-breakpad/bin
|
/src/libs/qt-breakpad/bin
|
||||||
/.cmake/
|
/.cmake/
|
||||||
|
|||||||
33
README.md
33
README.md
@@ -970,3 +970,36 @@ SQLite (https://www.sqlite.org) is in the Public Domain.
|
|||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
### RSTParser
|
||||||
|
|
||||||
|
RSTParser is an open-source C++ library for parsing reStructuredText
|
||||||
|
|
||||||
|
https://github.com/vitaut-archive/rstparser
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
Copyright (c) 2013, Victor Zverovich
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|||||||
@@ -938,6 +938,43 @@
|
|||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
|
\li \b RSTParser
|
||||||
|
|
||||||
|
RSTParser is an open-source C++ library for parsing reStructuredText
|
||||||
|
|
||||||
|
\list
|
||||||
|
\li \l https://github.com/vitaut-archive/rstparser
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
\badcode
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
Copyright (c) 2013, Victor Zverovich
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
\endlist
|
\endlist
|
||||||
*/
|
*/
|
||||||
|
|||||||
58
share/qtcreator/snippets/test.xml
Normal file
58
share/qtcreator/snippets/test.xml
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<snippets>
|
||||||
|
<snippet group="QML" trigger="TestCase" id="quicktest_case" complement="QuickTest Test Case">TestCase {
|
||||||
|
name: "$TestCaseName$"
|
||||||
|
|
||||||
|
function test_$TestFunctionName$() {
|
||||||
|
$$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</snippet>
|
||||||
|
<snippet group="C++" trigger="TEST" id="gtest_test_function" complement="GTest Function">TEST($TestSuite$, $TestName$)
|
||||||
|
{
|
||||||
|
$$
|
||||||
|
}
|
||||||
|
</snippet>
|
||||||
|
<snippet group="C++" trigger="TEST_F" id="gtest_test_function_fixture" complement="GTest Fixture">TEST_F($TestFixtureName$, $TestName$)
|
||||||
|
{
|
||||||
|
$$
|
||||||
|
}
|
||||||
|
</snippet>
|
||||||
|
<snippet group="C++" trigger="TEST_P" id="gtest_test_function_parameterized" complement="GTest Parameterized">INSTANTIATE_TEST_SUITE_P($InstantiationName$, $TestFixtureName$, $ParameterGenerator$);
|
||||||
|
|
||||||
|
TEST_P($TestFixtureName$, $TestName$)
|
||||||
|
{
|
||||||
|
$$
|
||||||
|
}
|
||||||
|
</snippet>
|
||||||
|
<snippet group="C++" trigger="BOOST_AUTO_TEST_CASE" id="boost_test_case" complement="Test Case">BOOST_AUTO_TEST_CASE($TestName$)
|
||||||
|
{
|
||||||
|
$$
|
||||||
|
}
|
||||||
|
</snippet>
|
||||||
|
<snippet group="C++" trigger="BOOST_AUTO_TEST_SUITE" id="boost_test_suite" complement="Test Suite">BOOST_AUTO_TEST_SUITE($SuiteName$)
|
||||||
|
BOOST_AUTO_TEST_CASE($TestName$)
|
||||||
|
{
|
||||||
|
$$
|
||||||
|
}
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
</snippet>
|
||||||
|
<snippet group="C++" trigger="TEST_CASE" id="catch_testcase_with_section" complement="Catch Test Case">TEST_CASE("$TestCaseName$") {
|
||||||
|
SECTION("$SectionName$") {
|
||||||
|
$$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</snippet>
|
||||||
|
<snippet group="C++" trigger="SCENARIO" id="catch_scenario" complement="Catch Scenario">SCENARIO("$ScenarioName$") {
|
||||||
|
GIVEN("$Initial$") {
|
||||||
|
$$
|
||||||
|
WHEN("$Condition$") {
|
||||||
|
$$
|
||||||
|
THEN("$Expectation$") {
|
||||||
|
$$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</snippet>
|
||||||
|
</snippets>
|
||||||
@@ -14,4 +14,16 @@
|
|||||||
# define EXTENSIONSYSTEM_EXPORT Q_DECL_IMPORT
|
# define EXTENSIONSYSTEM_EXPORT Q_DECL_IMPORT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(WITH_TESTS)
|
||||||
|
# if defined(EXTENSIONSYSTEM_LIBRARY)
|
||||||
|
# define EXTENSIONSYSTEM_TEST_EXPORT Q_DECL_EXPORT
|
||||||
|
# elif defined(EXTENSIONSYSTEM_STATIC_LIBRARY)
|
||||||
|
# define EXTENSIONSYSTEM_TEST_EXPORT
|
||||||
|
# else
|
||||||
|
# define EXTENSIONSYSTEM_TEST_EXPORT Q_DECL_IMPORT
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define QTSUPPORT_TEST_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
Q_DECLARE_LOGGING_CATEGORY(pluginLog)
|
Q_DECLARE_LOGGING_CATEGORY(pluginLog)
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace Internal {
|
|||||||
|
|
||||||
class PluginSpecPrivate;
|
class PluginSpecPrivate;
|
||||||
|
|
||||||
class EXTENSIONSYSTEM_EXPORT PluginManagerPrivate : public QObject
|
class EXTENSIONSYSTEM_TEST_EXPORT PluginManagerPrivate : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class IPlugin;
|
|||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class EXTENSIONSYSTEM_EXPORT PluginSpecPrivate : public QObject
|
class EXTENSIONSYSTEM_TEST_EXPORT PluginSpecPrivate : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
|||||||
@@ -3154,6 +3154,21 @@ void AspectList::removeItem(const std::shared_ptr<BaseAspect> &item)
|
|||||||
actualRemoveItem(item);
|
actualRemoveItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AspectList::clear()
|
||||||
|
{
|
||||||
|
if (undoStack()) {
|
||||||
|
undoStack()->beginMacro("Clear");
|
||||||
|
|
||||||
|
for (auto item : volatileItems())
|
||||||
|
undoStack()->push(new RemoveItemCommand(this, item));
|
||||||
|
|
||||||
|
undoStack()->endMacro();
|
||||||
|
} else {
|
||||||
|
for (auto item : volatileItems())
|
||||||
|
actualRemoveItem(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AspectList::apply()
|
void AspectList::apply()
|
||||||
{
|
{
|
||||||
d->items = d->volatileItems;
|
d->items = d->volatileItems;
|
||||||
@@ -3286,8 +3301,10 @@ QStandardItem *StringSelectionAspect::itemById(const QString &id)
|
|||||||
|
|
||||||
void StringSelectionAspect::bufferToGui()
|
void StringSelectionAspect::bufferToGui()
|
||||||
{
|
{
|
||||||
if (!m_model)
|
if (!m_model) {
|
||||||
|
m_undoable.setSilently(m_buffer);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto selected = itemById(m_buffer);
|
auto selected = itemById(m_buffer);
|
||||||
if (selected) {
|
if (selected) {
|
||||||
@@ -3302,8 +3319,10 @@ void StringSelectionAspect::bufferToGui()
|
|||||||
m_selectionModel->setCurrentIndex(m_model->item(0)->index(),
|
m_selectionModel->setCurrentIndex(m_model->item(0)->index(),
|
||||||
QItemSelectionModel::SelectionFlag::ClearAndSelect);
|
QItemSelectionModel::SelectionFlag::ClearAndSelect);
|
||||||
} else {
|
} else {
|
||||||
|
m_undoable.setSilently(m_buffer);
|
||||||
m_selectionModel->setCurrentIndex(QModelIndex(), QItemSelectionModel::SelectionFlag::Clear);
|
m_selectionModel->setCurrentIndex(QModelIndex(), QItemSelectionModel::SelectionFlag::Clear);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleGuiChanged();
|
handleGuiChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1031,6 +1031,7 @@ public:
|
|||||||
|
|
||||||
void removeItem(const std::shared_ptr<BaseAspect> &item);
|
void removeItem(const std::shared_ptr<BaseAspect> &item);
|
||||||
void actualRemoveItem(const std::shared_ptr<BaseAspect> &item);
|
void actualRemoveItem(const std::shared_ptr<BaseAspect> &item);
|
||||||
|
void clear();
|
||||||
|
|
||||||
void apply() override;
|
void apply() override;
|
||||||
|
|
||||||
|
|||||||
@@ -225,11 +225,12 @@ QString Environment::expandedValueForKey(const QString &key) const
|
|||||||
|
|
||||||
FilePath Environment::searchInPath(const QString &executable,
|
FilePath Environment::searchInPath(const QString &executable,
|
||||||
const FilePaths &additionalDirs,
|
const FilePaths &additionalDirs,
|
||||||
const FilePathPredicate &filter) const
|
const FilePathPredicate &filter,
|
||||||
|
FilePath::MatchScope scope) const
|
||||||
{
|
{
|
||||||
const FilePath exec = FilePath::fromUserInput(expandVariables(executable));
|
const FilePath exec = FilePath::fromUserInput(expandVariables(executable));
|
||||||
const FilePaths dirs = path() + additionalDirs;
|
const FilePaths dirs = path() + additionalDirs;
|
||||||
return exec.searchInDirectories(dirs, filter, FilePath::WithAnySuffix);
|
return exec.searchInDirectories(dirs, filter, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePaths Environment::path() const
|
FilePaths Environment::path() const
|
||||||
|
|||||||
@@ -61,7 +61,8 @@ public:
|
|||||||
|
|
||||||
FilePath searchInPath(const QString &executable,
|
FilePath searchInPath(const QString &executable,
|
||||||
const FilePaths &additionalDirs = FilePaths(),
|
const FilePaths &additionalDirs = FilePaths(),
|
||||||
const FilePathPredicate &func = {}) const;
|
const FilePathPredicate &func = {},
|
||||||
|
FilePath::MatchScope = FilePath::WithAnySuffix) const;
|
||||||
|
|
||||||
FilePaths path() const;
|
FilePaths path() const;
|
||||||
FilePaths pathListValue(const QString &varName) const;
|
FilePaths pathListValue(const QString &varName) const;
|
||||||
|
|||||||
@@ -2173,6 +2173,7 @@ FileFilter::FileFilter(const QStringList &nameFilters,
|
|||||||
fileFilters(fileFilters),
|
fileFilters(fileFilters),
|
||||||
iteratorFlags(flags)
|
iteratorFlags(flags)
|
||||||
{
|
{
|
||||||
|
QTC_CHECK(this->fileFilters != QDir::Filters());
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList FileFilter::asFindArguments(const QString &path) const
|
QStringList FileFilter::asFindArguments(const QString &path) const
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
#include <projectexplorer/kitaspects.h>
|
#include <projectexplorer/kitaspects.h>
|
||||||
#include <projectexplorer/kitmanager.h>
|
#include <projectexplorer/kitmanager.h>
|
||||||
#include <projectexplorer/project.h>
|
#include <projectexplorer/project.h>
|
||||||
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
#include <projectexplorer/projectmanager.h>
|
#include <projectexplorer/projectmanager.h>
|
||||||
#include <projectexplorer/target.h>
|
#include <projectexplorer/target.h>
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <projectexplorer/kitmanager.h>
|
#include <projectexplorer/kitmanager.h>
|
||||||
#include <projectexplorer/toolchainmanager.h>
|
#include <projectexplorer/toolchainmanager.h>
|
||||||
#include <projectexplorer/projectexplorer.h>
|
#include <projectexplorer/projectexplorer.h>
|
||||||
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
|
|
||||||
@@ -93,7 +94,8 @@ void AndroidToolChain::addToEnvironment(Environment &env) const
|
|||||||
if (javaHome.exists()) {
|
if (javaHome.exists()) {
|
||||||
env.set(Constants::JAVA_HOME_ENV_VAR, javaHome.toUserOutput());
|
env.set(Constants::JAVA_HOME_ENV_VAR, javaHome.toUserOutput());
|
||||||
const FilePath javaBin = javaHome.pathAppended("bin");
|
const FilePath javaBin = javaHome.pathAppended("bin");
|
||||||
const FilePath currentJavaFilePath = env.searchInPath("java");
|
const FilePath currentJavaFilePath
|
||||||
|
= env.searchInPath("java", {}, {}, FilePath::WithExeSuffix);
|
||||||
if (!currentJavaFilePath.isChildOf(javaBin))
|
if (!currentJavaFilePath.isChildOf(javaBin))
|
||||||
env.prependOrSetPath(javaBin);
|
env.prependOrSetPath(javaBin);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -231,10 +231,10 @@ ClangModelManagerSupport::ClangModelManagerSupport()
|
|||||||
connect(modelManager, &CppModelManager::fallbackProjectPartUpdated, this, [this] {
|
connect(modelManager, &CppModelManager::fallbackProjectPartUpdated, this, [this] {
|
||||||
if (sessionModeEnabled())
|
if (sessionModeEnabled())
|
||||||
return;
|
return;
|
||||||
if (ClangdClient * const fallbackClient = clientForProject(nullptr)) {
|
if (ClangdClient * const fallbackClient = clientForProject(nullptr))
|
||||||
LanguageClientManager::shutdownClient(fallbackClient);
|
LanguageClientManager::shutdownClient(fallbackClient);
|
||||||
|
if (ClangdSettings::instance().useClangd())
|
||||||
claimNonProjectSources(new ClangdClient(nullptr, {}));
|
claimNonProjectSources(new ClangdClient(nullptr, {}));
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
auto projectManager = ProjectManager::instance();
|
auto projectManager = ProjectManager::instance();
|
||||||
@@ -251,9 +251,6 @@ ClangModelManagerSupport::ClangModelManagerSupport()
|
|||||||
connect(&ClangdSettings::instance(), &ClangdSettings::changed,
|
connect(&ClangdSettings::instance(), &ClangdSettings::changed,
|
||||||
this, &ClangModelManagerSupport::onClangdSettingsChanged);
|
this, &ClangModelManagerSupport::onClangdSettingsChanged);
|
||||||
|
|
||||||
if (ClangdSettings::instance().useClangd())
|
|
||||||
new ClangdClient(nullptr, {});
|
|
||||||
|
|
||||||
new ClangdQuickFixFactory(); // memory managed by CppEditor::g_cppQuickFixFactories
|
new ClangdQuickFixFactory(); // memory managed by CppEditor::g_cppQuickFixFactories
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -777,8 +774,13 @@ void ClangModelManagerSupport::onEditorOpened(IEditor *editor)
|
|||||||
project = nullptr;
|
project = nullptr;
|
||||||
else if (!project && ProjectFile::isHeader(document->filePath()))
|
else if (!project && ProjectFile::isHeader(document->filePath()))
|
||||||
project = fallbackProject();
|
project = fallbackProject();
|
||||||
if (ClangdClient * const client = clientForProject(project))
|
ClangdClient *client = clientForProject(project);
|
||||||
LanguageClientManager::openDocumentWithClient(textDocument, client);
|
if (!client) {
|
||||||
|
if (project)
|
||||||
|
return;
|
||||||
|
client = new ClangdClient(nullptr, {});
|
||||||
|
}
|
||||||
|
LanguageClientManager::openDocumentWithClient(textDocument, client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
3
src/plugins/cmakeprojectmanager/3rdparty/rstparser/README.qt
vendored
Normal file
3
src/plugins/cmakeprojectmanager/3rdparty/rstparser/README.qt
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Files taken from the CMake repository https://github.com/vitaut-archive/rstparser.git
|
||||||
|
|
||||||
|
49e1e6626ba28357749acfe3bf07c4a19e5bc4ef
|
||||||
32
src/plugins/cmakeprojectmanager/3rdparty/rstparser/README.rst
vendored
Normal file
32
src/plugins/cmakeprojectmanager/3rdparty/rstparser/README.rst
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
RSTParser
|
||||||
|
=========
|
||||||
|
|
||||||
|
RSTParser is an open-source C++ library for parsing
|
||||||
|
`reStructuredText <http://docutils.sourceforge.net/rst.html>`__.
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
Copyright (c) 2013, Victor Zverovich
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
169
src/plugins/cmakeprojectmanager/3rdparty/rstparser/rstparser-test.cc
vendored
Normal file
169
src/plugins/cmakeprojectmanager/3rdparty/rstparser/rstparser-test.cc
vendored
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
reStructuredText parser tests.
|
||||||
|
|
||||||
|
Copyright (c) 2012, Victor Zverovich
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# include <crtdbg.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "rstparser.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class TestHandler : public rst::ContentHandler {
|
||||||
|
private:
|
||||||
|
std::stack<std::string> tags_;
|
||||||
|
std::string content_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
const std::string &content() const { return content_; }
|
||||||
|
|
||||||
|
void StartBlock(rst::BlockType type) {
|
||||||
|
std::string tag;
|
||||||
|
switch (type) {
|
||||||
|
case rst::PARAGRAPH:
|
||||||
|
tag = "p";
|
||||||
|
break;
|
||||||
|
case rst::LINE_BLOCK:
|
||||||
|
tag = "lineblock";
|
||||||
|
break;
|
||||||
|
case rst::BLOCK_QUOTE:
|
||||||
|
tag = "blockquote";
|
||||||
|
break;
|
||||||
|
case rst::BULLET_LIST:
|
||||||
|
tag = "ul";
|
||||||
|
break;
|
||||||
|
case rst::LIST_ITEM:
|
||||||
|
tag = "li";
|
||||||
|
break;
|
||||||
|
case rst::LITERAL_BLOCK:
|
||||||
|
tag = "code";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
content_ += "<" + tag + ">";
|
||||||
|
tags_.push(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EndBlock() {
|
||||||
|
content_ += "</" + tags_.top() + ">";
|
||||||
|
tags_.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleText(const char *text, std::size_t size) {
|
||||||
|
content_.append(text, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleDirective(const char *type) {
|
||||||
|
content_ += std::string("<") + type + " />";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string Parse(const char *s) {
|
||||||
|
TestHandler handler;
|
||||||
|
rst::Parser parser(&handler);
|
||||||
|
parser.Parse(s);
|
||||||
|
return handler.content();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserTest, Paragraph) {
|
||||||
|
EXPECT_EQ("<p>test</p>", Parse("test"));
|
||||||
|
EXPECT_EQ("<p>test</p>", Parse("\ntest"));
|
||||||
|
EXPECT_EQ("<p>.</p>", Parse("."));
|
||||||
|
EXPECT_EQ("<p>..test</p>", Parse("..test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserTest, LineBlock) {
|
||||||
|
EXPECT_EQ("<lineblock>test</lineblock>", Parse("| test"));
|
||||||
|
EXPECT_EQ("<lineblock> abc\ndef</lineblock>", Parse("| abc\n| def"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserTest, BlockQuote) {
|
||||||
|
EXPECT_EQ("<blockquote>test</blockquote>", Parse(" test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserTest, PreserveInnerSpace) {
|
||||||
|
EXPECT_EQ("<p>a b</p>", Parse("a b"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserTest, ReplaceWhitespace) {
|
||||||
|
EXPECT_EQ("<p>a b</p>", Parse("a\tb"));
|
||||||
|
EXPECT_EQ("<blockquote>a b</blockquote>", Parse(" a\tb"));
|
||||||
|
EXPECT_EQ("<p>a b</p>", Parse("a\vb"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserTest, StripTrailingSpace) {
|
||||||
|
EXPECT_EQ("<p>test</p>", Parse("test \t"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserTest, MultiLineBlock) {
|
||||||
|
EXPECT_EQ("<p>line 1\nline 2</p>", Parse("line 1\nline 2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserTest, UnindentBlock) {
|
||||||
|
EXPECT_EQ("<blockquote>abc</blockquote><p>def</p>", Parse(" abc\ndef"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserTest, BulletList) {
|
||||||
|
EXPECT_EQ("<ul><li>item</li></ul>", Parse("* item"));
|
||||||
|
EXPECT_EQ("<ul><li>abc\ndef</li></ul>", Parse("* abc\n def"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserTest, Literal) {
|
||||||
|
EXPECT_EQ("<p>abc:</p><code>def</code>", Parse("abc::\n\n def"));
|
||||||
|
EXPECT_EQ("<code>abc\ndef</code>", Parse("::\n\n abc\n def"));
|
||||||
|
EXPECT_EQ("<p>abc\ndef</p>", Parse("::\n\nabc\ndef"));
|
||||||
|
EXPECT_EQ("<p>::\nabc\ndef</p>", Parse("::\nabc\ndef"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserTest, Comment) {
|
||||||
|
EXPECT_EQ("", Parse(".."));
|
||||||
|
EXPECT_EQ("", Parse("..\n"));
|
||||||
|
EXPECT_EQ("", Parse(".. comment"));
|
||||||
|
EXPECT_EQ("", Parse(".. comment:"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserTest, Directive) {
|
||||||
|
EXPECT_EQ("<test />", Parse(".. test::"));
|
||||||
|
EXPECT_EQ("<test />", Parse(".. test::"));
|
||||||
|
EXPECT_EQ("<test />", Parse("..\ttest::"));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
// Disable message boxes on assertion failures.
|
||||||
|
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
|
||||||
|
_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
|
||||||
|
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
|
||||||
|
_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
|
||||||
|
#endif
|
||||||
|
testing::InitGoogleTest(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
||||||
249
src/plugins/cmakeprojectmanager/3rdparty/rstparser/rstparser.cc
vendored
Normal file
249
src/plugins/cmakeprojectmanager/3rdparty/rstparser/rstparser.cc
vendored
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
/*
|
||||||
|
A reStructuredText parser written in C++.
|
||||||
|
|
||||||
|
Copyright (c) 2013, Victor Zverovich
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "rstparser.h"
|
||||||
|
|
||||||
|
#include <cctype>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
inline bool IsSpace(char c) {
|
||||||
|
switch (c) {
|
||||||
|
case ' ': case '\t': case '\v': case '\f':
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if s ends with string end.
|
||||||
|
bool EndsWith(const std::string &s, const char *end) {
|
||||||
|
std::size_t size = s.size(), end_size = std::strlen(end);
|
||||||
|
return size >= end_size ? std::strcmp(&s[size - end_size], end) == 0 : false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rst::ContentHandler::~ContentHandler() {}
|
||||||
|
|
||||||
|
void rst::Parser::SkipSpace() {
|
||||||
|
while (IsSpace(*ptr_))
|
||||||
|
++ptr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string rst::Parser::ParseDirectiveType() {
|
||||||
|
const char *s = ptr_;
|
||||||
|
if (!std::isalnum(*s))
|
||||||
|
return std::string();
|
||||||
|
for (;;) {
|
||||||
|
++s;
|
||||||
|
if (std::isalnum(*s))
|
||||||
|
continue;
|
||||||
|
switch (*s) {
|
||||||
|
case '-': case '_': case '+': case ':': case '.':
|
||||||
|
if (std::isalnum(s[1])) {
|
||||||
|
++s;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Fall through.
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
std::string type;
|
||||||
|
if (s != ptr_)
|
||||||
|
type.assign(ptr_, s);
|
||||||
|
ptr_ = s;
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rst::Parser::EnterBlock(rst::BlockType &prev_type, rst::BlockType type) {
|
||||||
|
if (type == prev_type)
|
||||||
|
return;
|
||||||
|
if (prev_type == LIST_ITEM)
|
||||||
|
handler_->EndBlock();
|
||||||
|
if (type == LIST_ITEM)
|
||||||
|
handler_->StartBlock(BULLET_LIST);
|
||||||
|
prev_type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rst::Parser::ParseBlock(
|
||||||
|
rst::BlockType type, rst::BlockType &prev_type, int indent) {
|
||||||
|
std::string text;
|
||||||
|
for (bool first = true; ; first = false) {
|
||||||
|
const char *line_start = ptr_;
|
||||||
|
if (!first) {
|
||||||
|
// Check indentation.
|
||||||
|
SkipSpace();
|
||||||
|
if (ptr_ - line_start != indent)
|
||||||
|
break;
|
||||||
|
if (*ptr_ == '\n') {
|
||||||
|
++ptr_;
|
||||||
|
break; // Empty line ends the block.
|
||||||
|
}
|
||||||
|
if (!*ptr_)
|
||||||
|
break; // End of input.
|
||||||
|
}
|
||||||
|
// Strip indentation.
|
||||||
|
line_start = ptr_;
|
||||||
|
|
||||||
|
// Find the end of the line.
|
||||||
|
while (*ptr_ && *ptr_ != '\n')
|
||||||
|
++ptr_;
|
||||||
|
|
||||||
|
// Strip whitespace at the end of the line.
|
||||||
|
const char *end = ptr_;
|
||||||
|
while (end != line_start && IsSpace(end[-1]))
|
||||||
|
--end;
|
||||||
|
|
||||||
|
// Copy text converting all whitespace characters to spaces.
|
||||||
|
text.reserve(end - line_start + 1);
|
||||||
|
if (!first)
|
||||||
|
text.push_back('\n');
|
||||||
|
enum {TAB_WIDTH = 8};
|
||||||
|
for (const char *s = line_start; s != end; ++s) {
|
||||||
|
char c = *s;
|
||||||
|
if (c == '\t') {
|
||||||
|
text.append(" ",
|
||||||
|
TAB_WIDTH - ((indent + s - line_start) % TAB_WIDTH));
|
||||||
|
} else if (IsSpace(c)) {
|
||||||
|
text.push_back(' ');
|
||||||
|
} else {
|
||||||
|
text.push_back(*s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (*ptr_ == '\n')
|
||||||
|
++ptr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove a trailing newline.
|
||||||
|
if (*text.rbegin() == '\n')
|
||||||
|
text.resize(text.size() - 1);
|
||||||
|
|
||||||
|
bool literal = type == PARAGRAPH && EndsWith(text, "::");
|
||||||
|
if (!literal || text.size() != 2) {
|
||||||
|
std::size_t size = text.size();
|
||||||
|
if (literal)
|
||||||
|
--size;
|
||||||
|
EnterBlock(prev_type, type);
|
||||||
|
handler_->StartBlock(type);
|
||||||
|
handler_->HandleText(text.c_str(), size);
|
||||||
|
handler_->EndBlock();
|
||||||
|
}
|
||||||
|
if (literal) {
|
||||||
|
// Parse a literal block.
|
||||||
|
const char *line_start = ptr_;
|
||||||
|
SkipSpace();
|
||||||
|
int new_indent = static_cast<int>(ptr_ - line_start);
|
||||||
|
if (new_indent > indent)
|
||||||
|
ParseBlock(LITERAL_BLOCK, prev_type, new_indent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rst::Parser::ParseLineBlock(rst::BlockType &prev_type, int indent) {
|
||||||
|
std::string text;
|
||||||
|
for (bool first = true; ; first = false) {
|
||||||
|
const char *line_start = ptr_;
|
||||||
|
if (!first) {
|
||||||
|
// Check indentation.
|
||||||
|
SkipSpace();
|
||||||
|
if (*ptr_ != '|' || !IsSpace(ptr_[1]) || ptr_ - line_start != indent)
|
||||||
|
break;
|
||||||
|
ptr_ += 2;
|
||||||
|
if (!*ptr_)
|
||||||
|
break; // End of input.
|
||||||
|
}
|
||||||
|
// Strip indentation.
|
||||||
|
line_start = ptr_;
|
||||||
|
|
||||||
|
// Find the end of the line.
|
||||||
|
while (*ptr_ && *ptr_ != '\n')
|
||||||
|
++ptr_;
|
||||||
|
if (*ptr_ == '\n')
|
||||||
|
++ptr_;
|
||||||
|
text.append(line_start, ptr_);
|
||||||
|
}
|
||||||
|
|
||||||
|
EnterBlock(prev_type, rst::LINE_BLOCK);
|
||||||
|
handler_->StartBlock(rst::LINE_BLOCK);
|
||||||
|
handler_->HandleText(text.c_str(), text.size());
|
||||||
|
handler_->EndBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void rst::Parser::Parse(const char *s) {
|
||||||
|
BlockType prev_type = PARAGRAPH;
|
||||||
|
ptr_ = s;
|
||||||
|
while (*ptr_) {
|
||||||
|
// Skip whitespace and empty lines.
|
||||||
|
const char *line_start = ptr_;
|
||||||
|
SkipSpace();
|
||||||
|
if (*ptr_ == '\n') {
|
||||||
|
++ptr_;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (*ptr_) {
|
||||||
|
case '.':
|
||||||
|
if (ptr_[1] == '.') {
|
||||||
|
char c = ptr_[2];
|
||||||
|
if (!IsSpace(c) && c != '\n' && c)
|
||||||
|
break;
|
||||||
|
// Parse a directive or a comment.
|
||||||
|
ptr_ += 2;
|
||||||
|
SkipSpace();
|
||||||
|
std::string type = ParseDirectiveType();
|
||||||
|
if (!type.empty() && ptr_[0] == ':' && ptr_[1] == ':') {
|
||||||
|
ptr_ += 2;
|
||||||
|
handler_->HandleDirective(type.c_str());
|
||||||
|
}
|
||||||
|
// Skip everything till the end of the line.
|
||||||
|
while (*ptr_ && *ptr_ != '\n')
|
||||||
|
++ptr_;
|
||||||
|
if (*ptr_ == '\n')
|
||||||
|
++ptr_;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '*': case '+': case '-':
|
||||||
|
if (IsSpace(ptr_[1])) {
|
||||||
|
// Parse a bullet list item.
|
||||||
|
ptr_ += 2;
|
||||||
|
ParseBlock(LIST_ITEM, prev_type, static_cast<int>(ptr_ - line_start));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '|':
|
||||||
|
if (IsSpace(ptr_[1])) {
|
||||||
|
// Parse a line block.
|
||||||
|
int indent = static_cast<int>(ptr_ - line_start);
|
||||||
|
ptr_ += 2;
|
||||||
|
ParseLineBlock(prev_type, indent);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ParseBlock(std::isspace(line_start[0]) ? BLOCK_QUOTE : PARAGRAPH,
|
||||||
|
prev_type, static_cast<int>(ptr_ - line_start));
|
||||||
|
}
|
||||||
|
EnterBlock(prev_type, PARAGRAPH);
|
||||||
|
}
|
||||||
97
src/plugins/cmakeprojectmanager/3rdparty/rstparser/rstparser.h
vendored
Normal file
97
src/plugins/cmakeprojectmanager/3rdparty/rstparser/rstparser.h
vendored
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
A reStructuredText parser written in C++.
|
||||||
|
|
||||||
|
Copyright (c) 2013, Victor Zverovich
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RSTPARSER_H_
|
||||||
|
#define RSTPARSER_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace rst {
|
||||||
|
|
||||||
|
enum BlockType {
|
||||||
|
PARAGRAPH,
|
||||||
|
LINE_BLOCK,
|
||||||
|
BLOCK_QUOTE,
|
||||||
|
BULLET_LIST,
|
||||||
|
LIST_ITEM,
|
||||||
|
LITERAL_BLOCK
|
||||||
|
};
|
||||||
|
|
||||||
|
// Receive notification of the logical content of a document.
|
||||||
|
class ContentHandler {
|
||||||
|
public:
|
||||||
|
virtual ~ContentHandler();
|
||||||
|
|
||||||
|
// Receives notification of the beginning of a text block.
|
||||||
|
virtual void StartBlock(BlockType type) = 0;
|
||||||
|
|
||||||
|
// Receives notification of the end of a text block.
|
||||||
|
virtual void EndBlock() = 0;
|
||||||
|
|
||||||
|
// Receives notification of text.
|
||||||
|
virtual void HandleText(const char *text, std::size_t size) = 0;
|
||||||
|
|
||||||
|
// Receives notification of a directive.
|
||||||
|
virtual void HandleDirective(const char *type) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A parser for a subset of reStructuredText.
|
||||||
|
class Parser {
|
||||||
|
private:
|
||||||
|
ContentHandler *handler_;
|
||||||
|
const char *ptr_;
|
||||||
|
|
||||||
|
// Skips whitespace.
|
||||||
|
void SkipSpace();
|
||||||
|
|
||||||
|
// Parses a directive type.
|
||||||
|
std::string ParseDirectiveType();
|
||||||
|
|
||||||
|
// Parses a paragraph.
|
||||||
|
void ParseParagraph();
|
||||||
|
|
||||||
|
// Changes the current block type sending notifications if necessary.
|
||||||
|
void EnterBlock(rst::BlockType &prev_type, rst::BlockType type);
|
||||||
|
|
||||||
|
// Parses a block of text.
|
||||||
|
void ParseBlock(rst::BlockType type, rst::BlockType &prev_type, int indent);
|
||||||
|
|
||||||
|
// Parses a line block.
|
||||||
|
void ParseLineBlock(rst::BlockType &prev_type, int indent);
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Parser(ContentHandler *h) : handler_(h), ptr_(0) {}
|
||||||
|
|
||||||
|
// Parses a string containing reStructuredText and returns a document node.
|
||||||
|
void Parse(const char *s);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // RSTPARSER_H_
|
||||||
|
|
||||||
@@ -1278,9 +1278,9 @@ void CMakeBuildSystem::setupCMakeSymbolsHash()
|
|||||||
m_cmakeSymbolsHash.insert(QString::fromUtf8(arg.Value), link);
|
m_cmakeSymbolsHash.insert(QString::fromUtf8(arg.Value), link);
|
||||||
|
|
||||||
if (func.LowerCaseName() == "option")
|
if (func.LowerCaseName() == "option")
|
||||||
m_projectKeywords.variables << QString::fromUtf8(arg.Value);
|
m_projectKeywords.variables[QString::fromUtf8(arg.Value)] = FilePath();
|
||||||
else
|
else
|
||||||
m_projectKeywords.functions << QString::fromUtf8(arg.Value);
|
m_projectKeywords.functions[QString::fromUtf8(arg.Value)] = FilePath();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "cmakefilecompletionassist.h"
|
#include "cmakefilecompletionassist.h"
|
||||||
#include "cmakeindenter.h"
|
#include "cmakeindenter.h"
|
||||||
#include "cmakekitaspect.h"
|
#include "cmakekitaspect.h"
|
||||||
|
#include "cmakeproject.h"
|
||||||
#include "cmakeprojectconstants.h"
|
#include "cmakeprojectconstants.h"
|
||||||
|
|
||||||
#include "3rdparty/cmake/cmListFileCache.h"
|
#include "3rdparty/cmake/cmListFileCache.h"
|
||||||
@@ -19,11 +20,14 @@
|
|||||||
#include <projectexplorer/buildconfiguration.h>
|
#include <projectexplorer/buildconfiguration.h>
|
||||||
#include <projectexplorer/buildsystem.h>
|
#include <projectexplorer/buildsystem.h>
|
||||||
#include <projectexplorer/project.h>
|
#include <projectexplorer/project.h>
|
||||||
|
#include <projectexplorer/projectmanager.h>
|
||||||
#include <projectexplorer/projecttree.h>
|
#include <projectexplorer/projecttree.h>
|
||||||
#include <projectexplorer/target.h>
|
#include <projectexplorer/target.h>
|
||||||
|
#include <texteditor/basehoverhandler.h>
|
||||||
#include <texteditor/textdocument.h>
|
#include <texteditor/textdocument.h>
|
||||||
#include <texteditor/texteditoractionhandler.h>
|
#include <texteditor/texteditoractionhandler.h>
|
||||||
#include <utils/textutils.h>
|
#include <utils/textutils.h>
|
||||||
|
#include <utils/tooltip/tooltip.h>
|
||||||
|
|
||||||
#include <QTextDocument>
|
#include <QTextDocument>
|
||||||
|
|
||||||
@@ -31,6 +35,7 @@
|
|||||||
|
|
||||||
using namespace Core;
|
using namespace Core;
|
||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
|
using namespace Utils;
|
||||||
using namespace TextEditor;
|
using namespace TextEditor;
|
||||||
|
|
||||||
namespace CMakeProjectManager::Internal {
|
namespace CMakeProjectManager::Internal {
|
||||||
@@ -308,6 +313,83 @@ static TextDocument *createCMakeDocument()
|
|||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// CMakeHoverHandler
|
||||||
|
//
|
||||||
|
|
||||||
|
class CMakeHoverHandler : public TextEditor::BaseHoverHandler
|
||||||
|
{
|
||||||
|
mutable CMakeKeywords m_keywords;
|
||||||
|
QString m_helpToolTip;
|
||||||
|
|
||||||
|
public:
|
||||||
|
const CMakeKeywords &keywords() const;
|
||||||
|
|
||||||
|
void identifyMatch(TextEditor::TextEditorWidget *editorWidget,
|
||||||
|
int pos,
|
||||||
|
ReportPriority report) final;
|
||||||
|
void operateTooltip(TextEditorWidget *editorWidget, const QPoint &point) final;
|
||||||
|
};
|
||||||
|
|
||||||
|
const CMakeKeywords &CMakeHoverHandler::keywords() const
|
||||||
|
{
|
||||||
|
if (m_keywords.functions.isEmpty()) {
|
||||||
|
CMakeTool *tool = nullptr;
|
||||||
|
if (auto bs = ProjectTree::currentBuildSystem())
|
||||||
|
tool = CMakeKitAspect::cmakeTool(bs->target()->kit());
|
||||||
|
if (!tool)
|
||||||
|
tool = CMakeToolManager::defaultCMakeTool();
|
||||||
|
|
||||||
|
if (tool)
|
||||||
|
m_keywords = tool->keywords();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_keywords;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString readFirstParagraphs(const QString &element, const FilePath &helpFile);
|
||||||
|
|
||||||
|
void CMakeHoverHandler::identifyMatch(TextEditor::TextEditorWidget *editorWidget,
|
||||||
|
int pos,
|
||||||
|
ReportPriority report)
|
||||||
|
{
|
||||||
|
const QScopeGuard cleanup([this, report] { report(priority()); });
|
||||||
|
|
||||||
|
QTextCursor cursor = editorWidget->textCursor();
|
||||||
|
cursor.setPosition(pos);
|
||||||
|
const QString word = Utils::Text::wordUnderCursor(cursor);
|
||||||
|
|
||||||
|
FilePath helpFile;
|
||||||
|
for (const auto &map : {keywords().functions,
|
||||||
|
keywords().variables,
|
||||||
|
keywords().directoryProperties,
|
||||||
|
keywords().sourceProperties,
|
||||||
|
keywords().targetProperties,
|
||||||
|
keywords().testProperties,
|
||||||
|
keywords().properties,
|
||||||
|
keywords().includeStandardModules,
|
||||||
|
keywords().findModules,
|
||||||
|
keywords().policies}) {
|
||||||
|
if (map.contains(word)) {
|
||||||
|
helpFile = map.value(word);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_helpToolTip.clear();
|
||||||
|
if (!helpFile.isEmpty())
|
||||||
|
m_helpToolTip = readFirstParagraphs(word, helpFile);
|
||||||
|
|
||||||
|
setPriority(m_helpToolTip.isEmpty() ? Priority_Tooltip : Priority_None);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMakeHoverHandler::operateTooltip(TextEditorWidget *editorWidget, const QPoint &point)
|
||||||
|
{
|
||||||
|
if (!m_helpToolTip.isEmpty())
|
||||||
|
Utils::ToolTip::show(point, m_helpToolTip, Qt::MarkdownText, editorWidget);
|
||||||
|
else
|
||||||
|
Utils::ToolTip::hide();
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// CMakeEditorFactory
|
// CMakeEditorFactory
|
||||||
//
|
//
|
||||||
@@ -334,6 +416,8 @@ CMakeEditorFactory::CMakeEditorFactory()
|
|||||||
| TextEditorActionHandler::FollowSymbolUnderCursor
|
| TextEditorActionHandler::FollowSymbolUnderCursor
|
||||||
| TextEditorActionHandler::Format);
|
| TextEditorActionHandler::Format);
|
||||||
|
|
||||||
|
addHoverHandler(new CMakeHoverHandler);
|
||||||
|
|
||||||
ActionContainer *contextMenu = ActionManager::createMenu(Constants::M_CONTEXT);
|
ActionContainer *contextMenu = ActionManager::createMenu(Constants::M_CONTEXT);
|
||||||
contextMenu->addAction(ActionManager::command(TextEditor::Constants::FOLLOW_SYMBOL_UNDER_CURSOR));
|
contextMenu->addAction(ActionManager::command(TextEditor::Constants::FOLLOW_SYMBOL_UNDER_CURSOR));
|
||||||
contextMenu->addSeparator(Context(Constants::CMAKE_EDITOR_ID));
|
contextMenu->addSeparator(Context(Constants::CMAKE_EDITOR_ID));
|
||||||
|
|||||||
@@ -153,6 +153,40 @@ QList<AssistProposalItemInterface *> generateList(const T &words, const QIcon &i
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString readFirstParagraphs(const QString &element, const FilePath &helpFile)
|
||||||
|
{
|
||||||
|
static QMap<FilePath, QString> map;
|
||||||
|
if (map.contains(helpFile))
|
||||||
|
return map.value(helpFile);
|
||||||
|
|
||||||
|
auto content = helpFile.fileContents(1024).value_or(QByteArray());
|
||||||
|
const QString firstParagraphs
|
||||||
|
= QString("```\n%1\n```").arg(QString::fromUtf8(content.left(content.lastIndexOf("\n"))));
|
||||||
|
|
||||||
|
map[helpFile] = firstParagraphs;
|
||||||
|
return firstParagraphs;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<AssistProposalItemInterface *> generateList(const QMap<QString, FilePath> &words,
|
||||||
|
const QIcon &icon)
|
||||||
|
{
|
||||||
|
struct MarkDownAssitProposalItem : public AssistProposalItem
|
||||||
|
{
|
||||||
|
Qt::TextFormat detailFormat() const { return Qt::MarkdownText; }
|
||||||
|
};
|
||||||
|
|
||||||
|
QList<AssistProposalItemInterface *> list;
|
||||||
|
for (auto it = words.cbegin(); it != words.cend(); ++it) {
|
||||||
|
MarkDownAssitProposalItem *item = new MarkDownAssitProposalItem();
|
||||||
|
item->setText(it.key());
|
||||||
|
if (!it.value().isEmpty())
|
||||||
|
item->setDetail(readFirstParagraphs(it.key(), it.value()));
|
||||||
|
item->setIcon(icon);
|
||||||
|
list << item;
|
||||||
|
};
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
static int addFilePathItems(const AssistInterface *interface,
|
static int addFilePathItems(const AssistInterface *interface,
|
||||||
QList<AssistProposalItemInterface *> &items,
|
QList<AssistProposalItemInterface *> &items,
|
||||||
int symbolStartPos)
|
int symbolStartPos)
|
||||||
|
|||||||
@@ -89,19 +89,8 @@ public:
|
|||||||
bool m_didRun = true;
|
bool m_didRun = true;
|
||||||
|
|
||||||
QList<CMakeTool::Generator> m_generators;
|
QList<CMakeTool::Generator> m_generators;
|
||||||
QMap<QString, QStringList> m_functionArgs;
|
CMakeKeywords m_keywords;
|
||||||
QVector<FileApi> m_fileApis;
|
QVector<FileApi> m_fileApis;
|
||||||
QStringList m_variables;
|
|
||||||
QStringList m_functions;
|
|
||||||
QStringList m_properties;
|
|
||||||
QStringList m_generatorExpressions;
|
|
||||||
QStringList m_directoryProperties;
|
|
||||||
QStringList m_sourceProperties;
|
|
||||||
QStringList m_targetProperties;
|
|
||||||
QStringList m_testProperties;
|
|
||||||
QStringList m_includeStandardModules;
|
|
||||||
QStringList m_findModules;
|
|
||||||
QStringList m_policies;
|
|
||||||
CMakeTool::Version m_version;
|
CMakeTool::Version m_version;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -260,7 +249,7 @@ CMakeKeywords CMakeTool::keywords()
|
|||||||
if (!isValid())
|
if (!isValid())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
if (m_introspection->m_functions.isEmpty() && m_introspection->m_didRun) {
|
if (m_introspection->m_keywords.functions.isEmpty() && m_introspection->m_didRun) {
|
||||||
Process proc;
|
Process proc;
|
||||||
|
|
||||||
const FilePath findCMakeRoot = TemporaryDirectory::masterDirectoryFilePath()
|
const FilePath findCMakeRoot = TemporaryDirectory::masterDirectoryFilePath()
|
||||||
@@ -279,61 +268,52 @@ CMakeKeywords CMakeTool::keywords()
|
|||||||
const struct
|
const struct
|
||||||
{
|
{
|
||||||
const QString helpPath;
|
const QString helpPath;
|
||||||
QStringList &targetList;
|
QMap<QString, FilePath> &targetMap;
|
||||||
} introspections[] = {
|
} introspections[] = {
|
||||||
// Functions
|
// Functions
|
||||||
{"Help/command", m_introspection->m_functions},
|
{"Help/command", m_introspection->m_keywords.functions},
|
||||||
// Properties
|
// Properties
|
||||||
{"Help/prop_dir", m_introspection->m_directoryProperties},
|
{"Help/prop_dir", m_introspection->m_keywords.directoryProperties},
|
||||||
{"Help/prop_sf", m_introspection->m_sourceProperties},
|
{"Help/prop_sf", m_introspection->m_keywords.sourceProperties},
|
||||||
{"Help/prop_test", m_introspection->m_testProperties},
|
{"Help/prop_test", m_introspection->m_keywords.testProperties},
|
||||||
{"Help/prop_tgt", m_introspection->m_targetProperties},
|
{"Help/prop_tgt", m_introspection->m_keywords.targetProperties},
|
||||||
{"Help/prop_gbl", m_introspection->m_properties},
|
{"Help/prop_gbl", m_introspection->m_keywords.properties},
|
||||||
// Variables
|
// Variables
|
||||||
{"Help/variable", m_introspection->m_variables},
|
{"Help/variable", m_introspection->m_keywords.variables},
|
||||||
// Policies
|
// Policies
|
||||||
{"Help/policy", m_introspection->m_policies},
|
{"Help/policy", m_introspection->m_keywords.policies},
|
||||||
};
|
};
|
||||||
for (auto &i : introspections) {
|
for (auto &i : introspections) {
|
||||||
const FilePaths files = cmakeRoot.pathAppended(i.helpPath)
|
const FilePaths files = cmakeRoot.pathAppended(i.helpPath)
|
||||||
.dirEntries({{"*.rst"}, QDir::Files}, QDir::Name);
|
.dirEntries({{"*.rst"}, QDir::Files}, QDir::Name);
|
||||||
i.targetList = transform<QStringList>(files, &FilePath::completeBaseName);
|
for (const auto &filePath : files)
|
||||||
|
i.targetMap[filePath.completeBaseName()] = filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_introspection->m_properties << m_introspection->m_directoryProperties;
|
for (const auto &map : {m_introspection->m_keywords.directoryProperties,
|
||||||
m_introspection->m_properties << m_introspection->m_sourceProperties;
|
m_introspection->m_keywords.sourceProperties,
|
||||||
m_introspection->m_properties << m_introspection->m_testProperties;
|
m_introspection->m_keywords.testProperties,
|
||||||
m_introspection->m_properties << m_introspection->m_targetProperties;
|
m_introspection->m_keywords.targetProperties}) {
|
||||||
|
m_introspection->m_keywords.properties.insert(map);
|
||||||
|
}
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
const FilePaths files
|
const FilePaths files
|
||||||
= cmakeRoot.pathAppended("Help/module").dirEntries({{"*.rst"}, QDir::Files}, QDir::Name);
|
= cmakeRoot.pathAppended("Help/module").dirEntries({{"*.rst"}, QDir::Files}, QDir::Name);
|
||||||
const QStringList fileNames = transform<QStringList>(files, &FilePath::completeBaseName);
|
for (const FilePath &filePath : files) {
|
||||||
for (const QString &fileName : fileNames) {
|
const QString fileName = filePath.completeBaseName();
|
||||||
if (fileName.startsWith("Find"))
|
if (fileName.startsWith("Find"))
|
||||||
m_introspection->m_findModules << fileName.mid(4);
|
m_introspection->m_keywords.findModules[fileName.mid(4)] = filePath;
|
||||||
else
|
else
|
||||||
m_introspection->m_includeStandardModules << fileName;
|
m_introspection->m_keywords.includeStandardModules[fileName] = filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
parseSyntaxHighlightingXml();
|
const QStringList moduleFunctions = parseSyntaxHighlightingXml();
|
||||||
|
for (const auto &function : moduleFunctions)
|
||||||
|
m_introspection->m_keywords.functions[function] = FilePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
CMakeKeywords keywords;
|
return m_introspection->m_keywords;
|
||||||
keywords.functions = Utils::toSet(m_introspection->m_functions);
|
|
||||||
keywords.variables = Utils::toSet(m_introspection->m_variables);
|
|
||||||
keywords.functionArgs = m_introspection->m_functionArgs;
|
|
||||||
keywords.properties = Utils::toSet(m_introspection->m_properties);
|
|
||||||
keywords.generatorExpressions = Utils::toSet(m_introspection->m_generatorExpressions);
|
|
||||||
keywords.directoryProperties = Utils::toSet(m_introspection->m_directoryProperties);
|
|
||||||
keywords.sourceProperties = Utils::toSet(m_introspection->m_sourceProperties);
|
|
||||||
keywords.targetProperties = Utils::toSet(m_introspection->m_targetProperties);
|
|
||||||
keywords.testProperties = Utils::toSet(m_introspection->m_testProperties);
|
|
||||||
keywords.includeStandardModules = Utils::toSet(m_introspection->m_includeStandardModules);
|
|
||||||
keywords.findModules = Utils::toSet(m_introspection->m_findModules);
|
|
||||||
keywords.policies = Utils::toSet(m_introspection->m_policies);
|
|
||||||
|
|
||||||
return keywords;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CMakeTool::hasFileApi(bool ignoreCache) const
|
bool CMakeTool::hasFileApi(bool ignoreCache) const
|
||||||
@@ -495,8 +475,6 @@ static QStringList parseDefinition(const QString &definition)
|
|||||||
|
|
||||||
void CMakeTool::parseFunctionDetailsOutput(const QString &output)
|
void CMakeTool::parseFunctionDetailsOutput(const QString &output)
|
||||||
{
|
{
|
||||||
const QSet<QString> functionSet = Utils::toSet(m_introspection->m_functions);
|
|
||||||
|
|
||||||
bool expectDefinition = false;
|
bool expectDefinition = false;
|
||||||
QString currentDefinition;
|
QString currentDefinition;
|
||||||
|
|
||||||
@@ -515,14 +493,15 @@ void CMakeTool::parseFunctionDetailsOutput(const QString &output)
|
|||||||
QStringList words = parseDefinition(currentDefinition);
|
QStringList words = parseDefinition(currentDefinition);
|
||||||
if (!words.isEmpty()) {
|
if (!words.isEmpty()) {
|
||||||
const QString command = words.takeFirst();
|
const QString command = words.takeFirst();
|
||||||
if (functionSet.contains(command)) {
|
if (m_introspection->m_keywords.functions.contains(command)) {
|
||||||
const QStringList tmp = Utils::sorted(
|
const QStringList tmp = Utils::sorted(
|
||||||
words + m_introspection->m_functionArgs[command]);
|
words + m_introspection->m_keywords.functionArgs[command]);
|
||||||
m_introspection->m_functionArgs[command] = Utils::filteredUnique(tmp);
|
m_introspection->m_keywords.functionArgs[command] = Utils::filteredUnique(
|
||||||
|
tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!words.isEmpty() && functionSet.contains(words.at(0)))
|
if (!words.isEmpty() && m_introspection->m_keywords.functions.contains(words.at(0)))
|
||||||
m_introspection->m_functionArgs[words.at(0)];
|
m_introspection->m_keywords.functionArgs[words.at(0)];
|
||||||
currentDefinition.clear();
|
currentDefinition.clear();
|
||||||
} else {
|
} else {
|
||||||
currentDefinition.append(line.trimmed() + ' ');
|
currentDefinition.append(line.trimmed() + ' ');
|
||||||
@@ -560,9 +539,9 @@ QStringList CMakeTool::parseVariableOutput(const QString &output)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMakeTool::parseSyntaxHighlightingXml()
|
QStringList CMakeTool::parseSyntaxHighlightingXml()
|
||||||
{
|
{
|
||||||
QSet<QString> functionSet = Utils::toSet(m_introspection->m_functions);
|
QStringList moduleFunctions;
|
||||||
|
|
||||||
const FilePath cmakeXml = Core::ICore::resourcePath("generic-highlighter/syntax/cmake.xml");
|
const FilePath cmakeXml = Core::ICore::resourcePath("generic-highlighter/syntax/cmake.xml");
|
||||||
QXmlStreamReader reader(cmakeXml.fileContents().value_or(QByteArray()));
|
QXmlStreamReader reader(cmakeXml.fileContents().value_or(QByteArray()));
|
||||||
@@ -588,19 +567,19 @@ void CMakeTool::parseSyntaxHighlightingXml()
|
|||||||
const auto functionName = name.left(name.length() - 6);
|
const auto functionName = name.left(name.length() - 6);
|
||||||
QStringList arguments = readItemList(reader);
|
QStringList arguments = readItemList(reader);
|
||||||
|
|
||||||
if (m_introspection->m_functionArgs.contains(functionName))
|
if (m_introspection->m_keywords.functionArgs.contains(functionName))
|
||||||
arguments.append(m_introspection->m_functionArgs.value(functionName));
|
arguments.append(
|
||||||
|
m_introspection->m_keywords.functionArgs.value(functionName));
|
||||||
|
|
||||||
m_introspection->m_functionArgs[functionName] = arguments;
|
m_introspection->m_keywords.functionArgs[functionName] = arguments;
|
||||||
|
|
||||||
// Functions that are part of CMake modules like ExternalProject_Add
|
// Functions that are part of CMake modules like ExternalProject_Add
|
||||||
// which are not reported by cmake --help-list-commands
|
// which are not reported by cmake --help-list-commands
|
||||||
if (!functionSet.contains(functionName)) {
|
if (!m_introspection->m_keywords.functions.contains(functionName)) {
|
||||||
functionSet.insert(functionName);
|
moduleFunctions << functionName;
|
||||||
m_introspection->m_functions.append(functionName);
|
|
||||||
}
|
}
|
||||||
} else if (name == u"generator-expressions") {
|
} else if (name == u"generator-expressions") {
|
||||||
m_introspection->m_generatorExpressions = readItemList(reader);
|
m_introspection->m_keywords.generatorExpressions = toSet(readItemList(reader));
|
||||||
} else {
|
} else {
|
||||||
reader.skipCurrentElement();
|
reader.skipCurrentElement();
|
||||||
}
|
}
|
||||||
@@ -623,16 +602,19 @@ void CMakeTool::parseSyntaxHighlightingXml()
|
|||||||
{"set_target_properties", "set_directory_properties"},
|
{"set_target_properties", "set_directory_properties"},
|
||||||
{"set_tests_properties", "set_directory_properties"}};
|
{"set_tests_properties", "set_directory_properties"}};
|
||||||
for (const auto &pair : std::as_const(functionPairs)) {
|
for (const auto &pair : std::as_const(functionPairs)) {
|
||||||
if (!m_introspection->m_functionArgs.contains(pair.first))
|
if (!m_introspection->m_keywords.functionArgs.contains(pair.first))
|
||||||
m_introspection->m_functionArgs[pair.first] = m_introspection->m_functionArgs.value(
|
m_introspection->m_keywords.functionArgs[pair.first]
|
||||||
pair.second);
|
= m_introspection->m_keywords.functionArgs.value(pair.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case for cmake_print_variables, which will print the names and values for variables
|
// Special case for cmake_print_variables, which will print the names and values for variables
|
||||||
// and needs to be as a known function
|
// and needs to be as a known function
|
||||||
const QString cmakePrintVariables("cmake_print_variables");
|
const QString cmakePrintVariables("cmake_print_variables");
|
||||||
m_introspection->m_functionArgs[cmakePrintVariables] = {};
|
m_introspection->m_keywords.functionArgs[cmakePrintVariables] = {};
|
||||||
m_introspection->m_functions.append(cmakePrintVariables);
|
moduleFunctions << cmakePrintVariables;
|
||||||
|
|
||||||
|
moduleFunctions.removeDuplicates();
|
||||||
|
return moduleFunctions;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMakeTool::fetchFromCapabilities(bool ignoreCache) const
|
void CMakeTool::fetchFromCapabilities(bool ignoreCache) const
|
||||||
|
|||||||
@@ -21,17 +21,17 @@ namespace Internal { class IntrospectionData; }
|
|||||||
|
|
||||||
struct CMAKE_EXPORT CMakeKeywords
|
struct CMAKE_EXPORT CMakeKeywords
|
||||||
{
|
{
|
||||||
QSet<QString> variables;
|
QMap<QString, Utils::FilePath> variables;
|
||||||
QSet<QString> functions;
|
QMap<QString, Utils::FilePath> functions;
|
||||||
QSet<QString> properties;
|
QMap<QString, Utils::FilePath> properties;
|
||||||
QSet<QString> generatorExpressions;
|
QSet<QString> generatorExpressions;
|
||||||
QSet<QString> directoryProperties;
|
QMap<QString, Utils::FilePath> directoryProperties;
|
||||||
QSet<QString> sourceProperties;
|
QMap<QString, Utils::FilePath> sourceProperties;
|
||||||
QSet<QString> targetProperties;
|
QMap<QString, Utils::FilePath> targetProperties;
|
||||||
QSet<QString> testProperties;
|
QMap<QString, Utils::FilePath> testProperties;
|
||||||
QSet<QString> includeStandardModules;
|
QMap<QString, Utils::FilePath> includeStandardModules;
|
||||||
QSet<QString> findModules;
|
QMap<QString, Utils::FilePath> findModules;
|
||||||
QSet<QString> policies;
|
QMap<QString, Utils::FilePath> policies;
|
||||||
QMap<QString, QStringList> functionArgs;
|
QMap<QString, QStringList> functionArgs;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ private:
|
|||||||
void runCMake(Utils::Process &proc, const QStringList &args, int timeoutS = 1) const;
|
void runCMake(Utils::Process &proc, const QStringList &args, int timeoutS = 1) const;
|
||||||
void parseFunctionDetailsOutput(const QString &output);
|
void parseFunctionDetailsOutput(const QString &output);
|
||||||
QStringList parseVariableOutput(const QString &output);
|
QStringList parseVariableOutput(const QString &output);
|
||||||
void parseSyntaxHighlightingXml();
|
QStringList parseSyntaxHighlightingXml();
|
||||||
|
|
||||||
void fetchFromCapabilities(bool ignoreCache = false) const;
|
void fetchFromCapabilities(bool ignoreCache = false) const;
|
||||||
void parseFromCapabilities(const QString &input) const;
|
void parseFromCapabilities(const QString &input) const;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
add_qtc_plugin(CompilerExplorer
|
add_qtc_plugin(CompilerExplorer
|
||||||
PLUGIN_DEPENDS Core TextEditor
|
PLUGIN_DEPENDS Core ProjectExplorer TextEditor
|
||||||
DEPENDS Qt::Network TerminalLib Spinner
|
DEPENDS Qt::Network TerminalLib Spinner
|
||||||
SOURCES
|
SOURCES
|
||||||
api/config.h
|
api/config.h
|
||||||
@@ -14,6 +14,8 @@ add_qtc_plugin(CompilerExplorer
|
|||||||
api/library.h
|
api/library.h
|
||||||
api/request.h
|
api/request.h
|
||||||
|
|
||||||
|
compilerexplorer.qrc
|
||||||
|
|
||||||
compilerexploreraspects.cpp
|
compilerexploreraspects.cpp
|
||||||
compilerexploreraspects.h
|
compilerexploreraspects.h
|
||||||
compilerexplorerplugin.cpp
|
compilerexplorerplugin.cpp
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ QtcPlugin {
|
|||||||
name: "CompilerExplorer"
|
name: "CompilerExplorer"
|
||||||
|
|
||||||
Depends { name: "Core" }
|
Depends { name: "Core" }
|
||||||
|
Depends { name: "ProjectExplorer" }
|
||||||
Depends { name: "Spinner" }
|
Depends { name: "Spinner" }
|
||||||
Depends { name: "TerminalLib" }
|
Depends { name: "TerminalLib" }
|
||||||
Depends { name: "TextEditor" }
|
Depends { name: "TextEditor" }
|
||||||
@@ -22,6 +23,8 @@ QtcPlugin {
|
|||||||
"api/library.h",
|
"api/library.h",
|
||||||
"api/request.h",
|
"api/request.h",
|
||||||
|
|
||||||
|
"compilerexplorer.qrc",
|
||||||
|
|
||||||
"compilerexploreraspects.cpp",
|
"compilerexploreraspects.cpp",
|
||||||
"compilerexploreraspects.h",
|
"compilerexploreraspects.h",
|
||||||
"compilerexplorerconstants.h",
|
"compilerexplorerconstants.h",
|
||||||
|
|||||||
8
src/plugins/compilerexplorer/compilerexplorer.qrc
Normal file
8
src/plugins/compilerexplorer/compilerexplorer.qrc
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="/compilerexplorer/wizard/">
|
||||||
|
<file>wizard/cpp/wizard.json</file>
|
||||||
|
<file>wizard/cpp/file.qtce</file>
|
||||||
|
<file>wizard/python/wizard.json</file>
|
||||||
|
<file>wizard/python/file.qtce</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
||||||
@@ -107,8 +107,11 @@ JsonSettingsDocument::JsonSettingsDocument(QUndoStack *undoStack)
|
|||||||
{
|
{
|
||||||
setId(Constants::CE_EDITOR_ID);
|
setId(Constants::CE_EDITOR_ID);
|
||||||
setMimeType("application/compiler-explorer");
|
setMimeType("application/compiler-explorer");
|
||||||
connect(&m_ceSettings, &CompilerExplorerSettings::changed, this, [this] { emit changed(); });
|
connect(&m_ceSettings, &CompilerExplorerSettings::changed, this, [this] {
|
||||||
m_ceSettings.setAutoApply(true);
|
emit changed();
|
||||||
|
emit contentsChanged();
|
||||||
|
});
|
||||||
|
m_ceSettings.setAutoApply(false);
|
||||||
m_ceSettings.setUndoStack(undoStack);
|
m_ceSettings.setUndoStack(undoStack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,6 +136,8 @@ Core::IDocument::OpenResult JsonSettingsDocument::open(QString *errorString,
|
|||||||
return OpenResult::ReadError;
|
return OpenResult::ReadError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setFilePath(filePath);
|
||||||
|
|
||||||
m_ceSettings.fromMap(*result);
|
m_ceSettings.fromMap(*result);
|
||||||
emit settingsChanged();
|
emit settingsChanged();
|
||||||
return OpenResult::Success;
|
return OpenResult::Success;
|
||||||
@@ -157,8 +162,10 @@ bool JsonSettingsDocument::saveImpl(QString *errorString, const FilePath &newFil
|
|||||||
|
|
||||||
Utils::FilePath path = newFilePath.isEmpty() ? filePath() : newFilePath;
|
Utils::FilePath path = newFilePath.isEmpty() ? filePath() : newFilePath;
|
||||||
|
|
||||||
if (!newFilePath.isEmpty() && !autoSave)
|
if (!newFilePath.isEmpty() && !autoSave) {
|
||||||
|
setPreferredDisplayName({});
|
||||||
setFilePath(newFilePath);
|
setFilePath(newFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
auto result = path.writeFileContents(jsonFromStore(store));
|
auto result = path.writeFileContents(jsonFromStore(store));
|
||||||
if (!result && errorString) {
|
if (!result && errorString) {
|
||||||
@@ -166,6 +173,7 @@ bool JsonSettingsDocument::saveImpl(QString *errorString, const FilePath &newFil
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit changed();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,6 +190,8 @@ bool JsonSettingsDocument::setContents(const QByteArray &contents)
|
|||||||
m_ceSettings.fromMap(*result);
|
m_ceSettings.fromMap(*result);
|
||||||
|
|
||||||
emit settingsChanged();
|
emit settingsChanged();
|
||||||
|
emit changed();
|
||||||
|
emit contentsChanged();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,11 +323,6 @@ CompilerWidget::CompilerWidget(const std::shared_ptr<SourceSettings> &sourceSett
|
|||||||
m_spinner = new SpinnerSolution::Spinner(SpinnerSolution::SpinnerSize::Large, this);
|
m_spinner = new SpinnerSolution::Spinner(SpinnerSolution::SpinnerSize::Large, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompilerWidget::~CompilerWidget()
|
|
||||||
{
|
|
||||||
qDebug() << "Good bye!";
|
|
||||||
}
|
|
||||||
|
|
||||||
Core::SearchableTerminal *CompilerWidget::createTerminal()
|
Core::SearchableTerminal *CompilerWidget::createTerminal()
|
||||||
{
|
{
|
||||||
m_resultTerminal = new Core::SearchableTerminal();
|
m_resultTerminal = new Core::SearchableTerminal();
|
||||||
@@ -467,172 +472,31 @@ EditorWidget::EditorWidget(const QSharedPointer<JsonSettingsDocument> &document,
|
|||||||
QWidget *parent)
|
QWidget *parent)
|
||||||
: Utils::FancyMainWindow(parent)
|
: Utils::FancyMainWindow(parent)
|
||||||
, m_document(document)
|
, m_document(document)
|
||||||
|
, m_undoStack(undoStack)
|
||||||
|
, m_actionHandler(actionHandler)
|
||||||
{
|
{
|
||||||
setAutoHideTitleBars(false);
|
setAutoHideTitleBars(false);
|
||||||
setDockNestingEnabled(true);
|
setDockNestingEnabled(true);
|
||||||
setDocumentMode(true);
|
setDocumentMode(true);
|
||||||
setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::TabPosition::South);
|
setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::TabPosition::South);
|
||||||
|
|
||||||
document->setWindowStateCallback([this] {
|
document->setWindowStateCallback([this] { return windowStateCallback(); });
|
||||||
auto settings = saveSettings();
|
|
||||||
QVariantMap result;
|
|
||||||
|
|
||||||
for (const auto &key : settings.keys()) {
|
document->settings()->m_sources.setItemAddedCallback<SourceSettings>(
|
||||||
// QTBUG-116339
|
[this](const std::shared_ptr<SourceSettings> &source) { addSourceEditor(source); });
|
||||||
if (key != "State") {
|
|
||||||
result.insert(key, settings.value(key));
|
|
||||||
} else {
|
|
||||||
QVariantMap m;
|
|
||||||
m["type"] = "Base64";
|
|
||||||
m["value"] = settings.value(key).toByteArray().toBase64();
|
|
||||||
result.insert(key, m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
document->settings()->m_sources.setItemRemovedCallback<SourceSettings>(
|
||||||
|
[this](const std::shared_ptr<SourceSettings> &source) { removeSourceEditor(source); });
|
||||||
|
|
||||||
|
connect(document.get(),
|
||||||
|
&JsonSettingsDocument::settingsChanged,
|
||||||
|
this,
|
||||||
|
&EditorWidget::recreateEditors);
|
||||||
|
|
||||||
|
connect(this, &EditorWidget::gotFocus, this, [&actionHandler] {
|
||||||
|
actionHandler.updateCurrentEditor();
|
||||||
});
|
});
|
||||||
|
|
||||||
auto addCompiler = [this,
|
|
||||||
&actionHandler](const std::shared_ptr<SourceSettings> &sourceSettings,
|
|
||||||
const std::shared_ptr<CompilerSettings> &compilerSettings,
|
|
||||||
int idx) {
|
|
||||||
auto compiler = new CompilerWidget(sourceSettings, compilerSettings);
|
|
||||||
compiler->setWindowTitle("Compiler #" + QString::number(idx));
|
|
||||||
compiler->setObjectName("compiler_" + QString::number(idx));
|
|
||||||
QDockWidget *dockWidget = addDockForWidget(compiler);
|
|
||||||
addDockWidget(Qt::RightDockWidgetArea, dockWidget);
|
|
||||||
m_compilerWidgets.append(dockWidget);
|
|
||||||
|
|
||||||
connect(compiler,
|
|
||||||
&CompilerWidget::remove,
|
|
||||||
this,
|
|
||||||
[sourceSettings = sourceSettings.get(), compilerSettings = compilerSettings.get()] {
|
|
||||||
sourceSettings->compilers.removeItem(compilerSettings->shared_from_this());
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(compiler, &CompilerWidget::gotFocus, this, [&actionHandler] {
|
|
||||||
actionHandler.updateCurrentEditor();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
auto addSourceEditor = [this, &actionHandler, document = document.get(), addCompiler, undoStack](
|
|
||||||
const std::shared_ptr<SourceSettings> &sourceSettings) {
|
|
||||||
auto sourceEditor = new SourceEditorWidget(sourceSettings, undoStack);
|
|
||||||
sourceEditor->setWindowTitle("Source Code #" + QString::number(m_sourceWidgets.size() + 1));
|
|
||||||
sourceEditor->setObjectName("source_code_editor_"
|
|
||||||
+ QString::number(m_sourceWidgets.size() + 1));
|
|
||||||
|
|
||||||
QDockWidget *dockWidget = addDockForWidget(sourceEditor);
|
|
||||||
connect(sourceEditor,
|
|
||||||
&SourceEditorWidget::remove,
|
|
||||||
this,
|
|
||||||
[document, sourceSettings = sourceSettings.get()] {
|
|
||||||
document->settings()->m_sources.removeItem(sourceSettings->shared_from_this());
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(sourceEditor, &SourceEditorWidget::addCompiler, this, [sourceSettings] {
|
|
||||||
auto newCompiler = std::make_shared<CompilerSettings>(
|
|
||||||
sourceSettings->apiConfigFunction());
|
|
||||||
newCompiler->setLanguageId(sourceSettings->languageId());
|
|
||||||
sourceSettings->compilers.addItem(newCompiler);
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(sourceEditor, &SourceEditorWidget::gotFocus, this, [&actionHandler] {
|
|
||||||
actionHandler.updateCurrentEditor();
|
|
||||||
});
|
|
||||||
|
|
||||||
addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
|
|
||||||
|
|
||||||
sourceSettings->compilers.forEachItem<CompilerSettings>(
|
|
||||||
[addCompiler, sourceSettings](const std::shared_ptr<CompilerSettings> &compilerSettings,
|
|
||||||
int idx) {
|
|
||||||
addCompiler(sourceSettings, compilerSettings, idx + 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
sourceSettings->compilers.setItemAddedCallback<CompilerSettings>(
|
|
||||||
[addCompiler, sourceSettings = sourceSettings.get()](
|
|
||||||
const std::shared_ptr<CompilerSettings> &compilerSettings) {
|
|
||||||
addCompiler(sourceSettings->shared_from_this(),
|
|
||||||
compilerSettings,
|
|
||||||
sourceSettings->compilers.size());
|
|
||||||
});
|
|
||||||
|
|
||||||
sourceSettings->compilers.setItemRemovedCallback<CompilerSettings>(
|
|
||||||
[this](const std::shared_ptr<CompilerSettings> &compilerSettings) {
|
|
||||||
auto it = std::find_if(m_compilerWidgets.begin(),
|
|
||||||
m_compilerWidgets.end(),
|
|
||||||
[compilerSettings](const QDockWidget *c) {
|
|
||||||
return static_cast<CompilerWidget *>(c->widget())
|
|
||||||
->m_compilerSettings
|
|
||||||
== compilerSettings;
|
|
||||||
});
|
|
||||||
QTC_ASSERT(it != m_compilerWidgets.end(), return);
|
|
||||||
delete *it;
|
|
||||||
m_compilerWidgets.erase(it);
|
|
||||||
});
|
|
||||||
|
|
||||||
/*Aggregate *agg = Aggregate::parentAggregate(sourceEditor);
|
|
||||||
if (!agg) {
|
|
||||||
agg = new Aggregate;
|
|
||||||
agg->add(sourceEditor);
|
|
||||||
}
|
|
||||||
agg->add(this);
|
|
||||||
|
|
||||||
setFocusProxy(sourceEditor);
|
|
||||||
*/
|
|
||||||
m_sourceWidgets.append(dockWidget);
|
|
||||||
};
|
|
||||||
|
|
||||||
auto removeSourceEditor = [this](const std::shared_ptr<SourceSettings> &sourceSettings) {
|
|
||||||
auto it = std::find_if(m_sourceWidgets.begin(),
|
|
||||||
m_sourceWidgets.end(),
|
|
||||||
[sourceSettings](const QDockWidget *c) {
|
|
||||||
return static_cast<SourceEditorWidget *>(c->widget())
|
|
||||||
->sourceSettings()
|
|
||||||
== sourceSettings.get();
|
|
||||||
});
|
|
||||||
QTC_ASSERT(it != m_sourceWidgets.end(), return);
|
|
||||||
delete *it;
|
|
||||||
m_sourceWidgets.erase(it);
|
|
||||||
};
|
|
||||||
|
|
||||||
auto recreateEditors = [this, addSourceEditor]() {
|
|
||||||
qDeleteAll(m_sourceWidgets);
|
|
||||||
qDeleteAll(m_compilerWidgets);
|
|
||||||
|
|
||||||
m_sourceWidgets.clear();
|
|
||||||
m_compilerWidgets.clear();
|
|
||||||
|
|
||||||
m_document->settings()->m_sources.forEachItem<SourceSettings>(addSourceEditor);
|
|
||||||
QVariantMap windowState = m_document->settings()->windowState.value();
|
|
||||||
|
|
||||||
if (!windowState.isEmpty()) {
|
|
||||||
QHash<QString, QVariant> hashMap;
|
|
||||||
for (const auto &key : windowState.keys()) {
|
|
||||||
if (key != "State")
|
|
||||||
hashMap.insert(key, windowState.value(key));
|
|
||||||
else {
|
|
||||||
QVariant v = windowState.value(key);
|
|
||||||
if (v.userType() == QMetaType::QByteArray) {
|
|
||||||
hashMap.insert(key, v);
|
|
||||||
} else if (v.userType() == QMetaType::QVariantMap) {
|
|
||||||
QVariantMap m = v.toMap();
|
|
||||||
if (m.value("type") == "Base64") {
|
|
||||||
hashMap.insert(key,
|
|
||||||
QByteArray::fromBase64(m.value("value").toByteArray()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
restoreSettings(hashMap);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
document->settings()->m_sources.setItemAddedCallback<SourceSettings>(addSourceEditor);
|
|
||||||
document->settings()->m_sources.setItemRemovedCallback<SourceSettings>(removeSourceEditor);
|
|
||||||
connect(document.get(), &JsonSettingsDocument::settingsChanged, this, recreateEditors);
|
|
||||||
|
|
||||||
m_context = new Core::IContext(this);
|
m_context = new Core::IContext(this);
|
||||||
m_context->setWidget(this);
|
m_context->setWidget(this);
|
||||||
m_context->setContext(Core::Context(Constants::CE_EDITOR_CONTEXT_ID));
|
m_context->setContext(Core::Context(Constants::CE_EDITOR_CONTEXT_ID));
|
||||||
@@ -645,6 +509,203 @@ EditorWidget::~EditorWidget()
|
|||||||
m_sourceWidgets.clear();
|
m_sourceWidgets.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorWidget::focusInEvent(QFocusEvent *event)
|
||||||
|
{
|
||||||
|
emit gotFocus();
|
||||||
|
FancyMainWindow::focusInEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorWidget::addCompiler(const std::shared_ptr<SourceSettings> &sourceSettings,
|
||||||
|
const std::shared_ptr<CompilerSettings> &compilerSettings,
|
||||||
|
int idx,
|
||||||
|
QDockWidget *parentDockWidget)
|
||||||
|
{
|
||||||
|
auto compiler = new CompilerWidget(sourceSettings, compilerSettings);
|
||||||
|
compiler->setWindowTitle("Compiler #" + QString::number(idx));
|
||||||
|
compiler->setObjectName("compiler_" + QString::number(idx));
|
||||||
|
QDockWidget *dockWidget = addDockForWidget(compiler, parentDockWidget);
|
||||||
|
addDockWidget(Qt::RightDockWidgetArea, dockWidget);
|
||||||
|
m_compilerWidgets.append(dockWidget);
|
||||||
|
|
||||||
|
connect(compiler,
|
||||||
|
&CompilerWidget::remove,
|
||||||
|
this,
|
||||||
|
[sourceSettings = sourceSettings.get(), compilerSettings = compilerSettings.get()] {
|
||||||
|
sourceSettings->compilers.removeItem(compilerSettings->shared_from_this());
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(compiler, &CompilerWidget::gotFocus, this, [this]() {
|
||||||
|
m_actionHandler.updateCurrentEditor();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap EditorWidget::windowStateCallback()
|
||||||
|
{
|
||||||
|
auto settings = saveSettings();
|
||||||
|
QVariantMap result;
|
||||||
|
|
||||||
|
for (const auto &key : settings.keys()) {
|
||||||
|
// QTBUG-116339
|
||||||
|
if (key != "State") {
|
||||||
|
result.insert(key, settings.value(key));
|
||||||
|
} else {
|
||||||
|
QVariantMap m;
|
||||||
|
m["type"] = "Base64";
|
||||||
|
m["value"] = settings.value(key).toByteArray().toBase64();
|
||||||
|
result.insert(key, m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorWidget::addSourceEditor(const std::shared_ptr<SourceSettings> &sourceSettings)
|
||||||
|
{
|
||||||
|
auto sourceEditor = new SourceEditorWidget(sourceSettings, m_undoStack);
|
||||||
|
sourceEditor->setWindowTitle("Source Code #" + QString::number(m_sourceWidgets.size() + 1));
|
||||||
|
sourceEditor->setObjectName("source_code_editor_" + QString::number(m_sourceWidgets.size() + 1));
|
||||||
|
|
||||||
|
QDockWidget *dockWidget = addDockForWidget(sourceEditor);
|
||||||
|
connect(sourceEditor, &SourceEditorWidget::remove, this, [this, sourceSettings]() {
|
||||||
|
m_undoStack->beginMacro("Remove source");
|
||||||
|
sourceSettings->compilers.clear();
|
||||||
|
m_document->settings()->m_sources.removeItem(sourceSettings->shared_from_this());
|
||||||
|
m_undoStack->endMacro();
|
||||||
|
|
||||||
|
setupHelpWidget();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(sourceEditor, &SourceEditorWidget::addCompiler, this, [sourceSettings]() {
|
||||||
|
auto newCompiler = std::make_shared<CompilerSettings>(sourceSettings->apiConfigFunction());
|
||||||
|
newCompiler->setLanguageId(sourceSettings->languageId());
|
||||||
|
sourceSettings->compilers.addItem(newCompiler);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(sourceEditor, &SourceEditorWidget::gotFocus, this, [this]() {
|
||||||
|
m_actionHandler.updateCurrentEditor();
|
||||||
|
});
|
||||||
|
|
||||||
|
addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
|
||||||
|
|
||||||
|
sourceSettings->compilers.forEachItem<CompilerSettings>(
|
||||||
|
[this, sourceSettings, dockWidget](const std::shared_ptr<CompilerSettings> &compilerSettings,
|
||||||
|
int idx) {
|
||||||
|
addCompiler(sourceSettings, compilerSettings, idx + 1, dockWidget);
|
||||||
|
});
|
||||||
|
|
||||||
|
sourceSettings->compilers.setItemAddedCallback<CompilerSettings>(
|
||||||
|
[this, sourceSettings, dockWidget](
|
||||||
|
const std::shared_ptr<CompilerSettings> &compilerSettings) {
|
||||||
|
addCompiler(sourceSettings->shared_from_this(),
|
||||||
|
compilerSettings,
|
||||||
|
sourceSettings->compilers.size(),
|
||||||
|
dockWidget);
|
||||||
|
});
|
||||||
|
|
||||||
|
sourceSettings->compilers.setItemRemovedCallback<CompilerSettings>(
|
||||||
|
[this, sourceSettings](const std::shared_ptr<CompilerSettings> &compilerSettings) {
|
||||||
|
auto it = std::find_if(m_compilerWidgets.begin(),
|
||||||
|
m_compilerWidgets.end(),
|
||||||
|
[compilerSettings](const QDockWidget *c) {
|
||||||
|
return static_cast<CompilerWidget *>(c->widget())
|
||||||
|
->m_compilerSettings
|
||||||
|
== compilerSettings;
|
||||||
|
});
|
||||||
|
QTC_ASSERT(it != m_compilerWidgets.end(), return);
|
||||||
|
delete *it;
|
||||||
|
m_compilerWidgets.erase(it);
|
||||||
|
});
|
||||||
|
|
||||||
|
m_sourceWidgets.append(dockWidget);
|
||||||
|
|
||||||
|
setupHelpWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorWidget::removeSourceEditor(const std::shared_ptr<SourceSettings> &sourceSettings)
|
||||||
|
{
|
||||||
|
auto it
|
||||||
|
= std::find_if(m_sourceWidgets.begin(),
|
||||||
|
m_sourceWidgets.end(),
|
||||||
|
[sourceSettings](const QDockWidget *c) {
|
||||||
|
return static_cast<SourceEditorWidget *>(c->widget())->sourceSettings()
|
||||||
|
== sourceSettings.get();
|
||||||
|
});
|
||||||
|
QTC_ASSERT(it != m_sourceWidgets.end(), return);
|
||||||
|
delete *it;
|
||||||
|
m_sourceWidgets.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorWidget::recreateEditors()
|
||||||
|
{
|
||||||
|
qDeleteAll(m_sourceWidgets);
|
||||||
|
qDeleteAll(m_compilerWidgets);
|
||||||
|
|
||||||
|
m_sourceWidgets.clear();
|
||||||
|
m_compilerWidgets.clear();
|
||||||
|
|
||||||
|
m_document->settings()->m_sources.forEachItem<SourceSettings>(
|
||||||
|
[this](const auto &sourceSettings) { addSourceEditor(sourceSettings); });
|
||||||
|
|
||||||
|
QVariantMap windowState = m_document->settings()->windowState.value();
|
||||||
|
|
||||||
|
if (!windowState.isEmpty()) {
|
||||||
|
QHash<QString, QVariant> hashMap;
|
||||||
|
for (const auto &key : windowState.keys()) {
|
||||||
|
if (key != "State")
|
||||||
|
hashMap.insert(key, windowState.value(key));
|
||||||
|
else {
|
||||||
|
QVariant v = windowState.value(key);
|
||||||
|
if (v.userType() == QMetaType::QByteArray) {
|
||||||
|
hashMap.insert(key, v);
|
||||||
|
} else if (v.userType() == QMetaType::QVariantMap) {
|
||||||
|
QVariantMap m = v.toMap();
|
||||||
|
if (m.value("type") == "Base64") {
|
||||||
|
hashMap.insert(key, QByteArray::fromBase64(m.value("value").toByteArray()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
restoreSettings(hashMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorWidget::setupHelpWidget()
|
||||||
|
{
|
||||||
|
if (m_document->settings()->m_sources.size() == 0) {
|
||||||
|
setCentralWidget(createHelpWidget());
|
||||||
|
} else {
|
||||||
|
delete takeCentralWidget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *EditorWidget::createHelpWidget() const
|
||||||
|
{
|
||||||
|
using namespace Layouting;
|
||||||
|
|
||||||
|
auto addSourceButton = new QPushButton(Tr::tr("Add source code"));
|
||||||
|
connect(addSourceButton, &QPushButton::clicked, this, [this] {
|
||||||
|
auto newSource = std::make_shared<SourceSettings>(
|
||||||
|
[settings = m_document->settings()] { return settings->apiConfig(); });
|
||||||
|
m_document->settings()->m_sources.addItem(newSource);
|
||||||
|
});
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
return Column {
|
||||||
|
st,
|
||||||
|
Row {
|
||||||
|
st,
|
||||||
|
Column {
|
||||||
|
Tr::tr("No source code added yet. Add one using the button below."),
|
||||||
|
Row { st, addSourceButton, st }
|
||||||
|
},
|
||||||
|
st,
|
||||||
|
},
|
||||||
|
st,
|
||||||
|
}.emerge();
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
|
||||||
TextEditor::TextEditorWidget *EditorWidget::focusedEditorWidget() const
|
TextEditor::TextEditorWidget *EditorWidget::focusedEditorWidget() const
|
||||||
{
|
{
|
||||||
for (const QDockWidget *sourceWidget : m_sourceWidgets) {
|
for (const QDockWidget *sourceWidget : m_sourceWidgets) {
|
||||||
|
|||||||
@@ -140,8 +140,6 @@ public:
|
|||||||
CompilerWidget(const std::shared_ptr<SourceSettings> &sourceSettings,
|
CompilerWidget(const std::shared_ptr<SourceSettings> &sourceSettings,
|
||||||
const std::shared_ptr<CompilerSettings> &compilerSettings);
|
const std::shared_ptr<CompilerSettings> &compilerSettings);
|
||||||
|
|
||||||
~CompilerWidget();
|
|
||||||
|
|
||||||
Core::SearchableTerminal *createTerminal();
|
Core::SearchableTerminal *createTerminal();
|
||||||
|
|
||||||
void compile(const QString &source);
|
void compile(const QString &source);
|
||||||
@@ -188,11 +186,32 @@ public:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void sourceCodeChanged();
|
void sourceCodeChanged();
|
||||||
|
void gotFocus();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void focusInEvent(QFocusEvent *event) override;
|
||||||
|
|
||||||
|
void setupHelpWidget();
|
||||||
|
QWidget *createHelpWidget() const;
|
||||||
|
|
||||||
|
void addCompiler(const std::shared_ptr<SourceSettings> &sourceSettings,
|
||||||
|
const std::shared_ptr<CompilerSettings> &compilerSettings,
|
||||||
|
int idx,
|
||||||
|
QDockWidget *parentDockWidget);
|
||||||
|
|
||||||
|
void addSourceEditor(const std::shared_ptr<SourceSettings> &sourceSettings);
|
||||||
|
void removeSourceEditor(const std::shared_ptr<SourceSettings> &sourceSettings);
|
||||||
|
|
||||||
|
void recreateEditors();
|
||||||
|
|
||||||
|
QVariantMap windowStateCallback();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSplitter *m_mainSplitter;
|
QSplitter *m_mainSplitter;
|
||||||
int m_compilerCount{0};
|
int m_compilerCount{0};
|
||||||
QSharedPointer<JsonSettingsDocument> m_document;
|
QSharedPointer<JsonSettingsDocument> m_document;
|
||||||
|
QUndoStack *m_undoStack;
|
||||||
|
TextEditor::TextEditorActionHandler &m_actionHandler;
|
||||||
|
|
||||||
Core::IContext *m_context;
|
Core::IContext *m_context;
|
||||||
|
|
||||||
|
|||||||
@@ -14,10 +14,12 @@
|
|||||||
|
|
||||||
#include <cppeditor/cppeditorconstants.h>
|
#include <cppeditor/cppeditorconstants.h>
|
||||||
|
|
||||||
#include <QMenu>
|
|
||||||
|
|
||||||
#include <extensionsystem/iplugin.h>
|
#include <extensionsystem/iplugin.h>
|
||||||
|
|
||||||
|
#include <projectexplorer/jsonwizard/jsonwizardfactory.h>
|
||||||
|
|
||||||
|
#include <QMenu>
|
||||||
|
|
||||||
using namespace Core;
|
using namespace Core;
|
||||||
|
|
||||||
namespace CompilerExplorer::Internal {
|
namespace CompilerExplorer::Internal {
|
||||||
@@ -40,6 +42,8 @@ public:
|
|||||||
settings().defaultDocument().toUtf8());
|
settings().defaultDocument().toUtf8());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ProjectExplorer::JsonWizardFactory::addWizardPath(":/compilerexplorer/wizard/");
|
||||||
|
|
||||||
ActionContainer *mtools = ActionManager::actionContainer(Core::Constants::M_TOOLS);
|
ActionContainer *mtools = ActionManager::actionContainer(Core::Constants::M_TOOLS);
|
||||||
ActionContainer *mCompilerExplorer = ActionManager::createMenu("Tools.CompilerExplorer");
|
ActionContainer *mCompilerExplorer = ActionManager::createMenu("Tools.CompilerExplorer");
|
||||||
QMenu *menu = mCompilerExplorer->menu();
|
QMenu *menu = mCompilerExplorer->menu();
|
||||||
|
|||||||
10
src/plugins/compilerexplorer/wizard/cpp/file.qtce
Normal file
10
src/plugins/compilerexplorer/wizard/cpp/file.qtce
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"Sources": [{
|
||||||
|
"LanguageId": "c++",
|
||||||
|
"Source": "int main() {\n return 0;\n}",
|
||||||
|
"Compilers": [{
|
||||||
|
"Id": "clang_trunk",
|
||||||
|
"Options": "-O3"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}
|
||||||
37
src/plugins/compilerexplorer/wizard/cpp/wizard.json
Normal file
37
src/plugins/compilerexplorer/wizard/cpp/wizard.json
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"supportedProjectTypes": [],
|
||||||
|
"id": "QTCE.CppSource",
|
||||||
|
"category": "U.CompilerExplorer",
|
||||||
|
"trDescription": "Creates an example CompilerExplorer setup for C++.",
|
||||||
|
"trDisplayName": "Compiler Explorer C++ Source",
|
||||||
|
"trDisplayCategory": "Compiler Explorer",
|
||||||
|
"icon": "",
|
||||||
|
"iconKind": "Plain",
|
||||||
|
"options": {
|
||||||
|
"key": "DefaultSuffix",
|
||||||
|
"value": "%{JS: Util.preferredSuffix('application/compiler-explorer')}"
|
||||||
|
},
|
||||||
|
"pages": [
|
||||||
|
{
|
||||||
|
"trDisplayName": "Location",
|
||||||
|
"trShortTitle": "Location",
|
||||||
|
"typeId": "File"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"trDisplayName": "Project Management",
|
||||||
|
"trShortTitle": "Summary",
|
||||||
|
"typeId": "Summary"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"generators": [
|
||||||
|
{
|
||||||
|
"typeId": "File",
|
||||||
|
"data": {
|
||||||
|
"source": "file.qtce",
|
||||||
|
"target": "%{JS: Util.fileName(value('TargetPath'), value('DefaultSuffix'))}",
|
||||||
|
"openInEditor": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
9
src/plugins/compilerexplorer/wizard/python/file.qtce
Normal file
9
src/plugins/compilerexplorer/wizard/python/file.qtce
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"Sources": [{
|
||||||
|
"LanguageId": "python",
|
||||||
|
"Source": "def main():\\n print(\\"Hello World\\")\\n\\nif __name__ == \\"__main__\\":\\n main()",
|
||||||
|
"Compilers": [{
|
||||||
|
"Id": "python311"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}
|
||||||
37
src/plugins/compilerexplorer/wizard/python/wizard.json
Normal file
37
src/plugins/compilerexplorer/wizard/python/wizard.json
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"supportedProjectTypes": [],
|
||||||
|
"id": "QTCE.PySource",
|
||||||
|
"category": "U.CompilerExplorer",
|
||||||
|
"trDescription": "Creates an example CompilerExplorer setup for Python.",
|
||||||
|
"trDisplayName": "Compiler Explorer Python Source",
|
||||||
|
"trDisplayCategory": "Compiler Explorer",
|
||||||
|
"icon": "",
|
||||||
|
"iconKind": "Plain",
|
||||||
|
"options": {
|
||||||
|
"key": "DefaultSuffix",
|
||||||
|
"value": "%{JS: Util.preferredSuffix('application/compiler-explorer')}"
|
||||||
|
},
|
||||||
|
"pages": [
|
||||||
|
{
|
||||||
|
"trDisplayName": "Location",
|
||||||
|
"trShortTitle": "Location",
|
||||||
|
"typeId": "File"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"trDisplayName": "Project Management",
|
||||||
|
"trShortTitle": "Summary",
|
||||||
|
"typeId": "Summary"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"generators": [
|
||||||
|
{
|
||||||
|
"typeId": "File",
|
||||||
|
"data": {
|
||||||
|
"source": "file.qtce",
|
||||||
|
"target": "%{JS: Util.fileName(value('TargetPath'), value('DefaultSuffix'))}",
|
||||||
|
"openInEditor": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,7 @@
|
|||||||
#include "core_global.h"
|
#include "core_global.h"
|
||||||
#include "icontext.h"
|
#include "icontext.h"
|
||||||
|
|
||||||
|
#include <utils/appmainwindow.h>
|
||||||
#include <utils/filepath.h>
|
#include <utils/filepath.h>
|
||||||
#include <utils/qtcsettings.h>
|
#include <utils/qtcsettings.h>
|
||||||
|
|
||||||
@@ -17,6 +18,7 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QColor;
|
||||||
class QMainWindow;
|
class QMainWindow;
|
||||||
class QPrinter;
|
class QPrinter;
|
||||||
class QStatusBar;
|
class QStatusBar;
|
||||||
@@ -26,25 +28,25 @@ QT_END_NAMESPACE
|
|||||||
namespace Utils { class InfoBar; }
|
namespace Utils { class InfoBar; }
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
class Context;
|
class Context;
|
||||||
|
class IDocument;
|
||||||
class IWizardFactory;
|
class IWizardFactory;
|
||||||
|
class NewDialog;
|
||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
class MainWindowPrivate;
|
class MainWindowPrivate;
|
||||||
} // Internal
|
} // Internal
|
||||||
|
|
||||||
class NewDialog;
|
|
||||||
|
|
||||||
class CORE_EXPORT ICore : public QObject
|
class CORE_EXPORT ICore : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
friend class Internal::MainWindow;
|
friend class Internal::MainWindow;
|
||||||
friend class Internal::MainWindowPrivate;
|
friend class Internal::MainWindowPrivate;
|
||||||
friend class IWizardFactory;
|
|
||||||
|
|
||||||
explicit ICore(Internal::MainWindow *mw);
|
ICore();
|
||||||
~ICore() override;
|
~ICore() override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -154,9 +156,63 @@ public:
|
|||||||
|
|
||||||
static void saveSettings(SaveSettingsReason reason);
|
static void saveSettings(SaveSettingsReason reason);
|
||||||
static void setNewDialogFactory(const std::function<NewDialog *(QWidget *)> &newFactory);
|
static void setNewDialogFactory(const std::function<NewDialog *(QWidget *)> &newFactory);
|
||||||
|
|
||||||
private:
|
|
||||||
static void updateNewItemDialogState();
|
static void updateNewItemDialogState();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class MainWindow : public Utils::AppMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MainWindow();
|
||||||
|
~MainWindow() override;
|
||||||
|
|
||||||
|
void init();
|
||||||
|
void extensionsInitialized();
|
||||||
|
void aboutToShutdown();
|
||||||
|
|
||||||
|
IContext *contextObject(QWidget *widget) const;
|
||||||
|
void addContextObject(IContext *context);
|
||||||
|
void removeContextObject(IContext *context);
|
||||||
|
|
||||||
|
static IDocument *openFiles(const Utils::FilePaths &filePaths,
|
||||||
|
ICore::OpenFilesFlags flags,
|
||||||
|
const Utils::FilePath &workingDirectory = {});
|
||||||
|
|
||||||
|
QPrinter *printer() const;
|
||||||
|
IContext *currentContextObject() const;
|
||||||
|
QStatusBar *statusBar() const;
|
||||||
|
Utils::InfoBar *infoBar() const;
|
||||||
|
|
||||||
|
void updateAdditionalContexts(const Context &remove, const Context &add,
|
||||||
|
ICore::ContextPriority priority);
|
||||||
|
|
||||||
|
void setOverrideColor(const QColor &color);
|
||||||
|
|
||||||
|
QStringList additionalAboutInformation() const;
|
||||||
|
void clearAboutInformation();
|
||||||
|
void appendAboutInformation(const QString &line);
|
||||||
|
|
||||||
|
void addPreCloseListener(const std::function<bool()> &listener);
|
||||||
|
|
||||||
|
void saveSettings();
|
||||||
|
|
||||||
|
void restart();
|
||||||
|
|
||||||
|
void restartTrimmer();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
static void openFileWith();
|
||||||
|
void exit();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void closeEvent(QCloseEvent *event) override;
|
||||||
|
void keyPressEvent(QKeyEvent *event) override;
|
||||||
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -3,81 +3,4 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "icontext.h"
|
|
||||||
#include "icore.h"
|
#include "icore.h"
|
||||||
|
|
||||||
#include <utils/appmainwindow.h>
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
class QColor;
|
|
||||||
class QPrinter;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
namespace Utils { class InfoBar; }
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
|
|
||||||
class IDocument;
|
|
||||||
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class MainWindowPrivate;
|
|
||||||
|
|
||||||
class MainWindow : public Utils::AppMainWindow
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
MainWindow();
|
|
||||||
~MainWindow() override;
|
|
||||||
|
|
||||||
void init();
|
|
||||||
void extensionsInitialized();
|
|
||||||
void aboutToShutdown();
|
|
||||||
|
|
||||||
IContext *contextObject(QWidget *widget) const;
|
|
||||||
void addContextObject(IContext *context);
|
|
||||||
void removeContextObject(IContext *context);
|
|
||||||
|
|
||||||
static IDocument *openFiles(const Utils::FilePaths &filePaths,
|
|
||||||
ICore::OpenFilesFlags flags,
|
|
||||||
const Utils::FilePath &workingDirectory = {});
|
|
||||||
|
|
||||||
QPrinter *printer() const;
|
|
||||||
IContext *currentContextObject() const;
|
|
||||||
QStatusBar *statusBar() const;
|
|
||||||
Utils::InfoBar *infoBar() const;
|
|
||||||
|
|
||||||
void updateAdditionalContexts(const Context &remove, const Context &add,
|
|
||||||
ICore::ContextPriority priority);
|
|
||||||
|
|
||||||
void setOverrideColor(const QColor &color);
|
|
||||||
|
|
||||||
QStringList additionalAboutInformation() const;
|
|
||||||
void clearAboutInformation();
|
|
||||||
void appendAboutInformation(const QString &line);
|
|
||||||
|
|
||||||
void addPreCloseListener(const std::function<bool()> &listener);
|
|
||||||
|
|
||||||
void saveSettings();
|
|
||||||
|
|
||||||
void restart();
|
|
||||||
|
|
||||||
void restartTrimmer();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
static void openFileWith();
|
|
||||||
void exit();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void closeEvent(QCloseEvent *event) override;
|
|
||||||
void keyPressEvent(QKeyEvent *event) override;
|
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
|
||||||
|
|
||||||
MainWindowPrivate *d = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace Core
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "devicesupport/idevice.h"
|
#include "devicesupport/idevice.h"
|
||||||
#include "gccparser.h"
|
#include "gccparser.h"
|
||||||
#include "linuxiccparser.h"
|
#include "linuxiccparser.h"
|
||||||
|
#include "projectexplorerconstants.h"
|
||||||
#include "projectexplorertr.h"
|
#include "projectexplorertr.h"
|
||||||
#include "projectmacro.h"
|
#include "projectmacro.h"
|
||||||
#include "toolchainconfigwidget.h"
|
#include "toolchainconfigwidget.h"
|
||||||
@@ -1197,65 +1198,226 @@ static Utils::FilePaths renesasRl78SearchPathsFromRegistry()
|
|||||||
return searchPaths;
|
return searchPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
GccToolChainFactory::GccToolChainFactory()
|
static ToolChain *constructRealGccToolchain()
|
||||||
{
|
{
|
||||||
setDisplayName(Tr::tr("GCC"));
|
return new GccToolChain(Constants::GCC_TOOLCHAIN_TYPEID, GccToolChain::RealGcc);
|
||||||
setSupportedToolChainType(Constants::GCC_TOOLCHAIN_TYPEID);
|
}
|
||||||
|
|
||||||
|
static ToolChain *constructClangToolchain()
|
||||||
|
{
|
||||||
|
return new GccToolChain(Constants::CLANG_TOOLCHAIN_TYPEID, GccToolChain::Clang);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ToolChain *constructMinGWToolchain()
|
||||||
|
{
|
||||||
|
return new GccToolChain(Constants::MINGW_TOOLCHAIN_TYPEID, GccToolChain::MinGW);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ToolChain *constructLinuxIccToolchain()
|
||||||
|
{
|
||||||
|
return new GccToolChain(Constants::LINUXICC_TOOLCHAIN_TYPEID, GccToolChain::LinuxIcc);
|
||||||
|
}
|
||||||
|
|
||||||
|
GccToolChainFactory::GccToolChainFactory(GccToolChain::SubType subType)
|
||||||
|
: m_autoDetecting(subType == GccToolChain::RealGcc)
|
||||||
|
{
|
||||||
|
switch (subType) {
|
||||||
|
case GccToolChain::RealGcc:
|
||||||
|
setDisplayName(Tr::tr("GCC"));
|
||||||
|
setSupportedToolChainType(Constants::GCC_TOOLCHAIN_TYPEID);
|
||||||
|
setToolchainConstructor(&constructRealGccToolchain);
|
||||||
|
break;
|
||||||
|
case GccToolChain::Clang:
|
||||||
|
setDisplayName(Tr::tr("Clang"));
|
||||||
|
setSupportedToolChainType(Constants::CLANG_TOOLCHAIN_TYPEID);
|
||||||
|
setToolchainConstructor(&constructClangToolchain);
|
||||||
|
break;
|
||||||
|
case GccToolChain::MinGW:
|
||||||
|
setDisplayName(Tr::tr("MinGW"));
|
||||||
|
setSupportedToolChainType(Constants::MINGW_TOOLCHAIN_TYPEID);
|
||||||
|
setToolchainConstructor(&constructMinGWToolchain);
|
||||||
|
break;
|
||||||
|
case GccToolChain::LinuxIcc:
|
||||||
|
setDisplayName(Tr::tr("ICC"));
|
||||||
|
setSupportedToolChainType(Constants::LINUXICC_TOOLCHAIN_TYPEID);
|
||||||
|
setToolchainConstructor(&constructLinuxIccToolchain);
|
||||||
|
break;
|
||||||
|
}
|
||||||
setSupportedLanguages({Constants::C_LANGUAGE_ID, Constants::CXX_LANGUAGE_ID});
|
setSupportedLanguages({Constants::C_LANGUAGE_ID, Constants::CXX_LANGUAGE_ID});
|
||||||
setToolchainConstructor([] { return new GccToolChain(Constants::GCC_TOOLCHAIN_TYPEID); });
|
|
||||||
setUserCreatable(true);
|
setUserCreatable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Toolchains GccToolChainFactory::autoDetect(const ToolchainDetector &detector) const
|
Toolchains GccToolChainFactory::autoDetect(const ToolchainDetector &detector) const
|
||||||
{
|
{
|
||||||
// GCC is almost never what you want on macOS, but it is by default found in /usr/bin
|
Toolchains result;
|
||||||
if (HostOsInfo::isMacHost() && detector.device->type() == Constants::DESKTOP_DEVICE_TYPE)
|
|
||||||
return {};
|
// Do all autodetection in th 'RealGcc' case, and none in the others.
|
||||||
|
if (!m_autoDetecting)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Linux ICC
|
||||||
|
|
||||||
|
result += autoDetectToolchains("icpc",
|
||||||
|
DetectVariants::No,
|
||||||
|
Constants::CXX_LANGUAGE_ID,
|
||||||
|
Constants::LINUXICC_TOOLCHAIN_TYPEID,
|
||||||
|
detector,
|
||||||
|
&constructLinuxIccToolchain);
|
||||||
|
result += autoDetectToolchains("icc",
|
||||||
|
DetectVariants::Yes,
|
||||||
|
Constants::C_LANGUAGE_ID,
|
||||||
|
Constants::LINUXICC_TOOLCHAIN_TYPEID,
|
||||||
|
detector,
|
||||||
|
&constructLinuxIccToolchain);
|
||||||
|
|
||||||
|
// MinGW
|
||||||
|
|
||||||
|
static const auto tcChecker = [](const ToolChain *tc) {
|
||||||
|
return tc->targetAbi().osFlavor() == Abi::WindowsMSysFlavor;
|
||||||
|
};
|
||||||
|
result += autoDetectToolchains("g++",
|
||||||
|
DetectVariants::Yes,
|
||||||
|
Constants::CXX_LANGUAGE_ID,
|
||||||
|
Constants::MINGW_TOOLCHAIN_TYPEID,
|
||||||
|
detector,
|
||||||
|
&constructMinGWToolchain,
|
||||||
|
tcChecker);
|
||||||
|
result += autoDetectToolchains("gcc",
|
||||||
|
DetectVariants::Yes,
|
||||||
|
Constants::C_LANGUAGE_ID,
|
||||||
|
Constants::MINGW_TOOLCHAIN_TYPEID,
|
||||||
|
detector,
|
||||||
|
&constructMinGWToolchain,
|
||||||
|
tcChecker);
|
||||||
|
|
||||||
|
// Clang
|
||||||
|
|
||||||
Toolchains tcs;
|
Toolchains tcs;
|
||||||
static const auto tcChecker = [](const ToolChain *tc) {
|
Toolchains known = detector.alreadyKnown;
|
||||||
return tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor
|
|
||||||
&& tc->compilerCommand().fileName() != "c89-gcc"
|
tcs.append(autoDetectToolchains("clang++",
|
||||||
&& tc->compilerCommand().fileName() != "c99-gcc";
|
|
||||||
};
|
|
||||||
tcs.append(autoDetectToolchains("g++",
|
|
||||||
DetectVariants::Yes,
|
DetectVariants::Yes,
|
||||||
Constants::CXX_LANGUAGE_ID,
|
Constants::CXX_LANGUAGE_ID,
|
||||||
Constants::GCC_TOOLCHAIN_TYPEID,
|
Constants::CLANG_TOOLCHAIN_TYPEID,
|
||||||
detector,
|
detector,
|
||||||
toolchainConstructor(),
|
&constructClangToolchain));
|
||||||
tcChecker));
|
tcs.append(autoDetectToolchains("clang",
|
||||||
tcs.append(autoDetectToolchains("gcc",
|
|
||||||
DetectVariants::Yes,
|
DetectVariants::Yes,
|
||||||
Constants::C_LANGUAGE_ID,
|
Constants::C_LANGUAGE_ID,
|
||||||
Constants::GCC_TOOLCHAIN_TYPEID,
|
Constants::CLANG_TOOLCHAIN_TYPEID,
|
||||||
detector,
|
detector,
|
||||||
toolchainConstructor(),
|
&constructClangToolchain));
|
||||||
tcChecker));
|
known.append(tcs);
|
||||||
return tcs;
|
|
||||||
|
const FilePath compilerPath = Core::ICore::clangExecutable(CLANG_BINDIR);
|
||||||
|
if (!compilerPath.isEmpty()) {
|
||||||
|
const FilePath clang = compilerPath.parentDir().pathAppended("clang").withExecutableSuffix();
|
||||||
|
tcs.append(
|
||||||
|
autoDetectToolchains(clang.toString(),
|
||||||
|
DetectVariants::No,
|
||||||
|
Constants::C_LANGUAGE_ID,
|
||||||
|
Constants::CLANG_TOOLCHAIN_TYPEID,
|
||||||
|
ToolchainDetector(known, detector.device, detector.searchPaths),
|
||||||
|
&constructClangToolchain));
|
||||||
|
}
|
||||||
|
|
||||||
|
result += tcs;
|
||||||
|
|
||||||
|
// GCC
|
||||||
|
|
||||||
|
// Gcc is almost never what you want on macOS, but it is by default found in /usr/bin
|
||||||
|
if (!HostOsInfo::isMacHost() || detector.device->type() != Constants::DESKTOP_DEVICE_TYPE) {
|
||||||
|
|
||||||
|
static const auto tcChecker = [](const ToolChain *tc) {
|
||||||
|
return tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor
|
||||||
|
&& tc->compilerCommand().fileName() != "c89-gcc"
|
||||||
|
&& tc->compilerCommand().fileName() != "c99-gcc";
|
||||||
|
};
|
||||||
|
result += autoDetectToolchains("g++",
|
||||||
|
DetectVariants::Yes,
|
||||||
|
Constants::CXX_LANGUAGE_ID,
|
||||||
|
Constants::GCC_TOOLCHAIN_TYPEID,
|
||||||
|
detector,
|
||||||
|
&constructRealGccToolchain,
|
||||||
|
tcChecker);
|
||||||
|
result += autoDetectToolchains("gcc",
|
||||||
|
DetectVariants::Yes,
|
||||||
|
Constants::C_LANGUAGE_ID,
|
||||||
|
Constants::GCC_TOOLCHAIN_TYPEID,
|
||||||
|
detector,
|
||||||
|
&constructRealGccToolchain,
|
||||||
|
tcChecker);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Toolchains GccToolChainFactory::detectForImport(const ToolChainDescription &tcd) const
|
Toolchains GccToolChainFactory::detectForImport(const ToolChainDescription &tcd) const
|
||||||
{
|
{
|
||||||
|
Toolchains result;
|
||||||
|
|
||||||
|
// Do all autodetection in th 'RealGcc' case, and none in the others.
|
||||||
|
if (!m_autoDetecting)
|
||||||
|
return result;
|
||||||
|
|
||||||
const QString fileName = tcd.compilerPath.completeBaseName();
|
const QString fileName = tcd.compilerPath.completeBaseName();
|
||||||
const QString resolvedSymlinksFileName = tcd.compilerPath.resolveSymlinks().completeBaseName();
|
const QString resolvedSymlinksFileName = tcd.compilerPath.resolveSymlinks().completeBaseName();
|
||||||
|
|
||||||
const bool isCCompiler = tcd.language == Constants::C_LANGUAGE_ID
|
// Linux ICC
|
||||||
|
|
||||||
|
if ((tcd.language == Constants::CXX_LANGUAGE_ID && fileName.startsWith("icpc")) ||
|
||||||
|
(tcd.language == Constants::C_LANGUAGE_ID && fileName.startsWith("icc"))) {
|
||||||
|
result += autoDetectToolChain(tcd, &constructLinuxIccToolchain);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MingW
|
||||||
|
|
||||||
|
const bool cCompiler = tcd.language == Constants::C_LANGUAGE_ID
|
||||||
|
&& ((fileName.startsWith("gcc") || fileName.endsWith("gcc"))
|
||||||
|
|| fileName == "cc");
|
||||||
|
|
||||||
|
const bool cxxCompiler = tcd.language == Constants::CXX_LANGUAGE_ID
|
||||||
|
&& ((fileName.startsWith("g++") || fileName.endsWith("g++"))
|
||||||
|
|| (fileName.startsWith("c++") || fileName.endsWith("c++")));
|
||||||
|
|
||||||
|
if (cCompiler || cxxCompiler) {
|
||||||
|
result += autoDetectToolChain(tcd, &constructMinGWToolchain, [](const ToolChain *tc) {
|
||||||
|
return tc->targetAbi().osFlavor() == Abi::WindowsMSysFlavor;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clang
|
||||||
|
|
||||||
|
bool isCCompiler = tcd.language == Constants::C_LANGUAGE_ID
|
||||||
|
&& ((fileName.startsWith("clang") && !fileName.startsWith("clang++"))
|
||||||
|
|| (fileName == "cc" && resolvedSymlinksFileName.contains("clang")));
|
||||||
|
|
||||||
|
bool isCxxCompiler = tcd.language == Constants::CXX_LANGUAGE_ID
|
||||||
|
&& (fileName.startsWith("clang++")
|
||||||
|
|| (fileName == "c++" && resolvedSymlinksFileName.contains("clang")));
|
||||||
|
|
||||||
|
if (isCCompiler || isCxxCompiler)
|
||||||
|
result += autoDetectToolChain(tcd, &constructClangToolchain);
|
||||||
|
|
||||||
|
// GCC
|
||||||
|
|
||||||
|
isCCompiler = tcd.language == Constants::C_LANGUAGE_ID
|
||||||
&& (fileName.startsWith("gcc")
|
&& (fileName.startsWith("gcc")
|
||||||
|| fileName.endsWith("gcc")
|
|| fileName.endsWith("gcc")
|
||||||
|| (fileName == "cc" && !resolvedSymlinksFileName.contains("clang")));
|
|| (fileName == "cc" && !resolvedSymlinksFileName.contains("clang")));
|
||||||
|
|
||||||
const bool isCxxCompiler = tcd.language == Constants::CXX_LANGUAGE_ID
|
isCxxCompiler = tcd.language == Constants::CXX_LANGUAGE_ID
|
||||||
&& (fileName.startsWith("g++")
|
&& (fileName.startsWith("g++")
|
||||||
|| fileName.endsWith("g++")
|
|| fileName.endsWith("g++")
|
||||||
|| (fileName == "c++" && !resolvedSymlinksFileName.contains("clang")));
|
|| (fileName == "c++" && !resolvedSymlinksFileName.contains("clang")));
|
||||||
|
|
||||||
if (isCCompiler || isCxxCompiler) {
|
if (isCCompiler || isCxxCompiler) {
|
||||||
return autoDetectToolChain(tcd, toolchainConstructor(), [](const ToolChain *tc) {
|
result += autoDetectToolChain(tcd, &constructRealGccToolchain, [](const ToolChain *tc) {
|
||||||
return tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor;
|
return tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return {};
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FilePaths findCompilerCandidates(const ToolchainDetector &detector,
|
static FilePaths findCompilerCandidates(const ToolchainDetector &detector,
|
||||||
@@ -1792,73 +1954,6 @@ QString GccToolChain::sysRoot() const
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
// ClangToolChainFactory
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
ClangToolChainFactory::ClangToolChainFactory()
|
|
||||||
{
|
|
||||||
setDisplayName(Tr::tr("Clang"));
|
|
||||||
setSupportedToolChainType(Constants::CLANG_TOOLCHAIN_TYPEID);
|
|
||||||
setSupportedLanguages({Constants::CXX_LANGUAGE_ID, Constants::C_LANGUAGE_ID});
|
|
||||||
setToolchainConstructor([] {
|
|
||||||
return new GccToolChain(Constants::CLANG_TOOLCHAIN_TYPEID, GccToolChain::Clang);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Toolchains ClangToolChainFactory::autoDetect(const ToolchainDetector &detector) const
|
|
||||||
{
|
|
||||||
Toolchains tcs;
|
|
||||||
Toolchains known = detector.alreadyKnown;
|
|
||||||
|
|
||||||
tcs.append(autoDetectToolchains("clang++",
|
|
||||||
DetectVariants::Yes,
|
|
||||||
Constants::CXX_LANGUAGE_ID,
|
|
||||||
Constants::CLANG_TOOLCHAIN_TYPEID,
|
|
||||||
detector,
|
|
||||||
toolchainConstructor()));
|
|
||||||
tcs.append(autoDetectToolchains("clang",
|
|
||||||
DetectVariants::Yes,
|
|
||||||
Constants::C_LANGUAGE_ID,
|
|
||||||
Constants::CLANG_TOOLCHAIN_TYPEID,
|
|
||||||
detector,
|
|
||||||
toolchainConstructor()));
|
|
||||||
known.append(tcs);
|
|
||||||
|
|
||||||
const FilePath compilerPath = Core::ICore::clangExecutable(CLANG_BINDIR);
|
|
||||||
if (!compilerPath.isEmpty()) {
|
|
||||||
const FilePath clang = compilerPath.parentDir().pathAppended("clang").withExecutableSuffix();
|
|
||||||
tcs.append(
|
|
||||||
autoDetectToolchains(clang.toString(),
|
|
||||||
DetectVariants::No,
|
|
||||||
Constants::C_LANGUAGE_ID,
|
|
||||||
Constants::CLANG_TOOLCHAIN_TYPEID,
|
|
||||||
ToolchainDetector(known, detector.device, detector.searchPaths),
|
|
||||||
toolchainConstructor()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return tcs;
|
|
||||||
}
|
|
||||||
|
|
||||||
Toolchains ClangToolChainFactory::detectForImport(const ToolChainDescription &tcd) const
|
|
||||||
{
|
|
||||||
const QString fileName = tcd.compilerPath.completeBaseName();
|
|
||||||
const QString resolvedSymlinksFileName = tcd.compilerPath.resolveSymlinks().completeBaseName();
|
|
||||||
|
|
||||||
const bool isCCompiler = tcd.language == Constants::C_LANGUAGE_ID
|
|
||||||
&& ((fileName.startsWith("clang") && !fileName.startsWith("clang++"))
|
|
||||||
|| (fileName == "cc" && resolvedSymlinksFileName.contains("clang")));
|
|
||||||
|
|
||||||
const bool isCxxCompiler = tcd.language == Constants::CXX_LANGUAGE_ID
|
|
||||||
&& (fileName.startsWith("clang++")
|
|
||||||
|| (fileName == "c++" && resolvedSymlinksFileName.contains("clang")));
|
|
||||||
|
|
||||||
if (isCCompiler || isCxxCompiler) {
|
|
||||||
return autoDetectToolChain(tcd, toolchainConstructor());
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
void GccToolChainConfigWidget::updateParentToolChainComboBox()
|
void GccToolChainConfigWidget::updateParentToolChainComboBox()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(m_parentToolchainCombo, return);
|
QTC_ASSERT(m_parentToolchainCombo, return);
|
||||||
@@ -1886,104 +1981,6 @@ void GccToolChainConfigWidget::updateParentToolChainComboBox()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
// MingwToolChainFactory
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
MingwToolChainFactory::MingwToolChainFactory()
|
|
||||||
{
|
|
||||||
setDisplayName(Tr::tr("MinGW"));
|
|
||||||
setSupportedToolChainType(Constants::MINGW_TOOLCHAIN_TYPEID);
|
|
||||||
setSupportedLanguages({Constants::CXX_LANGUAGE_ID, Constants::C_LANGUAGE_ID});
|
|
||||||
setToolchainConstructor([] {
|
|
||||||
return new GccToolChain(Constants::MINGW_TOOLCHAIN_TYPEID, GccToolChain::MinGW);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Toolchains MingwToolChainFactory::autoDetect(const ToolchainDetector &detector) const
|
|
||||||
{
|
|
||||||
static const auto tcChecker = [](const ToolChain *tc) {
|
|
||||||
return tc->targetAbi().osFlavor() == Abi::WindowsMSysFlavor;
|
|
||||||
};
|
|
||||||
Toolchains result = autoDetectToolchains("g++",
|
|
||||||
DetectVariants::Yes,
|
|
||||||
Constants::CXX_LANGUAGE_ID,
|
|
||||||
Constants::MINGW_TOOLCHAIN_TYPEID,
|
|
||||||
detector,
|
|
||||||
toolchainConstructor(),
|
|
||||||
tcChecker);
|
|
||||||
result += autoDetectToolchains("gcc",
|
|
||||||
DetectVariants::Yes,
|
|
||||||
Constants::C_LANGUAGE_ID,
|
|
||||||
Constants::MINGW_TOOLCHAIN_TYPEID,
|
|
||||||
detector,
|
|
||||||
toolchainConstructor(),
|
|
||||||
tcChecker);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Toolchains MingwToolChainFactory::detectForImport(const ToolChainDescription &tcd) const
|
|
||||||
{
|
|
||||||
const QString fileName = tcd.compilerPath.completeBaseName();
|
|
||||||
|
|
||||||
const bool cCompiler = tcd.language == Constants::C_LANGUAGE_ID
|
|
||||||
&& ((fileName.startsWith("gcc") || fileName.endsWith("gcc"))
|
|
||||||
|| fileName == "cc");
|
|
||||||
|
|
||||||
const bool cxxCompiler = tcd.language == Constants::CXX_LANGUAGE_ID
|
|
||||||
&& ((fileName.startsWith("g++") || fileName.endsWith("g++"))
|
|
||||||
|| (fileName.startsWith("c++") || fileName.endsWith("c++")));
|
|
||||||
|
|
||||||
if (cCompiler || cxxCompiler) {
|
|
||||||
return autoDetectToolChain(tcd, toolchainConstructor(), [](const ToolChain *tc) {
|
|
||||||
return tc->targetAbi().osFlavor() == Abi::WindowsMSysFlavor;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
// LinuxIccToolChainFactory
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
LinuxIccToolChainFactory::LinuxIccToolChainFactory()
|
|
||||||
{
|
|
||||||
setDisplayName(Tr::tr("ICC"));
|
|
||||||
setSupportedToolChainType(Constants::LINUXICC_TOOLCHAIN_TYPEID);
|
|
||||||
setSupportedLanguages({Constants::CXX_LANGUAGE_ID, Constants::C_LANGUAGE_ID});
|
|
||||||
setToolchainConstructor([] {
|
|
||||||
return new GccToolChain(Constants::LINUXICC_TOOLCHAIN_TYPEID, GccToolChain::LinuxIcc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Toolchains LinuxIccToolChainFactory::autoDetect(const ToolchainDetector &detector) const
|
|
||||||
{
|
|
||||||
Toolchains result = autoDetectToolchains("icpc",
|
|
||||||
DetectVariants::No,
|
|
||||||
Constants::CXX_LANGUAGE_ID,
|
|
||||||
Constants::LINUXICC_TOOLCHAIN_TYPEID,
|
|
||||||
detector,
|
|
||||||
toolchainConstructor());
|
|
||||||
result += autoDetectToolchains("icc",
|
|
||||||
DetectVariants::Yes,
|
|
||||||
Constants::C_LANGUAGE_ID,
|
|
||||||
Constants::LINUXICC_TOOLCHAIN_TYPEID,
|
|
||||||
detector,
|
|
||||||
toolchainConstructor());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Toolchains LinuxIccToolChainFactory::detectForImport(const ToolChainDescription &tcd) const
|
|
||||||
{
|
|
||||||
const QString fileName = tcd.compilerPath.completeBaseName();
|
|
||||||
if ((tcd.language == Constants::CXX_LANGUAGE_ID && fileName.startsWith("icpc")) ||
|
|
||||||
(tcd.language == Constants::C_LANGUAGE_ID && fileName.startsWith("icc"))) {
|
|
||||||
return autoDetectToolChain(tcd, toolchainConstructor());
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
GccToolChain::WarningFlagAdder::WarningFlagAdder(const QString &flag, WarningFlags &flags) :
|
GccToolChain::WarningFlagAdder::WarningFlagAdder(const QString &flag, WarningFlags &flags) :
|
||||||
m_flags(flags)
|
m_flags(flags)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
#include "projectexplorer_export.h"
|
#include "projectexplorer_export.h"
|
||||||
|
|
||||||
#include "projectexplorerconstants.h"
|
|
||||||
#include "toolchain.h"
|
#include "toolchain.h"
|
||||||
#include "abi.h"
|
#include "abi.h"
|
||||||
#include "headerpath.h"
|
#include "headerpath.h"
|
||||||
@@ -17,11 +16,8 @@
|
|||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
class ClangToolChainFactory;
|
|
||||||
class GccToolChainConfigWidget;
|
class GccToolChainConfigWidget;
|
||||||
class GccToolChainFactory;
|
class GccToolChainFactory;
|
||||||
class MingwToolChainFactory;
|
|
||||||
class LinuxIccToolChainFactory;
|
|
||||||
|
|
||||||
const QStringList gccPredefinedMacrosOptions(Utils::Id languageId);
|
const QStringList gccPredefinedMacrosOptions(Utils::Id languageId);
|
||||||
}
|
}
|
||||||
@@ -30,7 +26,6 @@ const QStringList gccPredefinedMacrosOptions(Utils::Id languageId);
|
|||||||
// GccToolChain
|
// GccToolChain
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
class PROJECTEXPLORER_EXPORT GccToolChain : public ToolChain
|
class PROJECTEXPLORER_EXPORT GccToolChain : public ToolChain
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -174,9 +169,6 @@ private:
|
|||||||
|
|
||||||
friend class Internal::GccToolChainConfigWidget;
|
friend class Internal::GccToolChainConfigWidget;
|
||||||
friend class Internal::GccToolChainFactory;
|
friend class Internal::GccToolChainFactory;
|
||||||
friend class Internal::LinuxIccToolChainFactory;
|
|
||||||
friend class Internal::MingwToolChainFactory;
|
|
||||||
friend class Internal::ClangToolChainFactory;
|
|
||||||
friend class ToolChainFactory;
|
friend class ToolChainFactory;
|
||||||
|
|
||||||
// "resolved" on macOS from /usr/bin/clang(++) etc to <DeveloperDir>/usr/bin/clang(++)
|
// "resolved" on macOS from /usr/bin/clang(++) etc to <DeveloperDir>/usr/bin/clang(++)
|
||||||
@@ -188,20 +180,18 @@ private:
|
|||||||
QMetaObject::Connection m_thisToolchainRemovedConnection;
|
QMetaObject::Connection m_thisToolchainRemovedConnection;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
// Factories
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class GccToolChainFactory : public ToolChainFactory
|
class GccToolChainFactory : public ToolChainFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GccToolChainFactory();
|
explicit GccToolChainFactory(GccToolChain::SubType subType);
|
||||||
|
|
||||||
Toolchains autoDetect(const ToolchainDetector &detector) const override;
|
Toolchains autoDetect(const ToolchainDetector &detector) const final;
|
||||||
Toolchains detectForImport(const ToolChainDescription &tcd) const override;
|
Toolchains detectForImport(const ToolChainDescription &tcd) const final;
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
enum class DetectVariants { Yes, No };
|
enum class DetectVariants { Yes, No };
|
||||||
using ToolchainChecker = std::function<bool(const ToolChain *)>;
|
using ToolchainChecker = std::function<bool(const ToolChain *)>;
|
||||||
static Toolchains autoDetectToolchains(const QString &compilerName,
|
static Toolchains autoDetectToolchains(const QString &compilerName,
|
||||||
@@ -214,33 +204,8 @@ protected:
|
|||||||
static Toolchains autoDetectToolChain(const ToolChainDescription &tcd,
|
static Toolchains autoDetectToolChain(const ToolChainDescription &tcd,
|
||||||
const ToolChainConstructor &constructor,
|
const ToolChainConstructor &constructor,
|
||||||
const ToolchainChecker &checker = {});
|
const ToolchainChecker &checker = {});
|
||||||
};
|
|
||||||
|
|
||||||
class ClangToolChainFactory : public GccToolChainFactory
|
const bool m_autoDetecting;
|
||||||
{
|
|
||||||
public:
|
|
||||||
ClangToolChainFactory();
|
|
||||||
|
|
||||||
Toolchains autoDetect(const ToolchainDetector &detector) const final;
|
|
||||||
Toolchains detectForImport(const ToolChainDescription &tcd) const final;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MingwToolChainFactory : public GccToolChainFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MingwToolChainFactory();
|
|
||||||
|
|
||||||
Toolchains autoDetect(const ToolchainDetector &detector) const final;
|
|
||||||
Toolchains detectForImport(const ToolChainDescription &tcd) const final;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LinuxIccToolChainFactory : public GccToolChainFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LinuxIccToolChainFactory();
|
|
||||||
|
|
||||||
Toolchains autoDetect(const ToolchainDetector &detector) const final;
|
|
||||||
Toolchains detectForImport(const ToolChainDescription &tcd) const final;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -855,6 +855,8 @@ QSet<Id> DeviceTypeKitAspectFactory::availableFeatures(const Kit *k) const
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DeviceTypeKitAspectFactory theDeviceTypeKitAspectFactory;
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// DeviceKitAspect:
|
// DeviceKitAspect:
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -2057,7 +2057,7 @@ Toolchains ClangClToolChainFactory::autoDetect(const ToolchainDetector &detector
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Utils::Environment systemEnvironment = Utils::Environment::systemEnvironment();
|
const Utils::Environment systemEnvironment = Utils::Environment::systemEnvironment();
|
||||||
const Utils::FilePath clangClPath = systemEnvironment.searchInPath("clang-cl");
|
const Utils::FilePath clangClPath = systemEnvironment.searchInPath("clang-cl.exe");
|
||||||
if (!clangClPath.isEmpty())
|
if (!clangClPath.isEmpty())
|
||||||
results.append(detectClangClToolChainInPath(clangClPath, known, ""));
|
results.append(detectClangClToolChainInPath(clangClPath, known, ""));
|
||||||
|
|
||||||
|
|||||||
@@ -49,13 +49,13 @@
|
|||||||
#include "kitfeatureprovider.h"
|
#include "kitfeatureprovider.h"
|
||||||
#include "kitaspects.h"
|
#include "kitaspects.h"
|
||||||
#include "kitmanager.h"
|
#include "kitmanager.h"
|
||||||
#include "kitoptionspage.h"
|
|
||||||
#include "miniprojecttargetselector.h"
|
#include "miniprojecttargetselector.h"
|
||||||
#include "namedwidget.h"
|
#include "namedwidget.h"
|
||||||
#include "parseissuesdialog.h"
|
#include "parseissuesdialog.h"
|
||||||
#include "processstep.h"
|
#include "processstep.h"
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
#include "projectcommentssettings.h"
|
#include "projectcommentssettings.h"
|
||||||
|
#include "projectexplorerconstants.h"
|
||||||
#include "projectexplorericons.h"
|
#include "projectexplorericons.h"
|
||||||
#include "projectexplorersettings.h"
|
#include "projectexplorersettings.h"
|
||||||
#include "projectexplorertr.h"
|
#include "projectexplorertr.h"
|
||||||
@@ -625,15 +625,16 @@ public:
|
|||||||
MsvcToolChainFactory m_mscvToolChainFactory;
|
MsvcToolChainFactory m_mscvToolChainFactory;
|
||||||
ClangClToolChainFactory m_clangClToolChainFactory;
|
ClangClToolChainFactory m_clangClToolChainFactory;
|
||||||
#else
|
#else
|
||||||
LinuxIccToolChainFactory m_linuxToolChainFactory;
|
GccToolChainFactory m_linuxToolChainFactory{GccToolChain::LinuxIcc};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef Q_OS_MACOS
|
#ifndef Q_OS_MACOS
|
||||||
MingwToolChainFactory m_mingwToolChainFactory; // Mingw offers cross-compiling to windows
|
// Mingw offers cross-compiling to windows
|
||||||
|
GccToolChainFactory m_mingwToolChainFactory{GccToolChain::MinGW};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GccToolChainFactory m_gccToolChainFactory;
|
GccToolChainFactory m_gccToolChainFactory{GccToolChain::RealGcc};
|
||||||
ClangToolChainFactory m_clangToolChainFactory;
|
GccToolChainFactory m_clangToolChainFactory{GccToolChain::Clang};
|
||||||
CustomToolChainFactory m_customToolChainFactory;
|
CustomToolChainFactory m_customToolChainFactory;
|
||||||
|
|
||||||
DesktopDeviceFactory m_desktopDeviceFactory;
|
DesktopDeviceFactory m_desktopDeviceFactory;
|
||||||
|
|||||||
@@ -671,8 +671,7 @@ void ToolChainFactory::setSupportsAllLanguages(bool supportsAllLanguages)
|
|||||||
m_supportsAllLanguages = supportsAllLanguages;
|
m_supportsAllLanguages = supportsAllLanguages;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToolChainFactory::setToolchainConstructor
|
void ToolChainFactory::setToolchainConstructor(const ToolChainConstructor &toolchainContructor)
|
||||||
(const ToolChainConstructor &toolchainContructor)
|
|
||||||
{
|
{
|
||||||
m_toolchainConstructor = toolchainContructor;
|
m_toolchainConstructor = toolchainContructor;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,9 +27,9 @@
|
|||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileInfo>
|
|
||||||
#include <QStringList>
|
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
|
#include <QSet>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@@ -61,19 +61,18 @@ QmakeProjectImporter::QmakeProjectImporter(const FilePath &path) :
|
|||||||
|
|
||||||
FilePaths QmakeProjectImporter::importCandidates()
|
FilePaths QmakeProjectImporter::importCandidates()
|
||||||
{
|
{
|
||||||
FilePaths candidates;
|
FilePaths candidates{projectFilePath().absolutePath()};
|
||||||
|
|
||||||
const FilePath pfp = projectFilePath();
|
|
||||||
const QString prefix = pfp.baseName();
|
|
||||||
candidates << pfp.absolutePath();
|
|
||||||
|
|
||||||
|
QSet<FilePath> seenBaseDirs;
|
||||||
for (Kit *k : KitManager::kits()) {
|
for (Kit *k : KitManager::kits()) {
|
||||||
const FilePath sbdir = QmakeBuildConfiguration::shadowBuildDirectory
|
const FilePath sbdir = QmakeBuildConfiguration::shadowBuildDirectory
|
||||||
(projectFilePath(), k, QString(), BuildConfiguration::Unknown);
|
(projectFilePath(), k, QString(), BuildConfiguration::Unknown);
|
||||||
|
|
||||||
const FilePath baseDir = sbdir.absolutePath();
|
const FilePath baseDir = sbdir.absolutePath();
|
||||||
|
if (!Utils::insert(seenBaseDirs, baseDir))
|
||||||
|
continue;
|
||||||
for (const FilePath &path : baseDir.dirEntries(QDir::Dirs | QDir::NoDotAndDotDot)) {
|
for (const FilePath &path : baseDir.dirEntries(QDir::Dirs | QDir::NoDotAndDotDot)) {
|
||||||
if (path.fileName().startsWith(prefix) && !candidates.contains(path))
|
if (!candidates.contains(path))
|
||||||
candidates << path;
|
candidates << path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ const QByteArray livePreviewId = "LivePreview";
|
|||||||
|
|
||||||
static void handleAction(const SelectionContext &context)
|
static void handleAction(const SelectionContext &context)
|
||||||
{
|
{
|
||||||
if (context.view()->isAttached()) {
|
if (context.isValid()) {
|
||||||
if (context.toggled()) {
|
if (context.toggled()) {
|
||||||
bool skipDeploy = false;
|
bool skipDeploy = false;
|
||||||
if (const Target *startupTarget = ProjectManager::startupTarget()) {
|
if (const Target *startupTarget = ProjectManager::startupTarget()) {
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/dialogs/ioptionspage.h>
|
#include <coreplugin/dialogs/ioptionspage.h>
|
||||||
|
|
||||||
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
|
||||||
#include <utils/aspects.h>
|
#include <utils/aspects.h>
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
#include <utils/infolabel.h>
|
#include <utils/infolabel.h>
|
||||||
@@ -19,7 +21,6 @@
|
|||||||
#include <utils/pathchooser.h>
|
#include <utils/pathchooser.h>
|
||||||
#include <utils/utilsicons.h>
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
#include <QGroupBox>
|
|
||||||
#include <QTextBrowser>
|
#include <QTextBrowser>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user