<commit_before>// csatr_globaltypeonlyinsource.cpp                                   -*-C++-*-

#include <clang/AST/Decl.h>
#include <clang/AST/DeclBase.h>
#include <clang/AST/DeclarationName.h>
#include <csabase_analyser.h>
#include <csabase_diagnostic_builder.h>
#include <csabase_location.h>
#include <csabase_registercheck.h>
#include <algorithm>
#include <string>

using namespace csabase;
using namespace clang;

// ----------------------------------------------------------------------------

static std::string const check_name("global-type-only-in-source");

// ----------------------------------------------------------------------------

namespace
{
    struct decl_not_in_toplevel
    {
        decl_not_in_toplevel(Analyser* analyser) : analyser_(analyser)
        {
        }

        bool operator()(Decl const& decl) const
        {
            return (*this)(&decl);
        }

        bool operator()(Decl const* decl) const
        {
            return analyser_->get_location(decl).file()
                != analyser_->toplevel();
        }

        Analyser* analyser_;
    };
}

// ----------------------------------------------------------------------------

static void
global_type_only_in_source(Analyser& analyser, TypeDecl const* decl)
{
    if (decl->getDeclContext()->isFileContext()
        && !llvm::dyn_cast<TypedefDecl>(decl)
        && analyser.get_location(decl).file() == analyser.toplevel()
        && !analyser.is_component_header(analyser.toplevel())
        && !decl->isInAnonymousNamespace()
        && !analyser.is_test_driver()
        && decl->isExternallyVisible()
        && decl->getDeclName().isIdentifier()
        && !decl->getDeclName().getAsString().empty()
        )
    {
        auto r = llvm::dyn_cast<RecordDecl>(decl);<commit_msg>Don't complain about class template specializations in source files.<commit_after>// csatr_globaltypeonlyinsource.cpp                                   -*-C++-*-

#include <clang/AST/Decl.h>
#include <clang/AST/DeclBase.h>
#include <clang/AST/DeclTemplate.h>
#include <clang/AST/DeclarationName.h>
#include <csabase_analyser.h>
#include <csabase_diagnostic_builder.h>
#include <csabase_location.h>
#include <csabase_registercheck.h>
#include <algorithm>
#include <string>

using namespace csabase;
using namespace clang;

// ----------------------------------------------------------------------------

static std::string const check_name("global-type-only-in-source");

// ----------------------------------------------------------------------------

namespace
{
    struct decl_not_in_toplevel
    {
        decl_not_in_toplevel(Analyser* analyser) : analyser_(analyser)
        {
        }

        bool operator()(Decl const& decl) const
        {
            return (*this)(&decl);
        }

        bool operator()(Decl const* decl) const
        {
            return analyser_->get_location(decl).file()
                != analyser_->toplevel();
        }

        Analyser* analyser_;
    };
}

// ----------------------------------------------------------------------------

static void
global_type_only_in_source(Analyser& analyser, TypeDecl const* decl)
{
    if (decl->getDeclContext()->isFileContext()
        && !llvm::dyn_cast<TypedefDecl>(decl)
        && !llvm::dyn_cast<ClassTemplateSpecializationDecl>(decl)
        && analyser.get_location(decl).file() == analyser.toplevel()
        && !analyser.is_component_header(analyser.toplevel())
        && !decl->isInAnonymousNamespace()
        && !analyser.is_test_driver()
        && decl->isExternallyVisible()
        && decl->getDeclName().isIdentifier()
        && !decl->getDeclName().getAsString().empty()
        )
    {
        auto r = llvm::dyn_cast<RecordDecl>(decl);
{'fraction_non_alphanumeric': 0.24457540851861773, 'fraction_numerical': 0.0, 'mean_word_length': 1.835231586940015, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2884096', 'n_tokens_mistral': 1046, 'n_tokens_neox': 1052, 'n_words': 160}