Clang: Extract TranslationUnitUpdater

...in preparation for concurrent processing of documents.

Parsing and reparsing is handled by TranslationUnit. Since we will do
this in a different thread, extract the core logic into the new class
TranslationUnitUpdater, so that we can prepare the necessary data for
the run and then later incorporate the results of the parse/reparse.

Change-Id: Ic9d936d193ee6795a755f0cfc38c0b2a7bd402cc
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Nikolai Kosjar
2016-07-15 12:30:25 +02:00
parent 606d41187c
commit dc734f45fd
10 changed files with 541 additions and 157 deletions

View File

@@ -0,0 +1,218 @@
/****************************************************************************
**
** 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 "clangtranslationunitupdater.h"
#include "clangfilepath.h"
#include "clangstring.h"
#include "clangunsavedfilesshallowarguments.h"
#include "translationunitparseerrorexception.h"
#include "translationunitreparseerrorexception.h"
#include <QLoggingCategory>
static Q_LOGGING_CATEGORY(verboseLibLog, "qtc.clangbackend.verboselib");
static bool isVerboseModeEnabled()
{
return verboseLibLog().isDebugEnabled();
}
namespace ClangBackEnd {
TranslationUnitUpdater::TranslationUnitUpdater(CXIndex &index,
CXTranslationUnit &cxTranslationUnit,
const TranslationUnitUpdateInput &updateData)
: m_cxIndex(index)
, m_cxTranslationUnit(cxTranslationUnit)
, m_in(updateData)
{
}
TranslationUnitUpdateResult TranslationUnitUpdater::update(UpdateMode mode)
{
createIndexIfNeeded();
switch (mode) {
case UpdateMode::AsNeeded:
recreateAndParseIfNeeded();
reparseIfNeeded();
break;
case UpdateMode::ParseIfNeeded:
recreateAndParseIfNeeded();
break;
case UpdateMode::ForceReparse:
reparse();
break;
}
return m_out;
}
void TranslationUnitUpdater::recreateAndParseIfNeeded()
{
removeTranslationUnitIfProjectPartWasChanged();
createTranslationUnitIfNeeded();
}
void TranslationUnitUpdater::removeTranslationUnitIfProjectPartWasChanged()
{
if (m_in.parseNeeded) {
clang_disposeTranslationUnit(m_cxTranslationUnit);
m_cxTranslationUnit = nullptr;
}
}
void TranslationUnitUpdater::createTranslationUnitIfNeeded()
{
if (!m_cxTranslationUnit) {
m_cxTranslationUnit = CXTranslationUnit();
const auto args = commandLineArguments();
if (isVerboseModeEnabled())
args.print();
UnsavedFilesShallowArguments unsaved = m_in.unsavedFiles.shallowArguments();
m_parseErrorCode = clang_parseTranslationUnit2(m_cxIndex,
NULL,
args.data(),
args.count(),
unsaved.data(),
unsaved.count(),
defaultParseOptions(),
&m_cxTranslationUnit);
checkParseErrorCode();
updateIncludeFilePaths();
updateLastProjectPartChangeTimePoint();
}
}
void TranslationUnitUpdater::reparseIfNeeded()
{
if (m_in.reparseNeeded)
reparse();
}
void TranslationUnitUpdater::reparse()
{
UnsavedFilesShallowArguments unsaved = m_in.unsavedFiles.shallowArguments();
m_reparseErrorCode = clang_reparseTranslationUnit(
m_cxTranslationUnit,
unsaved.count(),
unsaved.data(),
clang_defaultReparseOptions(m_cxTranslationUnit));
checkReparseErrorCode();
updateIncludeFilePaths();
m_out.reparsed = true;
}
void TranslationUnitUpdater::updateIncludeFilePaths()
{
m_out.dependedOnFilePaths.clear();
m_out.dependedOnFilePaths.insert(m_in.filePath);
clang_getInclusions(m_cxTranslationUnit,
includeCallback,
const_cast<TranslationUnitUpdater *>(this));
}
void TranslationUnitUpdater::checkParseErrorCode() const
{
if (!parseWasSuccessful()) {
throw TranslationUnitParseErrorException(m_in.filePath,
m_in.projectId,
m_parseErrorCode);
}
}
void TranslationUnitUpdater::checkReparseErrorCode() const
{
if (!reparseWasSuccessful()) {
throw TranslationUnitReparseErrorException(m_in.filePath,
m_in.projectId,
m_reparseErrorCode);
}
}
uint TranslationUnitUpdater::defaultParseOptions()
{
return CXTranslationUnit_CacheCompletionResults
| CXTranslationUnit_PrecompiledPreamble
| CXTranslationUnit_IncludeBriefCommentsInCodeCompletion
| CXTranslationUnit_DetailedPreprocessingRecord;
}
void TranslationUnitUpdater::createIndexIfNeeded()
{
if (!m_cxIndex) {
const bool displayDiagnostics = isVerboseModeEnabled();
m_cxIndex = clang_createIndex(1, displayDiagnostics);
}
}
void TranslationUnitUpdater::updateLastProjectPartChangeTimePoint()
{
m_out.parseTimePointIsSet = true;
m_out.parseTimePoint = std::chrono::steady_clock::now();
}
void TranslationUnitUpdater::includeCallback(CXFile included_file,
CXSourceLocation *,
unsigned, CXClientData clientData)
{
ClangString includeFilePath(clang_getFileName(included_file));
TranslationUnitUpdater *updater = static_cast<TranslationUnitUpdater *>(clientData);
updater->m_out.dependedOnFilePaths.insert(FilePath::fromNativeSeparators(includeFilePath));
}
bool TranslationUnitUpdater::parseWasSuccessful() const
{
return m_parseErrorCode == CXError_Success;
}
bool TranslationUnitUpdater::reparseWasSuccessful() const
{
return m_reparseErrorCode == 0;
}
CommandLineArguments TranslationUnitUpdater::commandLineArguments() const
{
return CommandLineArguments(m_in.filePath.constData(),
m_in.projectArguments,
m_in.fileArguments,
isVerboseModeEnabled());
}
} // namespace ClangBackEnd