Merge remote-tracking branch 'origin/4.6'

Conflicts:
	src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp

Change-Id: I4c619efd7c1060ffd759df44a03a111269d3478d
This commit is contained in:
Eike Ziller
2018-01-24 13:41:34 +01:00
29 changed files with 419 additions and 238 deletions

View File

@@ -405,7 +405,7 @@ void ClangEditorDocumentProcessor::updateProjectPartAndTranslationUnitForEditor(
const CppTools::ProjectPart::Ptr projectPart = m_parser->projectPartInfo().projectPart;
if (isProjectPartLoadedOrIsFallback(projectPart)) {
registerTranslationUnitForEditor(projectPart.data());
registerTranslationUnitForEditor(*projectPart.data());
m_projectPart = projectPart;
m_isProjectFile = m_parser->projectPartInfo().hints
@@ -421,7 +421,132 @@ void ClangEditorDocumentProcessor::onParserFinished()
updateProjectPartAndTranslationUnitForEditor();
}
void ClangEditorDocumentProcessor::registerTranslationUnitForEditor(CppTools::ProjectPart *projectPart)
namespace {
// TODO: Can we marry this with CompilerOptionsBuilder?
class FileOptionsBuilder
{
public:
FileOptionsBuilder(const QString &filePath, CppTools::ProjectPart &projectPart)
: m_filePath(filePath)
, m_projectPart(projectPart)
{
addLanguageOptions();
addDiagnosticOptions();
addGlobalOptions();
addPrecompiledHeaderOptions();
}
const QStringList &options() const { return m_options; }
private:
void addLanguageOptions()
{
// Determine file kind with respect to ambiguous headers.
CppTools::ProjectFile::Kind fileKind = CppTools::ProjectFile::classify(m_filePath);
if (fileKind == CppTools::ProjectFile::AmbiguousHeader) {
fileKind = m_projectPart.languageVersion <= CppTools::ProjectPart::LatestCVersion
? CppTools::ProjectFile::CHeader
: CppTools::ProjectFile::CXXHeader;
}
CppTools::CompilerOptionsBuilder builder(m_projectPart);
builder.addLanguageOption(fileKind);
m_options.append(builder.options());
}
void addDiagnosticOptions()
{
if (m_projectPart.project) {
ClangProjectSettings projectSettings(m_projectPart.project);
if (!projectSettings.useGlobalConfig()) {
const Core::Id warningConfigId = projectSettings.warningConfigId();
const CppTools::ClangDiagnosticConfigsModel configsModel(
CppTools::codeModelSettings()->clangCustomDiagnosticConfigs());
if (configsModel.hasConfigWithId(warningConfigId)) {
m_options.append(
configsModel.configWithId(warningConfigId).commandLineWarnings());
return;
}
}
}
m_options.append(
CppTools::codeModelSettings()->clangDiagnosticConfig().commandLineWarnings());
}
void addXclangArg(const QString &argName, const QString &argValue = QString())
{
m_options.append("-Xclang");
m_options.append(argName);
if (!argValue.isEmpty()) {
m_options.append("-Xclang");
m_options.append(argValue);
}
}
void addTidyOptions()
{
const QString tidyChecks = CppTools::codeModelSettings()->tidyChecks();
if (tidyChecks.isEmpty())
return;
addXclangArg("-add-plugin", "clang-tidy");
addXclangArg("-plugin-arg-clang-tidy", "-checks='-*" + tidyChecks + "'");
}
void addClazyOptions()
{
const QString clazyChecks = CppTools::codeModelSettings()->clazyChecks();
if (clazyChecks.isEmpty())
return;
addXclangArg("-add-plugin", "clang-lazy");
addXclangArg("-plugin-arg-clang-lazy", clazyChecks);
// NOTE: we already use -isystem for all include paths to make libclang skip diagnostics for
// all of them. That means that ignore-included-files will not change anything unless we decide
// to return the original -I prefix for some include paths.
addXclangArg("-plugin-arg-clang-lazy", "ignore-included-files");
}
void addGlobalOptions()
{
if (!m_projectPart.project)
m_options.append(ClangProjectSettings::globalCommandLineOptions());
else
m_options.append(ClangProjectSettings{m_projectPart.project}.commandLineOptions());
addTidyOptions();
addClazyOptions();
}
void addPrecompiledHeaderOptions()
{
using namespace CppTools;
if (getPchUsage() == CompilerOptionsBuilder::PchUsage::None)
return;
if (m_projectPart.precompiledHeaders.contains(m_filePath))
return;
CompilerOptionsBuilder builder(m_projectPart);
builder.addPrecompiledHeaderOptions(CompilerOptionsBuilder::PchUsage::Use);
m_options.append(builder.options());
}
private:
const QString &m_filePath;
const CppTools::ProjectPart &m_projectPart;
QStringList m_options;
};
} // namespace
void ClangEditorDocumentProcessor::registerTranslationUnitForEditor(
CppTools::ProjectPart &projectPart)
{
// On registration we send the document content immediately as an unsaved
// file, because
@@ -433,12 +558,13 @@ void ClangEditorDocumentProcessor::registerTranslationUnitForEditor(CppTools::Pr
// like on Windows.
if (m_projectPart) {
if (projectPart->id() == m_projectPart->id())
if (projectPart.id() == m_projectPart->id())
return;
}
const FileOptionsBuilder fileOptions(filePath(), projectPart);
m_communicator.registerTranslationUnitsForEditor(
{fileContainerWithArgumentsAndDocumentContent(projectPart)});
{fileContainerWithOptionsAndDocumentContent(projectPart, fileOptions.options())});
ClangCodeModel::Utils::setLastSentDocumentRevision(filePath(), revision());
}
@@ -503,137 +629,12 @@ ClangBackEnd::FileContainer ClangEditorDocumentProcessor::simpleFileContainer(
Utf8String::fromByteArray(codecName));
}
static CppTools::ProjectPart projectPartForLanguageOption(CppTools::ProjectPart *projectPart)
ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainerWithOptionsAndDocumentContent(
CppTools::ProjectPart &projectPart, const QStringList &fileOptions) const
{
if (projectPart)
return *projectPart;
return *CppTools::CppModelManager::instance()->fallbackProjectPart().data();
}
static QStringList languageOptions(const QString &filePath, CppTools::ProjectPart *projectPart)
{
const auto theProjectPart = projectPartForLanguageOption(projectPart);
// Determine file kind with respect to ambiguous headers.
CppTools::ProjectFile::Kind fileKind = CppTools::ProjectFile::classify(filePath);
if (fileKind == CppTools::ProjectFile::AmbiguousHeader) {
fileKind = theProjectPart.languageVersion <= CppTools::ProjectPart::LatestCVersion
? CppTools::ProjectFile::CHeader
: CppTools::ProjectFile::CXXHeader;
}
CppTools::CompilerOptionsBuilder builder(theProjectPart);
builder.addLanguageOption(fileKind);
return builder.options();
}
static QStringList warningOptions(CppTools::ProjectPart *projectPart)
{
if (projectPart && projectPart->project) {
ClangProjectSettings projectSettings(projectPart->project);
if (!projectSettings.useGlobalConfig()) {
const Core::Id warningConfigId = projectSettings.warningConfigId();
const CppTools::ClangDiagnosticConfigsModel configsModel(
CppTools::codeModelSettings()->clangCustomDiagnosticConfigs());
if (configsModel.hasConfigWithId(warningConfigId))
return configsModel.configWithId(warningConfigId).commandLineWarnings();
}
}
return CppTools::codeModelSettings()->clangDiagnosticConfig().commandLineWarnings();
}
static void addXclangArg(QStringList &list, const QString &argName,
const QString &argValue = QString())
{
list.append("-Xclang");
list.append(argName);
if (!argValue.isEmpty()) {
list.append("-Xclang");
list.append(argValue);
}
}
static QStringList tidyCommandLine()
{
const QString tidyChecks = CppTools::codeModelSettings()->tidyChecks();
if (tidyChecks.isEmpty())
return QStringList();
QStringList result;
addXclangArg(result, "-add-plugin", "clang-tidy");
addXclangArg(result, "-plugin-arg-clang-tidy", "-checks='-*" + tidyChecks + "'");
return result;
}
static QStringList clazyCommandLine()
{
const QString clazyChecks = CppTools::codeModelSettings()->clazyChecks();
if (clazyChecks.isEmpty())
return QStringList();
QStringList result;
addXclangArg(result, "-add-plugin", "clang-lazy");
addXclangArg(result, "-plugin-arg-clang-lazy", clazyChecks);
// NOTE: we already use -isystem for all include paths to make libclang skip diagnostics for
// all of them. That means that ignore-included-files will not change anything unless we decide
// to return the original -I prefix for some include paths.
addXclangArg(result, "-plugin-arg-clang-lazy", "ignore-included-files");
return result;
}
static QStringList commandLineOptions(CppTools::ProjectPart *projectPart)
{
QStringList result;
if (!projectPart || !projectPart->project)
result.append(ClangProjectSettings::globalCommandLineOptions());
else
result.append(ClangProjectSettings{projectPart->project}.commandLineOptions());
result.append(tidyCommandLine());
result.append(clazyCommandLine());
return result;
}
static QStringList precompiledHeaderOptions(
const QString& filePath,
CppTools::ProjectPart *projectPart)
{
using namespace CppTools;
if (CppTools::getPchUsage() == CompilerOptionsBuilder::PchUsage::None)
return QStringList();
if (projectPart->precompiledHeaders.contains(filePath))
return QStringList();
const CppTools::ProjectPart theProjectPart = projectPartForLanguageOption(projectPart);
CppTools::CompilerOptionsBuilder builder(theProjectPart);
builder.addPrecompiledHeaderOptions(CompilerOptionsBuilder::PchUsage::Use);
return builder.options();
}
static QStringList fileArguments(const QString &filePath, CppTools::ProjectPart *projectPart)
{
return languageOptions(filePath, projectPart)
+ warningOptions(projectPart)
+ commandLineOptions(projectPart)
+ precompiledHeaderOptions(filePath, projectPart);
}
ClangBackEnd::FileContainer
ClangEditorDocumentProcessor::fileContainerWithArgumentsAndDocumentContent(
CppTools::ProjectPart *projectPart) const
{
const QStringList theFileArguments = fileArguments(filePath(), projectPart);
return ClangBackEnd::FileContainer(filePath(),
projectPart->id(),
Utf8StringVector(theFileArguments),
projectPart.id(),
Utf8StringVector(fileOptions),
textDocument()->toPlainText(),
true,
revision());