Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions scripts/clang-tidy-plugin/CMakeLists.txt
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
)

27 changes: 27 additions & 0 deletions scripts/clang-tidy-plugin/GeneralsGameCodeTidyModule.cpp
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;

24 changes: 24 additions & 0 deletions scripts/clang-tidy-plugin/GeneralsGameCodeTidyModule.h
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

94 changes: 94 additions & 0 deletions scripts/clang-tidy-plugin/README.md
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.

Loading
Loading