Merge remote-tracking branch 'origin/master' into 4.2

Change-Id: I96904f9c65b6c25bb4e04ca34e2d1acb27b8dd58
This commit is contained in:
Eike Ziller
2016-10-12 10:15:53 +02:00
131 changed files with 4220 additions and 505 deletions

View File

@@ -0,0 +1,40 @@
/****************************************************************************
**
** Copyright (C) 2016 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 <clang-c/Index.h>
inline
bool operator==(const CXSourceLocation &first, const CXSourceLocation &second)
{
return clang_equalLocations(first, second);
}
inline
bool operator==(const CXSourceRange &first, const CXSourceRange &second)
{
return clang_equalRanges(first, second);
}

View File

@@ -25,8 +25,11 @@
#include "googletest.h"
#include <clangclock.h>
#include <clangfilepath.h>
#include <clangtranslationunitupdater.h>
#include <clangtranslationunits.h>
#include <clangtranslationunit.h>
#include <commandlinearguments.h>
#include <diagnosticset.h>
#include <highlightingmarks.h>
@@ -45,9 +48,10 @@
#include <QTemporaryFile>
#include <chrono>
#include <thread>
using ClangBackEnd::Clock;
using ClangBackEnd::Duration;
using ClangBackEnd::FileContainer;
using ClangBackEnd::FilePath;
using ClangBackEnd::Document;
@@ -56,6 +60,8 @@ using ClangBackEnd::ProjectPart;
using ClangBackEnd::ProjectPartContainer;
using ClangBackEnd::Documents;
using ClangBackEnd::TranslationUnitUpdateResult;
using ClangBackEnd::TranslationUnit;
using ClangBackEnd::TranslationUnits;
using testing::IsNull;
using testing::NotNull;
@@ -161,7 +167,7 @@ TEST_F(Document, LastCommandLineArgumentIsFilePath)
TEST_F(Document, TimeStampForProjectPartChangeIsUpdatedAsNewCxTranslationUnitIsGenerated)
{
auto lastChangeTimePoint = document.lastProjectPartChangeTimePoint();
std::this_thread::sleep_for(std::chrono::steady_clock::duration(1));
std::this_thread::sleep_for(Duration(1));
document.parse();
@@ -173,7 +179,7 @@ TEST_F(Document, TimeStampForProjectPartChangeIsUpdatedAsProjectPartIsCleared)
ProjectPart projectPart = document.projectPart();
document.parse();
auto lastChangeTimePoint = document.lastProjectPartChangeTimePoint();
std::this_thread::sleep_for(std::chrono::steady_clock::duration(1));
std::this_thread::sleep_for(Duration(1));
projectPart.clear();
document.parse();
@@ -330,8 +336,9 @@ TEST_F(Document, IncorporateUpdaterResultResetsDirtyness)
{
document.setDirtyIfDependencyIsMet(document.filePath());
TranslationUnitUpdateResult result;
result.reparseTimePoint = std::chrono::steady_clock::now();
result.reparseTimePoint = Clock::now();
result.needsToBeReparsedChangeTimePoint = document.isNeededReparseChangeTimePoint();
result.translationUnitId = document.translationUnit().id();
document.incorporateUpdaterResult(result);
@@ -341,8 +348,9 @@ TEST_F(Document, IncorporateUpdaterResultResetsDirtyness)
TEST_F(Document, IncorporateUpdaterResultDoesNotResetDirtynessIfItWasChanged)
{
TranslationUnitUpdateResult result;
result.reparseTimePoint = std::chrono::steady_clock::now();
result.needsToBeReparsedChangeTimePoint = std::chrono::steady_clock::now();
result.reparseTimePoint = Clock::now();
result.needsToBeReparsedChangeTimePoint = Clock::now();
result.translationUnitId = document.translationUnit().id();
document.setDirtyIfDependencyIsMet(document.filePath());
document.incorporateUpdaterResult(result);
@@ -350,6 +358,25 @@ TEST_F(Document, IncorporateUpdaterResultDoesNotResetDirtynessIfItWasChanged)
ASSERT_TRUE(document.isNeedingReparse());
}
TEST_F(Document, IncorporateUpdaterResultUpdatesTranslationUnitsReparseTimePoint)
{
TranslationUnits &translationUnits = document.translationUnits();
const TranslationUnit initialTranslationUnit = translationUnits.get();
translationUnits.updateParseTimePoint(initialTranslationUnit.id(), Clock::now());
const TranslationUnit alternativeTranslationUnit = translationUnits.createAndAppend();
translationUnits.updateParseTimePoint(alternativeTranslationUnit.id(), Clock::now());
TranslationUnitUpdateResult result;
result.reparseTimePoint = Clock::now();
result.needsToBeReparsedChangeTimePoint = Clock::now();
result.translationUnitId = initialTranslationUnit.id();
document.setDirtyIfDependencyIsMet(document.filePath());
ASSERT_THAT(translationUnits.get().id(), Eq(alternativeTranslationUnit.id()));
document.incorporateUpdaterResult(result);
ASSERT_THAT(translationUnits.get().id(), Eq(initialTranslationUnit.id()));
}
void Document::SetUp()
{
projects.createOrUpdate({ProjectPartContainer(projectPartId)});

View File

@@ -0,0 +1,128 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "clangiasyncjob.h"
#include "dummyclangipcclient.h"
#include "processevents-utilities.h"
#include <clangdocument.h>
#include <clangdocumentprocessor.h>
#include <clangdocuments.h>
#include <clangjobrequest.h>
#include <clangjobs.h>
#include <projects.h>
#include <unsavedfiles.h>
#include <gmock/gmock.h>
#include <gmock/gmock-matchers.h>
#include <gtest/gtest.h>
#include "gtest-qt-printing.h"
using namespace ClangBackEnd;
namespace {
class DocumentProcessor : public ::testing::Test
{
protected:
void SetUp() override;
void TearDown() override;
ClangBackEnd::JobRequest createJobRequest(ClangBackEnd::JobRequest::Type type) const;
bool waitUntilAllJobsFinished(int timeOutInMs = 10000) const;
protected:
ClangBackEnd::ProjectParts projects;
ClangBackEnd::UnsavedFiles unsavedFiles;
ClangBackEnd::Documents documents{projects, unsavedFiles};
ClangBackEnd::Document document;
DummyIpcClient dummyIpcClient;
Utf8String filePath{Utf8StringLiteral(TESTDATA_DIR"/translationunits.cpp")};
Utf8String projectPartId{Utf8StringLiteral("/path/to/projectfile")};
ClangBackEnd::DocumentProcessor documentProcessor{document,
documents,
unsavedFiles,
projects,
dummyIpcClient};
};
TEST_F(DocumentProcessor, ProcessEmpty)
{
const JobRequests jobsStarted = documentProcessor.process();
ASSERT_THAT(jobsStarted.size(), 0);
}
TEST_F(DocumentProcessor, ProcessSingleJob)
{
const JobRequest jobRequest = createJobRequest(JobRequest::Type::UpdateDocumentAnnotations);
documentProcessor.addJob(jobRequest);
const JobRequests jobsStarted = documentProcessor.process();
ASSERT_THAT(jobsStarted.size(), 1);
}
void DocumentProcessor::SetUp()
{
projects.createOrUpdate({ProjectPartContainer(projectPartId)});
const QVector<FileContainer> fileContainer{FileContainer(filePath, projectPartId)};
document = documents.create(fileContainer).front();
documents.setVisibleInEditors({filePath});
documents.setUsedByCurrentEditor(filePath);
}
void DocumentProcessor::TearDown()
{
ASSERT_TRUE(waitUntilAllJobsFinished()); // QFuture/QFutureWatcher is implemented with events
}
JobRequest DocumentProcessor::createJobRequest(JobRequest::Type type) const
{
JobRequest jobRequest;
jobRequest.type = type;
jobRequest.requirements = JobRequest::requirementsForType(type);
jobRequest.filePath = filePath;
jobRequest.projectPartId = projectPartId;
jobRequest.unsavedFilesChangeTimePoint = unsavedFiles.lastChangeTimePoint();
jobRequest.documentRevision = document.documentRevision();
jobRequest.projectChangeTimePoint = projects.project(projectPartId).lastChangeTimePoint();
return jobRequest;
}
bool DocumentProcessor::waitUntilAllJobsFinished(int timeOutInMs) const
{
const auto noJobsRunningAnymore = [this](){ return documentProcessor.runningJobs().isEmpty(); };
return ProcessEventUtilities::processEventsUntilTrue(noJobsRunningAnymore, timeOutInMs);
}
} // anonymous

View File

@@ -0,0 +1,194 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "clangiasyncjob.h"
#include "dummyclangipcclient.h"
#include "processevents-utilities.h"
#include <clangdocument.h>
#include <clangdocumentprocessor.h>
#include <clangdocumentprocessors.h>
#include <clangdocuments.h>
#include <clangexceptions.h>
#include <clangjobrequest.h>
#include <clangjobs.h>
#include <projects.h>
#include <unsavedfiles.h>
#include <gmock/gmock.h>
#include <gmock/gmock-matchers.h>
#include <gtest/gtest.h>
#include "gtest-qt-printing.h"
using testing::Eq;
using namespace ClangBackEnd;
namespace {
class DocumentProcessors : public ::testing::Test
{
protected:
void SetUp() override;
void TearDown() override;
ClangBackEnd::JobRequest createJobRequest(ClangBackEnd::JobRequest::Type type) const;
bool waitUntilAllJobsFinished(int timeOutInMs = 10000) const;
protected:
ClangBackEnd::ProjectParts projects;
ClangBackEnd::UnsavedFiles unsavedFiles;
ClangBackEnd::Documents documents{projects, unsavedFiles};
ClangBackEnd::Document document;
DummyIpcClient dummyIpcClient;
Utf8String filePath{Utf8StringLiteral(TESTDATA_DIR"/translationunits.cpp")};
Utf8String projectPartId{Utf8StringLiteral("/path/to/projectfile")};
ClangBackEnd::JobRequest jobRequest;
ClangBackEnd::JobContext jobContext;
ClangBackEnd::DocumentProcessors documentProcessors{documents,
unsavedFiles,
projects,
dummyIpcClient};
};
TEST_F(DocumentProcessors, HasNoItemsInitially)
{
ASSERT_TRUE(documentProcessors.processors().empty());
}
TEST_F(DocumentProcessors, CreateAddsADocumentProcessor)
{
documentProcessors.create(document);
ASSERT_THAT(documentProcessors.processors().size(), Eq(1));
}
TEST_F(DocumentProcessors, CreateReturnsDocumentProcessor)
{
const DocumentProcessor documentProcessor = documentProcessors.create(document);
ASSERT_THAT(documentProcessor.document(), Eq(document));
}
TEST_F(DocumentProcessors, CreateThrowsForAlreadyExisting)
{
documentProcessors.create(document);
ASSERT_THROW(documentProcessors.create(document),
ClangBackEnd::DocumentProcessorAlreadyExists);
}
TEST_F(DocumentProcessors, Access)
{
documentProcessors.create(document);
const DocumentProcessor documentProcessor = documentProcessors.processor(document);
ASSERT_THAT(documentProcessor.document(), Eq(document));
}
TEST_F(DocumentProcessors, AccessThrowsForNotExisting)
{
ASSERT_THROW(documentProcessors.processor(document),
ClangBackEnd::DocumentProcessorDoesNotExist);
}
TEST_F(DocumentProcessors, Remove)
{
documentProcessors.create(document);
documentProcessors.remove(document);
ASSERT_TRUE(documentProcessors.processors().empty());
}
TEST_F(DocumentProcessors, RemoveThrowsForNotExisting)
{
ASSERT_THROW(documentProcessors.remove(document),
ClangBackEnd::DocumentProcessorDoesNotExist);
}
TEST_F(DocumentProcessors, ProcessEmpty)
{
documentProcessors.create(document);
const JobRequests jobsStarted = documentProcessors.process();
ASSERT_TRUE(jobsStarted.isEmpty());
}
TEST_F(DocumentProcessors, ProcessSingle)
{
DocumentProcessor documentProcessor = documentProcessors.create(document);
const JobRequest jobRequest = createJobRequest(JobRequest::Type::UpdateDocumentAnnotations);
documentProcessor.addJob(jobRequest);
const JobRequests jobsStarted = documentProcessors.process();
ASSERT_THAT(jobsStarted.size(), 1);
}
void DocumentProcessors::SetUp()
{
projects.createOrUpdate({ProjectPartContainer(projectPartId)});
const QVector<FileContainer> fileContainer{FileContainer(filePath, projectPartId)};
document = documents.create(fileContainer).front();
documents.setVisibleInEditors({filePath});
documents.setUsedByCurrentEditor(filePath);
}
void DocumentProcessors::TearDown()
{
ASSERT_TRUE(waitUntilAllJobsFinished()); // QFuture/QFutureWatcher is implemented with events
}
JobRequest DocumentProcessors::createJobRequest(JobRequest::Type type) const
{
JobRequest jobRequest;
jobRequest.type = type;
jobRequest.requirements = JobRequest::requirementsForType(type);
jobRequest.filePath = filePath;
jobRequest.projectPartId = projectPartId;
jobRequest.unsavedFilesChangeTimePoint = unsavedFiles.lastChangeTimePoint();
jobRequest.documentRevision = document.documentRevision();
jobRequest.projectChangeTimePoint = projects.project(projectPartId).lastChangeTimePoint();
return jobRequest;
}
bool DocumentProcessors::waitUntilAllJobsFinished(int timeOutInMs) const
{
const auto noJobsRunningAnymore = [this](){ return documentProcessors.runningJobs().isEmpty(); };
return ProcessEventUtilities::processEventsUntilTrue(noJobsRunningAnymore, timeOutInMs);
}
} // anonymous

View File

@@ -43,6 +43,7 @@ using ClangBackEnd::ProjectPartContainer;
using testing::IsNull;
using testing::NotNull;
using testing::Gt;
using testing::Eq;
using testing::Not;
using testing::Contains;
@@ -158,6 +159,18 @@ TEST_F(Documents, UpdateSingle)
IsDocument(filePath, projectPartId, 75u));
}
TEST_F(Documents, UpdateReturnsUpdatedDocument)
{
ClangBackEnd::FileContainer createFileContainer(filePath, projectPartId, Utf8StringVector(), 74u);
ClangBackEnd::FileContainer updateFileContainer(filePath, Utf8String(), Utf8StringVector(), 75u);
documents.create({createFileContainer});
const std::vector<Document> updatedDocuments = documents.update({updateFileContainer});
ASSERT_THAT(updatedDocuments.size(), Eq(1u));
ASSERT_THAT(updatedDocuments.front().documentRevision(), Eq(75u));
}
TEST_F(Documents, UpdateMultiple)
{
ClangBackEnd::FileContainer fileContainer(filePath, projectPartId, Utf8StringVector(), 74u);

View File

@@ -32,6 +32,7 @@
#include <highlightingmarkcontainer.h>
#include <clangcodemodelclientproxy.h>
#include <clangcodemodelserverproxy.h>
#include <clangtranslationunits.h>
#include <requestdocumentannotations.h>
#include <clangexceptions.h>
@@ -41,6 +42,7 @@
#include <cmbunregisterprojectsforeditormessage.h>
#include <cmbunregistertranslationunitsforeditormessage.h>
#include <QCoreApplication>
#include <QFile>
using testing::Property;
@@ -135,6 +137,8 @@ protected:
void completeCodeInFileA();
void completeCodeInFileB();
bool isSupportiveTranslationUnitInitialized(const Utf8String &filePath);
void expectDocumentAnnotationsChanged(int count);
void expectCompletion(const CodeCompletion &completion);
void expectCompletionFromFileA();
@@ -286,6 +290,64 @@ TEST_F(ClangClangCodeModelServer, SetCurrentAndVisibleEditor)
ASSERT_TRUE(functionDocument.isVisibleInEditor());
}
TEST_F(ClangClangCodeModelServer, StartCompletionJobFirstOnEditThatTriggersCompletion)
{
registerProjectAndFile(filePathA, 2);
ASSERT_TRUE(waitUntilAllJobsFinished());
expectCompletionFromFileA();
updateUnsavedContent(filePathA, unsavedContent(filePathAUnsavedVersion2), 1);
completeCodeInFileA();
const QList<Jobs::RunningJob> jobs = clangServer.runningJobsForTestsOnly();
ASSERT_THAT(jobs.size(), Eq(1));
ASSERT_THAT(jobs.first().jobRequest.type, Eq(JobRequest::Type::CompleteCode));
}
TEST_F(ClangClangCodeModelServer, SupportiveTranslationUnitNotInitializedAfterRegister)
{
registerProjectAndFile(filePathA, 1);
ASSERT_TRUE(waitUntilAllJobsFinished());
ASSERT_FALSE(isSupportiveTranslationUnitInitialized(filePathA));
}
TEST_F(ClangClangCodeModelServer, SupportiveTranslationUnitIsSetupAfterFirstEdit)
{
registerProjectAndFile(filePathA, 2);
ASSERT_TRUE(waitUntilAllJobsFinished());
updateUnsavedContent(filePathA, unsavedContent(filePathAUnsavedVersion2), 1);
ASSERT_TRUE(waitUntilAllJobsFinished());
ASSERT_TRUE(isSupportiveTranslationUnitInitialized(filePathA));
}
TEST_F(ClangClangCodeModelServer, DoNotRunDuplicateJobs)
{
registerProjectAndFile(filePathA, 3);
ASSERT_TRUE(waitUntilAllJobsFinished());
updateUnsavedContent(filePathA, unsavedContent(filePathAUnsavedVersion2), 1);
ASSERT_TRUE(waitUntilAllJobsFinished());
ASSERT_TRUE(isSupportiveTranslationUnitInitialized(filePathA));
updateUnsavedContent(filePathA, unsavedContent(filePathAUnsavedVersion2), 2);
QCoreApplication::processEvents(); // adds + runs a job
updateVisibilty(Utf8String(), Utf8String());
updateVisibilty(filePathA, filePathA); // triggers adding + runnings job on next processevents()
}
TEST_F(ClangClangCodeModelServer, OpenDocumentAndEdit)
{
registerProjectAndFile(filePathA, 4);
ASSERT_TRUE(waitUntilAllJobsFinished());
for (unsigned revision = 1; revision <= 3; ++revision) {
updateUnsavedContent(filePathA, unsavedContent(filePathAUnsavedVersion2), revision);
ASSERT_TRUE(waitUntilAllJobsFinished());
}
}
TEST_F(ClangClangCodeModelServer, IsNotCurrentCurrentAndVisibleEditorAnymore)
{
registerProjectAndFilesAndWaitForFinished();
@@ -323,8 +385,8 @@ void ClangClangCodeModelServer::TearDown()
bool ClangClangCodeModelServer::waitUntilAllJobsFinished(int timeOutInMs)
{
const auto noJobsRunningAnymore = [this]() {
return clangServer.jobsForTestOnly().runningJobs() == 0
&& clangServer.jobsForTestOnly().queue().size() == 0
return clangServer.runningJobsForTestsOnly().isEmpty()
&& clangServer.queueSizeForTestsOnly() == 0
&& !clangServer.isTimerRunningForTestOnly();
};
@@ -411,6 +473,16 @@ void ClangClangCodeModelServer::completeCodeInFileB()
completeCode(filePathB, 35, 1);
}
bool ClangClangCodeModelServer::isSupportiveTranslationUnitInitialized(const Utf8String &filePath)
{
Document document = clangServer.documentsForTestOnly().document(filePath, projectPartId);
DocumentProcessor documentProcessor = clangServer.documentProcessors().processor(document);
return document.translationUnits().size() == 2
&& documentProcessor.hasSupportiveTranslationUnit()
&& documentProcessor.isSupportiveTranslationUnitInitialized();
}
void ClangClangCodeModelServer::expectCompletion(const CodeCompletion &completion)
{
EXPECT_CALL(mockClangCodeModelClient,

View File

@@ -28,6 +28,8 @@
#include <clangdocument.h>
#include <clangdocuments.h>
#include <clangtranslationunit.h>
#include <clangtranslationunits.h>
#include <clangjobs.h>
#include <filecontainer.h>
#include <projectpart.h>
@@ -60,7 +62,9 @@ protected:
Utf8String createTranslationUnitForDeletedFile();
JobRequest createJobRequest(const Utf8String &filePath,
JobRequest::Type type) const;
JobRequest::Type type,
PreferredTranslationUnit preferredTranslationUnit
= PreferredTranslationUnit::RecentlyParsed) const;
void updateDocumentRevision();
void updateUnsavedFiles();
@@ -91,6 +95,29 @@ TEST_F(JobQueue, AddJob)
ASSERT_THAT(jobQueue.queue().size(), Eq(1));
}
TEST_F(JobQueue, DoNotAddDuplicate)
{
const JobRequest request = createJobRequest(filePath1,
JobRequest::Type::UpdateDocumentAnnotations);
jobQueue.add(request);
const bool added = jobQueue.add(request);
ASSERT_FALSE(added);
}
TEST_F(JobQueue, DoNotAddDuplicateForWhichAJobIsAlreadyRunning)
{
jobQueue.setIsJobRunningForJobRequestHandler([](const JobRequest &) {
return true;
});
const bool added = jobQueue.add(createJobRequest(filePath1,
JobRequest::Type::UpdateDocumentAnnotations));
ASSERT_FALSE(added);
}
TEST_F(JobQueue, ProcessEmpty)
{
jobQueue.processQueue();
@@ -111,7 +138,7 @@ TEST_F(JobQueue, ProcessSingleJob)
TEST_F(JobQueue, ProcessUntilEmpty)
{
jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateDocumentAnnotations));
jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateDocumentAnnotations));
jobQueue.add(createJobRequest(filePath1, JobRequest::Type::CreateInitialDocumentPreamble));
JobRequests jobsToRun;
ASSERT_THAT(jobQueue.size(), Eq(2));
@@ -231,7 +258,7 @@ TEST_F(JobQueue, PrioritizeCurrentDocumentOverVisible)
TEST_F(JobQueue, RunNothingForNotCurrentOrVisibleDocument)
{
jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateDocumentAnnotations));
jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateDocumentAnnotations));
jobQueue.add(createJobRequest(filePath1, JobRequest::Type::CreateInitialDocumentPreamble));
documents.setVisibleInEditors({});
documents.setUsedByCurrentEditor(Utf8StringLiteral("aNonExistingFilePath"));
@@ -240,10 +267,10 @@ TEST_F(JobQueue, RunNothingForNotCurrentOrVisibleDocument)
ASSERT_THAT(jobsToRun.size(), Eq(0));
}
TEST_F(JobQueue, RunOnlyOneJobPerDocumentIfMultipleAreInQueue)
TEST_F(JobQueue, RunOnlyOneJobPerTranslationUnitIfMultipleAreInQueue)
{
jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateDocumentAnnotations));
jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateDocumentAnnotations));
jobQueue.add(createJobRequest(filePath1, JobRequest::Type::CreateInitialDocumentPreamble));
const JobRequests jobsToRun = jobQueue.processQueue();
@@ -251,12 +278,30 @@ TEST_F(JobQueue, RunOnlyOneJobPerDocumentIfMultipleAreInQueue)
ASSERT_THAT(jobQueue.size(), Eq(1));
}
TEST_F(JobQueue, DoNotRunJobForDocumentThatIsBeingProcessed)
TEST_F(JobQueue, RunJobsForDistinctTranslationUnits)
{
const TranslationUnit initialTu = document.translationUnit();
document.translationUnits().updateParseTimePoint(initialTu.id(), std::chrono::steady_clock::now());
const TranslationUnit alternativeTu = document.translationUnits().createAndAppend();
document.translationUnits().updateParseTimePoint(alternativeTu.id(), std::chrono::steady_clock::now());
jobQueue.add(createJobRequest(filePath1,
JobRequest::Type::UpdateDocumentAnnotations,
PreferredTranslationUnit::RecentlyParsed));
jobQueue.add(createJobRequest(filePath1,
JobRequest::Type::UpdateDocumentAnnotations,
PreferredTranslationUnit::PreviouslyParsed));
const JobRequests jobsToRun = jobQueue.processQueue();
ASSERT_THAT(jobsToRun.size(), Eq(2));
ASSERT_THAT(jobQueue.size(), Eq(0));
}
TEST_F(JobQueue, DoNotRunJobForTranslationUnittThatIsBeingProcessed)
{
jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateDocumentAnnotations));
jobQueue.add(createJobRequest(filePath1, JobRequest::Type::UpdateDocumentAnnotations));
jobQueue.add(createJobRequest(filePath1, JobRequest::Type::CreateInitialDocumentPreamble));
JobRequests jobsToRun = jobQueue.processQueue();
jobQueue.setIsJobRunningHandler([](const Utf8String &, const Utf8String &) {
jobQueue.setIsJobRunningForTranslationUnitHandler([](const Utf8String &) {
return true;
});
@@ -397,8 +442,10 @@ Utf8String JobQueue::createTranslationUnitForDeletedFile()
return temporaryFilePath;
}
JobRequest JobQueue::createJobRequest(const Utf8String &filePath,
JobRequest::Type type) const
JobRequest JobQueue::createJobRequest(
const Utf8String &filePath,
JobRequest::Type type,
PreferredTranslationUnit preferredTranslationUnit) const
{
JobRequest jobRequest;
jobRequest.type = type;
@@ -407,6 +454,7 @@ JobRequest JobQueue::createJobRequest(const Utf8String &filePath,
jobRequest.projectPartId = projectPartId;
jobRequest.unsavedFilesChangeTimePoint = unsavedFiles.lastChangeTimePoint();
jobRequest.documentRevision = document.documentRevision();
jobRequest.preferredTranslationUnit = preferredTranslationUnit;
jobRequest.projectChangeTimePoint = projects.project(projectPartId).lastChangeTimePoint();
return jobRequest;

View File

@@ -79,7 +79,7 @@ TEST_F(Jobs, ProcessEmptyQueue)
const JobRequests jobsStarted = jobs.process();
ASSERT_THAT(jobsStarted.size(), Eq(0));
ASSERT_THAT(jobs.runningJobs(), Eq(0));
ASSERT_TRUE(jobs.runningJobs().isEmpty());
}
TEST_F(Jobs, ProcessQueueWithSingleJob)
@@ -89,7 +89,7 @@ TEST_F(Jobs, ProcessQueueWithSingleJob)
const JobRequests jobsStarted = jobs.process();
ASSERT_THAT(jobsStarted.size(), Eq(1));
ASSERT_THAT(jobs.runningJobs(), Eq(1));
ASSERT_THAT(jobs.runningJobs().size(), Eq(1));
}
TEST_F(Jobs, ProcessQueueUntilEmpty)
@@ -108,7 +108,7 @@ TEST_F(Jobs, IsJobRunning)
jobs.add(createJobRequest(filePath1, JobRequest::Type::UpdateDocumentAnnotations));
jobs.process();
const bool isJobRunning = jobs.isJobRunning(filePath1, projectPartId);
const bool isJobRunning = jobs.isJobRunningForTranslationUnit(document.translationUnit().id());
ASSERT_TRUE(isJobRunning);
}
@@ -130,7 +130,7 @@ void Jobs::TearDown()
bool Jobs::waitUntilAllJobsFinished(int timeOutInMs) const
{
const auto noJobsRunningAnymore = [this](){ return jobs.runningJobs() == 0; };
const auto noJobsRunningAnymore = [this](){ return jobs.runningJobs().isEmpty(); };
return ProcessEventUtilities::processEventsUntilTrue(noJobsRunningAnymore, timeOutInMs);
}
@@ -138,7 +138,7 @@ bool Jobs::waitUntilAllJobsFinished(int timeOutInMs) const
bool Jobs::waitUntilJobChainFinished(int timeOutInMs) const
{
const auto noJobsRunningAnymore = [this]() {
return jobs.runningJobs() == 0 && jobs.queue().isEmpty();
return jobs.runningJobs().isEmpty() && jobs.queue().isEmpty();
};
return ProcessEventUtilities::processEventsUntilTrue(noJobsRunningAnymore, timeOutInMs);

View File

@@ -0,0 +1,86 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "clangasyncjob-base.h"
#include <clangparsesupportivetranslationunitjob.h>
#include <clangtranslationunits.h>
using namespace ClangBackEnd;
using testing::Eq;
using testing::Not;
using testing::_;
namespace {
class ParseSupportiveTranslationUnitJob : public ClangAsyncJobTest
{
protected:
void SetUp() override { BaseSetUp(JobRequest::Type::ParseSupportiveTranslationUnit, job); }
TimePoint parseTimePointOfDocument();
protected:
ClangBackEnd::ParseSupportiveTranslationUnitJob job;
};
TEST_F(ParseSupportiveTranslationUnitJob, PrepareAsyncRun)
{
job.setContext(jobContext);
ASSERT_TRUE(job.prepareAsyncRun());
}
TEST_F(ParseSupportiveTranslationUnitJob, RunAsync)
{
job.setContext(jobContext);
job.prepareAsyncRun();
job.runAsync();
ASSERT_TRUE(waitUntilJobFinished(job));
}
TEST_F(ParseSupportiveTranslationUnitJob, DoNotIncorporateUpdaterResult)
{
const TimePoint parseTimePointBefore = parseTimePointOfDocument();
job.setContext(jobContext);
job.prepareAsyncRun();
job.runAsync();
ASSERT_TRUE(waitUntilJobFinished(job));
ASSERT_THAT(parseTimePointOfDocument(), Eq(parseTimePointBefore));
}
TimePoint ParseSupportiveTranslationUnitJob::parseTimePointOfDocument()
{
const Utf8String translationUnitId = document.translationUnit().id();
return document.translationUnits().parseTimePoint(translationUnitId);
}
} // anonymous

View File

@@ -0,0 +1,109 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "clangasyncjob-base.h"
#include <clangreparsesupportivetranslationunitjob.h>
#include <clangtranslationunits.h>
using namespace ClangBackEnd;
using testing::Eq;
using testing::Not;
using testing::_;
namespace {
class ReparseSupportiveTranslationUnitJob : public ClangAsyncJobTest
{
protected:
void SetUp() override { BaseSetUp(JobRequest::Type::ReparseSupportiveTranslationUnit, job); }
TimePoint parseTimePointOfDocument();
void parse();
protected:
ClangBackEnd::ReparseSupportiveTranslationUnitJob job;
};
TEST_F(ReparseSupportiveTranslationUnitJob, PrepareAsyncRun)
{
job.setContext(jobContext);
ASSERT_TRUE(job.prepareAsyncRun());
}
TEST_F(ReparseSupportiveTranslationUnitJob, RunAsync)
{
parse();
job.setContext(jobContext);
job.prepareAsyncRun();
job.runAsync();
ASSERT_TRUE(waitUntilJobFinished(job));
}
TEST_F(ReparseSupportiveTranslationUnitJob, IncorporateUpdaterResult)
{
parse();
const TimePoint parseTimePointBefore = parseTimePointOfDocument();
job.setContext(jobContext);
job.prepareAsyncRun();
job.runAsync();
ASSERT_TRUE(waitUntilJobFinished(job));
ASSERT_THAT(parseTimePointOfDocument(), Not(Eq(parseTimePointBefore)));
}
TEST_F(ReparseSupportiveTranslationUnitJob, DoNotIncorporateUpdaterResultIfDocumentWasClosed)
{
parse();
const TimePoint parseTimePointBefore = parseTimePointOfDocument();
job.setContext(jobContext);
job.prepareAsyncRun();
job.runAsync();
documents.remove({FileContainer{filePath, projectPartId}});
ASSERT_TRUE(waitUntilJobFinished(job));
ASSERT_THAT(parseTimePointOfDocument(), Eq(parseTimePointBefore));
}
TimePoint ReparseSupportiveTranslationUnitJob::parseTimePointOfDocument()
{
const Utf8String translationUnitId = document.translationUnit().id();
return document.translationUnits().parseTimePoint(translationUnitId);
}
void ReparseSupportiveTranslationUnitJob::parse()
{
projects.createOrUpdate({ProjectPartContainer{projectPartId, Utf8StringVector()}});
document.parse();
}
} // anonymous

View File

@@ -0,0 +1,262 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "dummyclangipcclient.h"
#include "processevents-utilities.h"
#include <clangbackend_global.h>
#include <clangdocuments.h>
#include <clangexceptions.h>
#include <clangsupportivetranslationunitinitializer.cpp>
#include <clangtranslationunit.h>
#include <clangtranslationunits.h>
#include <projects.h>
#include <utf8string.h>
#include <clang-c/Index.h>
#include <memory>
#include <gmock/gmock.h>
#include <gmock/gmock-matchers.h>
#include <gtest/gtest.h>
#include "gtest-qt-printing.h"
using namespace ClangBackEnd;
using testing::Eq;
namespace {
class Data {
public:
Data()
{
projects.createOrUpdate({ProjectPartContainer(projectPartId)});
const QVector<FileContainer> fileContainer{FileContainer(filePath, projectPartId)};
document = documents.create(fileContainer).front();
documents.setVisibleInEditors({filePath});
documents.setUsedByCurrentEditor(filePath);
const auto isDocumentClosed = [this](const Utf8String &filePath,
const Utf8String &projectPartId) {
return !documents.hasDocument(filePath, projectPartId);
};
const auto jobRequestCreator = [this](const Document &document,
JobRequest::Type type,
PreferredTranslationUnit preferredTranslationUnit) {
return createJobRequest(document, type, preferredTranslationUnit);
};
initializer.reset(new ClangBackEnd::SupportiveTranslationUnitInitializer{document, jobs});
initializer->setIsDocumentClosedChecker(isDocumentClosed);
initializer->setJobRequestCreator(jobRequestCreator);
}
JobRequest createJobRequest(const Document &document,
JobRequest::Type type,
PreferredTranslationUnit preferredTranslationUnit) const
{
JobRequest jobRequest;
jobRequest.type = type;
jobRequest.requirements = JobRequest::requirementsForType(type);
jobRequest.filePath = document.filePath();
jobRequest.projectPartId = document.projectPartId();
jobRequest.unsavedFilesChangeTimePoint = unsavedFiles.lastChangeTimePoint();
jobRequest.documentRevision = document.documentRevision();
jobRequest.preferredTranslationUnit = preferredTranslationUnit;
const ProjectPart &projectPart = projects.project(document.projectPartId());
jobRequest.projectChangeTimePoint = projectPart.lastChangeTimePoint();
return jobRequest;
}
public:
Utf8String filePath{Utf8StringLiteral(TESTDATA_DIR"/translationunits.cpp")};
Utf8String projectPartId{Utf8StringLiteral("/path/to/projectfile")};
ProjectParts projects;
UnsavedFiles unsavedFiles;
Documents documents{projects, unsavedFiles};
Document document;
DummyIpcClient dummyClientInterface;
Jobs jobs{documents, unsavedFiles, projects, dummyClientInterface};
std::unique_ptr<ClangBackEnd::SupportiveTranslationUnitInitializer> initializer;
};
class SupportiveTranslationUnitInitializer : public ::testing::Test
{
protected:
void parse();
Jobs::RunningJob createRunningJob(JobRequest::Type type) const;
void assertNoJobIsRunningAndEmptyQueue();
void assertSingleJobRunningAndEmptyQueue();
bool waitUntilJobChainFinished(int timeOutInMs = 10000) const;
protected:
Data d;
Utf8String &filePath{d.filePath};
Utf8String &projectPartId{d.projectPartId};
ProjectParts projects{d.projects};
Document &document{d.document};
Documents &documents{d.documents};
Jobs &jobs{d.jobs};
ClangBackEnd::SupportiveTranslationUnitInitializer &initializer{*d.initializer};
};
TEST_F(SupportiveTranslationUnitInitializer, HasInitiallyNotInitializedState)
{
ASSERT_THAT(initializer.state(), Eq(ClangBackEnd::SupportiveTranslationUnitInitializer::State::NotInitialized));
}
TEST_F(SupportiveTranslationUnitInitializer, StartInitializingAbortsIfDocumentIsClosed)
{
documents.remove({FileContainer(filePath, projectPartId)});
initializer.startInitializing();
assertNoJobIsRunningAndEmptyQueue();
ASSERT_THAT(initializer.state(), Eq(ClangBackEnd::SupportiveTranslationUnitInitializer::State::Aborted));
}
TEST_F(SupportiveTranslationUnitInitializer, StartInitializingAddsTranslationUnit)
{
initializer.startInitializing();
ASSERT_THAT(document.translationUnits().size(), Eq(2));
ASSERT_FALSE(document.translationUnits().areAllTranslationUnitsParsed());
}
TEST_F(SupportiveTranslationUnitInitializer, StartInitializingStartsJob)
{
initializer.startInitializing();
assertSingleJobRunningAndEmptyQueue();
const Jobs::RunningJob runningJob = jobs.runningJobs().first();
ASSERT_THAT(runningJob.jobRequest.type, JobRequest::Type::ParseSupportiveTranslationUnit);
}
TEST_F(SupportiveTranslationUnitInitializer, CheckIfParseJobFinishedAbortsIfDocumentIsClosed)
{
documents.remove({FileContainer(filePath, projectPartId)});
initializer.setState(ClangBackEnd::SupportiveTranslationUnitInitializer::State::WaitingForParseJob);
const Jobs::RunningJob runningJob = createRunningJob(JobRequest::Type::ParseSupportiveTranslationUnit);
initializer.checkIfParseJobFinished(runningJob);
assertNoJobIsRunningAndEmptyQueue();
ASSERT_THAT(initializer.state(), Eq(ClangBackEnd::SupportiveTranslationUnitInitializer::State::Aborted));
}
TEST_F(SupportiveTranslationUnitInitializer, CheckIfParseJobFinishedStartsJob)
{
parse();
initializer.setState(ClangBackEnd::SupportiveTranslationUnitInitializer::State::WaitingForParseJob);
Jobs::RunningJob runningJob = createRunningJob(JobRequest::Type::ParseSupportiveTranslationUnit);
initializer.checkIfParseJobFinished(runningJob);
jobs.process();
assertSingleJobRunningAndEmptyQueue();
runningJob = jobs.runningJobs().first();
ASSERT_THAT(runningJob.jobRequest.type, JobRequest::Type::ReparseSupportiveTranslationUnit);
}
TEST_F(SupportiveTranslationUnitInitializer, CheckIfReparseJobFinishedAbortsIfDocumentIsClosed)
{
documents.remove({FileContainer(filePath, projectPartId)});
initializer.setState(ClangBackEnd::SupportiveTranslationUnitInitializer::State::WaitingForReparseJob);
const Jobs::RunningJob runningJob = createRunningJob(JobRequest::Type::ReparseSupportiveTranslationUnit);
initializer.checkIfReparseJobFinished(runningJob);
assertNoJobIsRunningAndEmptyQueue();
ASSERT_THAT(initializer.state(), Eq(ClangBackEnd::SupportiveTranslationUnitInitializer::State::Aborted));
}
TEST_F(SupportiveTranslationUnitInitializer, CheckIfReparseJobFinishedStartsJob)
{
parse();
initializer.setState(ClangBackEnd::SupportiveTranslationUnitInitializer::State::WaitingForReparseJob);
Jobs::RunningJob runningJob = createRunningJob(JobRequest::Type::ReparseSupportiveTranslationUnit);
initializer.checkIfReparseJobFinished(runningJob);
jobs.process();
assertNoJobIsRunningAndEmptyQueue();
ASSERT_THAT(initializer.state(), Eq(ClangBackEnd::SupportiveTranslationUnitInitializer::State::Initialized));
}
TEST_F(SupportiveTranslationUnitInitializer, FullRun)
{
parse();
initializer.startInitializing();
waitUntilJobChainFinished();
ASSERT_THAT(initializer.state(), Eq(ClangBackEnd::SupportiveTranslationUnitInitializer::State::Initialized));
}
void SupportiveTranslationUnitInitializer::parse()
{
projects.createOrUpdate({ProjectPartContainer{projectPartId, Utf8StringVector()}});
document.parse();
}
Jobs::RunningJob SupportiveTranslationUnitInitializer::createRunningJob(JobRequest::Type type) const
{
const JobRequest jobRequest = d.createJobRequest(document,
type,
PreferredTranslationUnit::LastUninitialized);
return Jobs::RunningJob{jobRequest, Utf8String(), QFuture<void>()};
}
void SupportiveTranslationUnitInitializer::assertNoJobIsRunningAndEmptyQueue()
{
ASSERT_TRUE(jobs.runningJobs().isEmpty());
ASSERT_TRUE(jobs.queue().isEmpty());
}
void SupportiveTranslationUnitInitializer::assertSingleJobRunningAndEmptyQueue()
{
ASSERT_THAT(jobs.runningJobs().size(), Eq(1));
ASSERT_TRUE(jobs.queue().isEmpty());
}
bool SupportiveTranslationUnitInitializer::waitUntilJobChainFinished(int timeOutInMs) const
{
const auto noJobsRunningAnymore = [this]() {
return jobs.runningJobs().isEmpty() && jobs.queue().isEmpty();
};
return ProcessEventUtilities::processEventsUntilTrue(noJobsRunningAnymore, timeOutInMs);
}
} // anonymous namespace

View File

@@ -0,0 +1,197 @@
/****************************************************************************
**
** Copyright (C) 2016 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 <clangtranslationunit.h>
#include <clangtranslationunitupdater.h>
#include <diagnosticcontainer.h>
#include <utf8string.h>
#include <clang-c/Index.h>
#include <gmock/gmock.h>
#include <gmock/gmock-matchers.h>
#include <gtest/gtest.h>
#include "gtest-qt-printing.h"
using ClangBackEnd::DiagnosticContainer;
using ClangBackEnd::TranslationUnit;
using ClangBackEnd::TranslationUnitUpdateInput;
using ClangBackEnd::TranslationUnitUpdateResult;
using testing::ContainerEq;
using testing::Eq;
namespace {
class TranslationUnit : public ::testing::Test
{
protected:
void SetUp() override;
void TearDown() override;
void parse();
void reparse();
DiagnosticContainer createDiagnostic(const QString &text,
ClangBackEnd::DiagnosticSeverity severity,
uint line,
uint column,
const QString &filePath) const;
QVector<DiagnosticContainer> diagnosticsFromMainFile() const;
QVector<DiagnosticContainer> errorDiagnosticsFromHeaders() const;
protected:
Utf8String sourceFilePath = Utf8StringLiteral(TESTDATA_DIR"/diagnostic_erroneous_source.cpp");
Utf8String headerFilePath = Utf8StringLiteral(TESTDATA_DIR"/diagnostic_erroneous_header.h");
CXIndex cxIndex = nullptr;
CXTranslationUnit cxTranslationUnit = nullptr;
::TranslationUnit translationUnit{Utf8String(), sourceFilePath, cxIndex, cxTranslationUnit};
DiagnosticContainer extractedFirstHeaderErrorDiagnostic;
QVector<DiagnosticContainer> extractedMainFileDiagnostics;
};
TEST_F(TranslationUnit, HasExpectedMainFileDiagnostics)
{
translationUnit.extractDiagnostics(extractedFirstHeaderErrorDiagnostic,
extractedMainFileDiagnostics);
ASSERT_THAT(extractedMainFileDiagnostics, ContainerEq(diagnosticsFromMainFile()));
}
TEST_F(TranslationUnit, HasExpectedMainFileDiagnosticsAfterReparse)
{
reparse();
translationUnit.extractDiagnostics(extractedFirstHeaderErrorDiagnostic,
extractedMainFileDiagnostics);
ASSERT_THAT(extractedMainFileDiagnostics, ContainerEq(diagnosticsFromMainFile()));
}
TEST_F(TranslationUnit, HasErrorDiagnosticsInHeaders)
{
translationUnit.extractDiagnostics(extractedFirstHeaderErrorDiagnostic,
extractedMainFileDiagnostics);
ASSERT_THAT(extractedFirstHeaderErrorDiagnostic,
Eq(errorDiagnosticsFromHeaders().first()));
}
TEST_F(TranslationUnit, HasErrorDiagnosticsInHeadersAfterReparse)
{
reparse();
translationUnit.extractDiagnostics(extractedFirstHeaderErrorDiagnostic,
extractedMainFileDiagnostics);
ASSERT_THAT(extractedFirstHeaderErrorDiagnostic,
Eq(errorDiagnosticsFromHeaders().first()));
}
void TranslationUnit::SetUp()
{
parse();
}
void TranslationUnit::TearDown()
{
clang_disposeTranslationUnit(cxTranslationUnit);
clang_disposeIndex(cxIndex);
}
void TranslationUnit::parse()
{
TranslationUnitUpdateInput parseInput;
parseInput.filePath = sourceFilePath;
parseInput.parseNeeded = true;
const TranslationUnitUpdateResult parseResult = translationUnit.update(parseInput);
ASSERT_TRUE(parseResult.hasParsed());
}
void TranslationUnit::reparse()
{
TranslationUnitUpdateInput parseInput;
parseInput.filePath = sourceFilePath;
parseInput.reparseNeeded = true;
const TranslationUnitUpdateResult parseResult = translationUnit.update(parseInput);
ASSERT_TRUE(parseResult.hasReparsed());
}
DiagnosticContainer TranslationUnit::createDiagnostic(const QString &text,
ClangBackEnd::DiagnosticSeverity severity,
uint line,
uint column,
const QString &filePath) const
{
return DiagnosticContainer(
text,
Utf8StringLiteral(""),
{},
severity,
{filePath, line, column},
{},
{},
{}
);
}
QVector<ClangBackEnd::DiagnosticContainer> TranslationUnit::diagnosticsFromMainFile() const
{
return {
createDiagnostic(
QStringLiteral("warning: enumeration value 'Three' not handled in switch"),
ClangBackEnd::DiagnosticSeverity::Warning,
7,
13,
sourceFilePath),
createDiagnostic(
QStringLiteral("error: void function 'g' should not return a value"),
ClangBackEnd::DiagnosticSeverity::Error,
15,
5,
sourceFilePath),
createDiagnostic(
QStringLiteral("warning: using the result of an assignment as a condition without parentheses"),
ClangBackEnd::DiagnosticSeverity::Warning,
21,
11,
sourceFilePath),
};
}
QVector<ClangBackEnd::DiagnosticContainer> TranslationUnit::errorDiagnosticsFromHeaders() const
{
return {
createDiagnostic(
QStringLiteral("error: C++ requires a type specifier for all declarations"),
ClangBackEnd::DiagnosticSeverity::Error,
11,
1,
headerFilePath),
};
}
} // anonymous namespace

View File

@@ -0,0 +1,153 @@
/****************************************************************************
**
** Copyright (C) 2016 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 <clangbackend_global.h>
#include <clangexceptions.h>
#include <clangtranslationunit.h>
#include <clangtranslationunits.h>
#include <utf8string.h>
#include <clang-c/Index.h>
#include <gmock/gmock.h>
#include <gmock/gmock-matchers.h>
#include <gtest/gtest.h>
#include "gtest-qt-printing.h"
using ClangBackEnd::Clock;
using ClangBackEnd::TranslationUnit;
using ClangBackEnd::TranslationUnits;
using ClangBackEnd::TranslationUnitDoesNotExist;
using ClangBackEnd::PreferredTranslationUnit;
using testing::Eq;
namespace {
class TranslationUnits : public ::testing::Test
{
protected:
Utf8String someFilePath = Utf8StringLiteral("someFilePath");
ClangBackEnd::TranslationUnits translationUnits{someFilePath};
};
TEST_F(TranslationUnits, CreatedUnitIsNull)
{
TranslationUnit translationUnit = translationUnits.createAndAppend();
ASSERT_TRUE(translationUnit.isNull());
}
TEST_F(TranslationUnits, GetThrowsForNotExisting)
{
ASSERT_THROW(translationUnits.get(), TranslationUnitDoesNotExist);
}
TEST_F(TranslationUnits, GetForSingleTranslationUnit)
{
const TranslationUnit created = translationUnits.createAndAppend();
const TranslationUnit queried = translationUnits.get();
ASSERT_THAT(queried.id(), Eq(created.id()));
}
TEST_F(TranslationUnits, GetFirstForMultipleTranslationUnits)
{
const TranslationUnit created1 = translationUnits.createAndAppend();
translationUnits.createAndAppend();
const TranslationUnit queried = translationUnits.get();
ASSERT_THAT(queried.id(), Eq(created1.id()));
}
TEST_F(TranslationUnits, GetFirstForMultipleTranslationUnitsAndOnlyFirstParsed)
{
const TranslationUnit created1 = translationUnits.createAndAppend();
translationUnits.updateParseTimePoint(created1.id(), Clock::now());
translationUnits.createAndAppend();
const TranslationUnit queried = translationUnits.get();
ASSERT_THAT(queried.id(), Eq(created1.id()));
}
TEST_F(TranslationUnits, GetFirstForMultipleTranslationUnitsAndOnlySecondParsed)
{
const TranslationUnit created1 = translationUnits.createAndAppend();
const TranslationUnit created2 = translationUnits.createAndAppend();
translationUnits.updateParseTimePoint(created2.id(), Clock::now());
const TranslationUnit queried = translationUnits.get();
ASSERT_THAT(queried.id(), Eq(created1.id()));
}
TEST_F(TranslationUnits, GetLastUnitializedForMultipleTranslationUnits)
{
const TranslationUnit created1 = translationUnits.createAndAppend();
translationUnits.updateParseTimePoint(created1.id(), Clock::now());
const TranslationUnit created2 = translationUnits.createAndAppend();
const TranslationUnit queried = translationUnits.get(PreferredTranslationUnit::LastUninitialized);
ASSERT_THAT(queried.id(), Eq(created2.id()));
}
TEST_F(TranslationUnits, GetRecentForMultipleTranslationUnits)
{
const TranslationUnit created1 = translationUnits.createAndAppend();
translationUnits.updateParseTimePoint(created1.id(), Clock::now());
const TranslationUnit created2 = translationUnits.createAndAppend();
translationUnits.updateParseTimePoint(created2.id(), Clock::now());
const TranslationUnit queried = translationUnits.get(PreferredTranslationUnit::RecentlyParsed);
ASSERT_THAT(queried.id(), Eq(created2.id()));
}
TEST_F(TranslationUnits, GetPreviousForMultipleTranslationUnits)
{
const TranslationUnit created1 = translationUnits.createAndAppend();
translationUnits.updateParseTimePoint(created1.id(), Clock::now());
const TranslationUnit created2 = translationUnits.createAndAppend();
translationUnits.updateParseTimePoint(created2.id(), Clock::now());
const TranslationUnit queried = translationUnits.get(PreferredTranslationUnit::PreviouslyParsed);
ASSERT_THAT(queried.id(), Eq(created1.id()));
}
TEST_F(TranslationUnits, UpdateThrowsForNotExisting)
{
ClangBackEnd::TranslationUnits otherTranslationUnits{someFilePath};
const TranslationUnit translationUnit = otherTranslationUnits.createAndAppend();
ASSERT_THROW(translationUnits.updateParseTimePoint(translationUnit.id(), Clock::now()),
TranslationUnitDoesNotExist);
}
} // anonymous namespace

View File

@@ -97,7 +97,7 @@ TEST_F(UpdateDocumentAnnotationsJob, DontSendAnnotationsIfDocumentRevisionChange
TEST_F(UpdateDocumentAnnotationsJob, UpdatesTranslationUnit)
{
const time_point timePointBefore = document.lastProjectPartChangeTimePoint();
const TimePoint timePointBefore = document.lastProjectPartChangeTimePoint();
const QSet<Utf8String> dependendOnFilesBefore = document.dependedFilePaths();
job.setContext(jobContext);
job.prepareAsyncRun();

View File

@@ -277,6 +277,7 @@ TEST_F(ClientServerInProcess, SendDocumentAnnotationsChangedMessage)
ClangBackEnd::DocumentAnnotationsChangedMessage message(fileContainer,
{diagnostic},
{},
{highlightingMark},
QVector<SourceRangeContainer>());

View File

@@ -25,6 +25,8 @@
#include "googletest.h"
#include "clangcompareoperators.h"
#include <clangdocument.h>
#include <clangdocuments.h>
#include <clangstring.h>
@@ -68,6 +70,7 @@ struct Data {
{},
documents};
TranslationUnit translationUnit{filePath,
filePath,
document.translationUnit().cxIndex(),
document.translationUnit().cxTranslationUnit()};
};
@@ -84,6 +87,8 @@ protected:
const TranslationUnit &translationUnit = d->translationUnit;
};
TEST_F(Cursor, CreateNullCursor)
{
::Cursor cursor;
@@ -488,21 +493,21 @@ TEST_F(Cursor, HasNotFinaAttributeInClass)
TEST_F(Cursor, HasOutputValues)
{
auto callExpressionCursor = translationUnit.cursorAt(117, 19);
auto outputArgumentExpectedCursor = translationUnit.cursorAt(117, 20);
auto outputArgumentExpectedSourceLocation = translationUnit.cursorAt(117, 20).cxSourceRange();
auto outputArguments = callExpressionCursor.outputArguments();
auto outputArgumentLocations = callExpressionCursor.outputArgumentRanges();
ASSERT_THAT(outputArguments.size(), 1);
ASSERT_THAT(outputArguments[0], outputArgumentExpectedCursor);
ASSERT_THAT(outputArgumentLocations.size(), 2);
ASSERT_THAT(outputArgumentLocations[0], outputArgumentExpectedSourceLocation);
}
TEST_F(Cursor, HasOnlyInputValues)
{
auto callExpressionCursor = translationUnit.cursorAt(118, 18);
auto outputArguments = callExpressionCursor.outputArguments();
auto outputArgumentLocations = callExpressionCursor.outputArgumentRanges();
ASSERT_THAT(outputArguments, IsEmpty());
ASSERT_THAT(outputArgumentLocations, IsEmpty());
}
TEST_F(Cursor, ArgumentCountIsZero)
@@ -747,58 +752,58 @@ TEST_F(Cursor, PointerIsNotRefencingConstant)
ASSERT_FALSE(argument.isReferencingConstant());
}
TEST_F(Cursor, PointerIsOutputParameter)
TEST_F(Cursor, PointerIsOutputArgument)
{
auto callExpressionCursor = translationUnit.cursorAt(127, 13);
auto argument = callExpressionCursor.type().argument(0);
ASSERT_TRUE(argument.isOutputParameter());
ASSERT_TRUE(argument.isOutputArgument());
}
TEST_F(Cursor, ConstantReferenceIsNotOutputParameter)
TEST_F(Cursor, ConstantReferenceIsNotOutputArgument)
{
auto callExpressionCursor = translationUnit.cursorAt(125, 26);
auto argument = callExpressionCursor.type().argument(0);
ASSERT_FALSE(argument.isOutputParameter());
ASSERT_FALSE(argument.isOutputArgument());
}
TEST_F(Cursor, PointerToConstantIsNotOutputParameter)
TEST_F(Cursor, PointerToConstantIsNotOutputArgument)
{
auto callExpressionCursor = translationUnit.cursorAt(126, 20);
auto argument = callExpressionCursor.type().argument(0);
ASSERT_FALSE(argument.isOutputParameter()) << argument.isConstant() << argument.pointeeType().isConstant();
ASSERT_FALSE(argument.isOutputArgument()) << argument.isConstant() << argument.pointeeType().isConstant();
}
TEST_F(Cursor, ConstantPointerIsNotOutputParameter)
TEST_F(Cursor, ConstantPointerIsNotOutputArgument)
{
auto callExpressionCursor = translationUnit.cursorAt(128, 21);
auto argument = callExpressionCursor.type().argument(0);
ASSERT_TRUE(argument.isOutputParameter());
ASSERT_TRUE(argument.isOutputArgument());
}
TEST_F(Cursor, ReferenceIsOutputParameter)
TEST_F(Cursor, ReferenceIsOutputArgument)
{
auto callExpressionCursor = translationUnit.cursorAt(124, 21);
auto argument = callExpressionCursor.type().argument(0);
ASSERT_TRUE(argument.isOutputParameter());
ASSERT_TRUE(argument.isOutputArgument());
}
TEST_F(Cursor, ConstReferenceIsNotOutputParameter)
TEST_F(Cursor, ConstReferenceIsNotOutputArgument)
{
auto callExpressionCursor = translationUnit.cursorAt(125, 26);
auto argument = callExpressionCursor.type().argument(0);
ASSERT_FALSE(argument.isOutputParameter());
ASSERT_FALSE(argument.isOutputArgument());
}
Data *Cursor::d;

View File

@@ -278,12 +278,12 @@ void FinalClass::FinalClassThisCall()
}
void OutputParameter(int &one, const int &two, int *three=0);
void OutputArgument(int &one, const int &two, int *three=0);
void f12()
void f12b()
{
int One;
OutputParameter(One, 2);
OutputArgument(One, 2);
}
#include <highlightingmarks.h>
@@ -445,3 +445,83 @@ struct LambdaTester
lambda(var2);
}
};
void NonConstReferenceArgument(int &argument);
void f22()
{
int x = 1;
NonConstReferenceArgument(x);
}
void ConstReferenceArgument(const int &argument);
void f23()
{
int x = 1;
ConstReferenceArgument(x);
}
void RValueReferenceArgument(int &&argument);
void f24()
{
int x = 1;
RValueReferenceArgument(static_cast<int&&>(x));
}
void NonConstPointerArgument(int *argument);
void f25()
{
int *x;
NonConstPointerArgument(x);
}
void ConstPointerArgument(const int *argument);
void f26()
{
int *x;
ConstPointerArgument(x);
}
void NonConstReferenceArgumentCallInsideCall(int x, int &argument);
int GetArgument(int x);
void f27()
{
int x = 1;
NonConstReferenceArgumentCallInsideCall(GetArgument(x), x);
}
void f28(int &Reference)
{
NonConstReferenceArgument(Reference);
}
void f29()
{
int x;
NonConstPointerArgument(&x);
}
struct NonConstPointerArgumentAsMemberOfClass
{
int member;
};
void f30()
{
NonConstPointerArgumentAsMemberOfClass instance;
NonConstReferenceArgument(instance.member);
}

View File

@@ -107,10 +107,11 @@ struct Data {
Utf8String filePath{Utf8StringLiteral(TESTDATA_DIR"/highlightingmarks.cpp")};
Document document{filePath,
ProjectPart(Utf8StringLiteral("projectPartId"),
{Utf8StringLiteral("-std=c++14")}),
{Utf8StringLiteral("-std=c++14"), Utf8StringLiteral("-I" TESTDATA_DIR)}),
{},
documents};
TranslationUnit translationUnit{filePath,
filePath,
document.translationUnit().cxIndex(),
document.translationUnit().cxTranslationUnit()};
};
@@ -958,6 +959,106 @@ TEST_F(HighlightingMarks, TypeDefDeclarationUsage)
ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Type));
}
TEST_F(HighlightingMarks, NonConstReferenceArgument)
{
const auto infos = translationUnit.highlightingMarksInRange(sourceRange(455, 35));
infos[1];
ASSERT_THAT(infos[2],
HasTwoTypes(HighlightingType::LocalVariable, HighlightingType::OutputArgument));
}
TEST_F(HighlightingMarks, ConstReferenceArgument)
{
const auto infos = translationUnit.highlightingMarksInRange(sourceRange(464, 32));
infos[1];
ASSERT_THAT(infos[2],
HasOnlyType(HighlightingType::LocalVariable));
}
TEST_F(HighlightingMarks, RValueReferenceArgument)
{
const auto infos = translationUnit.highlightingMarksInRange(sourceRange(473, 52));
infos[1];
ASSERT_THAT(infos[8],
HasOnlyType(HighlightingType::LocalVariable));
}
TEST_F(HighlightingMarks, NonConstPointerArgument)
{
const auto infos = translationUnit.highlightingMarksInRange(sourceRange(482, 33));
infos[1];
ASSERT_THAT(infos[2],
HasTwoTypes(HighlightingType::LocalVariable, HighlightingType::OutputArgument));
}
TEST_F(HighlightingMarks, ConstPointerArgument)
{
const auto infos = translationUnit.highlightingMarksInRange(sourceRange(491, 30));
infos[1];
ASSERT_THAT(infos[2],
HasOnlyType(HighlightingType::LocalVariable));
}
TEST_F(HighlightingMarks, NonConstReferenceArgumentCallInsideCall)
{
const auto infos = translationUnit.highlightingMarksInRange(sourceRange(501, 64));
infos[1];
infos[3];
ASSERT_THAT(infos[7],
HasTwoTypes(HighlightingType::LocalVariable, HighlightingType::OutputArgument));
}
TEST_F(HighlightingMarks, OutputArgumentsAreEmptyAfterIteration)
{
const auto infos = translationUnit.highlightingMarksInRange(sourceRange(501, 63));
for (const auto &info : infos ) {}
ASSERT_TRUE(infos.currentOutputArgumentRangesAreEmpty());
}
TEST_F(HighlightingMarks, NonConstReferenceArgumentFromFunctionParameter)
{
const auto infos = translationUnit.highlightingMarksInRange(sourceRange(506, 42));
infos[1];
ASSERT_THAT(infos[2],
HasTwoTypes(HighlightingType::LocalVariable, HighlightingType::OutputArgument));
}
TEST_F(HighlightingMarks, NonConstPointerArgumentAsExpression)
{
const auto infos = translationUnit.highlightingMarksInRange(sourceRange(513, 33));
infos[1];
ASSERT_THAT(infos[3],
HasTwoTypes(HighlightingType::LocalVariable, HighlightingType::OutputArgument));
}
TEST_F(HighlightingMarks, NonConstPointerArgumentAsMemberOfClass)
{
const auto infos = translationUnit.highlightingMarksInRange(sourceRange(525, 46));
infos[1];
ASSERT_THAT(infos[4],
HasTwoTypes(HighlightingType::Field, HighlightingType::OutputArgument));
}
TEST_F(HighlightingMarks, DISABLED_EnumerationTypeDef)
{
const auto infos = translationUnit.highlightingMarksInRange(sourceRange(424, 41));

View File

@@ -25,12 +25,12 @@
#include "googletest.h"
#include <clangclock.h>
#include <projectpart.h>
#include <clangexceptions.h>
#include <projects.h>
#include <utf8stringvector.h>
#include <chrono>
#include <thread>
using testing::ElementsAre;
@@ -82,7 +82,7 @@ TEST(ProjectPart, TimeStampIsUpdatedAsArgumentChanged)
{
ClangBackEnd::ProjectPart project(Utf8StringLiteral("/tmp/blah.pro"));
auto lastChangeTimePoint = project.lastChangeTimePoint();
std::this_thread::sleep_for(std::chrono::steady_clock::duration(1));
std::this_thread::sleep_for(ClangBackEnd::Duration(1));
project.setArguments(Utf8StringVector({Utf8StringLiteral("-O"), Utf8StringLiteral("-fast")}));
@@ -163,7 +163,7 @@ TEST(ProjectPart, ProjectPartIsClearedAfterRemove)
projects.createOrUpdate({projectContainer});
ClangBackEnd::ProjectPart project = *projects.findProjectPart(projectContainer.projectPartId());
const auto lastChangeTimePoint = project.lastChangeTimePoint();
std::this_thread::sleep_for(std::chrono::steady_clock::duration(1));
std::this_thread::sleep_for(ClangBackEnd::Duration(1));
projects.remove({projectContainer.projectPartId()});

View File

@@ -186,6 +186,7 @@ TEST_F(ReadAndWriteMessageBlock, CompareDocumentAnnotationsChangedMessage)
CompareMessage(ClangBackEnd::DocumentAnnotationsChangedMessage(fileContainer,
{diagnostic},
{},
{highlightingMark},
QVector<ClangBackEnd::SourceRangeContainer>()));
}

View File

@@ -99,6 +99,7 @@ struct Data {
{},
documents};
TranslationUnit translationUnit{filePath,
filePath,
document.translationUnit().cxIndex(),
document.translationUnit().cxTranslationUnit()};
};

View File

@@ -103,6 +103,7 @@ struct Data {
Utf8StringVector(),
documents};
TranslationUnit translationUnit{filePath,
filePath,
document.translationUnit().cxIndex(),
document.translationUnit().cxTranslationUnit()};

View File

@@ -25,14 +25,18 @@
#include "googletest.h"
#include <clangclock.h>
#include <clangtranslationunitupdater.h>
#include <clang-c/Index.h>
using ClangBackEnd::Clock;
using ClangBackEnd::TimePoint;
using ClangBackEnd::TranslationUnitUpdater;
using ClangBackEnd::TranslationUnitUpdateInput;
using ClangBackEnd::TranslationUnitUpdateResult;
using testing::Eq;
using testing::Gt;
namespace {
@@ -42,7 +46,8 @@ class TranslationUnitUpdater : public ::testing::Test
protected:
void TearDown() override;
::TranslationUnitUpdater createUpdater(const TranslationUnitUpdateInput &input);
::TranslationUnitUpdater createUpdater(const TranslationUnitUpdateInput &input,
const Utf8String &translationUnitId = Utf8String());
enum ReparseMode { SetReparseNeeded, DoNotSetReparseNeeded };
TranslationUnitUpdateInput createInput(ReparseMode reparseMode = DoNotSetReparseNeeded);
@@ -73,10 +78,20 @@ TEST_F(TranslationUnitUpdater, ReparsesIfNeeded)
ASSERT_TRUE(result.hasReparsed());
}
TEST_F(TranslationUnitUpdater, PropagatesTranslationUnitId)
{
const Utf8String translationUnitId = Utf8StringLiteral("myId");
::TranslationUnitUpdater updater = createUpdater(createInput(SetReparseNeeded), translationUnitId);
TranslationUnitUpdateResult result = updater.update(::TranslationUnitUpdater::UpdateMode::AsNeeded);
ASSERT_THAT(result.translationUnitId, Eq(translationUnitId));
}
TEST_F(TranslationUnitUpdater, UpdatesParseTimePoint)
{
::TranslationUnitUpdater updater = createUpdater(createInput());
const std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
const TimePoint now = Clock::now();
TranslationUnitUpdateResult result = updater.update(::TranslationUnitUpdater::UpdateMode::AsNeeded);
@@ -111,9 +126,10 @@ void TranslationUnitUpdater::TearDown()
}
::TranslationUnitUpdater
TranslationUnitUpdater::createUpdater(const TranslationUnitUpdateInput &input)
TranslationUnitUpdater::createUpdater(const TranslationUnitUpdateInput &input,
const Utf8String &translationUnitId)
{
return ::TranslationUnitUpdater(cxIndex, cxTranslationUnit, input);
return ::TranslationUnitUpdater(translationUnitId, cxIndex, cxTranslationUnit, input);
}
TranslationUnitUpdateInput

View File

@@ -49,13 +49,20 @@ SOURCES += \
clangdiagnosticfilter-test.cpp \
clangdocuments-test.cpp \
clangdocument-test.cpp \
clangdocumentprocessor-test.cpp \
clangdocumentprocessors-test.cpp \
clangfixitoperation-test.cpp \
clangipcserver-test.cpp \
clangisdiagnosticrelatedtolocation-test.cpp \
clangjobqueue-test.cpp \
clangjobs-test.cpp \
clangparsesupportivetranslationunitjobtest.cpp \
clangreparsesupportivetranslationunitjobtest.cpp \
clangrequestdocumentannotationsjob-test.cpp \
clangsupportivetranslationunitinitializertest.cpp \
clangstring-test.cpp \
clangtranslationunit-test.cpp \
clangtranslationunits-test.cpp \
clangupdatedocumentannotationsjob-test.cpp \
codecompletionsextractor-test.cpp \
codecompletion-test.cpp \
@@ -111,6 +118,7 @@ HEADERS += \
chunksreportedmonitor.h \
clangasyncjob-base.h \
diagnosticcontainer-matcher.h \
clangcompareoperators.h \
dummyclangipcclient.h \
mockclangcodemodelclient.h \
mockclangcodemodelserver.h