/* * 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 . */ #include "lintmanager.h" #include "rulebase.h" #include "stringutils.h" #include #include #include #include #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::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 &rules) { FOR_EACH (std::vector::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 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::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::iterator, it, mSelectedRules) { RuleBase *const rule = *it; int line = 1; FOR_EACH (std::vector::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::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 &masks = rule->getMasks(); FOR_EACH (std::set::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; }