forked from qt-creator/qt-creator
CMake: Delay initialization of CMakeTools
Do not run cmake 5 times during startup. Delay that as far as possible. Also add a supportedGenerators() method while visiting the code anyway. Fix up and simplify the other cmake help output parsers. Change-Id: I6622d552ffe559bf099b4b278618676a045e350e Reviewed-by: Tobias Hunger <tobias.hunger@theqtcompany.com>
This commit is contained in:
@@ -46,8 +46,6 @@ using namespace ProjectExplorer;
|
||||
// -------------------------------
|
||||
// CMakeFileCompletionAssistProvider
|
||||
// -------------------------------
|
||||
CMakeFileCompletionAssistProvider::CMakeFileCompletionAssistProvider()
|
||||
{}
|
||||
|
||||
bool CMakeFileCompletionAssistProvider::supportsEditor(Core::Id editorId) const
|
||||
{
|
||||
@@ -56,31 +54,26 @@ bool CMakeFileCompletionAssistProvider::supportsEditor(Core::Id editorId) const
|
||||
|
||||
IAssistProcessor *CMakeFileCompletionAssistProvider::createProcessor() const
|
||||
{
|
||||
return new CMakeFileCompletionAssist();
|
||||
return new CMakeFileCompletionAssist;
|
||||
}
|
||||
|
||||
|
||||
CMakeFileCompletionAssist::CMakeFileCompletionAssist() :
|
||||
KeywordsCompletionAssistProcessor(Keywords())
|
||||
{}
|
||||
|
||||
IAssistProposal *CMakeFileCompletionAssist::perform(const AssistInterface *interface)
|
||||
{
|
||||
TextEditor::Keywords keywords;
|
||||
|
||||
Keywords kw;
|
||||
QString fileName = interface->fileName();
|
||||
if (!fileName.isEmpty() && QFileInfo(fileName).isFile()) {
|
||||
Utils::FileName file = Utils::FileName::fromString(fileName);
|
||||
if (Project *p = SessionManager::projectForFile(file)) {
|
||||
if (Target *t = p->activeTarget()) {
|
||||
if (CMakeTool *cmake = CMakeKitInformation::cmakeTool(t->kit())) {
|
||||
if (cmake->isValid())
|
||||
keywords = cmake->keywords();
|
||||
}
|
||||
}
|
||||
Project *p = SessionManager::projectForFile(Utils::FileName::fromString(fileName));
|
||||
if (p && p->activeTarget()) {
|
||||
CMakeTool *cmake = CMakeKitInformation::cmakeTool(p->activeTarget()->kit());
|
||||
if (cmake && cmake->isValid())
|
||||
kw = cmake->keywords();
|
||||
}
|
||||
}
|
||||
|
||||
setKeywords(keywords);
|
||||
setKeywords(kw);
|
||||
return KeywordsCompletionAssistProcessor::perform(interface);
|
||||
}
|
||||
|
@@ -47,8 +47,6 @@ class CMakeFileCompletionAssistProvider : public TextEditor::CompletionAssistPro
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CMakeFileCompletionAssistProvider();
|
||||
|
||||
bool supportsEditor(Core::Id editorId) const override;
|
||||
TextEditor::IAssistProcessor *createProcessor() const override;
|
||||
};
|
||||
|
@@ -26,12 +26,16 @@
|
||||
#include "cmaketool.h"
|
||||
#include "cmaketoolmanager.h"
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/environment.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QProcess>
|
||||
#include <QFileInfo>
|
||||
#include <QProcess>
|
||||
#include <QSet>
|
||||
#include <QTextDocument>
|
||||
#include <QUuid>
|
||||
#include <QVariantMap>
|
||||
|
||||
using namespace CMakeProjectManager;
|
||||
|
||||
@@ -44,16 +48,12 @@ const char CMAKE_INFORMATION_AUTODETECTED[] = "AutoDetected";
|
||||
// CMakeTool
|
||||
///////////////////////////
|
||||
CMakeTool::CMakeTool(Detection d, const Core::Id &id) :
|
||||
m_isAutoDetected(d == AutoDetection),
|
||||
m_id(id)
|
||||
m_id(id), m_isAutoDetected(d == AutoDetection)
|
||||
{
|
||||
//make sure every CMakeTool has a valid ID
|
||||
if (!m_id.isValid())
|
||||
createId();
|
||||
QTC_ASSERT(m_id.isValid(), m_id = Core::Id::fromString(QUuid::createUuid().toString()));
|
||||
}
|
||||
|
||||
CMakeTool::CMakeTool(const QVariantMap &map, bool fromSdk) :
|
||||
m_isAutoDetected(fromSdk)
|
||||
CMakeTool::CMakeTool(const QVariantMap &map, bool fromSdk) : m_isAutoDetected(fromSdk)
|
||||
{
|
||||
m_id = Core::Id::fromSetting(map.value(QLatin1String(CMAKE_INFORMATION_ID)));
|
||||
m_displayName = map.value(QLatin1String(CMAKE_INFORMATION_DISPLAYNAME)).toString();
|
||||
@@ -62,106 +62,57 @@ CMakeTool::CMakeTool(const QVariantMap &map, bool fromSdk) :
|
||||
if (!fromSdk)
|
||||
m_isAutoDetected = map.value(QLatin1String(CMAKE_INFORMATION_AUTODETECTED), false).toBool();
|
||||
|
||||
setCMakeExecutable(Utils::FileName::fromUserInput(map.value(QLatin1String(CMAKE_INFORMATION_COMMAND)).toString()));
|
||||
setCMakeExecutable(Utils::FileName::fromString(map.value(QLatin1String(CMAKE_INFORMATION_COMMAND)).toString()));
|
||||
}
|
||||
|
||||
CMakeTool::~CMakeTool()
|
||||
Core::Id CMakeTool::createId()
|
||||
{
|
||||
cancel();
|
||||
}
|
||||
|
||||
void CMakeTool::cancel()
|
||||
{
|
||||
if (m_process) {
|
||||
disconnect(m_process, static_cast<void (QProcess::*)(int)>(&QProcess::finished),
|
||||
this, &CMakeTool::finished);
|
||||
|
||||
if (m_process->state() != QProcess::NotRunning)
|
||||
m_process->kill();
|
||||
|
||||
m_process->waitForFinished();
|
||||
delete m_process;
|
||||
m_process = 0;
|
||||
}
|
||||
return Core::Id::fromString(QUuid::createUuid().toString());
|
||||
}
|
||||
|
||||
void CMakeTool::setCMakeExecutable(const Utils::FileName &executable)
|
||||
{
|
||||
cancel();
|
||||
m_process = new QProcess();
|
||||
connect(m_process, static_cast<void (QProcess::*)(int)>(&QProcess::finished), this, &CMakeTool::finished);
|
||||
if (m_executable == executable)
|
||||
return;
|
||||
|
||||
m_didRun = false;
|
||||
m_didAttemptToRun = false;
|
||||
|
||||
m_executable = executable;
|
||||
QFileInfo fi = m_executable.toFileInfo();
|
||||
if (fi.exists() && fi.isExecutable()) {
|
||||
// Run it to find out more
|
||||
m_state = CMakeTool::RunningBasic;
|
||||
if (!startProcess(QStringList(QLatin1String("--help"))))
|
||||
m_state = CMakeTool::Invalid;
|
||||
} else {
|
||||
m_state = CMakeTool::Invalid;
|
||||
}
|
||||
|
||||
CMakeToolManager::notifyAboutUpdate(this);
|
||||
}
|
||||
|
||||
void CMakeTool::finished(int exitCode)
|
||||
{
|
||||
if (exitCode) {
|
||||
m_state = CMakeTool::Invalid;
|
||||
return;
|
||||
}
|
||||
if (m_state == CMakeTool::RunningBasic) {
|
||||
QByteArray response = m_process->readAll();
|
||||
|
||||
m_hasCodeBlocksMsvcGenerator = response.contains("CodeBlocks - NMake Makefiles");
|
||||
m_hasCodeBlocksNinjaGenerator = response.contains("CodeBlocks - Ninja");
|
||||
|
||||
if (response.isEmpty()) {
|
||||
m_state = CMakeTool::Invalid;
|
||||
} else {
|
||||
m_state = CMakeTool::RunningFunctionList;
|
||||
if (!startProcess(QStringList(QLatin1String("--help-command-list"))))
|
||||
finished(0); // should never happen, just continue
|
||||
}
|
||||
} else if (m_state == CMakeTool::RunningFunctionList) {
|
||||
parseFunctionOutput(m_process->readAll());
|
||||
m_state = CMakeTool::RunningFunctionDetails;
|
||||
if (!startProcess(QStringList(QLatin1String("--help-commands"))))
|
||||
finished(0); // should never happen, just continue
|
||||
} else if (m_state == CMakeTool::RunningFunctionDetails) {
|
||||
parseFunctionDetailsOutput(m_process->readAll());
|
||||
m_state = CMakeTool::RunningPropertyList;
|
||||
if (!startProcess(QStringList(QLatin1String("--help-property-list"))))
|
||||
finished(0); // should never happen, just continue
|
||||
} else if (m_state == CMakeTool::RunningPropertyList) {
|
||||
parseVariableOutput(m_process->readAll());
|
||||
m_state = CMakeTool::RunningVariableList;
|
||||
if (!startProcess(QStringList(QLatin1String("--help-variable-list"))))
|
||||
finished(0); // should never happen, just continue
|
||||
} else if (m_state == CMakeTool::RunningVariableList) {
|
||||
parseVariableOutput(m_process->readAll());
|
||||
parseDone();
|
||||
m_state = CMakeTool::RunningDone;
|
||||
}
|
||||
}
|
||||
|
||||
bool CMakeTool::isValid() const
|
||||
{
|
||||
if (m_state == CMakeTool::Invalid || !m_id.isValid())
|
||||
if (!m_id.isValid())
|
||||
return false;
|
||||
if (m_state == CMakeTool::RunningBasic) {
|
||||
if (!m_process->waitForFinished(10000)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return (m_state != CMakeTool::Invalid);
|
||||
|
||||
if (!m_didAttemptToRun)
|
||||
supportedGenerators();
|
||||
|
||||
return m_didRun;
|
||||
}
|
||||
|
||||
void CMakeTool::createId()
|
||||
Utils::SynchronousProcessResponse CMakeTool::run(const QString &arg) const
|
||||
{
|
||||
QTC_ASSERT(!m_id.isValid(), return);
|
||||
m_id = Core::Id::fromString(QUuid::createUuid().toString());
|
||||
if (m_didAttemptToRun && !m_didRun) {
|
||||
Utils::SynchronousProcessResponse response;
|
||||
response.result = Utils::SynchronousProcessResponse::StartFailed;
|
||||
return response;
|
||||
}
|
||||
|
||||
Utils::SynchronousProcess cmake;
|
||||
cmake.setTimeoutS(1);
|
||||
cmake.setFlags(Utils::SynchronousProcess::UnixTerminalDisabled);
|
||||
Utils::Environment env = Utils::Environment::systemEnvironment();
|
||||
env.set(QLatin1String("LC_ALL"), QLatin1String("C"));
|
||||
cmake.setProcessEnvironment(env.toProcessEnvironment());
|
||||
cmake.setTimeOutMessageBoxEnabled(false);
|
||||
|
||||
Utils::SynchronousProcessResponse response = cmake.run(m_executable.toString(), QStringList() << arg);
|
||||
m_didAttemptToRun = true;
|
||||
m_didRun = (response.result == Utils::SynchronousProcessResponse::Finished);
|
||||
return response;
|
||||
}
|
||||
|
||||
QVariantMap CMakeTool::toMap() const
|
||||
@@ -174,12 +125,6 @@ QVariantMap CMakeTool::toMap() const
|
||||
return data;
|
||||
}
|
||||
|
||||
bool CMakeTool::startProcess(const QStringList &args)
|
||||
{
|
||||
m_process->start(m_executable.toString(), args);
|
||||
return m_process->waitForStarted(2000);
|
||||
}
|
||||
|
||||
Utils::FileName CMakeTool::cmakeExecutable() const
|
||||
{
|
||||
return m_executable;
|
||||
@@ -189,24 +134,70 @@ bool CMakeTool::hasCodeBlocksMsvcGenerator() const
|
||||
{
|
||||
if (!isValid())
|
||||
return false;
|
||||
return m_hasCodeBlocksMsvcGenerator;
|
||||
return supportedGenerators().contains(QLatin1String("CodeBlocks - NMake Makefiles"));
|
||||
}
|
||||
|
||||
bool CMakeTool::hasCodeBlocksNinjaGenerator() const
|
||||
{
|
||||
if (!isValid())
|
||||
return false;
|
||||
return m_hasCodeBlocksNinjaGenerator;
|
||||
return supportedGenerators().contains(QLatin1String("CodeBlocks - Ninja"));
|
||||
}
|
||||
|
||||
QStringList CMakeTool::supportedGenerators() const
|
||||
{
|
||||
if (m_generators.isEmpty()) {
|
||||
Utils::SynchronousProcessResponse response = run(QLatin1String("--help"));
|
||||
if (response.result == Utils::SynchronousProcessResponse::Finished) {
|
||||
bool inGeneratorSection = false;
|
||||
const QStringList lines = response.stdOut.split(QLatin1Char('\n'));
|
||||
foreach (const QString &line, lines) {
|
||||
if (line.isEmpty())
|
||||
continue;
|
||||
if (line == QLatin1String("Generators"))
|
||||
inGeneratorSection = true;
|
||||
if (!inGeneratorSection)
|
||||
continue;
|
||||
|
||||
if (line.startsWith(QLatin1String(" "))) {
|
||||
int pos = line.indexOf(QLatin1Char('='));
|
||||
if (pos < 0)
|
||||
pos = line.length();
|
||||
if (pos >= 0) {
|
||||
--pos;
|
||||
while (pos > 2 && line.at(pos).isSpace())
|
||||
--pos;
|
||||
}
|
||||
if (pos > 2)
|
||||
m_generators.append(line.mid(2, pos - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return m_generators;
|
||||
}
|
||||
|
||||
TextEditor::Keywords CMakeTool::keywords()
|
||||
{
|
||||
while (m_state != RunningDone && m_state != CMakeTool::Invalid) {
|
||||
m_process->waitForFinished();
|
||||
}
|
||||
if (m_functions.isEmpty()) {
|
||||
Utils::SynchronousProcessResponse response;
|
||||
response = run(QLatin1String("--help-command-list"));
|
||||
if (response.result == Utils::SynchronousProcessResponse::Finished)
|
||||
m_functions = response.stdOut.split(QLatin1Char('\n'));
|
||||
|
||||
if (m_state == CMakeTool::Invalid)
|
||||
return TextEditor::Keywords(QStringList(), QStringList(), QMap<QString, QStringList>());
|
||||
response = run(QLatin1String("--help-commands"));
|
||||
if (response.result == Utils::SynchronousProcessResponse::Finished)
|
||||
parseFunctionDetailsOutput(response.stdOut);
|
||||
|
||||
response = run(QLatin1String("--help-property-list"));
|
||||
if (response.result == Utils::SynchronousProcessResponse::Finished)
|
||||
m_variables = parseVariableOutput(response.stdOut);
|
||||
|
||||
response = run(QLatin1String("--help-variable-list"));
|
||||
if (response.result == Utils::SynchronousProcessResponse::Finished) {
|
||||
m_variables.append(parseVariableOutput(response.stdOut));
|
||||
m_variables = Utils::filteredUnique(m_variables);
|
||||
Utils::sort(m_variables);
|
||||
}
|
||||
}
|
||||
|
||||
return TextEditor::Keywords(m_variables, m_functions, m_functionArgs);
|
||||
}
|
||||
@@ -216,53 +207,6 @@ bool CMakeTool::isAutoDetected() const
|
||||
return m_isAutoDetected;
|
||||
}
|
||||
|
||||
static void extractKeywords(const QByteArray &input, QStringList *destination)
|
||||
{
|
||||
if (!destination)
|
||||
return;
|
||||
|
||||
QString keyword;
|
||||
int ignoreZone = 0;
|
||||
for (int i = 0; i < input.count(); ++i) {
|
||||
const QChar chr = QLatin1Char(input.at(i));
|
||||
if (chr == QLatin1Char('{'))
|
||||
++ignoreZone;
|
||||
if (chr == QLatin1Char('}'))
|
||||
--ignoreZone;
|
||||
if (ignoreZone == 0) {
|
||||
if ((chr.isLetterOrNumber() && chr.isUpper())
|
||||
|| chr == QLatin1Char('_')) {
|
||||
keyword += chr;
|
||||
} else {
|
||||
if (!keyword.isEmpty()) {
|
||||
if (keyword.size() > 1)
|
||||
*destination << keyword;
|
||||
keyword.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (keyword.size() > 1)
|
||||
*destination << keyword;
|
||||
}
|
||||
|
||||
void CMakeTool::parseFunctionOutput(const QByteArray &output)
|
||||
{
|
||||
QList<QByteArray> cmakeFunctionsList = output.split('\n');
|
||||
m_functions.clear();
|
||||
if (!cmakeFunctionsList.isEmpty()) {
|
||||
cmakeFunctionsList.removeFirst(); //remove version string
|
||||
foreach (const QByteArray &function, cmakeFunctionsList)
|
||||
m_functions << QString::fromLocal8Bit(function.trimmed());
|
||||
}
|
||||
}
|
||||
|
||||
QString CMakeTool::formatFunctionDetails(const QString &command, const QString &args)
|
||||
{
|
||||
return QString::fromLatin1("<table><tr><td><b>%1</b></td><td>%2</td></tr>")
|
||||
.arg(command.toHtmlEscaped(), args.toHtmlEscaped());
|
||||
}
|
||||
|
||||
QString CMakeTool::displayName() const
|
||||
{
|
||||
return m_displayName;
|
||||
@@ -286,78 +230,91 @@ QString CMakeTool::mapAllPaths(ProjectExplorer::Kit *kit, const QString &in) con
|
||||
return in;
|
||||
}
|
||||
|
||||
void CMakeTool::parseFunctionDetailsOutput(const QByteArray &output)
|
||||
static QStringList parseDefinition(const QString &definition)
|
||||
{
|
||||
QStringList cmakeFunctionsList = m_functions;
|
||||
QList<QByteArray> cmakeCommandsHelp = output.split('\n');
|
||||
for (int i = 0; i < cmakeCommandsHelp.count(); ++i) {
|
||||
QByteArray lineTrimmed = cmakeCommandsHelp.at(i).trimmed();
|
||||
if (cmakeFunctionsList.isEmpty())
|
||||
break;
|
||||
if (cmakeFunctionsList.first().toLatin1() == lineTrimmed) {
|
||||
QStringList commandSyntaxes;
|
||||
QString currentCommandSyntax;
|
||||
QString currentCommand = cmakeFunctionsList.takeFirst();
|
||||
++i;
|
||||
for (; i < cmakeCommandsHelp.count(); ++i) {
|
||||
lineTrimmed = cmakeCommandsHelp.at(i).trimmed();
|
||||
QStringList result;
|
||||
QString word;
|
||||
bool ignoreWord = false;
|
||||
QVector<QChar> braceStack;
|
||||
|
||||
if (!cmakeFunctionsList.isEmpty() && cmakeFunctionsList.first().toLatin1() == lineTrimmed) {
|
||||
//start of next function in output
|
||||
if (!currentCommandSyntax.isEmpty())
|
||||
commandSyntaxes << currentCommandSyntax.append(QLatin1String("</table>"));
|
||||
--i;
|
||||
break;
|
||||
}
|
||||
if (lineTrimmed.startsWith(currentCommand.toLatin1() + "(")) {
|
||||
if (!currentCommandSyntax.isEmpty())
|
||||
commandSyntaxes << currentCommandSyntax.append(QLatin1String("</table>"));
|
||||
foreach (const QChar &c, definition) {
|
||||
if (c == QLatin1Char('[') || c == QLatin1Char('<') || c == QLatin1Char('(')) {
|
||||
braceStack.append(c);
|
||||
ignoreWord = false;
|
||||
} else if (c == QLatin1Char(']') || c == QLatin1Char('>') || c == QLatin1Char(')')) {
|
||||
if (braceStack.isEmpty() || braceStack.takeLast() == QLatin1Char('<'))
|
||||
ignoreWord = true;
|
||||
}
|
||||
|
||||
QByteArray argLine = lineTrimmed.mid(currentCommand.length());
|
||||
extractKeywords(argLine, &m_variables);
|
||||
currentCommandSyntax = formatFunctionDetails(currentCommand, QString::fromUtf8(argLine));
|
||||
} else {
|
||||
if (!currentCommandSyntax.isEmpty()) {
|
||||
if (lineTrimmed.isEmpty()) {
|
||||
commandSyntaxes << currentCommandSyntax.append(QLatin1String("</table>"));
|
||||
currentCommandSyntax.clear();
|
||||
} else {
|
||||
extractKeywords(lineTrimmed, &m_variables);
|
||||
currentCommandSyntax += QString::fromLatin1("<tr><td> </td><td>%1</td></tr>")
|
||||
.arg(QString::fromLocal8Bit(lineTrimmed).toHtmlEscaped());
|
||||
}
|
||||
if (c == QLatin1Char(' ') || c == QLatin1Char('[') || c == QLatin1Char('<') || c == QLatin1Char('(')
|
||||
|| c == QLatin1Char(']') || c == QLatin1Char('>') || c == QLatin1Char(')')) {
|
||||
if (!ignoreWord && !word.isEmpty()) {
|
||||
if (result.isEmpty() || Utils::allOf(word, [](const QChar &c) { return c.isUpper() || c == QLatin1Char('_'); }))
|
||||
result.append(word);
|
||||
}
|
||||
word.clear();
|
||||
ignoreWord = false;
|
||||
} else {
|
||||
word.append(c);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void CMakeTool::parseFunctionDetailsOutput(const QString &output)
|
||||
{
|
||||
QSet<QString> functionSet;
|
||||
functionSet.fromList(m_functions);
|
||||
|
||||
bool expectDefinition = false;
|
||||
QString currentDefinition;
|
||||
|
||||
const QStringList lines = output.split(QLatin1Char('\n'));
|
||||
for (int i = 0; i < lines.count(); ++i) {
|
||||
const QString line = lines.at(i);
|
||||
|
||||
if (line == QLatin1String("::")) {
|
||||
expectDefinition = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (expectDefinition) {
|
||||
if (!line.startsWith(QLatin1Char(' ')) && !line.isEmpty()) {
|
||||
expectDefinition = false;
|
||||
QStringList words = parseDefinition(currentDefinition);
|
||||
if (!words.isEmpty()) {
|
||||
const QString command = words.takeFirst();
|
||||
if (functionSet.contains(command)) {
|
||||
QStringList tmp = words + m_functionArgs[command];
|
||||
Utils::sort(tmp);
|
||||
m_functionArgs[command] = Utils::filteredUnique(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_functionArgs[currentCommand] = commandSyntaxes;
|
||||
}
|
||||
}
|
||||
m_functions = m_functionArgs.keys();
|
||||
}
|
||||
|
||||
void CMakeTool::parseVariableOutput(const QByteArray &output)
|
||||
{
|
||||
QList<QByteArray> variableList = output.split('\n');
|
||||
if (!variableList.isEmpty()) {
|
||||
variableList.removeFirst(); //remove version string
|
||||
foreach (const QByteArray &variable, variableList) {
|
||||
if (variable.contains("_<CONFIG>")) {
|
||||
m_variables << QString::fromLocal8Bit(variable).replace(QLatin1String("_<CONFIG>"), QLatin1String("_DEBUG"));
|
||||
m_variables << QString::fromLocal8Bit(variable).replace(QLatin1String("_<CONFIG>"), QLatin1String("_RELEASE"));
|
||||
m_variables << QString::fromLocal8Bit(variable).replace(QLatin1String("_<CONFIG>"), QLatin1String("_MINSIZEREL"));
|
||||
m_variables << QString::fromLocal8Bit(variable).replace(QLatin1String("_<CONFIG>"), QLatin1String("_RELWITHDEBINFO"));
|
||||
} else if (variable.contains("_<LANG>")) {
|
||||
m_variables << QString::fromLocal8Bit(variable).replace(QLatin1String("_<LANG>"), QLatin1String("_C"));
|
||||
m_variables << QString::fromLocal8Bit(variable).replace(QLatin1String("_<LANG>"), QLatin1String("_CXX"));
|
||||
} else if (!variable.contains("_<") && !variable.contains('[')) {
|
||||
m_variables << QString::fromLocal8Bit(variable);
|
||||
if (!words.isEmpty() && functionSet.contains(words.at(0)))
|
||||
m_functionArgs[words.at(0)];
|
||||
currentDefinition.clear();
|
||||
} else {
|
||||
currentDefinition.append(line.trimmed() + QLatin1Char(' '));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CMakeTool::parseDone()
|
||||
QStringList CMakeTool::parseVariableOutput(const QString &output)
|
||||
{
|
||||
m_variables.sort();
|
||||
m_variables.removeDuplicates();
|
||||
const QStringList variableList = output.split(QLatin1Char('\n'));
|
||||
QStringList result;
|
||||
foreach (const QString &v, variableList) {
|
||||
if (v.contains(QLatin1String("<CONFIG>"))) {
|
||||
const QString tmp = QString(v).replace(QLatin1String("<CONFIG>"), QLatin1String("%1"));
|
||||
result << tmp.arg(QLatin1String("DEBUG")) << tmp.arg(QLatin1String("RELEASE"))
|
||||
<< tmp.arg(QLatin1String("MINSIZEREL")) << tmp.arg(QLatin1String("RELWITHDEBINFO"));
|
||||
} else if (v.contains(QLatin1String("<LANG>"))) {
|
||||
const QString tmp = QString(v).replace(QLatin1String("<LANG>"), QLatin1String("%1"));
|
||||
result << tmp.arg(QLatin1String("C")) << tmp.arg(QLatin1String("CXX"));
|
||||
} else if (!v.contains(QLatin1Char('<')) && !v.contains(QLatin1Char('['))) {
|
||||
result << v;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@@ -27,12 +27,14 @@
|
||||
|
||||
#include "cmake_global.h"
|
||||
|
||||
#include <texteditor/codeassist/keywordscompletionassist.h>
|
||||
#include <utils/fileutils.h>
|
||||
#include <coreplugin/id.h>
|
||||
#include <texteditor/codeassist/keywordscompletionassist.h>
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/synchronousprocess.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QMap>
|
||||
#include <QStringList>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QProcess)
|
||||
@@ -52,23 +54,25 @@ public:
|
||||
|
||||
typedef std::function<QString (ProjectExplorer::Kit *, const QString &)> PathMapper;
|
||||
|
||||
explicit CMakeTool(Detection d, const Core::Id &id = Core::Id());
|
||||
explicit CMakeTool(Detection d, const Core::Id &id);
|
||||
explicit CMakeTool(const QVariantMap &map, bool fromSdk);
|
||||
~CMakeTool() override;
|
||||
~CMakeTool() override = default;
|
||||
|
||||
static Core::Id createId();
|
||||
|
||||
enum State { Invalid, RunningBasic, RunningFunctionList, RunningFunctionDetails,
|
||||
RunningPropertyList, RunningVariableList, RunningDone };
|
||||
void cancel();
|
||||
bool isValid() const;
|
||||
|
||||
Core::Id id() const { return m_id; }
|
||||
QVariantMap toMap () const;
|
||||
|
||||
void setCMakeExecutable(const Utils::FileName &executable);
|
||||
|
||||
Utils::FileName cmakeExecutable() const;
|
||||
bool hasCodeBlocksMsvcGenerator() const;
|
||||
bool hasCodeBlocksNinjaGenerator() const;
|
||||
QStringList supportedGenerators() const;
|
||||
TextEditor::Keywords keywords();
|
||||
|
||||
bool isAutoDetected() const;
|
||||
QString displayName() const;
|
||||
void setDisplayName(const QString &displayName);
|
||||
@@ -77,32 +81,24 @@ public:
|
||||
QString mapAllPaths(ProjectExplorer::Kit *kit, const QString &in) const;
|
||||
|
||||
private:
|
||||
void finished(int exitCode);
|
||||
|
||||
void createId();
|
||||
void finishStep();
|
||||
void startNextStep();
|
||||
bool startProcess(const QStringList &args);
|
||||
void parseFunctionOutput(const QByteArray &output);
|
||||
void parseFunctionDetailsOutput(const QByteArray &output);
|
||||
void parseVariableOutput(const QByteArray &output);
|
||||
void parseDone();
|
||||
QString formatFunctionDetails(const QString &command, const QString &args);
|
||||
|
||||
State m_state = Invalid;
|
||||
QProcess *m_process = 0;
|
||||
Utils::FileName m_executable;
|
||||
|
||||
bool m_isAutoDetected;
|
||||
bool m_hasCodeBlocksMsvcGenerator = false;
|
||||
bool m_hasCodeBlocksNinjaGenerator = false;
|
||||
|
||||
QMap<QString, QStringList> m_functionArgs;
|
||||
QStringList m_variables;
|
||||
QStringList m_functions;
|
||||
Utils::SynchronousProcessResponse run(const QString &arg) const;
|
||||
void parseFunctionDetailsOutput(const QString &output);
|
||||
QStringList parseVariableOutput(const QString &output);
|
||||
|
||||
Core::Id m_id;
|
||||
QString m_displayName;
|
||||
Utils::FileName m_executable;
|
||||
|
||||
bool m_isAutoDetected;
|
||||
|
||||
mutable bool m_didAttemptToRun;
|
||||
mutable bool m_didRun;
|
||||
|
||||
mutable QStringList m_generators;
|
||||
mutable QMap<QString, QStringList> m_functionArgs;
|
||||
mutable QStringList m_variables;
|
||||
mutable QStringList m_functions;
|
||||
|
||||
PathMapper m_pathMapper;
|
||||
};
|
||||
|
||||
|
@@ -131,7 +131,7 @@ static void readAndDeleteLegacyCMakeSettings ()
|
||||
if (exec.toFileInfo().isExecutable()) {
|
||||
CMakeTool *item = CMakeToolManager::findByCommand(exec);
|
||||
if (!item) {
|
||||
item = new CMakeTool(CMakeTool::ManualDetection);
|
||||
item = new CMakeTool(CMakeTool::ManualDetection, CMakeTool::createId());
|
||||
item->setCMakeExecutable(exec);
|
||||
item->setDisplayName(CMakeToolManager::tr("CMake at %1").arg(item->cmakeExecutable().toUserOutput()));
|
||||
|
||||
@@ -182,7 +182,7 @@ static QList<CMakeTool *> autoDetectCMakeTools()
|
||||
|
||||
QList<CMakeTool *> found;
|
||||
foreach (const FileName &command, suspects) {
|
||||
auto item = new CMakeTool(CMakeTool::AutoDetection);
|
||||
auto item = new CMakeTool(CMakeTool::AutoDetection, CMakeTool::createId());
|
||||
item->setCMakeExecutable(command);
|
||||
item->setDisplayName(CMakeToolManager::tr("System CMake at %1").arg(command.toUserOutput()));
|
||||
|
||||
@@ -247,7 +247,7 @@ Id CMakeToolManager::registerOrFindCMakeTool(const FileName &command)
|
||||
if (cmake)
|
||||
return cmake->id();
|
||||
|
||||
cmake = new CMakeTool(CMakeTool::ManualDetection);
|
||||
cmake = new CMakeTool(CMakeTool::ManualDetection, CMakeTool::createId());
|
||||
cmake->setCMakeExecutable(command);
|
||||
cmake->setDisplayName(tr("CMake at %1").arg(command.toUserOutput()));
|
||||
|
||||
|
Reference in New Issue
Block a user