summaryrefslogtreecommitdiff
path: root/src/plugins/clangcodemodel
diff options
context:
space:
mode:
authorhjk <hjk@qt.io>2017-02-24 16:09:39 +0100
committerTobias Hunger <tobias.hunger@qt.io>2017-02-24 16:49:18 +0000
commit3e225628ee6967d224fcdcc30e42015c9be74862 (patch)
tree09a681abe98f5fa683196af31923e5c17182e256 /src/plugins/clangcodemodel
parent92d818f327b43c50411f4ffffca30700d82024a0 (diff)
downloadqt-creator-3e225628ee6967d224fcdcc30e42015c9be74862.tar.gz
Revert "Clang: Add possibility to "pgo-train" libclang with a batch file"
This reverts commit 07f4ae622770cc99782edc8bf14d2a385bf17778, which broke compilation clangbatchfileprocessor.cpp:170:27: error: ambiguous overload for 'operator==' (operand types are 'const QChar' and 'char') and only worked in QT_TEST=1 cases. Change-Id: I089427359958221882cb4e4369c4b88d71779acf Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
Diffstat (limited to 'src/plugins/clangcodemodel')
-rw-r--r--src/plugins/clangcodemodel/clangautomationutils.cpp140
-rw-r--r--src/plugins/clangcodemodel/clangautomationutils.h46
-rw-r--r--src/plugins/clangcodemodel/clangbatchfileprocessor.cpp799
-rw-r--r--src/plugins/clangcodemodel/clangbatchfileprocessor.h36
-rw-r--r--src/plugins/clangcodemodel/clangcodemodel.pro4
-rw-r--r--src/plugins/clangcodemodel/clangcodemodel.qbs4
-rw-r--r--src/plugins/clangcodemodel/clangcodemodelplugin.cpp20
-rw-r--r--src/plugins/clangcodemodel/clangcodemodelplugin.h3
-rw-r--r--src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp99
9 files changed, 99 insertions, 1052 deletions
diff --git a/src/plugins/clangcodemodel/clangautomationutils.cpp b/src/plugins/clangcodemodel/clangautomationutils.cpp
deleted file mode 100644
index 29dc1c7155..0000000000
--- a/src/plugins/clangcodemodel/clangautomationutils.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangautomationutils.h"
-
-#include "clangcompletionassistinterface.h"
-#include "clangcompletionassistprovider.h"
-
-#include <texteditor/codeassist/assistinterface.h>
-#include <texteditor/codeassist/assistproposalitem.h>
-#include <texteditor/codeassist/completionassistprovider.h>
-#include <texteditor/codeassist/genericproposalmodel.h>
-#include <texteditor/codeassist/iassistprocessor.h>
-#include <texteditor/codeassist/iassistproposal.h>
-#include <texteditor/textdocument.h>
-#include <texteditor/texteditor.h>
-
-#include <utils/qtcassert.h>
-
-#include <QCoreApplication>
-#include <QElapsedTimer>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-class WaitForAsyncCompletions
-{
-public:
- enum WaitResult { GotResults, GotInvalidResults, Timeout };
-
- WaitResult wait(TextEditor::IAssistProcessor *processor,
- TextEditor::AssistInterface *assistInterface,
- int timeoutInMs)
- {
- QTC_ASSERT(processor, return Timeout);
- QTC_ASSERT(assistInterface, return Timeout);
-
- bool gotResults = false;
-
- processor->setAsyncCompletionAvailableHandler(
- [this, &gotResults] (TextEditor::IAssistProposal *proposal) {
- QTC_ASSERT(proposal, return);
- proposalModel = proposal->model();
- delete proposal;
- gotResults = true;
- });
-
- // Are there any immediate results?
- if (TextEditor::IAssistProposal *proposal = processor->perform(assistInterface)) {
- delete processor;
- proposalModel = proposal->model();
- delete proposal;
- QTC_ASSERT(proposalModel, return GotInvalidResults);
- return GotResults;
- }
-
- // There are not any, so wait for async results.
- QElapsedTimer timer;
- timer.start();
- while (!gotResults) {
- if (timer.elapsed() >= timeoutInMs)
- return Timeout;
- QCoreApplication::processEvents();
- }
-
- return proposalModel ? GotResults : GotInvalidResults;
- }
-
-public:
- TextEditor::IAssistProposalModel *proposalModel;
-};
-
-static const CppTools::ProjectPartHeaderPaths toHeaderPaths(const QStringList &paths)
-{
- using namespace CppTools;
-
- ProjectPartHeaderPaths result;
- foreach (const QString &path, paths)
- result << ProjectPartHeaderPath(path, ProjectPartHeaderPath::IncludePath);
- return result;
-}
-
-ProposalModel completionResults(TextEditor::BaseTextEditor *textEditor,
- const QStringList &includePaths,
- int timeOutInMs)
-{
- using namespace TextEditor;
-
- TextEditorWidget *textEditorWidget = qobject_cast<TextEditorWidget *>(textEditor->widget());
- QTC_ASSERT(textEditorWidget, return ProposalModel());
- AssistInterface *assistInterface = textEditorWidget->createAssistInterface(
- TextEditor::Completion, TextEditor::ExplicitlyInvoked);
- QTC_ASSERT(assistInterface, return ProposalModel());
- if (!includePaths.isEmpty()) {
- auto clangAssistInterface = static_cast<ClangCompletionAssistInterface *>(assistInterface);
- clangAssistInterface->setHeaderPaths(toHeaderPaths(includePaths));
- }
-
- CompletionAssistProvider *assistProvider
- = textEditor->textDocument()->completionAssistProvider();
- QTC_ASSERT(qobject_cast<ClangCompletionAssistProvider *>(assistProvider),
- return ProposalModel());
- QTC_ASSERT(assistProvider, return ProposalModel());
- QTC_ASSERT(assistProvider->runType() == IAssistProvider::Asynchronous, return ProposalModel());
-
- IAssistProcessor *processor = assistProvider->createProcessor();
- QTC_ASSERT(processor, return ProposalModel());
-
- WaitForAsyncCompletions waitForCompletions;
- const WaitForAsyncCompletions::WaitResult result = waitForCompletions.wait(processor,
- assistInterface,
- timeOutInMs);
- QTC_ASSERT(result == WaitForAsyncCompletions::GotResults, return ProposalModel());
- return QSharedPointer<TextEditor::IAssistProposalModel>(waitForCompletions.proposalModel);
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangautomationutils.h b/src/plugins/clangcodemodel/clangautomationutils.h
deleted file mode 100644
index 9942a597fd..0000000000
--- a/src/plugins/clangcodemodel/clangautomationutils.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QString>
-#include <QSharedPointer>
-
-namespace TextEditor {
-class BaseTextEditor;
-class IAssistProposalModel;
-}
-
-namespace ClangCodeModel {
-namespace Internal {
-
-using ProposalModel = QSharedPointer<TextEditor::IAssistProposalModel>;
-
-ProposalModel completionResults(TextEditor::BaseTextEditor *textEditor,
- const QStringList &includePaths = QStringList(),
- int timeOutInMs = 10000);
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangbatchfileprocessor.cpp b/src/plugins/clangcodemodel/clangbatchfileprocessor.cpp
deleted file mode 100644
index 1e6557d36d..0000000000
--- a/src/plugins/clangcodemodel/clangbatchfileprocessor.cpp
+++ /dev/null
@@ -1,799 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangbatchfileprocessor.h"
-
-#include "clangautomationutils.h"
-
-#include <clangcodemodel/clangeditordocumentprocessor.h>
-
-#include <coreplugin/editormanager/editormanager.h>
-#include <coreplugin/editormanager/ieditor.h>
-#include <coreplugin/icore.h>
-#include <cpptools/cpptoolsreuse.h>
-#include <cpptools/cpptoolstestcase.h>
-#include <cpptools/modelmanagertesthelper.h>
-#include <cpptools/projectinfo.h>
-#include <projectexplorer/projectexplorer.h>
-#include <texteditor/codeassist/assistinterface.h>
-#include <texteditor/codeassist/assistproposalitem.h>
-#include <texteditor/codeassist/completionassistprovider.h>
-#include <texteditor/codeassist/genericproposalmodel.h>
-#include <texteditor/codeassist/iassistprocessor.h>
-#include <texteditor/codeassist/iassistproposal.h>
-#include <texteditor/textdocument.h>
-#include <texteditor/texteditor.h>
-
-#include <utils/executeondestruction.h>
-#include <utils/qtcassert.h>
-
-#include <QDebug>
-#include <QFileInfo>
-#include <QLoggingCategory>
-#include <QSharedPointer>
-#include <QString>
-#include <QtTest>
-
-using namespace ClangBackEnd;
-using namespace ClangCodeModel;
-using namespace ClangCodeModel::Internal;
-using namespace ProjectExplorer;
-
-static Q_LOGGING_CATEGORY(debug, "qtc.clangcodemodel.batch");
-
-static int timeOutFromEnvironmentVariable()
-{
- const QByteArray timeoutAsByteArray = qgetenv("QTC_CLANG_BATCH_TIMEOUT");
-
- bool isConversionOk = false;
- const int intervalAsInt = timeoutAsByteArray.toInt(&isConversionOk);
- if (!isConversionOk) {
- qCDebug(debug, "Environment variable QTC_CLANG_BATCH_TIMEOUT is not set, assuming 30000.");
- return 30000;
- }
-
- return intervalAsInt;
-}
-
-static int timeOutInMs()
-{
- static int timeOut = timeOutFromEnvironmentVariable();
- return timeOut;
-}
-
-namespace {
-
-class BatchFileLineTokenizer
-{
-public:
- BatchFileLineTokenizer(const QString &line);
-
- QString nextToken();
-
-private:
- const QChar *advanceToTokenBegin();
- const QChar *advanceToTokenEnd();
-
- bool atEnd() const;
- bool atWhiteSpace() const;
- bool atQuotationMark() const;
-
-private:
- bool m_isWithinQuotation = false;
- QString m_line;
- const QChar *m_currentChar;
-};
-
-BatchFileLineTokenizer::BatchFileLineTokenizer(const QString &line)
- : m_line(line)
- , m_currentChar(m_line.unicode())
-{
-}
-
-QString BatchFileLineTokenizer::nextToken()
-{
- if (const QChar *tokenBegin = advanceToTokenBegin()) {
- if (const QChar *tokenEnd = advanceToTokenEnd()) {
- const int length = tokenEnd - tokenBegin;
- return QString(tokenBegin, length);
- }
- }
-
- return QString();
-}
-
-const QChar *BatchFileLineTokenizer::advanceToTokenBegin()
-{
- m_isWithinQuotation = false;
-
- forever {
- if (atEnd())
- return 0;
-
- if (atQuotationMark()) {
- m_isWithinQuotation = true;
- ++m_currentChar;
- return m_currentChar;
- }
-
- if (!atWhiteSpace())
- return m_currentChar;
-
- ++m_currentChar;
- }
-}
-
-const QChar *BatchFileLineTokenizer::advanceToTokenEnd()
-{
- forever {
- if (m_isWithinQuotation) {
- if (atEnd()) {
- qWarning("ClangBatchFileProcessor: error: unfinished quotation.");
- return 0;
- }
-
- if (atQuotationMark())
- return m_currentChar++;
-
- } else if (atWhiteSpace() || atEnd()) {
- return m_currentChar;
- }
-
- ++m_currentChar;
- }
-}
-
-bool BatchFileLineTokenizer::atEnd() const
-{
- return *m_currentChar == '\0';
-}
-
-bool BatchFileLineTokenizer::atWhiteSpace() const
-{
- return *m_currentChar == ' '
- || *m_currentChar == '\t'
- || *m_currentChar == '\n';
-}
-
-bool BatchFileLineTokenizer::atQuotationMark() const
-{
- return *m_currentChar == '"';
-}
-
-struct CommandContext {
- QString filePath;
- int lineNumber = -1;
-};
-
-class Command
-{
-public:
- using Ptr = QSharedPointer<Command>;
-
-public:
- Command(const CommandContext &context) : m_commandContext(context) {}
- virtual ~Command() {}
-
- const CommandContext &context() const { return m_commandContext; }
- virtual bool run() { return true; }
-
-private:
- const CommandContext m_commandContext;
-};
-
-class OpenProjectCommand : public Command
-{
-public:
- OpenProjectCommand(const CommandContext &context,
- const QString &projectFilePath);
-
- bool run() override;
-
- static Command::Ptr parse(BatchFileLineTokenizer &arguments,
- const CommandContext &context);
-
-private:
- QString m_projectFilePath;
-};
-
-OpenProjectCommand::OpenProjectCommand(const CommandContext &context,
- const QString &projectFilePath)
- : Command(context)
- , m_projectFilePath(projectFilePath)
-{
-}
-
-bool OpenProjectCommand::run()
-{
- qCDebug(debug) << "line" << context().lineNumber << "OpenProjectCommand" << m_projectFilePath;
-
- const ProjectExplorerPlugin::OpenProjectResult openProjectSucceeded
- = ProjectExplorerPlugin::openProject(m_projectFilePath);
- QTC_ASSERT(openProjectSucceeded, return false);
-
- Project *project = openProjectSucceeded.project();
- project->configureAsExampleProject({});
-
- return CppTools::Tests::TestCase::waitUntilCppModelManagerIsAwareOf(project, timeOutInMs());
-}
-
-Command::Ptr OpenProjectCommand::parse(BatchFileLineTokenizer &arguments,
- const CommandContext &context)
-{
- const QString projectFilePath = arguments.nextToken();
- if (projectFilePath.isEmpty()) {
- qWarning("%s:%d: error: No project file path given.",
- qPrintable(context.filePath),
- context.lineNumber);
- return Command::Ptr();
- }
-
- const QString absoluteProjectFilePath = QFileInfo(projectFilePath).absoluteFilePath();
-
- return Command::Ptr(new OpenProjectCommand(context, absoluteProjectFilePath));
-}
-
-class OpenDocumentCommand : public Command
-{
-public:
- OpenDocumentCommand(const CommandContext &context,
- const QString &documentFilePath);
-
- bool run() override;
-
- static Command::Ptr parse(BatchFileLineTokenizer &arguments, const CommandContext &context);
-
-private:
- QString m_documentFilePath;
-};
-
-OpenDocumentCommand::OpenDocumentCommand(const CommandContext &context,
- const QString &documentFilePath)
- : Command(context)
- , m_documentFilePath(documentFilePath)
-{
-}
-
-class WaitForUpdatedCodeWarnings : public QObject
-{
- Q_OBJECT
-
-public:
- WaitForUpdatedCodeWarnings(ClangEditorDocumentProcessor *processor);
-
- bool wait(int timeOutInMs) const;
-
-private:
- void onCodeWarningsUpdated() { m_gotResults = true; }
-
-private:
-
- bool m_gotResults = false;
-};
-
-WaitForUpdatedCodeWarnings::WaitForUpdatedCodeWarnings(ClangEditorDocumentProcessor *processor)
-{
- connect(processor,
- &ClangEditorDocumentProcessor::codeWarningsUpdated,
- this, &WaitForUpdatedCodeWarnings::onCodeWarningsUpdated);
-}
-
-bool WaitForUpdatedCodeWarnings::wait(int timeOutInMs) const
-{
- QTime time;
- time.start();
-
- forever {
- if (time.elapsed() > timeOutInMs) {
- qWarning("WaitForUpdatedCodeWarnings: timeout of %d ms reached.", timeOutInMs);
- return false;
- }
-
- if (m_gotResults)
- return true;
-
- QCoreApplication::processEvents();
- QThread::msleep(20);
- }
-}
-
-bool OpenDocumentCommand::run()
-{
- qCDebug(debug) << "line" << context().lineNumber << "OpenDocumentCommand" << m_documentFilePath;
-
- const bool openEditorSucceeded = Core::EditorManager::openEditor(m_documentFilePath);
- QTC_ASSERT(openEditorSucceeded, return false);
-
- auto *processor = ClangEditorDocumentProcessor::get(m_documentFilePath);
- QTC_ASSERT(processor, return false);
-
- WaitForUpdatedCodeWarnings waiter(processor);
- return waiter.wait(timeOutInMs());
-}
-
-Command::Ptr OpenDocumentCommand::parse(BatchFileLineTokenizer &arguments,
- const CommandContext &context)
-{
- const QString documentFilePath = arguments.nextToken();
- if (documentFilePath.isEmpty()) {
- qWarning("%s:%d: error: No document file path given.",
- qPrintable(context.filePath),
- context.lineNumber);
- return Command::Ptr();
- }
-
- const QString absoluteDocumentFilePath = QFileInfo(documentFilePath).absoluteFilePath();
-
- return Command::Ptr(new OpenDocumentCommand(context, absoluteDocumentFilePath));
-}
-
-class CloseAllDocuments : public Command
-{
-public:
- CloseAllDocuments(const CommandContext &context);
-
- bool run() override;
-
- static Command::Ptr parse(BatchFileLineTokenizer &arguments, const CommandContext &context);
-};
-
-CloseAllDocuments::CloseAllDocuments(const CommandContext &context)
- : Command(context)
-{
-}
-
-bool CloseAllDocuments::run()
-{
- qCDebug(debug) << "line" << context().lineNumber << "CloseAllDocuments";
-
- return Core::EditorManager::closeAllEditors(/*askAboutModifiedEditors=*/ false);
-}
-
-Command::Ptr CloseAllDocuments::parse(BatchFileLineTokenizer &arguments,
- const CommandContext &context)
-{
- const QString argument = arguments.nextToken();
- if (!argument.isEmpty()) {
- qWarning("%s:%d: error: Unexpected argument.",
- qPrintable(context.filePath),
- context.lineNumber);
- return Command::Ptr();
- }
-
- return Command::Ptr(new CloseAllDocuments(context));
-}
-
-class InsertTextCommand : public Command
-{
-public:
- // line and column are 1-based
- InsertTextCommand(const CommandContext &context, const QString &text);
-
- bool run() override;
-
- static Command::Ptr parse(BatchFileLineTokenizer &arguments,
- const CommandContext &context);
-
-private:
- const QString m_textToInsert;
-};
-
-InsertTextCommand::InsertTextCommand(const CommandContext &context, const QString &text)
- : Command(context)
- , m_textToInsert(text)
-{
-}
-
-TextEditor::BaseTextEditor *currentTextEditor()
-{
- return qobject_cast<TextEditor::BaseTextEditor*>(Core::EditorManager::currentEditor());
-}
-
-bool InsertTextCommand::run()
-{
- qCDebug(debug) << "line" << context().lineNumber << "InsertTextCommand" << m_textToInsert;
-
- TextEditor::BaseTextEditor *editor = currentTextEditor();
- QTC_ASSERT(editor, return false);
- const QString documentFilePath = editor->document()->filePath().toString();
- auto *processor = ClangEditorDocumentProcessor::get(documentFilePath);
- QTC_ASSERT(processor, return false);
-
- editor->insert(m_textToInsert);
-
- WaitForUpdatedCodeWarnings waiter(processor);
- return waiter.wait(timeOutInMs());
-}
-
-Command::Ptr InsertTextCommand::parse(BatchFileLineTokenizer &arguments,
- const CommandContext &context)
-{
- const QString textToInsert = arguments.nextToken();
- if (textToInsert.isEmpty()) {
- qWarning("%s:%d: error: No text to insert given.",
- qPrintable(context.filePath),
- context.lineNumber);
- return Command::Ptr();
- }
-
- return Command::Ptr(new InsertTextCommand(context, textToInsert));
-}
-
-class CompleteCommand : public Command
-{
-public:
- CompleteCommand(const CommandContext &context);
-
- bool run() override;
-
- static Command::Ptr parse(BatchFileLineTokenizer &arguments,
- const CommandContext &context);
-};
-
-CompleteCommand::CompleteCommand(const CommandContext &context)
- : Command(context)
-{
-}
-
-bool CompleteCommand::run()
-{
- qCDebug(debug) << "line" << context().lineNumber << "CompleteCommand";
-
- TextEditor::BaseTextEditor *editor = currentTextEditor();
- QTC_ASSERT(editor, return false);
-
- const QString documentFilePath = editor->document()->filePath().toString();
- auto *processor = ClangEditorDocumentProcessor::get(documentFilePath);
- QTC_ASSERT(processor, return false);
-
- return completionResults(editor, QStringList(), timeOutInMs());
-}
-
-Command::Ptr CompleteCommand::parse(BatchFileLineTokenizer &arguments,
- const CommandContext &context)
-{
- Q_UNUSED(arguments)
- Q_UNUSED(context)
-
- return Command::Ptr(new CompleteCommand(context));
-}
-
-class SetCursorCommand : public Command
-{
-public:
- // line and column are 1-based
- SetCursorCommand(const CommandContext &context, int line, int column);
-
- bool run() override;
-
- static Command::Ptr parse(BatchFileLineTokenizer &arguments,
- const CommandContext &context);
-
-private:
- int m_line;
- int m_column;
-};
-
-SetCursorCommand::SetCursorCommand(const CommandContext &context, int line, int column)
- : Command(context)
- , m_line(line)
- , m_column(column)
-{
-}
-
-bool SetCursorCommand::run()
-{
- qCDebug(debug) << "line" << context().lineNumber << "SetCursorCommand" << m_line << m_column;
-
- TextEditor::BaseTextEditor *editor = currentTextEditor();
- QTC_ASSERT(editor, return false);
-
- editor->gotoLine(m_line, m_column - 1);
-
- return true;
-}
-
-Command::Ptr SetCursorCommand::parse(BatchFileLineTokenizer &arguments,
- const CommandContext &context)
-{
- // Process line
- const QString line = arguments.nextToken();
- if (line.isEmpty()) {
- qWarning("%s:%d: error: No line number given.",
- qPrintable(context.filePath),
- context.lineNumber);
- return Command::Ptr();
- }
- bool converted = false;
- const int lineNumber = line.toInt(&converted);
- if (!converted) {
- qWarning("%s:%d: error: Invalid line number.",
- qPrintable(context.filePath),
- context.lineNumber);
- return Command::Ptr();
- }
-
- // Process column
- const QString column = arguments.nextToken();
- if (column.isEmpty()) {
- qWarning("%s:%d: error: No column number given.",
- qPrintable(context.filePath),
- context.lineNumber);
- return Command::Ptr();
- }
- converted = false;
- const int columnNumber = column.toInt(&converted);
- if (!converted) {
- qWarning("%s:%d: error: Invalid column number.",
- qPrintable(context.filePath),
- context.lineNumber);
- return Command::Ptr();
- }
-
- return Command::Ptr(new SetCursorCommand(context, lineNumber, columnNumber));
-}
-
-class ProcessEventsCommand : public Command
-{
-public:
- ProcessEventsCommand(const CommandContext &context, int durationInMs);
-
- bool run() override;
-
- static Command::Ptr parse(BatchFileLineTokenizer &arguments,
- const CommandContext &context);
-
-private:
- int m_durationInMs;
-};
-
-ProcessEventsCommand::ProcessEventsCommand(const CommandContext &context,
- int durationInMs)
- : Command(context)
- , m_durationInMs(durationInMs)
-{
-}
-
-bool ProcessEventsCommand::run()
-{
- qCDebug(debug) << "line" << context().lineNumber << "ProcessEventsCommand" << m_durationInMs;
-
- QTime time;
- time.start();
-
- forever {
- if (time.elapsed() > m_durationInMs)
- return true;
-
- QCoreApplication::processEvents();
- QThread::msleep(20);
- }
-}
-
-Command::Ptr ProcessEventsCommand::parse(BatchFileLineTokenizer &arguments,
- const CommandContext &context)
-{
- const QString durationInMsText = arguments.nextToken();
- if (durationInMsText.isEmpty()) {
- qWarning("%s:%d: error: No duration given.",
- qPrintable(context.filePath),
- context.lineNumber);
- return Command::Ptr();
- }
-
- bool converted = false;
- const int durationInMs = durationInMsText.toInt(&converted);
- if (!converted) {
- qWarning("%s:%d: error: Invalid duration given.",
- qPrintable(context.filePath),
- context.lineNumber);
- return Command::Ptr();
- }
-
- return Command::Ptr(new ProcessEventsCommand(context, durationInMs));
-}
-
-class BatchFileReader
-{
-public:
- BatchFileReader(const QString &filePath);
-
- bool isFilePathValid() const;
-
- QString read() const;
-
-private:
- const QString m_batchFilePath;
-};
-
-BatchFileReader::BatchFileReader(const QString &filePath)
- : m_batchFilePath(filePath)
-{
-}
-
-bool BatchFileReader::isFilePathValid() const
-{
- QFileInfo fileInfo(m_batchFilePath);
-
- return !m_batchFilePath.isEmpty()
- && fileInfo.isFile()
- && fileInfo.isReadable();
-}
-
-QString BatchFileReader::read() const
-{
- QFile file(m_batchFilePath);
- QTC_CHECK(file.open(QFile::ReadOnly | QFile::Text));
-
- return QString::fromLocal8Bit(file.readAll());
-}
-
-class BatchFileParser
-{
-public:
- BatchFileParser(const QString &filePath,
- const QString &commands);
-
- bool parse();
- QVector<Command::Ptr> commands() const;
-
-private:
- bool advanceLine();
- QString currentLine() const;
- bool parseLine(const QString &line);
-
-private:
- using ParseFunction = Command::Ptr (*)(BatchFileLineTokenizer &, const CommandContext &);
- using CommandToParseFunction = QHash<QString, ParseFunction>;
- CommandToParseFunction m_commandParsers;
-
- int m_currentLineIndex = -1;
- CommandContext m_context;
- QStringList m_lines;
- QVector<Command::Ptr> m_commands;
-};
-
-BatchFileParser::BatchFileParser(const QString &filePath,
- const QString &commands)
- : m_lines(commands.split('\n'))
-{
- m_context.filePath = filePath;
-
- m_commandParsers.insert("openProject", &OpenProjectCommand::parse);
- m_commandParsers.insert("openDocument", &OpenDocumentCommand::parse);
- m_commandParsers.insert("closeAllDocuments", &CloseAllDocuments::parse);
- m_commandParsers.insert("setCursor", &SetCursorCommand::parse);
- m_commandParsers.insert("insertText", &InsertTextCommand::parse);
- m_commandParsers.insert("complete", &CompleteCommand::parse);
- m_commandParsers.insert("processEvents", &ProcessEventsCommand::parse);
-}
-
-bool BatchFileParser::parse()
-{
- while (advanceLine()) {
- const QString line = currentLine().trimmed();
- if (line.isEmpty() || line.startsWith('#'))
- continue;
-
- if (!parseLine(line))
- return false;
- }
-
- return true;
-}
-
-QVector<Command::Ptr> BatchFileParser::commands() const
-{
- return m_commands;
-}
-
-bool BatchFileParser::advanceLine()
-{
- ++m_currentLineIndex;
- m_context.lineNumber = m_currentLineIndex + 1;
- return m_currentLineIndex < m_lines.size();
-}
-
-QString BatchFileParser::currentLine() const
-{
- return m_lines[m_currentLineIndex];
-}
-
-bool BatchFileParser::parseLine(const QString &line)
-{
- BatchFileLineTokenizer tokenizer(line);
- QString command = tokenizer.nextToken();
- QTC_CHECK(!command.isEmpty());
-
- if (const ParseFunction parseFunction = m_commandParsers.value(command)) {
- if (Command::Ptr cmd = parseFunction(tokenizer, m_context)) {
- m_commands.append(cmd);
- return true;
- }
-
- return false;
- }
-
- qWarning("%s:%d: error: Unknown command \"%s\".",
- qPrintable(m_context.filePath),
- m_context.lineNumber,
- qPrintable(command));
-
- return false;
-}
-
-} // anonymous namespace
-
-namespace ClangCodeModel {
-namespace Internal {
-
-static QString applySubstitutions(const QString &filePath, const QString &text)
-{
- const QString dirPath = QFileInfo(filePath).absolutePath();
-
- QString result = text;
- result.replace("${PWD}", dirPath);
-
- return result;
-}
-
-bool runClangBatchFile(const QString &filePath)
-{
- qWarning("ClangBatchFileProcessor: Running \"%s\".", qPrintable(filePath));
-
- BatchFileReader reader(filePath);
- QTC_ASSERT(reader.isFilePathValid(), return false);
- const QString fileContent = reader.read();
- const QString fileContentWithSubstitutionsApplied = applySubstitutions(filePath, fileContent);
-
- BatchFileParser parser(filePath, fileContentWithSubstitutionsApplied);
- QTC_ASSERT(parser.parse(), return false);
- const QVector<Command::Ptr> commands = parser.commands();
-
- Utils::ExecuteOnDestruction closeAllEditors([](){
- qWarning("ClangBatchFileProcessor: Finished, closing all documents.");
- QTC_CHECK(Core::EditorManager::closeAllEditors(/*askAboutModifiedEditors=*/ false));
- });
-
- foreach (const Command::Ptr &command, commands) {
- const bool runSucceeded = command->run();
- QCoreApplication::processEvents(); // Update GUI
-
- if (!runSucceeded) {
- const CommandContext context = command->context();
- qWarning("%s:%d: Failed to run.",
- qPrintable(context.filePath),
- context.lineNumber);
- return false;
- }
- }
-
- return true;
-}
-
-} // namespace Internal
-} // namespace ClangCodeModel
-
-#include "clangbatchfileprocessor.moc"
diff --git a/src/plugins/clangcodemodel/clangbatchfileprocessor.h b/src/plugins/clangcodemodel/clangbatchfileprocessor.h
deleted file mode 100644
index 40f0bceee3..0000000000
--- a/src/plugins/clangcodemodel/clangbatchfileprocessor.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QString>
-
-namespace ClangCodeModel {
-namespace Internal {
-
-bool runClangBatchFile(const QString &filePath);
-
-} // namespace Internal
-} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangcodemodel.pro b/src/plugins/clangcodemodel/clangcodemodel.pro
index 3089483407..ef9302a1d1 100644
--- a/src/plugins/clangcodemodel/clangcodemodel.pro
+++ b/src/plugins/clangcodemodel/clangcodemodel.pro
@@ -9,9 +9,7 @@ SOURCES += \
clangassistproposal.cpp \
clangassistproposalitem.cpp \
clangassistproposalmodel.cpp \
- clangautomationutils.cpp \
clangbackendipcintegration.cpp \
- clangbatchfileprocessor.cpp \
clangcodemodelplugin.cpp \
clangcompletionassistinterface.cpp \
clangcompletionassistprocessor.cpp \
@@ -41,9 +39,7 @@ HEADERS += \
clangassistproposal.h \
clangassistproposalitem.h \
clangassistproposalmodel.h \
- clangautomationutils.h \
clangbackendipcintegration.h \
- clangbatchfileprocessor.h \
clangcodemodelplugin.h \
clangcompletionassistinterface.h \
clangcompletionassistprocessor.h \
diff --git a/src/plugins/clangcodemodel/clangcodemodel.qbs b/src/plugins/clangcodemodel/clangcodemodel.qbs
index 28e4dffcd8..02ff530760 100644
--- a/src/plugins/clangcodemodel/clangcodemodel.qbs
+++ b/src/plugins/clangcodemodel/clangcodemodel.qbs
@@ -41,12 +41,8 @@ QtcPlugin {
"clangassistproposalitem.h",
"clangassistproposalmodel.cpp",
"clangassistproposalmodel.h",
- "clangautomationutils.cpp",
- "clangautomationutils.h",
"clangbackendipcintegration.cpp",
"clangbackendipcintegration.h",
- "clangbatchfileprocessor.cpp",
- "clangbatchfileprocessor.h",
"clangcodemodel.qrc",
"clangcodemodelplugin.cpp",
"clangcodemodelplugin.h",
diff --git a/src/plugins/clangcodemodel/clangcodemodelplugin.cpp b/src/plugins/clangcodemodel/clangcodemodelplugin.cpp
index 0aa9cbff3f..ba1bc10376 100644
--- a/src/plugins/clangcodemodel/clangcodemodelplugin.cpp
+++ b/src/plugins/clangcodemodel/clangcodemodelplugin.cpp
@@ -25,7 +25,6 @@
#include "clangcodemodelplugin.h"
-#include "clangbatchfileprocessor.h"
#include "clangconstants.h"
#include "clangprojectsettingswidget.h"
@@ -75,13 +74,8 @@ void addProjectPanelWidget()
bool ClangCodeModelPlugin::initialize(const QStringList &arguments, QString *errorMessage)
{
- Q_UNUSED(arguments);
- Q_UNUSED(errorMessage);
-
- connect(ProjectExplorer::ProjectExplorerPlugin::instance(),
- &ProjectExplorer::ProjectExplorerPlugin::finishedInitialization,
- this,
- &ClangCodeModelPlugin::maybeHandleBatchFileAndExit);
+ Q_UNUSED(arguments)
+ Q_UNUSED(errorMessage)
CppTools::CppModelManager::instance()->activateClangCodeModel(&m_modelManagerSupportProvider);
@@ -95,16 +89,6 @@ void ClangCodeModelPlugin::extensionsInitialized()
{
}
-// For e.g. creation of profile-guided optimization builds.
-void ClangCodeModelPlugin::maybeHandleBatchFileAndExit() const
-{
- const QString batchFilePath = QString::fromLocal8Bit(qgetenv("QTC_CLANG_BATCH"));
- if (!batchFilePath.isEmpty() && QTC_GUARD(QFileInfo::exists(batchFilePath))) {
- const bool runSucceeded = runClangBatchFile(batchFilePath);
- QCoreApplication::exit(!runSucceeded);
- }
-}
-
#ifdef WITH_TESTS
QList<QObject *> ClangCodeModelPlugin::createTestObjects() const
{
diff --git a/src/plugins/clangcodemodel/clangcodemodelplugin.h b/src/plugins/clangcodemodel/clangcodemodelplugin.h
index 8e41fe6020..0b94c93c2c 100644
--- a/src/plugins/clangcodemodel/clangcodemodelplugin.h
+++ b/src/plugins/clangcodemodel/clangcodemodelplugin.h
@@ -42,9 +42,6 @@ public:
void extensionsInitialized();
private:
- void maybeHandleBatchFileAndExit() const;
-
-private:
ModelManagerSupportProviderClang m_modelManagerSupportProvider;
#ifdef WITH_TESTS
diff --git a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp
index f5072068f6..0f9793dc15 100644
--- a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp
+++ b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp
@@ -25,7 +25,6 @@
#include "clangcodecompletion_test.h"
-#include "../clangautomationutils.h"
#include "../clangbackendipcintegration.h"
#include "../clangcompletionassistinterface.h"
#include "../clangmodelmanagersupport.h"
@@ -39,8 +38,12 @@
#include <cpptools/cpptoolstestcase.h>
#include <cpptools/modelmanagertesthelper.h>
#include <cpptools/projectinfo.h>
+#include <texteditor/codeassist/assistinterface.h>
#include <texteditor/codeassist/assistproposalitem.h>
+#include <texteditor/codeassist/completionassistprovider.h>
#include <texteditor/codeassist/genericproposalmodel.h>
+#include <texteditor/codeassist/iassistprocessor.h>
+#include <texteditor/codeassist/iassistproposal.h>
#include <texteditor/textdocument.h>
#include <texteditor/texteditor.h>
@@ -177,6 +180,53 @@ void insertTextAtTopOfEditor(TextEditor::BaseTextEditor *editor, const QByteArra
cs.apply(&textCursor);
}
+class WaitForAsyncCompletions
+{
+public:
+ enum WaitResult { GotResults, GotInvalidResults, Timeout };
+ WaitResult wait(TextEditor::IAssistProcessor *processor,
+ TextEditor::AssistInterface *assistInterface);
+
+ TextEditor::IAssistProposalModel *proposalModel;
+};
+
+WaitForAsyncCompletions::WaitResult WaitForAsyncCompletions::wait(
+ TextEditor::IAssistProcessor *processor,
+ TextEditor::AssistInterface *assistInterface)
+{
+ QTC_ASSERT(processor, return Timeout);
+ QTC_ASSERT(assistInterface, return Timeout);
+
+ bool gotResults = false;
+
+ processor->setAsyncCompletionAvailableHandler(
+ [this, &gotResults] (TextEditor::IAssistProposal *proposal) {
+ QTC_ASSERT(proposal, return);
+ proposalModel = proposal->model();
+ delete proposal;
+ gotResults = true;
+ });
+
+ // Are there any immediate results?
+ if (TextEditor::IAssistProposal *proposal = processor->perform(assistInterface)) {
+ delete processor;
+ proposalModel = proposal->model();
+ delete proposal;
+ QTC_ASSERT(proposalModel, return GotInvalidResults);
+ return GotResults;
+ }
+
+ // There are not any, so wait for async results.
+ QElapsedTimer timer; timer.start();
+ while (!gotResults) {
+ if (timer.elapsed() >= 30 * 1000)
+ return Timeout;
+ QCoreApplication::processEvents();
+ }
+
+ return proposalModel ? GotResults : GotInvalidResults;
+}
+
class ChangeDocumentReloadSetting
{
public:
@@ -371,6 +421,51 @@ public:
QString senderLog;
};
+const CppTools::ProjectPartHeaderPaths toHeaderPaths(const QStringList &paths)
+{
+ using namespace CppTools;
+
+ ProjectPartHeaderPaths result;
+ foreach (const QString &path, paths)
+ result << ProjectPartHeaderPath(path, ProjectPartHeaderPath::IncludePath);
+ return result;
+}
+
+using ProposalModel = QSharedPointer<TextEditor::IAssistProposalModel>;
+
+ProposalModel completionResults(
+ TextEditor::BaseTextEditor *textEditor,
+ const QStringList &includePaths = QStringList())
+{
+ using namespace TextEditor;
+
+ TextEditorWidget *textEditorWidget = qobject_cast<TextEditorWidget *>(textEditor->widget());
+ QTC_ASSERT(textEditorWidget, return ProposalModel());
+ AssistInterface *assistInterface = textEditorWidget->createAssistInterface(
+ TextEditor::Completion, TextEditor::ExplicitlyInvoked);
+ QTC_ASSERT(assistInterface, return ProposalModel());
+ if (!includePaths.isEmpty()) {
+ auto clangAssistInterface = static_cast<ClangCompletionAssistInterface *>(assistInterface);
+ clangAssistInterface->setHeaderPaths(toHeaderPaths(includePaths));
+ }
+
+ CompletionAssistProvider *assistProvider
+ = textEditor->textDocument()->completionAssistProvider();
+ QTC_ASSERT(qobject_cast<ClangCompletionAssistProvider *>(assistProvider),
+ return ProposalModel());
+ QTC_ASSERT(assistProvider, return ProposalModel());
+ QTC_ASSERT(assistProvider->runType() == IAssistProvider::Asynchronous, return ProposalModel());
+
+ IAssistProcessor *processor = assistProvider->createProcessor();
+ QTC_ASSERT(processor, return ProposalModel());
+
+ WaitForAsyncCompletions waitForCompletions;
+ const WaitForAsyncCompletions::WaitResult result = waitForCompletions.wait(processor,
+ assistInterface);
+ QTC_ASSERT(result == WaitForAsyncCompletions::GotResults, return ProposalModel());
+ return QSharedPointer<TextEditor::IAssistProposalModel>(waitForCompletions.proposalModel);
+}
+
class TestDocument
{
public:
@@ -594,7 +689,7 @@ public:
if (!textToInsert.isEmpty())
openEditor.editor()->insert(textToInsert);
- proposal = completionResults(openEditor.editor(), includePaths, 15000);
+ proposal = completionResults(openEditor.editor(), includePaths);
}
ProposalModel proposal;