forked from qt-creator/qt-creator
RunControl: Handle also ProjectInfo::CompilerCallData
...if it's available. Change-Id: I41b8ab30e0c87ddd223f115e759bbd2a2c86cc68 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
This commit is contained in:
@@ -58,27 +58,103 @@ ClangStaticAnalyzerRunControl::ClangStaticAnalyzerRunControl(
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static QList<ClangStaticAnalyzerRunControl::SourceFileConfiguration> calculateFilesToProcess(
|
// Removes (1) filePath (2) -o <somePath>
|
||||||
Project *project)
|
static QStringList tweakedArguments(const QString &filePath, const QStringList &arguments)
|
||||||
{
|
{
|
||||||
typedef ClangStaticAnalyzerRunControl::SourceFileConfiguration SourceFileConfiguration;
|
QStringList newArguments;
|
||||||
QTC_ASSERT(project, return QList<SourceFileConfiguration>());
|
|
||||||
ProjectInfo projectInfo = CppModelManager::instance()->projectInfo(project);
|
bool skip = false;
|
||||||
QTC_ASSERT(projectInfo.isValid(), return QList<SourceFileConfiguration>());
|
foreach (const QString &argument, arguments) {
|
||||||
|
if (skip) {
|
||||||
|
skip = false;
|
||||||
|
continue;
|
||||||
|
} else if (argument == QLatin1String("-o")) {
|
||||||
|
skip = true;
|
||||||
|
continue;
|
||||||
|
} else if (argument == filePath) {
|
||||||
|
continue; // TODO: Let it in?
|
||||||
|
}
|
||||||
|
|
||||||
|
newArguments << argument;
|
||||||
|
}
|
||||||
|
QTC_CHECK(skip == false);
|
||||||
|
|
||||||
|
return newArguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QStringList argumentsFromProjectPart(const CppTools::ProjectPart::Ptr &projectPart,
|
||||||
|
CppTools::ProjectFile::Kind fileKind)
|
||||||
|
{
|
||||||
|
QStringList result;
|
||||||
|
|
||||||
|
const bool objcExt = projectPart->languageExtensions & ProjectPart::ObjectiveCExtensions;
|
||||||
|
result += CppTools::CompilerOptionsBuilder::createLanguageOption(fileKind, objcExt);
|
||||||
|
result += CppTools::CompilerOptionsBuilder::createOptionsForLanguage(
|
||||||
|
projectPart->languageVersion,
|
||||||
|
projectPart->languageExtensions);
|
||||||
|
result += CppTools::CompilerOptionsBuilder::createDefineOptions(projectPart->toolchainDefines);
|
||||||
|
result += CppTools::CompilerOptionsBuilder::createDefineOptions(projectPart->projectDefines);
|
||||||
|
result += CppTools::CompilerOptionsBuilder::createHeaderPathOptions(projectPart->headerPaths);
|
||||||
|
result += QLatin1String("-fPIC"); // TODO: Remove?
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QList<ClangStaticAnalyzerRunControl::AnalyzeUnit> unitsToAnalyzeFromCompilerCallData(
|
||||||
|
const ProjectInfo::CompilerCallData &compilerCallData)
|
||||||
|
{
|
||||||
|
typedef ClangStaticAnalyzerRunControl::AnalyzeUnit AnalyzeUnit;
|
||||||
|
qCDebug(LOG) << "Taking arguments for analyzing from CompilerCallData.";
|
||||||
|
|
||||||
|
QList<ClangStaticAnalyzerRunControl::AnalyzeUnit> unitsToAnalyze;
|
||||||
|
|
||||||
|
QHashIterator<QString, QList<QStringList> > it(compilerCallData);
|
||||||
|
while (it.hasNext()) {
|
||||||
|
it.next();
|
||||||
|
const QString file = it.key();
|
||||||
|
const QList<QStringList> compilerCalls = it.value();
|
||||||
|
foreach (const QStringList &options, compilerCalls) {
|
||||||
|
const QStringList arguments = tweakedArguments(file, options);
|
||||||
|
unitsToAnalyze << AnalyzeUnit(file, arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return unitsToAnalyze;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QList<ClangStaticAnalyzerRunControl::AnalyzeUnit> unitsToAnalyzeFromProjectParts(
|
||||||
|
const QList<ProjectPart::Ptr> projectParts)
|
||||||
|
{
|
||||||
|
typedef ClangStaticAnalyzerRunControl::AnalyzeUnit AnalyzeUnit;
|
||||||
|
qCDebug(LOG) << "Taking arguments for analyzing from ProjectParts.";
|
||||||
|
|
||||||
|
QList<ClangStaticAnalyzerRunControl::AnalyzeUnit> unitsToAnalyze;
|
||||||
|
|
||||||
QList<SourceFileConfiguration> files;
|
|
||||||
const QList<ProjectPart::Ptr> projectParts = projectInfo.projectParts();
|
|
||||||
foreach (const ProjectPart::Ptr &projectPart, projectParts) {
|
foreach (const ProjectPart::Ptr &projectPart, projectParts) {
|
||||||
foreach (const ProjectFile &file, projectPart->files) {
|
foreach (const ProjectFile &file, projectPart->files) {
|
||||||
if (file.path == CppModelManager::configurationFileName())
|
if (file.path == CppModelManager::configurationFileName())
|
||||||
continue;
|
continue;
|
||||||
QTC_CHECK(file.kind != ProjectFile::Unclassified);
|
QTC_CHECK(file.kind != ProjectFile::Unclassified);
|
||||||
if (ProjectFile::isSource(file.kind))
|
if (ProjectFile::isSource(file.kind)) {
|
||||||
files << SourceFileConfiguration(file, projectPart);
|
const QStringList arguments = argumentsFromProjectPart(projectPart, file.kind);
|
||||||
|
unitsToAnalyze << AnalyzeUnit(file.path, arguments);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return files;
|
return unitsToAnalyze;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QList<ClangStaticAnalyzerRunControl::AnalyzeUnit> unitsToAnalyze(Project *project)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(project, return QList<ClangStaticAnalyzerRunControl::AnalyzeUnit>());
|
||||||
|
ProjectInfo projectInfo = CppModelManager::instance()->projectInfo(project);
|
||||||
|
QTC_ASSERT(projectInfo.isValid(), return QList<ClangStaticAnalyzerRunControl::AnalyzeUnit>());
|
||||||
|
|
||||||
|
const ProjectInfo::CompilerCallData compilerCallData = projectInfo.compilerCallData();
|
||||||
|
if (!compilerCallData.isEmpty())
|
||||||
|
return unitsToAnalyzeFromCompilerCallData(compilerCallData);
|
||||||
|
return unitsToAnalyzeFromProjectParts(projectInfo.projectParts());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClangStaticAnalyzerRunControl::startEngine()
|
bool ClangStaticAnalyzerRunControl::startEngine()
|
||||||
@@ -120,14 +196,12 @@ bool ClangStaticAnalyzerRunControl::startEngine()
|
|||||||
m_clangLogFileDir = temporaryDir.path();
|
m_clangLogFileDir = temporaryDir.path();
|
||||||
|
|
||||||
// Collect files
|
// Collect files
|
||||||
const QList<SourceFileConfiguration> filesToProcess = calculateFilesToProcess(project);
|
const QList<AnalyzeUnit> filesToProcess = unitsToAnalyze(project);
|
||||||
qCDebug(LOG) << "Files to process:";
|
qCDebug(LOG) << "Files to process:";
|
||||||
foreach (const SourceFileConfiguration &fileConfig, filesToProcess) {
|
foreach (const AnalyzeUnit &fileConfig, filesToProcess)
|
||||||
qCDebug(LOG) << fileConfig.file.path + QLatin1String(" [")
|
qCDebug(LOG) << fileConfig.file;
|
||||||
+ fileConfig.projectPart->projectFile + QLatin1Char(']');
|
m_unitsToProcess = filesToProcess;
|
||||||
}
|
m_initialFilesToProcessSize = m_unitsToProcess.count();
|
||||||
m_filesToProcess = filesToProcess;
|
|
||||||
m_initialFilesToProcessSize = m_filesToProcess.count();
|
|
||||||
m_filesAnalyzed = 0;
|
m_filesAnalyzed = 0;
|
||||||
m_filesNotAnalyzed = 0;
|
m_filesNotAnalyzed = 0;
|
||||||
|
|
||||||
@@ -145,7 +219,7 @@ bool ClangStaticAnalyzerRunControl::startEngine()
|
|||||||
m_runners.clear();
|
m_runners.clear();
|
||||||
const int parallelRuns = ClangStaticAnalyzerSettings::instance()->simultaneousProcesses();
|
const int parallelRuns = ClangStaticAnalyzerSettings::instance()->simultaneousProcesses();
|
||||||
QTC_ASSERT(parallelRuns >= 1, emit finished(); return false);
|
QTC_ASSERT(parallelRuns >= 1, emit finished(); return false);
|
||||||
while (m_runners.size() < parallelRuns && !m_filesToProcess.isEmpty())
|
while (m_runners.size() < parallelRuns && !m_unitsToProcess.isEmpty())
|
||||||
analyzeNextFile();
|
analyzeNextFile();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -159,7 +233,7 @@ void ClangStaticAnalyzerRunControl::stopEngine()
|
|||||||
delete runner;
|
delete runner;
|
||||||
}
|
}
|
||||||
m_runners.clear();
|
m_runners.clear();
|
||||||
m_filesToProcess.clear();
|
m_unitsToProcess.clear();
|
||||||
appendMessage(tr("Clang Static Analyzer stopped by user.") + QLatin1Char('\n'),
|
appendMessage(tr("Clang Static Analyzer stopped by user.") + QLatin1Char('\n'),
|
||||||
Utils::NormalMessageFormat);
|
Utils::NormalMessageFormat);
|
||||||
m_progress.reportFinished();
|
m_progress.reportFinished();
|
||||||
@@ -171,7 +245,7 @@ void ClangStaticAnalyzerRunControl::analyzeNextFile()
|
|||||||
if (m_progress.isFinished())
|
if (m_progress.isFinished())
|
||||||
return; // The previous call already reported that we are finished.
|
return; // The previous call already reported that we are finished.
|
||||||
|
|
||||||
if (m_filesToProcess.isEmpty()) {
|
if (m_unitsToProcess.isEmpty()) {
|
||||||
if (m_runners.size() == 0) {
|
if (m_runners.size() == 0) {
|
||||||
appendMessage(tr("Clang Static Analyzer finished: "
|
appendMessage(tr("Clang Static Analyzer finished: "
|
||||||
"Processed %1 files successfully, %2 failed.")
|
"Processed %1 files successfully, %2 failed.")
|
||||||
@@ -185,15 +259,14 @@ void ClangStaticAnalyzerRunControl::analyzeNextFile()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SourceFileConfiguration config = m_filesToProcess.takeFirst();
|
const AnalyzeUnit unit = m_unitsToProcess.takeFirst();
|
||||||
const QString filePath = config.file.path;
|
qCDebug(LOG) << "analyzeNextFile:" << unit.file;
|
||||||
const QStringList options = config.createClangOptions();
|
|
||||||
|
|
||||||
ClangStaticAnalyzerRunner *runner = createRunner();
|
ClangStaticAnalyzerRunner *runner = createRunner();
|
||||||
m_runners.insert(runner);
|
m_runners.insert(runner);
|
||||||
qCDebug(LOG) << "analyzeNextFile:" << filePath;
|
QTC_ASSERT(runner->run(unit.file, unit.arguments), return);
|
||||||
QTC_ASSERT(runner->run(filePath, options), return);
|
|
||||||
appendMessage(tr("Analyzing \"%1\".").arg(filePath) + QLatin1Char('\n'),
|
appendMessage(tr("Analyzing \"%1\".").arg(unit.file) + QLatin1Char('\n'),
|
||||||
Utils::StdOutFormat);
|
Utils::StdOutFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,24 +337,7 @@ void ClangStaticAnalyzerRunControl::onProgressCanceled()
|
|||||||
|
|
||||||
void ClangStaticAnalyzerRunControl::updateProgressValue()
|
void ClangStaticAnalyzerRunControl::updateProgressValue()
|
||||||
{
|
{
|
||||||
m_progress.setProgressValue(m_initialFilesToProcessSize - m_filesToProcess.size());
|
m_progress.setProgressValue(m_initialFilesToProcessSize - m_unitsToProcess.size());
|
||||||
}
|
|
||||||
|
|
||||||
QStringList ClangStaticAnalyzerRunControl::SourceFileConfiguration::createClangOptions() const
|
|
||||||
{
|
|
||||||
QStringList result;
|
|
||||||
|
|
||||||
const bool objcExt = projectPart->languageExtensions & ProjectPart::ObjectiveCExtensions;
|
|
||||||
result += CppTools::CompilerOptionsBuilder::createLanguageOption(file.kind, objcExt);
|
|
||||||
result += CppTools::CompilerOptionsBuilder::createOptionsForLanguage(
|
|
||||||
projectPart->languageVersion,
|
|
||||||
projectPart->languageExtensions);
|
|
||||||
result += CppTools::CompilerOptionsBuilder::createDefineOptions(projectPart->toolchainDefines);
|
|
||||||
result += CppTools::CompilerOptionsBuilder::createDefineOptions(projectPart->projectDefines);
|
|
||||||
result += CppTools::CompilerOptionsBuilder::createHeaderPathOptions(projectPart->headerPaths);
|
|
||||||
result += QLatin1String("-fPIC"); // TODO: Remove?
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -36,16 +36,12 @@ class ClangStaticAnalyzerRunControl : public Analyzer::AnalyzerRunControl
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct SourceFileConfiguration {
|
struct AnalyzeUnit {
|
||||||
SourceFileConfiguration(const CppTools::ProjectFile &projectFile,
|
AnalyzeUnit(const QString &file, const QStringList &options)
|
||||||
const CppTools::ProjectPart::Ptr &projectPart)
|
: file(file), arguments(options) {}
|
||||||
: file(projectFile)
|
|
||||||
, projectPart(projectPart) {}
|
|
||||||
|
|
||||||
QStringList createClangOptions() const;
|
QString file;
|
||||||
|
QStringList arguments; // without file itself and "-o somePath"
|
||||||
CppTools::ProjectFile file;
|
|
||||||
CppTools::ProjectPart::Ptr projectPart;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -73,7 +69,7 @@ private:
|
|||||||
QString m_clangExecutable;
|
QString m_clangExecutable;
|
||||||
QString m_clangLogFileDir;
|
QString m_clangLogFileDir;
|
||||||
QFutureInterface<void> m_progress;
|
QFutureInterface<void> m_progress;
|
||||||
QList<SourceFileConfiguration> m_filesToProcess;
|
QList<AnalyzeUnit> m_unitsToProcess;
|
||||||
QSet<ClangStaticAnalyzerRunner *> m_runners;
|
QSet<ClangStaticAnalyzerRunner *> m_runners;
|
||||||
int m_initialFilesToProcessSize;
|
int m_initialFilesToProcessSize;
|
||||||
int m_filesAnalyzed;
|
int m_filesAnalyzed;
|
||||||
|
Reference in New Issue
Block a user