SERVER-71770 Move CollectionShardingRuntime into clang tidy

This commit is contained in:
Juan Gu 2023-05-26 20:48:58 +00:00 committed by Evergreen Agent
parent 197fbc88eb
commit c0423f3ab1
10 changed files with 221 additions and 13 deletions

View File

@ -35,6 +35,7 @@ Checks: '-*,
modernize-unary-static-assert,
mongo-cctype-check,
mongo-config-header-check,
mongo-collection-sharding-runtime-check,
mongo-cxx20-banned-includes-check,
mongo-header-bracket-check,
mongo-std-atomic-check,
@ -130,6 +131,8 @@ CheckOptions:
value: assert
- key: mongo-header-bracket-check.mongoSourceDirs
value: 'src/mongo;@MONGO_BUILD_DIR@'
- key: mongo-collection-sharding-runtime-check.exceptionDirs
value: 'src/mongo/db/s'
- key: bugprone-assert-side-effect.CheckFunctionCalls
value: '0'
- key: bugprone-dangling-handle.HandleClasses

View File

@ -6378,7 +6378,7 @@ if get_option('ninja') == 'disabled':
compileCommands = env.CompilationDatabase('compile_commands.json')
# Initialize generated-sources Alias as a placeholder so that it can be used as a
# dependency for compileCommands. This Alias will be properly updated in other SConscripts.
env.Requires(compileCommands, env.Alias("generated-sources"))
env.Depends(compileCommands, env.Alias("generated-sources"))
compileDb = env.Alias("compiledb", compileCommands)
msvc_version = ""

View File

@ -54,7 +54,6 @@ _RE_LINT = re.compile("//.*NOLINT")
_RE_COMMENT_STRIP = re.compile("//.*")
_RE_PATTERN_MONGO_POLYFILL = _make_polyfill_regex()
_RE_COLLECTION_SHARDING_RUNTIME = re.compile(r'\bCollectionShardingRuntime\b')
_RE_RAND = re.compile(r'\b(srand\(|rand\(\))')
_RE_GENERIC_FCV_COMMENT = re.compile(r'\(Generic FCV reference\):')
@ -151,7 +150,6 @@ class Linter:
continue
self._check_for_mongo_polyfill(linenum)
self._check_for_collection_sharding_runtime(linenum)
self._check_for_rand(linenum)
self._check_for_c_stdlib_headers(linenum)
@ -240,16 +238,6 @@ class Linter:
'Illegal use of banned name from std::/boost:: for "%s", use mongo::stdx:: variant instead'
% (match.group(0)))
def _check_for_collection_sharding_runtime(self, linenum):
line = self.clean_lines[linenum]
if _RE_COLLECTION_SHARDING_RUNTIME.search(
line
) and "/src/mongo/db/s/" not in self.file_name and "_test.cpp" not in self.file_name:
self._error(
linenum, 'mongodb/collection_sharding_runtime', 'Illegal use of '
'CollectionShardingRuntime outside of mongo/db/s/; use CollectionShardingState '
'instead; see src/mongo/db/s/collection_sharding_state.h for details.')
def _check_for_rand(self, linenum):
line = self.clean_lines[linenum]
if _RE_RAND.search(line):

View File

