summaryrefslogblamecommitdiff
path: root/src/lintmanager.cpp
blob: 1f1714e5de94bbf8922f116992218ab364298810 (plain) (tree)






















                                                                         
                        
 







                        

                 


                            



                                       
 







                                             


                    





                                                           
                                               
 
                           

 

                                                  











                                                           


                        
                            




                   












                                                   

                                                 
                                   
                                     
                
                                  






















                                                                 
                                                                   

                                   
                     




                                                                             

                                 

                    

                            






























                                                            

                                                              
                         
                                     
                          

                                               





                                                   

                                                                    


                                                               
                                                      

                                              

                                  
                        
         


                 
/*
 *  The ManaPlus Client
 *  Copyright (C) 2014  The ManaPlus Developers
 *
 *  This file is part of The ManaPlus Client.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "lintmanager.h"

#include "rulebase.h"
#include "stringutils.h"

#include <dirent.h>
#include <fstream>
#include <regex>

#include <sys/stat.h>

#include "localconsts.h"

LintManager lint;

LintManager::LintManager() :
    mFileName(),
    mRootPath()
{
}

void LintManager::run(std::string path)
{
    mRootPath = path;
    size_t idx = path.rfind("src/");
    if (idx != std::string::npos)
        mRootPath = mRootPath.substr(0, idx);
    if (!strEndWith(mRootPath, "/"))
        mRootPath.append("/");

    updateRules();
    enumFiles(path);
}

void LintManager::updateRules()
{
    FOR_EACH (std::vector<RuleBase*>::iterator, it, mRules)
        (*it)->setRootDir(mRootPath);
}

void LintManager::addRule(RuleBase *const rule)
{
    mRules.push_back(rule);
}

void LintManager::deleteRule(RuleBase *const rule)
{
    deleteFrom(rule, mRules);
}

void LintManager::deleteSelectedRule(RuleBase *const rule)
{
    deleteFrom(rule, mSelectedRules);
}

void LintManager::deleteFrom(RuleBase *const rule,
                             std::vector<RuleBase*> &rules)
{
    FOR_EACH (std::vector<RuleBase*>::iterator, it, rules)
    {
        if (*it == rule)
        {
            rules.erase(it);
            return;
        }
    }
}

void LintManager::enumFiles(std::string path)
{
    path += "/";
    struct dirent *next_file = nullptr;
    DIR *const dir = opendir(path.c_str());
    struct stat s;
    std::vector<std::string> dirs;

    while ((next_file = readdir(dir)))
    {
        const std::string file = next_file->d_name;
        if (file != "." && file != "..")
        {
            const std::string name = path + file;
            stat(name.c_str(), &s);
            if (S_ISDIR(s.st_mode))
                dirs.push_back(name);
            else
                processFile(name);
        }
    }
    if (dir)
        closedir(dir);

    FOR_EACH (std::vector<std::string>::const_iterator, it, dirs)
        enumFiles(*it);
}

void LintManager::processFile(std::string fileName)
{
//    printf("file: %s\n", fileName.c_str());
    mFileName = fileName;
    selectRulesForFile();
    if (!mSelectedRules.empty())
    {
        readFile();
        applyRulesToFile();
    }
}

void LintManager::applyRulesToFile()
{
    FOR_EACH (std::vector<RuleBase*>::iterator, it, mSelectedRules)
    {
        RuleBase *const rule = *it;
        int line = 1;
        FOR_EACH (std::vector<std::string>::const_iterator, itStr, mFileData)
        {
            const std::string &str = *itStr;
            rule->setLine(line);
            rule->parseLine(str);
            if (!rule->getFlag())
                break;
            line ++;
        }
        if (rule->getFlag())
            rule->end();
    }
}

void LintManager::readFile()
{
//    printf("readFile: %s\n", mFileName.c_str());
    std::ifstream file;
    char line[3001];

    mFileData.clear();

    file.open(mFileName.c_str(), std::ios::in);
    if (!file.is_open())
        return;

    while (file.getline(line, 3000))
        mFileData.push_back(line);

    if (file.is_open())
        file.close();
}

void LintManager::selectRulesForFile()
{
//    printf("selectRulesForFile: %s\n", mFileName.c_str());
    mSelectedRules.clear();
    FOR_EACH (std::vector<RuleBase*>::iterator, it, mRules)
    {
        RuleBase *const rule = *it;
        if (isMatchFile(rule))
        {
//            printf("set file %s, for rule %s\n",
//                mFileName.c_str(), rule->getName().c_str());
            rule->init();
            rule->setFile(mFileName);
            rule->start();
            if (rule->getFlag())
                mSelectedRules.push_back(rule);
        }
    }
}

bool LintManager::isMatchFile(RuleBase *const rule)
{
//    printf("rule: %s, isMatchFile: %s\n", rule->getName().c_str(),
//        mFileName.c_str());
    const std::set<std::string> &masks = rule->getMasks();
    FOR_EACH (std::set<std::string>::const_iterator, it, masks)
    {
//        printf("check regexp: %s\n", (*it).c_str());
        std::regex exp(*it);
        if (std::regex_match (mFileName, exp))
        {
//            printf("matched\n");
            return true;
        }
    }
    return false;
}