forked from qt-creator/qt-creator
CMakePM: Integrate RSTParser into hover help / code completion
Change-Id: I1618be1aff83e8164c53040bb2c7230bcc1ec8ee Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
@@ -46,4 +46,5 @@ add_qtc_plugin(CMakeProjectManager
|
|||||||
3rdparty/cmake/cmListFileCache.cxx
|
3rdparty/cmake/cmListFileCache.cxx
|
||||||
3rdparty/cmake/cmListFileLexer.cxx
|
3rdparty/cmake/cmListFileLexer.cxx
|
||||||
3rdparty/cmake/cmListFileCache.h
|
3rdparty/cmake/cmListFileCache.h
|
||||||
|
3rdparty/rstparser/rstparser.cc 3rdparty/rstparser/rstparser.h
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
#include "cmakebuildsystem.h"
|
#include "cmakebuildsystem.h"
|
||||||
#include "cmakefilecompletionassist.h"
|
#include "cmakefilecompletionassist.h"
|
||||||
#include "cmakeindenter.h"
|
#include "cmakeindenter.h"
|
||||||
#include "cmakekitaspect.h"
|
|
||||||
#include "cmakeprojectconstants.h"
|
#include "cmakeprojectconstants.h"
|
||||||
|
|
||||||
#include "3rdparty/cmake/cmListFileCache.h"
|
#include "3rdparty/cmake/cmListFileCache.h"
|
||||||
@@ -53,13 +52,7 @@ public:
|
|||||||
|
|
||||||
CMakeEditor::CMakeEditor()
|
CMakeEditor::CMakeEditor()
|
||||||
{
|
{
|
||||||
CMakeTool *tool = nullptr;
|
if (auto tool = CMakeToolManager::defaultProjectOrDefaultCMakeTool())
|
||||||
if (auto bs = ProjectTree::currentBuildSystem())
|
|
||||||
tool = CMakeKitAspect::cmakeTool(bs->target()->kit());
|
|
||||||
if (!tool)
|
|
||||||
tool = CMakeToolManager::defaultCMakeTool();
|
|
||||||
|
|
||||||
if (tool)
|
|
||||||
m_keywords = tool->keywords();
|
m_keywords = tool->keywords();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,6 +313,7 @@ class CMakeHoverHandler : public TextEditor::BaseHoverHandler
|
|||||||
{
|
{
|
||||||
mutable CMakeKeywords m_keywords;
|
mutable CMakeKeywords m_keywords;
|
||||||
QString m_helpToolTip;
|
QString m_helpToolTip;
|
||||||
|
QString m_contextHelp;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const CMakeKeywords &keywords() const;
|
const CMakeKeywords &keywords() const;
|
||||||
@@ -332,16 +326,9 @@ public:
|
|||||||
|
|
||||||
const CMakeKeywords &CMakeHoverHandler::keywords() const
|
const CMakeKeywords &CMakeHoverHandler::keywords() const
|
||||||
{
|
{
|
||||||
if (m_keywords.functions.isEmpty()) {
|
if (m_keywords.functions.isEmpty())
|
||||||
CMakeTool *tool = nullptr;
|
if (auto tool = CMakeToolManager::defaultProjectOrDefaultCMakeTool())
|
||||||
if (auto bs = ProjectTree::currentBuildSystem())
|
|
||||||
tool = CMakeKitAspect::cmakeTool(bs->target()->kit());
|
|
||||||
if (!tool)
|
|
||||||
tool = CMakeToolManager::defaultCMakeTool();
|
|
||||||
|
|
||||||
if (tool)
|
|
||||||
m_keywords = tool->keywords();
|
m_keywords = tool->keywords();
|
||||||
}
|
|
||||||
|
|
||||||
return m_keywords;
|
return m_keywords;
|
||||||
}
|
}
|
||||||
@@ -357,24 +344,39 @@ void CMakeHoverHandler::identifyMatch(TextEditor::TextEditorWidget *editorWidget
|
|||||||
const QString word = Utils::Text::wordUnderCursor(cursor);
|
const QString word = Utils::Text::wordUnderCursor(cursor);
|
||||||
|
|
||||||
FilePath helpFile;
|
FilePath helpFile;
|
||||||
for (const auto &map : {keywords().functions,
|
QString helpCategory;
|
||||||
keywords().variables,
|
struct
|
||||||
keywords().directoryProperties,
|
{
|
||||||
keywords().sourceProperties,
|
const QMap<QString, Utils::FilePath> ↦
|
||||||
keywords().targetProperties,
|
QString helpCategory;
|
||||||
keywords().testProperties,
|
} keywordsListMaps[] = {{keywords().functions, "command"},
|
||||||
keywords().properties,
|
{keywords().variables, "variable"},
|
||||||
keywords().includeStandardModules,
|
{keywords().directoryProperties, "prop_dir"},
|
||||||
keywords().findModules,
|
{keywords().sourceProperties, "prop_sf"},
|
||||||
keywords().policies}) {
|
{keywords().targetProperties, "prop_tgt"},
|
||||||
if (map.contains(word)) {
|
{keywords().testProperties, "prop_test"},
|
||||||
helpFile = map.value(word);
|
{keywords().properties, "prop_gbl"},
|
||||||
|
{keywords().includeStandardModules, "module"},
|
||||||
|
{keywords().findModules, "module"},
|
||||||
|
{keywords().policies, "policy"}};
|
||||||
|
|
||||||
|
for (const auto &pair : keywordsListMaps) {
|
||||||
|
if (pair.map.contains(word)) {
|
||||||
|
helpFile = pair.map.value(word);
|
||||||
|
helpCategory = pair.helpCategory;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_helpToolTip.clear();
|
m_helpToolTip.clear();
|
||||||
if (!helpFile.isEmpty())
|
if (!helpFile.isEmpty())
|
||||||
m_helpToolTip = CMakeToolManager::readFirstParagraphs(helpFile);
|
m_helpToolTip = CMakeToolManager::toolTipForRstHelpFile(helpFile);
|
||||||
|
|
||||||
|
if (auto tool = CMakeToolManager::defaultProjectOrDefaultCMakeTool())
|
||||||
|
m_contextHelp = QString("%1/%2/%3")
|
||||||
|
.arg(tool->documentationUrl(tool->version(),
|
||||||
|
tool->qchFilePath().isEmpty()),
|
||||||
|
helpCategory,
|
||||||
|
word);
|
||||||
|
|
||||||
setPriority(m_helpToolTip.isEmpty() ? Priority_Tooltip : Priority_None);
|
setPriority(m_helpToolTip.isEmpty() ? Priority_Tooltip : Priority_None);
|
||||||
}
|
}
|
||||||
@@ -382,7 +384,7 @@ void CMakeHoverHandler::identifyMatch(TextEditor::TextEditorWidget *editorWidget
|
|||||||
void CMakeHoverHandler::operateTooltip(TextEditorWidget *editorWidget, const QPoint &point)
|
void CMakeHoverHandler::operateTooltip(TextEditorWidget *editorWidget, const QPoint &point)
|
||||||
{
|
{
|
||||||
if (!m_helpToolTip.isEmpty())
|
if (!m_helpToolTip.isEmpty())
|
||||||
Utils::ToolTip::show(point, m_helpToolTip, Qt::MarkdownText, editorWidget);
|
Utils::ToolTip::show(point, m_helpToolTip, Qt::MarkdownText, editorWidget, m_contextHelp);
|
||||||
else
|
else
|
||||||
Utils::ToolTip::hide();
|
Utils::ToolTip::hide();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
|
|
||||||
#include "cmakebuildsystem.h"
|
#include "cmakebuildsystem.h"
|
||||||
#include "cmakebuildtarget.h"
|
#include "cmakebuildtarget.h"
|
||||||
#include "cmakekitaspect.h"
|
|
||||||
#include "cmakeproject.h"
|
|
||||||
#include "cmakeprojectconstants.h"
|
#include "cmakeprojectconstants.h"
|
||||||
#include "cmaketool.h"
|
#include "cmaketool.h"
|
||||||
#include "cmaketoolmanager.h"
|
#include "cmaketoolmanager.h"
|
||||||
@@ -166,7 +164,7 @@ static QList<AssistProposalItemInterface *> generateList(const QMap<QString, Fil
|
|||||||
MarkDownAssitProposalItem *item = new MarkDownAssitProposalItem();
|
MarkDownAssitProposalItem *item = new MarkDownAssitProposalItem();
|
||||||
item->setText(it.key());
|
item->setText(it.key());
|
||||||
if (!it.value().isEmpty())
|
if (!it.value().isEmpty())
|
||||||
item->setDetail(CMakeToolManager::readFirstParagraphs(it.value()));
|
item->setDetail(CMakeToolManager::toolTipForRstHelpFile(it.value()));
|
||||||
item->setIcon(icon);
|
item->setIcon(icon);
|
||||||
list << item;
|
list << item;
|
||||||
}
|
}
|
||||||
@@ -244,16 +242,8 @@ IAssistProposal *CMakeFileCompletionAssist::performAsync()
|
|||||||
Project *project = nullptr;
|
Project *project = nullptr;
|
||||||
const FilePath &filePath = interface()->filePath();
|
const FilePath &filePath = interface()->filePath();
|
||||||
if (!filePath.isEmpty() && filePath.isFile()) {
|
if (!filePath.isEmpty() && filePath.isFile()) {
|
||||||
CMakeTool *cmake = nullptr;
|
if (auto tool = CMakeToolManager::defaultProjectOrDefaultCMakeTool())
|
||||||
project = static_cast<CMakeProject *>(ProjectManager::projectForFile(filePath));
|
keywords = tool->keywords();
|
||||||
if (project && project->activeTarget())
|
|
||||||
cmake = CMakeKitAspect::cmakeTool(project->activeTarget()->kit());
|
|
||||||
|
|
||||||
if (!cmake)
|
|
||||||
cmake = CMakeToolManager::defaultCMakeTool();
|
|
||||||
|
|
||||||
if (cmake && cmake->isValid())
|
|
||||||
keywords = cmake->keywords();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList buildTargets;
|
QStringList buildTargets;
|
||||||
|
|||||||
@@ -93,13 +93,15 @@ QtcPlugin {
|
|||||||
name: "3rdparty"
|
name: "3rdparty"
|
||||||
cpp.includePaths: base.concat("3rdparty/cmake")
|
cpp.includePaths: base.concat("3rdparty/cmake")
|
||||||
|
|
||||||
prefix: "3rdparty/cmake/"
|
prefix: "3rdparty/"
|
||||||
files: [
|
files: [
|
||||||
"cmListFileCache.cxx",
|
"cmake/cmListFileCache.cxx",
|
||||||
"cmListFileCache.h",
|
"cmake/cmListFileCache.h",
|
||||||
"cmListFileLexer.cxx",
|
"cmake/cmListFileLexer.cxx",
|
||||||
"cmListFileLexer.h",
|
"cmake/cmListFileLexer.h",
|
||||||
"cmStandardLexer.h",
|
"cmake/cmStandardLexer.h",
|
||||||
|
"rstparser/rstparser.cc",
|
||||||
|
"rstparser/rstparser.h"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,17 @@
|
|||||||
#include "cmakespecificsettings.h"
|
#include "cmakespecificsettings.h"
|
||||||
#include "cmaketoolsettingsaccessor.h"
|
#include "cmaketoolsettingsaccessor.h"
|
||||||
|
|
||||||
|
#include "3rdparty/rstparser/rstparser.h"
|
||||||
|
|
||||||
#include <extensionsystem/pluginmanager.h>
|
#include <extensionsystem/pluginmanager.h>
|
||||||
|
|
||||||
#include <coreplugin/helpmanager.h>
|
#include <coreplugin/helpmanager.h>
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
|
#include <projectexplorer/buildsystem.h>
|
||||||
|
#include <projectexplorer/projecttree.h>
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
#include <stack>
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
#include <utils/pointeralgorithm.h>
|
#include <utils/pointeralgorithm.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
@@ -32,6 +38,137 @@ public:
|
|||||||
Internal::CMakeToolSettingsAccessor m_accessor;
|
Internal::CMakeToolSettingsAccessor m_accessor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class HtmlHandler : public rst::ContentHandler
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::stack<QString> m_tags;
|
||||||
|
|
||||||
|
QStringList m_p;
|
||||||
|
QStringList m_h3;
|
||||||
|
QStringList m_cmake_code;
|
||||||
|
|
||||||
|
QString m_last_directive_type;
|
||||||
|
QString m_last_directive_class;
|
||||||
|
|
||||||
|
void StartBlock(rst::BlockType type) final
|
||||||
|
{
|
||||||
|
QString tag;
|
||||||
|
switch (type) {
|
||||||
|
case rst::REFERENCE_LINK:
|
||||||
|
// not used, HandleReferenceLink is used instead
|
||||||
|
break;
|
||||||
|
case rst::H1:
|
||||||
|
tag = "h1";
|
||||||
|
break;
|
||||||
|
case rst::H2:
|
||||||
|
tag = "h2";
|
||||||
|
break;
|
||||||
|
case rst::H3:
|
||||||
|
tag = "h3";
|
||||||
|
break;
|
||||||
|
case rst::H4:
|
||||||
|
tag = "h4";
|
||||||
|
break;
|
||||||
|
case rst::H5:
|
||||||
|
tag = "h5";
|
||||||
|
break;
|
||||||
|
case rst::CODE:
|
||||||
|
tag = "code";
|
||||||
|
break;
|
||||||
|
case rst::PARAGRAPH:
|
||||||
|
tag = "p";
|
||||||
|
break;
|
||||||
|
case rst::LINE_BLOCK:
|
||||||
|
tag = "pre";
|
||||||
|
break;
|
||||||
|
case rst::BLOCK_QUOTE:
|
||||||
|
if (m_last_directive_type == "code-block" && m_last_directive_class == "cmake")
|
||||||
|
tag = "cmake-code";
|
||||||
|
else
|
||||||
|
tag = "blockquote";
|
||||||
|
break;
|
||||||
|
case rst::BULLET_LIST:
|
||||||
|
tag = "ul";
|
||||||
|
break;
|
||||||
|
case rst::LIST_ITEM:
|
||||||
|
tag = "li";
|
||||||
|
break;
|
||||||
|
case rst::LITERAL_BLOCK:
|
||||||
|
tag = "pre";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tag == "p")
|
||||||
|
m_p.push_back(QString());
|
||||||
|
if (tag == "h3")
|
||||||
|
m_h3.push_back(QString());
|
||||||
|
if (tag == "cmake-code")
|
||||||
|
m_cmake_code.push_back(QString());
|
||||||
|
|
||||||
|
if (tag == "code" && m_tags.top() == "p")
|
||||||
|
m_p.last().append("`");
|
||||||
|
|
||||||
|
m_tags.push(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EndBlock() final
|
||||||
|
{
|
||||||
|
// Add a new "p" collector for any `code` markup that comes afterwads
|
||||||
|
// since we are insterested only in the first paragraph.
|
||||||
|
if (m_tags.top() == "p")
|
||||||
|
m_p.push_back(QString());
|
||||||
|
|
||||||
|
if (m_tags.top() == "code" && !m_p.isEmpty()) {
|
||||||
|
m_tags.pop();
|
||||||
|
|
||||||
|
if (m_tags.size() > 0 && m_tags.top() == "p")
|
||||||
|
m_p.last().append("`");
|
||||||
|
} else {
|
||||||
|
m_tags.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleText(const char *text, std::size_t size) final
|
||||||
|
{
|
||||||
|
if (m_last_directive_type.endsWith("replace"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString str = QString::fromUtf8(text, size);
|
||||||
|
|
||||||
|
if (m_tags.top() == "h3")
|
||||||
|
m_h3.last().append(str);
|
||||||
|
if (m_tags.top() == "p")
|
||||||
|
m_p.last().append(str);
|
||||||
|
if (m_tags.top() == "cmake-code")
|
||||||
|
m_cmake_code.last().append(str);
|
||||||
|
if (m_tags.top() == "code" && !m_p.isEmpty())
|
||||||
|
m_p.last().append(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleDirective(const std::string &type, const std::string &name) final
|
||||||
|
{
|
||||||
|
m_last_directive_type = QString::fromStdString(type);
|
||||||
|
m_last_directive_class = QString::fromStdString(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleReferenceLink(const std::string &type, const std::string &text) final
|
||||||
|
{
|
||||||
|
Q_UNUSED(type)
|
||||||
|
if (!m_p.isEmpty())
|
||||||
|
m_p.last().append(QString::fromStdString(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
QString content() const
|
||||||
|
{
|
||||||
|
const QString title = m_h3.isEmpty() ? QString() : m_h3.first();
|
||||||
|
const QString description = m_p.isEmpty() ? QString() : m_p.first();
|
||||||
|
const QString cmakeCode = m_cmake_code.isEmpty() ? QString() : m_cmake_code.first();
|
||||||
|
|
||||||
|
return QString("### %1\n\n%2\n\n````\n%3\n````").arg(title, description, cmakeCode);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static CMakeToolManagerPrivate *d = nullptr;
|
static CMakeToolManagerPrivate *d = nullptr;
|
||||||
CMakeToolManager *CMakeToolManager::m_instance = nullptr;
|
CMakeToolManager *CMakeToolManager::m_instance = nullptr;
|
||||||
|
|
||||||
@@ -108,6 +245,37 @@ void CMakeToolManager::deregisterCMakeTool(const Id &id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CMakeTool *CMakeToolManager::defaultProjectOrDefaultCMakeTool()
|
||||||
|
{
|
||||||
|
static CMakeTool *tool = nullptr;
|
||||||
|
|
||||||
|
auto updateTool = [&] {
|
||||||
|
tool = nullptr;
|
||||||
|
if (auto bs = ProjectExplorer::ProjectTree::currentBuildSystem())
|
||||||
|
tool = CMakeKitAspect::cmakeTool(bs->target()->kit());
|
||||||
|
if (!tool)
|
||||||
|
tool = CMakeToolManager::defaultCMakeTool();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!tool)
|
||||||
|
updateTool();
|
||||||
|
|
||||||
|
QObject::connect(CMakeToolManager::instance(),
|
||||||
|
&CMakeToolManager::cmakeUpdated,
|
||||||
|
CMakeToolManager::instance(),
|
||||||
|
[&]() { updateTool(); });
|
||||||
|
QObject::connect(CMakeToolManager::instance(),
|
||||||
|
&CMakeToolManager::cmakeRemoved,
|
||||||
|
CMakeToolManager::instance(),
|
||||||
|
[&]() { updateTool(); });
|
||||||
|
QObject::connect(CMakeToolManager::instance(),
|
||||||
|
&CMakeToolManager::defaultCMakeChanged,
|
||||||
|
CMakeToolManager::instance(),
|
||||||
|
[&]() { updateTool(); });
|
||||||
|
|
||||||
|
return tool;
|
||||||
|
}
|
||||||
|
|
||||||
CMakeTool *CMakeToolManager::defaultCMakeTool()
|
CMakeTool *CMakeToolManager::defaultCMakeTool()
|
||||||
{
|
{
|
||||||
return findById(d->m_defaultCMake);
|
return findById(d->m_defaultCMake);
|
||||||
@@ -167,21 +335,25 @@ void CMakeToolManager::updateDocumentation()
|
|||||||
Core::HelpManager::registerDocumentation(docs);
|
Core::HelpManager::registerDocumentation(docs);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CMakeToolManager::readFirstParagraphs(const FilePath &helpFile)
|
QString CMakeToolManager::toolTipForRstHelpFile(const FilePath &helpFile)
|
||||||
{
|
{
|
||||||
static QMap<FilePath, QString> map;
|
static QHash<FilePath, QString> map;
|
||||||
if (map.contains(helpFile))
|
if (map.contains(helpFile))
|
||||||
return map.value(helpFile);
|
return map.value(helpFile);
|
||||||
|
|
||||||
auto content = helpFile.fileContents(1024).value_or(QByteArray());
|
auto content = helpFile.fileContents(1024).value_or(QByteArray());
|
||||||
const QString firstParagraphs
|
content.replace("\r\n", "\n");
|
||||||
= QString("```\n%1\n```").arg(QString::fromUtf8(content.left(content.lastIndexOf("\n"))));
|
|
||||||
|
|
||||||
map[helpFile] = firstParagraphs;
|
HtmlHandler handler;
|
||||||
return firstParagraphs;
|
rst::Parser parser(&handler);
|
||||||
|
parser.Parse(content.left(content.lastIndexOf('\n')));
|
||||||
|
|
||||||
|
const QString tooltip = handler.content();
|
||||||
|
|
||||||
|
map[helpFile] = tooltip;
|
||||||
|
return tooltip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QList<Id> CMakeToolManager::autoDetectCMakeForDevice(const FilePaths &searchPaths,
|
QList<Id> CMakeToolManager::autoDetectCMakeForDevice(const FilePaths &searchPaths,
|
||||||
const QString &detectionSource,
|
const QString &detectionSource,
|
||||||
QString *logMessage)
|
QString *logMessage)
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ public:
|
|||||||
static bool registerCMakeTool(std::unique_ptr<CMakeTool> &&tool);
|
static bool registerCMakeTool(std::unique_ptr<CMakeTool> &&tool);
|
||||||
static void deregisterCMakeTool(const Utils::Id &id);
|
static void deregisterCMakeTool(const Utils::Id &id);
|
||||||
|
|
||||||
|
static CMakeTool *defaultProjectOrDefaultCMakeTool();
|
||||||
|
|
||||||
static CMakeTool *defaultCMakeTool();
|
static CMakeTool *defaultCMakeTool();
|
||||||
static void setDefaultCMakeTool(const Utils::Id &id);
|
static void setDefaultCMakeTool(const Utils::Id &id);
|
||||||
static CMakeTool *findByCommand(const Utils::FilePath &command);
|
static CMakeTool *findByCommand(const Utils::FilePath &command);
|
||||||
@@ -40,7 +42,7 @@ public:
|
|||||||
|
|
||||||
static void updateDocumentation();
|
static void updateDocumentation();
|
||||||
|
|
||||||
static QString readFirstParagraphs(const Utils::FilePath &helpFile);
|
static QString toolTipForRstHelpFile(const Utils::FilePath &helpFile);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
QList<Utils::Id> autoDetectCMakeForDevice(const Utils::FilePaths &searchPaths,
|
QList<Utils::Id> autoDetectCMakeForDevice(const Utils::FilePaths &searchPaths,
|
||||||
|
|||||||
Reference in New Issue
Block a user