@ -0,0 +1,109 @@
/**
* Copyright (C) 2023-present MongoDB, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the Server Side Public License in all respects for
* all of the code used other than as permitted herein. If you modify file(s)
* with this exception, you may extend this exception to your version of the
* file(s), but you are not obligated to do so. If you do not wish to do so,
* delete this exception statement from your version. If you delete this
* exception statement from all source files in the program, then also delete
* it in the license file.
*/
#include "MongoCollectionShardingRuntimeCheck.h"
#include <clang-tidy/utils/OptionsUtils.h>
namespace mongo::tidy {
using namespace clang;
using namespace clang::ast_matchers;
MongoCollectionShardingRuntimeCheck::MongoCollectionShardingRuntimeCheck(
StringRef Name, clang::tidy::ClangTidyContext* Context)
: ClangTidyCheck(Name, Context),
exceptionDirs(clang::tidy::utils::options::parseStringList(
Options.get("exceptionDirs", "src/mongo/db/s"))) {}
void MongoCollectionShardingRuntimeCheck::registerMatchers(MatchFinder* Finder) {
// Match instances of the CollectionShardingRuntime class
Finder->addMatcher(
varDecl(hasType(cxxRecordDecl(hasName("CollectionShardingRuntime")))).bind("instanceCall"),
this);
// Match function calls made by the CollectionShardingRuntime class
Finder->addMatcher(callExpr(callee(functionDecl(hasParent(
cxxRecordDecl(hasName("CollectionShardingRuntime"))))))
.bind("funcCall"),
this);
}
void MongoCollectionShardingRuntimeCheck::check(const MatchFinder::MatchResult& Result) {
const auto* SM = Result.SourceManager;
if (!SM) {
return;
}
// Get the location of the current source file
const auto FileLoc = SM->getLocForStartOfFile(SM->getMainFileID());
if (FileLoc.isInvalid()) {
return;
}
// Get the current source file path
const auto FilePath = SM->getFilename(FileLoc);
if (FilePath.empty()) {
return;
}
std::string suffix = "_test.cpp";
// Check if FilePath ends with the suffix "_test.cpp"
if (FilePath.size() > suffix.size() &&
FilePath.rfind(suffix) == FilePath.size() - suffix.size()) {
return;
}
// If the file path is in an exception directory, skip the check.
for (const auto& dir : this->exceptionDirs) {
if (FilePath.startswith(dir)) {
return;
}
}
// Get the matched instance or function call
const auto* instanceDecl = Result.Nodes.getNodeAs<VarDecl>("instanceCall");
if (instanceDecl) {
diag(instanceDecl->getBeginLoc(),
"Illegal use of CollectionShardingRuntime outside of mongo/db/s/; use "
"CollectionShardingState instead; see src/mongo/db/s/collection_sharding_state.h for "
"details.");
}
const auto* funcCallExpr = Result.Nodes.getNodeAs<CallExpr>("funcCall");
if (funcCallExpr) {
diag(funcCallExpr->getBeginLoc(),
"Illegal use of CollectionShardingRuntime outside of mongo/db/s/; use "
"CollectionShardingState instead; see src/mongo/db/s/collection_sharding_state.h for "
"details.");
}
}
} // namespace mongo::tidy

View File

@ -0,0 +1,59 @@
/**
* Copyright (C) 2023-present MongoDB, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the Server Side Public License in all respects for
* all of the code used other than as permitted herein. If you modify file(s)
* with this exception, you may extend this exception to your version of the
* file(s), but you are not obligated to do so. If you do not wish to do so,
* delete this exception statement from your version. If you delete this
* exception statement from all source files in the program, then also delete
* it in the license file.
*/
#pragma once
#include <clang-tidy/ClangTidy.h>
#include <clang-tidy/ClangTidyCheck.h>
namespace mongo::tidy {
/**
* MongoCollectionShardingRuntimeCheck is a custom clang-tidy check for detecting
* the usage of CollectionShardingRuntime outside of the "mongo/db/s/" directory.
*
* It extends ClangTidyCheck and overrides the registerMatchers and check functions.
* The registerMatchers function adds custom AST Matchers to detect the instances and function calls
* of CollectionShardingRuntime. These matchers bind matched nodes with names for later retrieval in
* check function.
*
* The check function then retrieves the nodes bound by the matchers and emit diagnostics if
* any illegal usage is detected. An usage is considered illegal if the source file is not in the
* exception directories (e.g., "src/mongo/db/s/").
*
*/
class MongoCollectionShardingRuntimeCheck : public clang::tidy::ClangTidyCheck {
public:
MongoCollectionShardingRuntimeCheck(clang::StringRef Name,
clang::tidy::ClangTidyContext* Context);
void registerMatchers(clang::ast_matchers::MatchFinder* Finder) override;
void check(const clang::ast_matchers::MatchFinder::MatchResult& Result) override;
std::vector<std::string> exceptionDirs;
};
} // namespace mongo::tidy

