/**************************************************************************** ** ** 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 "clangdiagnosticfilter.h" #include #include namespace { bool isWarningOrNote(ClangBackEnd::DiagnosticSeverity severity) { using ClangBackEnd::DiagnosticSeverity; switch (severity) { case DiagnosticSeverity::Ignored: case DiagnosticSeverity::Note: case DiagnosticSeverity::Warning: return true; case DiagnosticSeverity::Error: case DiagnosticSeverity::Fatal: return false; } Q_UNREACHABLE(); } bool isBlackListedHeaderDiagnostic(const ClangBackEnd::DiagnosticContainer &diagnostic, bool isHeaderFile) { static const Utf8StringVector blackList{ Utf8StringLiteral("warning: #pragma once in main file"), Utf8StringLiteral("warning: #include_next in primary source file") }; return isHeaderFile && blackList.contains(diagnostic.text); } bool isBlackListedQtDiagnostic(const ClangBackEnd::DiagnosticContainer &diagnostic) { static const Utf8StringVector blackList{ // From Q_OBJECT: Utf8StringLiteral("warning: " "'metaObject' overrides a member function but is not marked 'override'"), Utf8StringLiteral("warning: " "'qt_metacast' overrides a member function but is not marked 'override'"), Utf8StringLiteral("warning: " "'qt_metacall' overrides a member function but is not marked 'override'"), }; return blackList.contains(diagnostic.text); } template QVector filterDiagnostics(const QVector &diagnostics, const Condition &condition) { QVector filteredDiagnostics; std::copy_if(diagnostics.cbegin(), diagnostics.cend(), std::back_inserter(filteredDiagnostics), condition); return filteredDiagnostics; } template void filterDiagnostics(const QVector &diagnostics, const Condition &condition, QVector &filteredDiagnostic) { std::copy_if(diagnostics.cbegin(), diagnostics.cend(), std::back_inserter(filteredDiagnostic), condition); } } // anonymous namespace namespace ClangCodeModel { namespace Internal { void ClangDiagnosticFilter::filterDocumentRelatedWarnings( const QVector &diagnostics) { using namespace CppEditor; const bool isHeaderFile = ProjectFile::isHeader(ProjectFile::classify(m_filePath)); const auto isLocalWarning = [this, isHeaderFile] (const ClangBackEnd::DiagnosticContainer &diagnostic) { return isWarningOrNote(diagnostic.severity) && !isBlackListedHeaderDiagnostic(diagnostic, isHeaderFile) && !isBlackListedQtDiagnostic(diagnostic) && diagnostic.location.filePath == m_filePath; }; m_warningDiagnostics = filterDiagnostics(diagnostics, isLocalWarning); } void ClangDiagnosticFilter::filterDocumentRelatedErrors( const QVector &diagnostics) { const auto isLocalWarning = [this] (const ClangBackEnd::DiagnosticContainer &diagnostic) { return !isWarningOrNote(diagnostic.severity) && diagnostic.location.filePath == m_filePath; }; m_errorDiagnostics = filterDiagnostics(diagnostics, isLocalWarning); } void ClangDiagnosticFilter::filterFixits() { const auto hasFixIts = [] (const ClangBackEnd::DiagnosticContainer &diagnostic) { return diagnostic.fixIts.size() > 0; }; m_fixItdiagnostics.clear(); filterDiagnostics(m_warningDiagnostics, hasFixIts, m_fixItdiagnostics); filterDiagnostics(m_errorDiagnostics, hasFixIts, m_fixItdiagnostics); for (const auto &warningDiagnostic : m_warningDiagnostics) filterDiagnostics(warningDiagnostic.children, hasFixIts, m_fixItdiagnostics); for (const auto &warningDiagnostic : m_errorDiagnostics) filterDiagnostics(warningDiagnostic.children, hasFixIts, m_fixItdiagnostics); } ClangDiagnosticFilter::ClangDiagnosticFilter(const QString &filePath) : m_filePath(filePath) { } void ClangDiagnosticFilter::filter(const QVector &diagnostics) { filterDocumentRelatedWarnings(diagnostics); filterDocumentRelatedErrors(diagnostics); filterFixits(); } QVector ClangDiagnosticFilter::takeWarnings() { auto diagnostics = m_warningDiagnostics; m_warningDiagnostics.clear(); return diagnostics; } QVector ClangDiagnosticFilter::takeErrors() { auto diagnostics = m_errorDiagnostics; m_errorDiagnostics.clear(); return diagnostics; } QVector ClangDiagnosticFilter::takeFixIts() { auto diagnostics = m_fixItdiagnostics; m_fixItdiagnostics.clear(); return diagnostics; } } // namespace Internal } // namespace ClangCodeModel