QtAccessSpecifierType AccessSpecifierManager::qtAccessSpecifierType()

in src/AccessSpecifierManager.cpp [203:273]


QtAccessSpecifierType AccessSpecifierManager::qtAccessSpecifierType(const CXXMethodDecl *method) const
{
    if (!method || method->getBeginLoc().isMacroID()) {
        return QtAccessSpecifier_Unknown;
    }

    if (clion::isJetbrainsModeOn()) {
        for (const auto *I : method->specific_attrs<AnnotateAttr>()) {
            if (I->getAnnotation() == "signal_from_qt")
                return QtAccessSpecifier_Signal;
            if (I->getAnnotation() == "slot_from_qt")
                return QtAccessSpecifier_Slot;
        }
    }

    // We want the declaration that's inside class {}, not the ones that are also a method definition
    // and possibly outside the class
    method = method->getCanonicalDecl();

    const CXXRecordDecl *record = method->getParent();
    if (!record || isa<clang::ClassTemplateSpecializationDecl>(record) || method->isTemplateInstantiation()) {
        return QtAccessSpecifier_None;
    }

    const SourceLocation methodLoc = method->getBeginLoc();

    // Process Q_SIGNAL:
    for (auto signalLoc : m_preprocessorCallbacks->m_individualSignals) {
        if (signalLoc == methodLoc.getRawEncoding()) {
            return QtAccessSpecifier_Signal;
        }
    }

    // Process Q_SLOT:
    for (auto slotLoc : m_preprocessorCallbacks->m_individualSlots) {
        if (slotLoc == methodLoc.getRawEncoding()) {
            return QtAccessSpecifier_Slot;
        }
    }

    // Process Q_INVOKABLE:
    for (auto loc : m_preprocessorCallbacks->m_invokables) {
        if (loc == methodLoc.getRawEncoding()) {
            return QtAccessSpecifier_Invokable;
        }
    }

    // Process Q_SLOTS and Q_SIGNALS:

    auto it = m_specifiersMap.find(record);
    if (it == m_specifiersMap.cend()) {
        return QtAccessSpecifier_None;
    }

    const ClazySpecifierList &accessSpecifiers = it->second;

    auto pred = [this](const ClazyAccessSpecifier &lhs, const ClazyAccessSpecifier &rhs) {
        return accessSpecifierCompare(lhs, rhs, m_ci.getSourceManager());
    };

    const ClazyAccessSpecifier dummy = {methodLoc, // we're only interested in the location
                                        /*dummy*/ clang::AS_none,
                                        /*dummy*/ QtAccessSpecifier_None};
    auto i = std::upper_bound(accessSpecifiers.cbegin(), accessSpecifiers.cend(), dummy, pred);
    if (i == accessSpecifiers.cbegin()) {
        return QtAccessSpecifier_None;
    }

    --i; // One before the upper bound is the last access specifier before our method
    return (*i).qtAccessSpecifier;
}