View File

@ -29,6 +29,7 @@
#include "MongoAssertCheck.h"
#include "MongoCctypeCheck.h"
#include "MongoCollectionShardingRuntimeCheck.h"
#include "MongoConfigHeaderCheck.h"
#include "MongoCxx20BannedIncludesCheck.h"
#include "MongoFCVConstantCheck.h"
@ -67,6 +68,8 @@ public:
CheckFactories.registerCheck<MongoAssertCheck>("mongo-assert-check");
CheckFactories.registerCheck<MongoFCVConstantCheck>("mongo-fcv-constant-check");
CheckFactories.registerCheck<MongoUnstructuredLogCheck>("mongo-unstructured-log-check");
CheckFactories.registerCheck<MongoCollectionShardingRuntimeCheck>(
"mongo-collection-sharding-runtime-check");
}
};

View File

@ -135,6 +135,7 @@ mongo_custom_check = env.SharedLibrary(
"MongoAssertCheck.cpp",
"MongoFCVConstantCheck.cpp",
"MongoUnstructuredLogCheck.cpp",
"MongoCollectionShardingRuntimeCheck.cpp",
],
LIBDEPS_NO_INHERIT=[
'$BUILD_DIR/third_party/shim_allocator',

View File

@ -292,6 +292,23 @@ class MongoTidyTests(unittest.TestCase):
"error: MONGO_CONFIG define used without prior inclusion of config.h [mongo-config-header-check,-warnings-as-errors]\n#ifndef MONGO_CONFIG_TEST2",
"error: MONGO_CONFIG define used without prior inclusion of config.h [mongo-config-header-check,-warnings-as-errors]\n#if defined(MONGO_CONFIG_TEST1)",
]
self.run_clang_tidy()
def test_MongoCollectionShardingRuntimeCheck(self):
self.write_config(
textwrap.dedent("""\
Checks: '-*,mongo-collection-sharding-runtime-check'
WarningsAsErrors: '*'
CheckOptions:
- key: mongo-collection-sharding-runtime-check.exceptionDirs
value: 'src/mongo/db/s'
"""))
self.expected_output = [
"error: Illegal use of CollectionShardingRuntime outside of mongo/db/s/; use CollectionShardingState instead; see src/mongo/db/s/collection_sharding_state.h for details. [mongo-collection-sharding-runtime-check,-warnings-as-errors]\n CollectionShardingRuntime csr(5, \"Test\");",
"error: Illegal use of CollectionShardingRuntime outside of mongo/db/s/; use CollectionShardingState instead; see src/mongo/db/s/collection_sharding_state.h for details. [mongo-collection-sharding-runtime-check,-warnings-as-errors]\n int result = CollectionShardingRuntime::functionTest(7, \"Test\");",
]
self.run_clang_tidy()

View File

@ -38,6 +38,7 @@ if env.GetOption('ninja') == 'disabled':
'test_MongoAssertCheck.cpp',
'test_MongoFCVConstantCheck.cpp',
'test_MongoUnstructuredLogCheck.cpp',
'test_MongoCollectionShardingRuntimeCheck.cpp',
]
# So that we can do fast runs, we will generate a separate compilation database file for each

View File

@ -0,0 +1,27 @@
#include <string>
namespace mongo {
class CollectionShardingRuntime {
public:
// Constructor
CollectionShardingRuntime(int a, std::string s) : value(a), name(s) {}
// Static function
static int functionTest(int a, std::string s) {
return a + s.length();
}
private:
int value;
std::string name;
};
int testMongoUnstructuredLogFuncton1111() {
// Create an instance of the object
CollectionShardingRuntime csr(5, "Test");
// Call the static function
int result = CollectionShardingRuntime::functionTest(7, "Test");
}
} // namespace mongo