File indexing completed on 2024-05-12 05:41:01

0001 /*
0002     SPDX-FileCopyrightText: 2018 Sergio Martins <smartins@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "ifndef-define-typo.h"
0008 #include "QtUtils.h"
0009 #include "TypeUtils.h"
0010 #include "Utils.h"
0011 #include "levenshteindistance.h"
0012 
0013 #include <clang/AST/AST.h>
0014 
0015 using namespace clang;
0016 
0017 IfndefDefineTypo::IfndefDefineTypo(const std::string &name, ClazyContext *context)
0018     : CheckBase(name, context)
0019 {
0020     enablePreProcessorCallbacks();
0021 }
0022 
0023 void IfndefDefineTypo::VisitMacroDefined(const Token &macroNameTok)
0024 {
0025     if (!m_lastIfndef.empty()) {
0026         if (IdentifierInfo *ii = macroNameTok.getIdentifierInfo()) {
0027             maybeWarn(static_cast<std::string>(ii->getName()), macroNameTok.getLocation());
0028         }
0029     }
0030 }
0031 
0032 void IfndefDefineTypo::VisitDefined(const Token &macroNameTok, const SourceRange &)
0033 {
0034     if (!m_lastIfndef.empty()) {
0035         if (IdentifierInfo *ii = macroNameTok.getIdentifierInfo()) {
0036             maybeWarn(static_cast<std::string>(ii->getName()), macroNameTok.getLocation());
0037         }
0038     }
0039 }
0040 
0041 void IfndefDefineTypo::VisitIfdef(SourceLocation, const Token &)
0042 {
0043     m_lastIfndef.clear();
0044 }
0045 
0046 void IfndefDefineTypo::VisitIfndef(SourceLocation, const Token &macroNameTok)
0047 {
0048     if (IdentifierInfo *ii = macroNameTok.getIdentifierInfo()) {
0049         m_lastIfndef = static_cast<std::string>(ii->getName());
0050     }
0051 }
0052 
0053 void IfndefDefineTypo::VisitIf(SourceLocation, SourceRange, PPCallbacks::ConditionValueKind)
0054 {
0055     m_lastIfndef.clear();
0056 }
0057 
0058 void IfndefDefineTypo::VisitElif(SourceLocation, SourceRange, PPCallbacks::ConditionValueKind, SourceLocation)
0059 {
0060     m_lastIfndef.clear();
0061 }
0062 
0063 void IfndefDefineTypo::VisitElse(SourceLocation, SourceLocation)
0064 {
0065     m_lastIfndef.clear();
0066 }
0067 
0068 void IfndefDefineTypo::VisitEndif(SourceLocation, SourceLocation)
0069 {
0070     m_lastIfndef.clear();
0071 }
0072 
0073 void IfndefDefineTypo::maybeWarn(const std::string &define, SourceLocation loc)
0074 {
0075     if (m_lastIfndef == "Q_CONSTRUCTOR_FUNCTION") { // Transform into a list if more false-positives need to be added
0076         return;
0077     }
0078 
0079     if (define == m_lastIfndef) {
0080         m_lastIfndef.clear();
0081         return;
0082     }
0083 
0084     if (define.length() < 4) {
0085         return;
0086     }
0087 
0088     const int levDistance = levenshtein_distance(define, m_lastIfndef);
0089     if (levDistance < 3) {
0090         emitWarning(loc, std::string("Possible typo in define. ") + m_lastIfndef + " vs " + define);
0091     }
0092 }