forked from electronicarts/CnC_Generals_Zero_Hour
-
Notifications
You must be signed in to change notification settings - Fork 128
chore: Add custom clang-tidy plugin for isEmpty() checks #1988
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
bobtista
wants to merge
11
commits into
TheSuperHackers:main
Choose a base branch
from
bobtista:bobtista/tools/clang-tidy-plugin
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
cd94a29
chore: remove accidentally committed .clang-tidy file
bobtista 910b1b9
tools: add custom clang-tidy plugin for AsciiString/UnicodeString isE…
bobtista 1319652
tools: attempt constructor-based plugin registration
bobtista 9770f28
tools: fix plugin registration - check now works!
bobtista dad508e
tools: rename check from generalsgamecode-use-is-empty to generals-us…
bobtista e93edd2
nit: clean up
bobtista 18b3192
tools: add StringClass and WideStringClass support to UseIsEmptyCheck
bobtista 99637ba
tools: move clang-tidy-plugin to scripts directory
bobtista 8c98170
tools: add compare() support to UseIsEmptyCheck
bobtista 5c3f40e
tools: add compareNoCase() support to UseIsEmptyCheck
bobtista ab3416a
docs: update UseIsEmptyCheck documentation for compare() and compareN…
bobtista File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| # Custom clang-tidy plugin for GeneralsGameCode | ||
| # This plugin provides checks for custom types like AsciiString and UnicodeString | ||
|
|
||
| cmake_minimum_required(VERSION 3.20) | ||
| project(GeneralsGameCodeClangTidyPlugin) | ||
|
|
||
| # Find LLVM and Clang | ||
| find_package(LLVM REQUIRED CONFIG) | ||
| find_package(Clang REQUIRED CONFIG) | ||
|
|
||
| message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") | ||
| message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") | ||
| message(STATUS "Using ClangConfig.cmake in: ${Clang_DIR}") | ||
|
|
||
| # Set up include directories | ||
| include_directories(${LLVM_INCLUDE_DIRS}) | ||
| include_directories(${CLANG_INCLUDE_DIRS}) | ||
|
|
||
| # Add definitions | ||
| add_definitions(${LLVM_DEFINITIONS}) | ||
| add_definitions(${CLANG_DEFINITIONS}) | ||
|
|
||
| # Set C++ standard | ||
| set(CMAKE_CXX_STANDARD 17) | ||
| set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||
|
|
||
| # Source files | ||
| set(SOURCES | ||
| GeneralsGameCodeTidyModule.cpp | ||
| readability/UseIsEmptyCheck.cpp | ||
| ) | ||
|
|
||
| # Header files | ||
| set(HEADERS | ||
| GeneralsGameCodeTidyModule.h | ||
| readability/UseIsEmptyCheck.h | ||
| ) | ||
|
|
||
| # Create the module library | ||
| add_library(GeneralsGameCodeClangTidyPlugin MODULE ${SOURCES} ${HEADERS}) | ||
|
|
||
| # Link against required libraries | ||
| target_link_libraries(GeneralsGameCodeClangTidyPlugin | ||
| PRIVATE | ||
| clangTidy | ||
| clangTidyReadabilityModule | ||
| clangAST | ||
| clangASTMatchers | ||
| clangBasic | ||
| clangFrontend | ||
| clangLex | ||
| clangTooling | ||
| LLVMSupport | ||
| ) | ||
|
|
||
| # Set output directory | ||
| set_target_properties(GeneralsGameCodeClangTidyPlugin PROPERTIES | ||
| LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib | ||
| RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin | ||
| ) | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| //===--- GeneralsGameCodeTidyModule.cpp - GeneralsGameCode Tidy Module ---===// | ||
| // | ||
| // Custom clang-tidy module for GeneralsGameCode | ||
| // Provides checks for custom types like AsciiString and UnicodeString | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "GeneralsGameCodeTidyModule.h" | ||
| #include "readability/UseIsEmptyCheck.h" | ||
| #include "llvm/Support/Registry.h" | ||
|
|
||
| namespace clang::tidy::generalsgamecode { | ||
|
|
||
| void GeneralsGameCodeTidyModule::addCheckFactories( | ||
| ClangTidyCheckFactories &CheckFactories) { | ||
| CheckFactories.registerCheck<readability::UseIsEmptyCheck>( | ||
| "generals-use-is-empty"); | ||
| } | ||
|
|
||
| } // namespace clang::tidy::generalsgamecode | ||
|
|
||
| static llvm::Registry<::clang::tidy::ClangTidyModule>::Add< | ||
| ::clang::tidy::generalsgamecode::GeneralsGameCodeTidyModule> | ||
| X("generalsgamecode", "GeneralsGameCode-specific checks"); | ||
|
|
||
| volatile int GeneralsGameCodeTidyModuleAnchorSource = 0; | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| //===--- GeneralsGameCodeTidyModule.h - GeneralsGameCode Tidy Module -----===// | ||
| // | ||
| // Custom clang-tidy module for GeneralsGameCode | ||
| // Provides checks for custom types like AsciiString and UnicodeString | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GENERALSGAMECODE_GENERALSGAMECODETIDYMODULE_H | ||
| #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GENERALSGAMECODE_GENERALSGAMECODETIDYMODULE_H | ||
|
|
||
| #include "clang-tidy/ClangTidyModule.h" | ||
|
|
||
| namespace clang::tidy::generalsgamecode { | ||
|
|
||
| /// This module is for GeneralsGameCode-specific checks. | ||
| class GeneralsGameCodeTidyModule : public ClangTidyModule { | ||
| public: | ||
| void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override; | ||
| }; | ||
|
|
||
| } // namespace clang::tidy::generalsgamecode | ||
|
|
||
| #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GENERALSGAMECODE_GENERALSGAMECODETIDYMODULE_H | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| # GeneralsGameCode Clang-Tidy Plugin | ||
|
|
||
| This is a custom clang-tidy plugin that provides checks specific to the GeneralsGameCode codebase. | ||
|
|
||
| ## Checks | ||
|
|
||
| ### `generals-use-is-empty` | ||
|
|
||
| Finds uses of `getLength() == 0` or `getLength() > 0` on `AsciiString` and `UnicodeString`, and `Get_Length() == 0` on `StringClass` and `WideStringClass`, and suggests using `isEmpty()`/`Is_Empty()` or `!isEmpty()`/`!Is_Empty()` instead. | ||
|
|
||
| Also finds uses of `compare("") == 0`, `compare(TheEmptyString) == 0`, `compareNoCase("") == 0`, and similar patterns, suggesting `isEmpty()` instead. | ||
|
|
||
| **Examples:** | ||
|
|
||
| ```cpp | ||
| // Before (AsciiString/UnicodeString) | ||
| if (str.getLength() == 0) { ... } | ||
| if (str.getLength() > 0) { ... } | ||
| if (str.compare("") == 0) { ... } | ||
| if (str.compare(AsciiString::TheEmptyString) == 0) { ... } | ||
| if (str.compareNoCase("") == 0) { ... } | ||
|
|
||
| // After (AsciiString/UnicodeString) | ||
| if (str.isEmpty()) { ... } | ||
| if (!str.isEmpty()) { ... } | ||
| if (str.isEmpty()) { ... } | ||
| if (str.isEmpty()) { ... } | ||
| if (str.isEmpty()) { ... } | ||
|
|
||
| // Before (StringClass/WideStringClass) | ||
| if (str.Get_Length() == 0) { ... } | ||
| if (str.Get_Length() > 0) { ... } | ||
|
|
||
| // After (StringClass/WideStringClass) | ||
| if (str.Is_Empty()) { ... } | ||
| if (!str.Is_Empty()) { ... } | ||
| ``` | ||
|
|
||
| ## Building | ||
|
|
||
| This plugin requires LLVM and Clang to be installed. Build it with CMake: | ||
|
|
||
| ```bash | ||
| cd scripts/clang-tidy-plugin | ||
| mkdir build && cd build | ||
| cmake .. -DLLVM_DIR=/path/to/llvm/lib/cmake/llvm -DClang_DIR=/path/to/clang/lib/cmake/clang | ||
| make | ||
| ``` | ||
|
|
||
| The plugin will be built as a shared library (`.so` on Linux, `.dylib` on macOS, `.dll` on Windows) in the `build/lib/` directory. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| Before using the plugin, you need to generate a compile commands database: | ||
|
|
||
| ```bash | ||
| cmake -B build/clang-tidy -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON -G Ninja | ||
| ``` | ||
|
|
||
| This creates `build/clang-tidy/compile_commands.json` which tells clang-tidy how to compile each file. | ||
|
|
||
| ## Usage | ||
|
|
||
| ### Basic Usage | ||
|
|
||
| ```bash | ||
| clang-tidy -p build/clang-tidy \ | ||
| --checks='-*,generals-use-is-empty' \ | ||
| -load scripts/clang-tidy-plugin/build/lib/libGeneralsGameCodeClangTidyPlugin.so \ | ||
| file.cpp | ||
| ``` | ||
|
|
||
| ### With Automatic Fixes | ||
|
|
||
| ```bash | ||
| clang-tidy -p build/clang-tidy \ | ||
| --checks='-*,generals-use-is-empty' \ | ||
| -load scripts/clang-tidy-plugin/build/lib/libGeneralsGameCodeClangTidyPlugin.so \ | ||
| -fix-errors \ | ||
| file.cpp | ||
| ``` | ||
|
|
||
| ### On Multiple Files | ||
|
|
||
| ```bash | ||
| find Core -name "*.cpp" -type f -exec clang-tidy \ | ||
| -p build/clang-tidy \ | ||
| --checks='-*,generals-use-is-empty' \ | ||
| -load scripts/clang-tidy-plugin/build/lib/libGeneralsGameCodeClangTidyPlugin.so \ | ||
| -fix-errors {} \; | ||
| ``` | ||
|
|
||
| The `-p build/clang-tidy` flag tells clang-tidy to use the compile commands database to understand how to parse each file. | ||
|
|
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.