diff --git a/lib/path.cpp b/lib/path.cpp index f17aa0a07..5a30aa410 100644 --- a/lib/path.cpp +++ b/lib/path.cpp @@ -108,6 +108,13 @@ bool Path::sameFileName(const std::string &fname1, const std::string &fname2) #endif } +// This wrapper exists because Sun's CC does not allow a static_cast +// from extern "C" int(*)(int) to int(*)(int). +static int tolowerWrapper(int c) +{ + return std::tolower(c); +} + std::string Path::removeQuotationMarks(std::string path) { path.erase(std::remove(path.begin(), path.end(), '\"'), path.end()); @@ -124,26 +131,29 @@ std::string Path::getFilenameExtension(const std::string &path) return extension; } - -// This wrapper exists because Sun's CC does not allow a static_cast -// from extern "C" int(*)(int) to int(*)(int). -static int tolowerWrapper(int c) +std::string Path::getFilenameExtensionInLowerCase(const std::string &path) { - return std::tolower(c); + std::string extension = getFilenameExtension(path); + std::transform(extension.begin(), extension.end(), extension.begin(), tolowerWrapper); + return extension; } - -bool Path::acceptFile(const std::string &filename) +bool Path::isC(const std::string &path) { - std::string extension = Path::getFilenameExtension(filename); - if (extension == "") - return false; - std::transform(extension.begin(), extension.end(), extension.begin(), tolowerWrapper); + const std::string extension = getFilenameExtensionInLowerCase(path); + if (extension == ".c") { + return true; + } + return false; +} + +bool Path::isCPP(const std::string &path) +{ + const std::string extension = getFilenameExtensionInLowerCase(path); if (extension == ".cpp" || extension == ".cxx" || extension == ".cc" || - extension == ".c" || extension == ".c++" || extension == ".tpp" || extension == ".txx") { @@ -153,3 +163,33 @@ bool Path::acceptFile(const std::string &filename) return false; } +bool Path::isJava(const std::string &path) +{ + const std::string extension = getFilenameExtensionInLowerCase(path); + if (extension == ".java") { + return true; + } + + return false; +} + +bool Path::isCSharp(const std::string &path) +{ + const std::string extension = getFilenameExtensionInLowerCase(path); + if (extension == ".cs") { + return true; + } + + return false; +} + +bool Path::acceptFile(const std::string &filename) +{ + if (Path::isCPP(filename) || + Path::isC(filename)) { + return true; + } + + return false; +} + diff --git a/lib/path.h b/lib/path.h index 8b22f880a..5ecd71d40 100644 --- a/lib/path.h +++ b/lib/path.h @@ -73,10 +73,17 @@ public: /** * @brief Get an extension of the filename. * @param path Path containing filename. - * @return Filename extension (containing the dot, e.g. ".h"). + * @return Filename extension (containing the dot, e.g. ".h" or ".CPP"). */ static std::string getFilenameExtension(const std::string &path); + /** + * @brief Get an extension of the filename in lower case. + * @param path Path containing filename. + * @return Filename extension (containing the dot, e.g. ".h"). + */ + static std::string getFilenameExtensionInLowerCase(const std::string &path); + /** * @brief Check if the file extension indicates that it's a C/C++ source file. * Check if the file has source file extension: *.c;*.cpp;*.cxx;*.c++;*.cc;*.txx @@ -85,6 +92,33 @@ public: */ static bool acceptFile(const std::string &filename); + /** + * @brief Identify language based on file extension. + * @param extensionInLowerCase e.g. ".c" + * @return true if extension is meant for C files + */ + static bool isC(const std::string &extensionInLowerCase); + + /** + * @brief Identify language based on file extension. + * @param extensionInLowerCase e.g. ".cpp" + * @return true if extension is meant for C++ files + */ + static bool isCPP(const std::string &extensionInLowerCase); + + /** + * @brief Identify language based on file extension. + * @param extensionInLowerCase e.g. ".java" + * @return true if extension is meant for Java files + */ + static bool isJava(const std::string &extensionInLowerCase); + + /** + * @brief Identify language based on file extension. + * @param extensionInLowerCase e.g. ".cs" + * @return true if extension is meant for C# files + */ + static bool isCSharp(const std::string &extensionInLowerCase); }; /// @} diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 4496989e7..314f65b39 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -9503,3 +9503,29 @@ void Tokenizer::printUnknownTypes() _errorLogger->reportOut(ss.str()); } } + +std::string Tokenizer::getSourceFilePath() const { + if (_files.empty()) + return std::string(""); + return _files[0]; +} + +bool Tokenizer::isJava() const { + return Path::isJava(getSourceFilePath()); +} + +bool Tokenizer::isCSharp() const { + return Path::isCSharp(getSourceFilePath()); +} + +bool Tokenizer::isJavaOrCSharp() const { + return isJava() || isCSharp(); +} + +bool Tokenizer::isC() const { + return Path::isC(getSourceFilePath()); +} + +bool Tokenizer::isCPP() const { + return Path::isCPP(getSourceFilePath()); +} diff --git a/lib/tokenize.h b/lib/tokenize.h index 4eca96ec0..03a41f59e 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -49,38 +49,23 @@ public: Tokenizer(const Settings * settings, ErrorLogger *errorLogger); virtual ~Tokenizer(); - /** The file extension. Used by isC() etc. */ - std::string fileExtension() const { - if (_files.empty()) - return std::string(""); - return Path::getFilenameExtension(_files[0]); - } + /** Returns the source file path. e.g. "file.cpp" */ + std::string getSourceFilePath() const; /** Is the code JAVA. Used for bailouts */ - bool isJava() const { - return fileExtension() == ".java"; - } + bool isJava() const; /** Is the code C#. Used for bailouts */ - bool isCSharp() const { - return fileExtension() == ".cs"; - } + bool isCSharp() const; /** Is the code JAVA/C#. Used for bailouts */ - bool isJavaOrCSharp() const { - return isJava() || isCSharp(); - } + bool isJavaOrCSharp() const; /** Is the code C. Used for bailouts */ - bool isC() const { - const std::string ext = fileExtension(); - return (ext == ".c" || ext == ".C"); - } + bool isC() const; /** Is the code CPP. Used for bailouts */ - bool isCPP() const { - return !isC() && (_files.size() && Path::acceptFile(_files[0])); - } + bool isCPP() const; /** * Check if inner scope ends with a call to a noreturn function diff --git a/test/testpath.cpp b/test/testpath.cpp index 0d519ff14..75f98344c 100644 --- a/test/testpath.cpp +++ b/test/testpath.cpp @@ -29,6 +29,11 @@ private: void run() { TEST_CASE(simplify_path); + TEST_CASE(accept_file); + TEST_CASE(is_c); + TEST_CASE(is_cpp); + TEST_CASE(is_java); + TEST_CASE(is_csharp); } void simplify_path() { @@ -58,6 +63,48 @@ private: ASSERT_EQUALS("the/path to/index.cpp", Path::removeQuotationMarks("the/\"path to\"/index.cpp")); ASSERT_EQUALS("the/path to/index.cpp", Path::removeQuotationMarks("\"the/path to/index.cpp\"")); } + + void accept_file() { + ASSERT(Path::acceptFile("index.cpp")); + ASSERT(Path::acceptFile("index.invalid.cpp")); + ASSERT(Path::acceptFile("index.invalid.Cpp")); + ASSERT(Path::acceptFile("index.invalid.C")); + ASSERT(Path::acceptFile("index.invalid.C++")); + ASSERT(Path::acceptFile("index.")==false); + ASSERT(Path::acceptFile("index")==false); + ASSERT(Path::acceptFile("")==false); + ASSERT(Path::acceptFile("C")==false); + } + + void is_c() { + ASSERT(Path::isC("index.cpp")==false); + ASSERT(Path::isC("")==false); + ASSERT(Path::isC("c")==false); + ASSERT(Path::isC("index.c")); + ASSERT(Path::isC("C:\\foo\\index.c")); + ASSERT(Path::isC("C:\\foo\\index.C")); + } + + void is_cpp() { + ASSERT(Path::isCPP("index.c")==false); + ASSERT(Path::isCPP("index.cpp")); + ASSERT(Path::isCPP("C:\\foo\\index.cpp")); + ASSERT(Path::isCPP("C:\\foo\\index.Cpp")); + } + + void is_java() { + ASSERT(Path::isJava("index.cpp")==false); + ASSERT(Path::isJava("index.java")); + ASSERT(Path::isJava("C:\\foo\\index.java")); + ASSERT(Path::isJava("C:\\foo\\index.Java")); + } + + void is_csharp() { + ASSERT(Path::isCSharp("index.cpp")==false); + ASSERT(Path::isCSharp("index.cs")); + ASSERT(Path::isCSharp("C:\\foo\\index.cs")); + ASSERT(Path::isCSharp("C:\\foo\\index.Cs")); + } }; REGISTER_TEST(TestPath)