diff options
author | Ivan Donchevskii <ivan.donchevskii@qt.io> | 2018-10-30 10:31:34 +0100 |
---|---|---|
committer | Ivan Donchevskii <ivan.donchevskii@qt.io> | 2018-11-01 14:52:05 +0000 |
commit | f604c8a77cf86663fc751bcf23c94697088cfda1 (patch) | |
tree | c98bc2ff2e694f3d93650260f8144e1e8c522f2f /src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp | |
parent | cb75aa3e58987ed3cd8ac5e1dde089b855f731b2 (diff) |
CompilationDatabase: Support both code models
Extract headers, defines and fileKind from flags in
order to have complete project parts.
Side-effect: better support for MSVC-specific flags.
Change-Id: Iaa1413c91c96c3cf89ddbe76a7a1f0f46c5289c0
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
Diffstat (limited to 'src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp')
-rw-r--r-- | src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp new file mode 100644 index 00000000000..30ad52160ed --- /dev/null +++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseutils.cpp @@ -0,0 +1,216 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 "compilationdatabaseutils.h" + +#include <projectexplorer/headerpath.h> +#include <projectexplorer/projectmacro.h> + +#include <utils/hostosinfo.h> +#include <utils/optional.h> + +#include <QDir> +#include <QRegularExpression> + +using namespace ProjectExplorer; + +namespace CompilationDatabaseProjectManager { + +static QString updatedPathFlag(const QString &pathStr, const QString &workingDir) +{ + QString result = pathStr; + if (!QDir(pathStr).exists() + && QDir(workingDir + "/" + pathStr).exists()) { + result = workingDir + "/" + pathStr; + } + + return result; +} + +static CppTools::ProjectFile::Kind fileKindFromString(const QString &flag) +{ + using namespace CppTools; + if (flag == "c++-header") + return ProjectFile::CXXHeader; + if (flag == "c-header") + return ProjectFile::CHeader; + if (flag == "c++" || flag == "/TP" || flag.startsWith("/Tp")) + return ProjectFile::CXXSource; + if (flag == "c" || flag == "/TC" || flag.startsWith("/Tc")) + return ProjectFile::CSource; + + if (flag == "objective-c++") + return ProjectFile::ObjCXXSource; + if (flag == "objective-c++-header") + return ProjectFile::ObjCXXHeader; + if (flag == "objective-c") + return ProjectFile::ObjCSource; + if (flag == "objective-c-header") + return ProjectFile::ObjCHeader; + + if (flag == "cl") + return ProjectFile::OpenCLSource; + if (flag == "cuda") + return ProjectFile::CudaSource; + + return ProjectFile::Unclassified; +} + +void filteredFlags(const QString &fileName, + const QString &workingDir, + QStringList &flags, + HeaderPaths &headerPaths, + Macros ¯os, + CppTools::ProjectFile::Kind &fileKind) +{ + if (flags.isEmpty()) + return; + + // Skip compiler call if present. + bool skipNext = Utils::HostOsInfo::isWindowsHost() + ? (!flags.first().startsWith('/') && !flags.first().startsWith('-')) + : (!flags.first().startsWith('-')); + Utils::optional<HeaderPathType> includePathType; + Utils::optional<MacroType> macroType; + bool fileKindIsNext = false; + + QStringList filtered; + for (const QString &flag : flags) { + if (skipNext) { + skipNext = false; + continue; + } + + if (includePathType) { + const QString pathStr = updatedPathFlag(flag, workingDir); + headerPaths.append({pathStr, includePathType.value()}); + includePathType.reset(); + continue; + } + + if (macroType) { + Macro macro = Macro::fromKeyValue(flag); + macro.type = macroType.value(); + macros.append(macro); + macroType.reset(); + continue; + } + + if (fileKindIsNext || flag == "/TC" || flag == "/TP" + || flag.startsWith("/Tc") || flag.startsWith("/Tp")) { + fileKindIsNext = false; + fileKind = fileKindFromString(flag); + continue; + } + + if (flag == "-x") { + fileKindIsNext = true; + continue; + } + + if (flag == "-c" || flag == "-pedantic" + || flag.startsWith("-O") || flag.startsWith("-W") || flag.startsWith("-w") + || QString::compare(flag, "-fpic", Qt::CaseInsensitive) == 0 + || QString::compare(flag, "-fpie", Qt::CaseInsensitive) == 0) { + continue; + } + + if (flag.endsWith(fileName)) + continue; + + if ((flag.startsWith("-I") || flag.startsWith("-isystem") || flag.startsWith("/I")) + && flag != "-I" && flag != "-isystem" && flag != "/I") { + bool userInclude = flag.startsWith("-I"); + const QString pathStr = updatedPathFlag(flag.mid(userInclude ? 2 : 8), + workingDir); + headerPaths.append({pathStr, userInclude + ? HeaderPathType::User + : HeaderPathType::System}); + continue; + } + + if ((flag.startsWith("-D") || flag.startsWith("-U") || flag.startsWith("/D") || flag.startsWith("/U")) + && flag != "-D" && flag != "-U" && flag != "/D" && flag != "/U") { + Macro macro = Macro::fromKeyValue(flag.mid(2)); + macro.type = (flag.startsWith("-D") || flag.startsWith("/D")) ? MacroType::Define : MacroType::Undefine; + macros.append(macro); + continue; + } + + if (flag == "-I" || flag == "-isystem" || flag == "/I") { + includePathType = (flag != "-isystem") ? HeaderPathType::User : HeaderPathType::System; + continue; + } + + if (flag == "-D" || flag == "-U" || flag == "/D" || flag == "/U") { + macroType = (flag == "-D" || flag == "/D") ? MacroType::Define : MacroType::Undefine; + continue; + } + + if ((flag.startsWith("-std=") || flag.startsWith("/std:")) + && fileKind == CppTools::ProjectFile::Unclassified) { + const bool cpp = (flag.contains("c++") || flag.contains("gnu++")); + if (CppTools::ProjectFile::isHeader(CppTools::ProjectFile::classify(fileName))) + fileKind = cpp ? CppTools::ProjectFile::CXXHeader : CppTools::ProjectFile::CHeader; + else + fileKind = cpp ? CppTools::ProjectFile::CXXSource : CppTools::ProjectFile::CXXHeader; + } + + // Skip all remaining Windows flags except feature flags. + if (flag.startsWith("/") && !flag.startsWith("/Z")) + continue; + + filtered.push_back(flag); + } + + if (fileKind == CppTools::ProjectFile::Unclassified) + fileKind = CppTools::ProjectFile::classify(fileName); + + flags = filtered; +} + +QStringList splitCommandLine(QString commandLine) +{ + QStringList result; + bool insideQuotes = false; + + // Remove escaped quotes. + commandLine.replace("\\\"", "'"); + for (const QString &part : commandLine.split(QRegularExpression("\""))) { + if (insideQuotes) { + const QString quotedPart = "\"" + part + "\""; + if (result.last().endsWith("=")) + result.last().append(quotedPart); + else + result.append(quotedPart); + } else { // If 's' is outside quotes ... + result.append(part.split(QRegularExpression("\\s+"), QString::SkipEmptyParts)); + } + insideQuotes = !insideQuotes; + } + return result; +} + +} // namespace CompilationDatabaseProjectManager |