feat(clang): add claude suggestion

This commit is contained in:
2025-09-09 11:11:53 +08:00
parent cfc13ff82c
commit d5350c35a8
9 changed files with 360 additions and 1 deletions

View File

@@ -0,0 +1,16 @@
# 基於 Google 風格但較寬鬆,適合舊代碼
BasedOnStyle: Google
IndentWidth: 4
TabWidth: 4
UseTab: Never
ColumnLimit: 100
AccessModifierOffset: -2
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
BreakBeforeBraces: Attach
IndentCaseLabels: true
SpacesBeforeTrailingComments: 2
Standard: Cpp03 # 針對舊代碼

View File

@@ -0,0 +1,26 @@
# 階段一:只檢查最關鍵的錯誤,適合舊代碼
Checks: '-*,
clang-analyzer-core.NullDereference,
clang-analyzer-core.DivideZero,
clang-analyzer-core.UndefinedBinaryOperatorResult,
bugprone-argument-comment,
bugprone-bool-pointer-implicit-conversion,
bugprone-dangling-handle,
bugprone-use-after-move,
readability-braces-around-statements,
readability-container-size-empty'
# 不將警告視為錯誤(階段一)
WarningsAsErrors: ''
# 包含所有標頭檔
HeaderFilterRegex: '.*'
# 分析設定
AnalyzeTemporaryDtors: false
FormatStyle: none
# 檢查參數
CheckOptions:
- key: readability-braces-around-statements.ShortStatementLines
value: '2'

View File

@@ -0,0 +1,39 @@
cmake_minimum_required(VERSION 3.10)
project(CppLinterTemplate)
# 設定 C++ 標準(針對舊代碼)
set(CMAKE_CXX_STANDARD 98)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 編譯選項
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
# 尋找 clang-tidy
find_program(CLANG_TIDY_EXE NAMES "clang-tidy")
if(CLANG_TIDY_EXE)
message(STATUS "Found clang-tidy: ${CLANG_TIDY_EXE}")
option(ENABLE_CLANG_TIDY "Enable clang-tidy checks" OFF)
endif()
# 原始碼
add_executable(main
src/main.cpp
src/utils.cpp
)
target_include_directories(main PRIVATE src)
# 如果啟用 clang-tidy
if(CLANG_TIDY_EXE AND ENABLE_CLANG_TIDY)
set_target_properties(main PROPERTIES
CXX_CLANG_TIDY "${CLANG_TIDY_EXE};--config-file=${CMAKE_SOURCE_DIR}/.clang-tidy"
)
endif()
# 測試執行檔
add_executable(tests
tests/test_main.cpp
src/utils.cpp
)
target_include_directories(tests PRIVATE src)

View File

@@ -1,4 +1,77 @@
# cpp-linter-template
# C++ Linter Template
這是一個展示如何在 C++ 專案中整合 linter 工具的模板專案。
## 目的
- 展示 clang-tidy 在舊 C++ 代碼中的應用
- 提供漸進式導入 linter 的範例
- Azure DevOps CI/CD 整合範例
## 快速開始
### 1. 本地開發環境設定
```bash
# 安裝相依套件 (Ubuntu/Debian)
sudo apt install clang-tidy clang-format cmake build-essential
# 安裝相依套件 (macOS)
brew install llvm cmake
# 克隆專案
git clone <your-repo-url>
cd cpp-linter-template
```
### 2. 執行 Linter
```bash
# 使用提供的腳本
./scripts/run-linter.sh
# 或手動執行
clang-tidy src/*.cpp src/*.h tests/*.cpp --config-file=.clang-tidy
```
### 3. 建構專案
```bash
mkdir build && cd build
cmake ..
make
./main
```
## Linter 配置說明
### 當前採用階段一設定:
- 只檢查最關鍵的錯誤
- 不會因 linter 警告而中斷 CI
- 適合舊代碼逐步改進
### 後續階段計劃
- 階段二:增加記憶體和資源管理檢查
- 階段三:加入可讀性和現代化建議
- 階段四:強制執行,警告視為錯誤
## 在 Azure DevOps 中使用
1. 將此專案推送到 Azure DevOps
2. 設定 Pipeline 使用 azure-pipelines.yml
3. 建立 Pull Request 時會自動執行 linter
## 自定義配置
編輯 .clang-tidy 檔案來調整檢查規則:
```yaml
# 增加更多檢查
Checks: '-*,clang-analyzer-*,bugprone-*,readability-*'
```
## 檔案說明
`.clang-tidy:` Linter 配置檔
`.clang-format`: 程式碼格式化配置
`azure-pipelines.yml`: Azure DevOps CI/CD 配置
`scripts/run-linter.sh`: 本地執行 linter 腳本
## 注意事項
- 此模板使用 C++98 標準,適合舊代碼
- Linter 設定較為寬鬆,適合逐步導入
- 可以根據團隊需求調整檢查規則
## 專案結構
cpp-linter-template/

View File

