-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a framework for a subspace clang-tidy module
- Loading branch information
Showing
9 changed files
with
376 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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,81 @@ | ||
# Copyright 2023 Google LLC | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
add_library(subspace_clang_tidy_module MODULE "") | ||
add_library(subspace::clang_tidy ALIAS subspace_clang_tidy_module) | ||
target_sources(subspace_clang_tidy_module PUBLIC | ||
"llvm.h" | ||
"module.cc" | ||
"smoke_check.cc" | ||
"smoke_check.h" | ||
) | ||
|
||
target_link_libraries(subspace_clang_tidy_module | ||
subspace::lib | ||
|
||
clangTidy | ||
|
||
clangAnalysis | ||
clangAnalysisFlowSensitive | ||
clangAnalysisFlowSensitiveModels | ||
clangAPINotes | ||
clangARCMigrate | ||
clangAST | ||
clangASTMatchers | ||
clangBasic | ||
clangCodeGen | ||
clangCrossTU | ||
clangDependencyScanning | ||
clangDirectoryWatcher | ||
clangDriver | ||
clangDynamicASTMatchers | ||
clangEdit | ||
clangExtractAPI | ||
clangFormat | ||
clangFrontend | ||
clangFrontendTool | ||
clangHandleCXX | ||
clangHandleLLVM | ||
clangIndex | ||
clangIndexSerialization | ||
clangInterpreter | ||
clangLex | ||
clangParse | ||
clangRewrite | ||
clangRewriteFrontend | ||
clangSema | ||
clangSerialization | ||
clangStaticAnalyzerCheckers | ||
clangStaticAnalyzerCore | ||
clangStaticAnalyzerFrontend | ||
clangSupport | ||
clangTooling | ||
clangToolingASTDiff | ||
clangToolingCore | ||
clangToolingInclusions | ||
clangToolingInclusionsStdlib | ||
clangToolingRefactoring | ||
clangToolingSyntax | ||
clangTransformer | ||
) | ||
|
||
find_package(Clang REQUIRED) | ||
llvm_config(subdoc_lib) | ||
target_include_directories(subspace_clang_tidy_module PUBLIC ${LLVM_INCLUDE_DIRS}) | ||
target_link_directories(subspace_clang_tidy_module PUBLIC ${LLVM_LIBRARY_DIRS}) | ||
|
||
# Subspace clang-tidy module. | ||
subspace_default_compile_options(subspace_clang_tidy_module) | ||
|
||
add_subdirectory(tests) |
This file contains 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,47 @@ | ||
// Copyright 2023 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#pragma once | ||
|
||
// All LLVM and Clang includes go here, because they are full of compiler | ||
// warnings that we have to disable. | ||
|
||
#pragma warning(push) | ||
#pragma warning(disable : 4100) | ||
#pragma warning(disable : 4127) | ||
#pragma warning(disable : 4146) | ||
#pragma warning(disable : 4244) | ||
#pragma warning(disable : 4245) | ||
#pragma warning(disable : 4267) | ||
#pragma warning(disable : 4291) | ||
#pragma warning(disable : 4324) | ||
#pragma warning(disable : 4389) | ||
#pragma warning(disable : 4456) | ||
#pragma warning(disable : 4458) | ||
#pragma warning(disable : 4459) | ||
#pragma warning(disable : 4616) | ||
#pragma warning(disable : 4624) | ||
#pragma warning(disable : 4702) | ||
|
||
#include "clang-tidy/ClangTidyCheck.h" | ||
#include "clang-tidy/ClangTidyModule.h" | ||
#include "clang-tidy/ClangTidyModuleRegistry.h" | ||
#include "clang/AST/Decl.h" | ||
#include "clang/AST/DeclGroup.h" | ||
#include "clang/AST/DeclTemplate.h" | ||
#include "clang/AST/RecursiveASTVisitor.h" | ||
#include "clang/ASTMatchers/ASTMatchFinder.h" | ||
#include "clang/ASTMatchers/ASTMatchers.h" | ||
|
||
#pragma warning(pop) |
This file contains 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,30 @@ | ||
// Copyright 2023 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#include "tidy/llvm.h" | ||
#include "tidy/smoke_check.h" | ||
|
||
namespace clang::tidy::subspace { | ||
|
||
class SubspaceClangTidyModule : public ClangTidyModule { | ||
void addCheckFactories(ClangTidyCheckFactories& factories) override { | ||
factories.registerCheck<SmokeCheck>("subspace-smoke"); | ||
} | ||
}; | ||
|
||
static ClangTidyModuleRegistry::Add<SubspaceClangTidyModule> X( | ||
"subspace-clang-tidy-module", | ||
"Adds lint checks to be used with the Subspace library."); | ||
|
||
} // namespace clang::tidy::subspace |
This file contains 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,41 @@ | ||
// Copyright 2023 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#include "tidy/smoke_check.h" | ||
|
||
#include "subspace/prelude.h" | ||
#include "tidy/llvm.h" | ||
|
||
namespace clang::tidy::subspace { | ||
|
||
SmokeCheck::SmokeCheck(llvm::StringRef name, ClangTidyContext* context) | ||
: ClangTidyCheck(sus::move(name), context) {} | ||
|
||
void SmokeCheck::registerMatchers(ast_matchers::MatchFinder* finder) { | ||
using namespace ast_matchers; | ||
|
||
finder->addMatcher(functionDecl().bind("x"), this); | ||
} | ||
|
||
void SmokeCheck::check(const ast_matchers::MatchFinder::MatchResult& match) { | ||
const auto* MatchedDecl = match.Nodes.getNodeAs<FunctionDecl>("x"); | ||
if (!MatchedDecl->getIdentifier() || | ||
MatchedDecl->getName().startswith("awesome_")) | ||
return; | ||
diag(MatchedDecl->getLocation(), "function %0 is insufficiently awesome") | ||
<< MatchedDecl | ||
<< FixItHint::CreateInsertion(MatchedDecl->getLocation(), "awesome_"); | ||
} | ||
|
||
} // namespace clang::tidy::subspace |
This file contains 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,29 @@ | ||
// Copyright 2023 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#pragma once | ||
|
||
#include "subspace/macros/compiler.h" | ||
#include "tidy/llvm.h" | ||
|
||
namespace clang::tidy::subspace { | ||
|
||
class SmokeCheck : public ClangTidyCheck { | ||
public: | ||
SmokeCheck(llvm::StringRef name, ClangTidyContext* context); | ||
void registerMatchers(ast_matchers::MatchFinder* finder) override; | ||
void check(const ast_matchers::MatchFinder::MatchResult& match) override; | ||
}; | ||
|
||
} // namespace clang::tidy::subspace |
This file contains 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 @@ | ||
# Copyright 2023 Google LLC | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
enable_testing() | ||
|
||
function(tidy_test check_name) | ||
add_test(NAME "RunClangTidy.${check_name}" COMMAND ${CMAKE_COMMAND} | ||
"-DCLANG_TIDY_COMMAND=$<TARGET_FILE:clang-tidy>" | ||
"-DCLANG_TIDY_MODULE=$<TARGET_FILE:subspace_clang_tidy_module>" | ||
"-DCHECK_NAME=${check_name}" | ||
"-DRunClangTidy_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}" | ||
-P "${CMAKE_CURRENT_SOURCE_DIR}/run_clang_tidy.cmake" | ||
) | ||
endfunction() | ||
|
||
tidy_test(subspace-smoke) |
This file contains 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,107 @@ | ||
# Copyright 2023 Google LLC | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
set(config_arg) | ||
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}.clang-tidy") | ||
set(config_arg "--config-file=${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}.clang-tidy") | ||
endif() | ||
|
||
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}-stdout.txt") | ||
file(READ "${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}-stdout.txt" expect_stdout) | ||
string(REGEX REPLACE "\n+$" "" expect_stdout "${expect_stdout}") | ||
else() | ||
set(expect_stdout "") | ||
endif() | ||
|
||
set(source_file "${RunClangTidy_BINARY_DIR}/${CHECK_NAME}.cc") | ||
configure_file("${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}.cc" "${source_file}" COPYONLY) | ||
|
||
file(GLOB header_files RELATIVE "${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}" "${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}/*") | ||
file(REMOVE_RECURSE "${RunClangTiy_BINARY_DIR}/${CHECK_NAME}") | ||
foreach(header_file IN LISTS header_files) | ||
if(NOT header_file MATCHES "-fixit\\.h\$") | ||
file(MAKE_DIRECTORY "${RunClangTidy_BINARY_DIR}/${CHECK_NAME}") | ||
configure_file("${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}/${header_file}" "${RunClangTidy_BINARY_DIR}/${CHECK_NAME}/${header_file}" COPYONLY) | ||
endif() | ||
endforeach() | ||
|
||
set(command | ||
"${CLANG_TIDY_COMMAND}" | ||
"--load=${CLANG_TIDY_MODULE}" | ||
"--checks=-*,${CHECK_NAME}" | ||
"--fix" | ||
"--format-style=file" | ||
"--header-filter=/${CHECK_NAME}/" | ||
${config_arg} | ||
"${source_file}" | ||
-- | ||
) | ||
execute_process( | ||
COMMAND ${command} | ||
RESULT_VARIABLE result | ||
OUTPUT_VARIABLE actual_stdout | ||
ERROR_VARIABLE actual_stderr | ||
) | ||
string(REPLACE "${RunClangTidy_BINARY_DIR}/" "" actual_stdout "${actual_stdout}") | ||
|
||
set(RunClangTidy_TEST_FAILED) | ||
|
||
if(NOT result EQUAL 0) | ||
string(APPEND RunClangTidy_TEST_FAILED "Expected result: 0, actual result: ${result}\n") | ||
endif() | ||
|
||
string(REGEX REPLACE "\n+$" "" actual_stdout "${actual_stdout}") | ||
if(NOT actual_stdout STREQUAL expect_stdout) | ||
string(REPLACE "\n" "\n " expect_stdout_formatted " ${expect_stdout}") | ||
string(REPLACE "\n" "\n " actual_stdout_formatted " ${actual_stdout}") | ||
string(APPEND RunClangTidy_TEST_FAILED "Expected stdout:\n${expect_stdout_formatted}\nActual stdout:\n${actual_stdout_formatted}\n") | ||
endif() | ||
|
||
function(check_fixit expected fallback_expected actual) | ||
if(EXISTS "${expected}") | ||
set(expect_fixit_file "${expected}") | ||
else() | ||
set(expect_fixit_file "${fallback_expected}") | ||
endif() | ||
file(READ "${expect_fixit_file}" expect_fixit) | ||
file(READ "${actual}" actual_fixit) | ||
if(NOT expect_fixit STREQUAL actual_fixit) | ||
string(REPLACE "\n" "\n " expect_fixit_formatted " ${expect_fixit}") | ||
string(REPLACE "\n" "\n " actual_fixit_formatted " ${actual_fixit}") | ||
string(APPEND RunClangTidy_TEST_FAILED "Expected fixit for ${actual}:\n${expect_fixit_formatted}\nActual fixit:\n${actual_fixit_formatted}\n") | ||
set(RunClangTidy_TEST_FAILED "${RunClangTidy_TEST_FAILED}" PARENT_SCOPE) | ||
endif() | ||
endfunction() | ||
|
||
check_fixit( | ||
"${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}-fixit.cc" | ||
"${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}.cc" | ||
"${source_file}" | ||
) | ||
|
||
foreach(header_file IN LISTS header_files) | ||
if(NOT header_file MATCHES "-fixit\\.h\$") | ||
string(REGEX REPLACE "\\.h\$" "-fixit.h" header_fixit "${header_file}") | ||
check_fixit( | ||
"${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}/${header_fixit}" | ||
"${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}/${header_file}" | ||
"${RunClangTidy_BINARY_DIR}/${CHECK_NAME}/${header_file}" | ||
) | ||
endif() | ||
endforeach() | ||
|
||
if(RunClangTidy_TEST_FAILED) | ||
string(REPLACE ";" " " command_formatted "${command}") | ||
message(FATAL_ERROR "Command:\n ${command_formatted}\n${RunClangTidy_TEST_FAILED}") | ||
endif() |
This file contains 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 @@ | ||
void f() {} |