@@ -0,0 +1,106 @@
# Azure DevOps Pipeline for C++ Linter Template
trigger:
branches:
include:
- main
- develop
pr:
branches:
include:
- main
- develop
pool:
vmImage: 'ubuntu-latest'
variables:
buildConfiguration: 'Debug'
stages:
- stage: LintAndBuild
displayName: 'Lint and Build'
jobs:
- job: StaticAnalysis
displayName: 'Static Analysis with clang-tidy'
steps:
- task: Bash@3
displayName: 'Install Dependencies'
inputs:
targetType: 'inline'
script: |
sudo apt-get update
sudo apt-get install -y clang-tidy clang-format cmake build-essential
clang-tidy --version
- task: Bash@3
displayName: 'Check Code Format'
inputs:
targetType: 'inline'
script: |
echo "Checking code format..."
find src tests -name "*.cpp" -o -name "*.h" | xargs clang-format --dry-run --Werror
- task: Bash@3
displayName: 'Run clang-tidy on all files'
inputs:
targetType: 'inline'
script: |
echo "Running clang-tidy..."
find src tests -name "*.cpp" -o -name "*.h" | xargs clang-tidy --config-file=.clang-tidy
# 階段一:只顯示警告,不中斷 CI
echo "Linter completed. Review warnings above."
- task: Bash@3
displayName: 'Build Project'
inputs:
targetType: 'inline'
script: |
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=${{ variables.buildConfiguration }}
make -j$(nproc)
- task: Bash@3
displayName: 'Run Tests'
inputs:
targetType: 'inline'
script: |
cd build
./tests
./main
- job: PRAnalysis
displayName: 'PR Changed Files Analysis'
condition: eq(variables['Build.Reason'], 'PullRequest')
steps:
- task: Bash@3
displayName: 'Install Dependencies'
inputs:
targetType: 'inline'
script: |
sudo apt-get update
sudo apt-get install -y clang-tidy
- task: Bash@3
displayName: 'Analyze Changed Files Only'
inputs:
targetType: 'inline'
script: |
echo "Analyzing only changed files in PR..."
# 取得變更的檔案
git fetch origin $(System.PullRequest.TargetBranch)
CHANGED_FILES=$(git diff origin/$(System.PullRequest.TargetBranch)...HEAD --name-only | grep -E '\.(cpp|cxx|cc|c\+\+|h|hpp|hxx)$' || true)
if [ -z "$CHANGED_FILES" ]; then
echo "No C++ files changed in this PR"
exit 0
fi
echo "Changed C++ files:"
echo "$CHANGED_FILES"
echo "Running clang-tidy on changed files..."
echo "$CHANGED_FILES" | xargs clang-tidy --config-file=.clang-tidy -- -std=c++98

29
scripts/run-linter.sh Normal file → Executable file
View File

@@ -0,0 +1,29 @@
#!/bin/bash
# 本地執行 linter 的腳本
echo "Running clang-tidy on C++ files..."
# 檢查 clang-tidy 是否存在
if ! command -v clang-tidy &> /dev/null; then
echo "clang-tidy not found. Please install it first."
echo "Ubuntu/Debian: sudo apt install clang-tidy"
echo "macOS: brew install llvm"
exit 1
fi
# 尋找所有 C++ 檔案
CPP_FILES=$(find src tests -name "*.cpp" -o -name "*.h" 2>/dev/null)
if [ -z "$CPP_FILES" ]; then
echo "No C++ files found."
exit 0
fi
echo "Found files:"
echo "$CPP_FILES"
echo
# 執行 clang-tidy
echo "$CPP_FILES" | xargs clang-tidy --config-file=.clang-tidy
echo "Linter check completed."

View File

@@ -0,0 +1,33 @@
// 這個檔案故意包含一些會被 linter 檢查的情況
#include <iostream>
#include <vector>
#include "utils.h"
int main() {
std::cout << "C++ Linter Template Demo" << std::endl;
// 測試案例 1: 正常的代碼
std::vector<int> numbers;
numbers.push_back(1);
numbers.push_back(2);
numbers.push_back(3);
// 測試案例 2: 可能被 linter 警告的代碼
int* ptr = new int(42);
if (ptr) {
std::cout << "Value: " << *ptr << std::endl;
delete ptr;
ptr = NULL; // 好習慣,避免 dangling pointer
}
// 測試案例 3: 容器大小檢查
if (!numbers.empty()) { // 比 numbers.size() > 0 好
std::cout << "Numbers count: " << numbers.size() << std::endl;
}
// 測試案例 4: 呼叫工具函數
int result = calculateSum(numbers);
std::cout << "Sum: " << result << std::endl;
return 0;
}

View File

@@ -0,0 +1,22 @@
#include "utils.h"
#include <cstring>
int calculateSum(const std::vector<int>& vec) {
int sum = 0;
// 使用舊式的 iterator模擬舊代碼
for (std::vector<int>::const_iterator it = vec.begin(); it != vec.end(); ++it) {
sum += *it;
}
return sum;
}
bool isPositive(int number) {
return number > 0;
}
void safeCopy(char* dest, const char* src, int maxLen) {
if (dest && src && maxLen > 0) {
strncpy(dest, src, maxLen - 1);
dest[maxLen - 1] = '\0'; // 確保字串結尾
}
}

View File

@@ -0,0 +1,15 @@
#ifndef UTILS_H
#define UTILS_H
#include <vector>
// 計算向量元素總和
int calculateSum(const std::vector<int>& vec);
// 檢查數字是否為正數
bool isPositive(int number);
// 安全的字串複製(展示舊式 C++ 代碼)
void safeCopy(char* dest, const char* src, int maxLen);
#endif // UTILS_H